1. 程式人生 > 實用技巧 >python和c#的 opencv文字區域識別

python和c#的 opencv文字區域識別

//var filename = @"E:\test\amap-binary.bmp";
//讀取灰度圖
using (Mat src = new Mat(filename, ImreadModes.Grayscale))
{
//Cv2.ImShow("Demo", src);

//1.Sobel運算元,x方向求梯度
Mat sobel = new Mat();
Cv2.Sobel(src, sobel, MatType.CV_8U, 1, 0, 3);

//2.二值化
Mat binary = new Mat();
Cv2.Threshold(sobel, binary, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

//3. 膨脹和腐蝕操作的核函式 Mat element1 = new Mat(); Mat element2 = new Mat(); OpenCvSharp.Size size1 = new OpenCvSharp.Size(30, 9); OpenCvSharp.Size size2 = new OpenCvSharp.Size(24, 6); element1 = Cv2.GetStructuringElement(MorphShapes.Rect, size1); element2 = Cv2.GetStructuringElement(MorphShapes.Rect, size2);
//4. 膨脹一次,讓輪廓突出 Mat dilation = new Mat(); Cv2.Dilate(binary, dilation, element2); //5. 腐蝕一次,去掉細節,如表格線等。注意這裡去掉的是豎直的線 Mat erosion = new Mat(); Cv2.Erode(dilation, erosion, element1); //6. 再次膨脹,讓輪廓明顯一些 Mat dilation2 = new Mat(); Cv2.Dilate(erosion, dilation2, element2, null, 2); OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchly; Cv2.FindContours(dilation2,
out contours, out hierarchly, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point(0, 0)); //Mat dst_Image = Mat.Zeros(src.Size(), src.Type()); Mat dst_Image = src.Clone(); string pts = ""; for (int i = 0; i < contours.Length; i++) { Scalar color = new Scalar(0, 255, 255);// //Cv2.DrawContours(dst_Image, contours, i, color, 1, LineTypes.Link8, hierarchly); double area = Cv2.ContourArea(contours[i]); if (area < 1000) continue; var epsilon = 0.001 * Cv2.ArcLength(contours[i], true); var approx = Cv2.ApproxPolyDP(contours[i], epsilon, true); //找到最小矩形,可能有方向 var rect2 = Cv2.MinAreaRect(contours[i]); var box = rect2.Points(); //篩選那些太細的矩形,留下扁的 var height = Math.Abs(box[0].Y - box[2].Y); var width = Math.Abs(box[0].X - box[2].X); if (height > width * 1.2) continue; pts += rect2.Center.X.ToString() + "," + rect2.Center.Y.ToString() + ";"; Cv2.DrawContours(dst_Image, contours, i, color, 1, LineTypes.Link8, hierarchly); } Cv2.ImShow(pts, dst_Image); Cv2.WaitKey(0);

#coding=utf-8
import sys
import cv2
import numpy as np

# img = cv2.imread(r'E:\test\amap-binary.bmp') 
# cv2.namedWindow("Image") 
# cv2.imshow("Image", img) 
# cv2.waitKey (0)
# cv2.destroyAllWindows()


def preprocess(gray):
    # 1. Sobel運算元,x方向求梯度
    sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize = 3)
    # 2. 二值化
    ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)

    # 3. 膨脹和腐蝕操作的核函式
    element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))
    element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))

    # 4. 膨脹一次,讓輪廓突出
    dilation = cv2.dilate(binary, element2, iterations = 1)

    # 5. 腐蝕一次,去掉細節,如表格線等。注意這裡去掉的是豎直的線
    erosion = cv2.erode(dilation, element1, iterations = 1)

    # 6. 再次膨脹,讓輪廓明顯一些
    dilation2 = cv2.dilate(erosion, element2, iterations = 2)

    # 7. 儲存中間圖片 
    cv2.imwrite("binary.png", binary)
    cv2.imwrite("dilation.png", dilation)
    cv2.imwrite("erosion.png", erosion)
    cv2.imwrite("dilation2.png", dilation2)
    return dilation2


def findTextRegion(img):
    region = []
    # 1. 查詢輪廓
    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    # 2. 篩選那些面積小的
    for i in range(len(contours)):
        cnt = contours[i]
        # 計算該輪廓的面積
        area = cv2.contourArea(cnt) 

        # 面積小的都篩選掉
        if(area < 1000):
            continue

        # 輪廓近似,作用很小
        epsilon = 0.001 * cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, epsilon, True)

        # 找到最小的矩形,該矩形可能有方向
        rect = cv2.minAreaRect(cnt)
        print "rect is: "
        print rect

        # box是四個點的座標
        box = cv2.cv.BoxPoints(rect)
        box = np.int0(box)

        # 計算高和寬
        height = abs(box[0][1] - box[2][1])
        width = abs(box[0][0] - box[2][0])

        # 篩選那些太細的矩形,留下扁的
        if(height > width * 1.2):
            continue

        region.append(box)
    return region


def detect(img):
    # 1.  轉化成灰度圖
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 2. 形態學變換的預處理,得到可以查詢矩形的圖片
    dilation = preprocess(gray)

    # 3. 查詢和篩選文字區域
    region = findTextRegion(dilation)

    # 4. 用綠線畫出這些找到的輪廓
    for box in region:
        cv2.drawContours(img, [box], 0, (0, 255, 0), 2)

    cv2.namedWindow("img", cv2.WINDOW_NORMAL)
    cv2.imshow("img", img)

    # 帶輪廓的圖片
    cv2.imwrite("contours.png", img)

    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == '__main__':
    # 讀取檔案
    imagePath = r'E:\test\amap-binary.bmp'
    img = cv2.imread(imagePath)
    detect(img)