基於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




未經許可嚴禁轉載。

相關文章
相關標籤/搜索