• opencv在python和c#中的对照应用-文字区域识别


    先来c#的,

            private void button1_Click(object sender, EventArgs e)
            {
                var fileName = @"d:Screenshot4.jpg";
                fileName = @"d:Screenshot6.png";
                //mat = new Mat(fileName);
                //pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
                //pictureBox1.Image = mat.ToBitmap();
    
    
                var img = Cv2.ImRead(fileName);
                var pos = detect(img);
                foreach (var p in pos)
                {
                    Debug.WriteLine(p);
                }
    
            }
    
    
            private List<OpenCvSharp.Point> detect(Mat img)
            {
                var pos = new List<OpenCvSharp.Point>();
                //1.转化成灰度图
                Mat gray = img.CvtColor(ColorConversionCodes.BGR2GRAY);
                //Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY);
                //2. 形态学变换的预处理,得到可以查找矩形的图片
                Mat dilation = preprocess(gray);
                //3. 查找和筛选文字区域
                var region = findTextRegion(dilation);
                //4. 用绿线画出这些找到的轮廓
                var nrootdir = @"d:/cut_image/";
                var nrootdir2 = @"d:/cut_image2/";
                int i = 0;
                int j = 1;
                foreach (var item in region)
                {
                    var newimage=img[item.Y>0?item.Y:0,  item.Y+item.Height,    item.X>0?item.X:0, item.X+item.Width];
                    //放大4倍
                    Mat img_gray = new Mat();
                    //var img_gray = img.Resize(newimage.Size(), 4, 4, InterpolationFlags.Nearest);
                    OpenCvSharp.Size size = new OpenCvSharp.Size();
                    Cv2.Resize(newimage, img_gray, size, 4, 4, InterpolationFlags.Nearest);
    
                    var file_name = nrootdir + i.ToString() + ".jpg";                
                    Cv2.ImWrite(file_name, newimage);
    
                    var file_sub = "";
                    var gray2 = img_gray.CvtColor(ColorConversionCodes.BGR2GRAY);
                    var dilation2 = preprocess(gray2);
                    var region2 = findTextRegion(dilation2);
                    foreach (var item2 in region2)
                    {
                        var newimage2 = img_gray[item2.Y>0?item2.Y:0,item2.Y+item2.Height,   item2.X>0?item2.X:0, item2.X+item2.Width];
                        if (newimage2.Size().Width > 0)
                        {
                            file_sub = nrootdir2 + i.ToString() + "-" + j.ToString() + ".jpg";
                            Cv2.ImWrite(file_sub, newimage2);
                            j++;
                            pos.Add(new OpenCvSharp.Point(item.X+item2.X/4+item2.Width/8, item.Y+item2.Y/4+item2.Height/8));
                        }
                    }
                    //如果第一次检测只有一个文字区域,第二次放大再检测则没有。这样直接复制过去
                    if (region2 == null || region2.Count == 0)
                    {
                        file_sub = nrootdir2 + i.ToString() + "-0" + ".jpg";
                        Cv2.ImWrite(file_sub, newimage);
                        pos.Add(new OpenCvSharp.Point(item.X+item.Width/2, item.Y+item.Height/2));
                    }
                    i++;
    
                    //画线
                    //img.Rectangle(item, new Scalar(0, 255, 0), 2);
                }
    
                //Cv2.ImShow("img", img);
    
                return pos;
            }
    
    
            public List<Rect> findTextRegion(Mat dilation)
            {
                List<Rect> region = new List<Rect>();
                // 1. 查找轮廓
                OpenCvSharp.Point[][] contours;
                HierarchyIndex[] hierarchly;
                Rect biggestContourRect = new Rect();
    
                Cv2.FindContours(dilation, out contours, out hierarchly, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple);
    
                // 2. 筛选那些面积小的
                int i = 0;
                foreach (OpenCvSharp.Point[] contour in contours)
                {
                    double area = Cv2.ContourArea(contour);
                    //面积小的都筛选掉
                    if (area < 1000 || area> 10000)
                    {
                        continue;
                    }
                    //轮廓近似,作用很小
                    double epsilon = 0.001 * Cv2.ArcLength(contour, true);
                    RotatedRect rect = Cv2.MinAreaRect(contour);
    
                    //找到最小的矩形
                    biggestContourRect = Cv2.BoundingRect(contour);
    
                    if (biggestContourRect.Height > (biggestContourRect.Width * 1.2))
                    {
                        continue;
                    }
                    region.Add(biggestContourRect);                
                }
                return region;
                //pictureBox1.Image = mat.ToBitmap();
                
            }
    
            private Mat preprocess(Mat gray)
            {
                //1.Sobel算子,x方向求梯度
                Mat sobel = new Mat();
                Cv2.Sobel(gray, 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(36, 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);
                return dilation2;
            }
    View Code

    python3的,

    # coding=utf-8
    import cv2
    import numpy as np
    import os
    
    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, (36, 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_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
        # 2. 筛选那些面积小的
        for i in range(len(contours)):
            cnt = contours[i]
            # 计算该轮廓的面积
            area = cv2.contourArea(cnt) 
            # 面积小的都筛选掉
            if(area < 1000 or area> 10000):  #也过滤太的外框
                continue
            # 轮廓近似,作用很小
            epsilon = 0.001 * cv2.arcLength(cnt, True)
            approx = cv2.approxPolyDP(cnt, epsilon, True)
            # 找到最小的矩形,该矩形可能有方向
            rect = cv2.minAreaRect(cnt)
            # print ("rect is: ",rect)
            # box是四个点的坐标
            box = cv2.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, 0, 0), 2)
        cv2.namedWindow("img", cv2.WINDOW_NORMAL)
        cv2.imshow("img", img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
    
    
    
        nrootdir=("d:/cut_image/")
        if not os.path.isdir(nrootdir):
            os.makedirs(nrootdir)
        nrootdir2=("d:/cut_image2/")
        if not os.path.isdir(nrootdir2):
            os.makedirs(nrootdir2)
    
        pos=[]
        idx=1
        for i in range(0,len(region)): 
            px, py, w, h = cv2.boundingRect(region[i])  
            #print(i,px,py,w,h)
            
            #cv2.rectangle(img, (x,y), (x+w,y+h), (153,153,0), 5)
            # newimage=img[y+2:y+h-2,x+2:x+w-2] # 先用y确定高,再用x确定宽
            newimage=img[py if py>0 else 0:py+h,px if px>0 else 0:px+w]
            # 放大4倍
            img_gray=cv2.resize(newimage,(0,0),fx=4,fy=4,interpolation=cv2.INTER_NEAREST)
            file_name=nrootdir+str(i)+".jpg"
            cv2.imwrite(file_name, newimage)
    
            gray2 = cv2.cvtColor(img_gray, cv2.COLOR_BGR2GRAY)
            dilation2 = preprocess(gray2)
            region2 = findTextRegion(dilation2)
            for j in range(0,len(region2)): 
                x2, y2, w2, h2 = cv2.boundingRect(region2[j])  
                cx = x2+w2/2
                cy = y2+h2/2 
                #print(j,x2,y2,w2,h2, (cx, cy))
                newimage2=img_gray[y2 if y2>0 else 0:y2+h2,x2 if x2>0 else 0:x2+w2]
                if newimage2.size>0:
                    file_name=nrootdir2+str(idx)+".jpg"
                    cv2.imwrite(file_name, newimage2)
                    idx+=1
                    pos.append((px+cx/4,py+cy/4))
        return pos
    
        # cv2.imwrite("contours.png", img)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
    
    
    # img = cv2.imread("d:Screenshot1.png")
    img = cv2.imread("d:Screenshot4.jpg")
    pos=detect(img)
    for p in pos:
        print(p)
    View Code

     

     然后坐标就得到了

    (x:1513 y:955)
    (x:1036 y:949)
    (x:993 y:944)
    (x:811 y:947)
    (x:751 y:939)
    (x:871 y:934)
    (x:815 y:920)
    (x:754 y:912)
    。。。

    还有然后。

  • 相关阅读:
    linux安装tmux分屏插件
    美化linux客户端zsh和oh-my-zsh
    使用Feign通过服务名调用服务,找不到服务
    Docker Compose 配置文件详解
    Dockerfile构建jar镜像
    Mysql数据库主从同步
    【Java】Java划水练习
    【2-SAT】Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) D. Innokenty and a Football League
    【贪心】【DFS】Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) C. Andryusha and Colored Balloons
    【三分】Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) B. The Meeting Place Cannot Be Changed
  • 原文地址:https://www.cnblogs.com/yansc/p/15040019.html
Copyright © 2020-2023  润新知