基于OpenCV及连通域分析进行文本块分割

上一次经过投影的方式进行了文本块分割,但这种方法有很大的局限性,要求分行清晰、不能有字符跨多行、不能倾斜,并且对噪声比较敏感。仍是拿上一回的图片,可是我在上面加了一个比较大的字,得出的结果就有问题了:c#

wKioL1XVOuOhQRO8AAMwzSkeEHE127.jpg


能够看到,因为右下角大大的“测”字跨了多行,致使水平投影分行时就出错了。ide


本次换一种方法,基于连通性分析来作。简单讲,就是把图像作必定的膨胀操做,使得同一个字符的不一样部分以及相邻字符相互重叠到一块儿,变成一个总体,而后再经过分析找到每个独立的块,排除掉噪声,剩下的基本就是符合条件的结果了。spa


直接上代码,后面再分析:blog

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
 
using OpenCvSharp;
using OpenCvSharp.Extensions;
using OpenCvSharp.Utilities;
 
namespace OpenCvTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //读入源文件
            var src = IplImage.FromFile("source.jpg");
                
            //转换到灰度图
            var gray = Cv.CreateImage(src.Size, BitDepth.U8, 1);
            Cv.CvtColor(src, gray, ColorConversion.BgrToGray);
                
            //作一下膨胀,x与y方向都作,但系数不一样
            //使用了Erode方法,腐蚀操做,针对白色区域,因此等效于对文字进行了膨胀
            var kernal = Cv.CreateStructuringElementEx(5, 2, 1, 1, ElementShape.Rect);
            Cv.Erode(gray, gray, kernal, 2);
                
            //二值化
            Cv.Threshold(gray, gray, 0, 255, ThresholdType.BinaryInv | ThresholdType.Otsu);
                
            //检测连通域,每个连通域以一系列的点表示,FindContours方法只能获得第一个域
            var storage = Cv.CreateMemStorage();
            CvSeq<CvPoint> contour = null;
            Cv.FindContours(gray, storage, out contour, CvContour.SizeOf, ContourRetrieval.CComp, ContourChain.ApproxSimple);
            var color = new CvScalar(0, 0, 255);
                
            //开始遍历
            while (contour != null)
            {
                //获得这个连通区域的外接矩形
                var rect = Cv.BoundingRect(contour);
                    
                //若是高度不足,或者长宽比过小,认为是无效数据,不然把矩形画到原图上
                if(rect.Height > 10 && (rect.Width * 1.0 / rect.Height) > 0.2)
                    Cv.DrawRect(src, rect, color);
                        
                //取下一个连通域
                contour = contour.HNext;
            }
            Cv.ReleaseMemStorage(storage);
                
            //显示
            Cv.ShowImage("Result", src);
            Cv.WaitKey();
            Cv.DestroyAllWindows();
        }
    }
}


下面来一步一步分析。读入的原图是这样的:图片

wKiom1XVOWfylP4LAAKUZyvZX5U616.jpg


转换到灰度图并膨胀处理后,已经能够大体看出同一文本块的多个字符已经连到一块儿了:get

wKiom1XVOX7RU6WyAAHdFb1475I305.jpg


二值化后的图像:string

wKioL1XVO4ywZViUAAHAR4YogMQ944.jpg


作连通性分析后,原始分析出的结果是这样的:it

Cv.DrawContours(src, contour, color, color, 1);


wKiom1XenTCylzvfAAPoDQVhtBo400.jpg


对每一个连通域取外接矩形,获得的最终结果是这样的:
io

wKiom1XVOayxgGlCAAMjKEeLsQk465.jpg


能够看到效果比以前好了不少,比较大的字能够做为独立的文本块被检测出来了。另外即便是同一行的文本块,也会有轻微的上下浮动,再也不是绝对按行对齐了。class




未经许可严禁转载。

相关文章
相关标签/搜索