如何在OpenCV中删除不需要的线路/噪音?

Ash*_*Ali 2 c++ java android opencv

我正在为android开发一个OCR应用程序(构建为java Application).我想检测从相机捕获的图像中的文本和预处理我正在使用OpenCV,但我得到一些额外的行作为文本读取,我已遵循这种方法:

1-RGB到GreyScale 2-Threshold 3-Gaussian Blur 4-Median Blur 5-Dilation 6-Erosion

结果至少比以前好,但仍然没有得到正确的结果.我怎样才能消除这种噪音,这些过滤器的一般序列是什么,可以应用于任何图像以改善OCR的结果.我是OpenCV的新手,请指导我.谢谢.

旧图像


更新的图像


从上面的图像我能够找到3号的结果,但只有当所有的轮廓被绘制,这是我不想要的东西,因为还有噪音.我在这里缺少什么.不知道该怎么做进一步.修订代码:

package simple_contours;

import java.util.ArrayList;
import java.util.List;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

public class Main {

    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        Mat src_img,src_grey,src_blur,src_thresh,src_dilate,dest_img; 
        src_img=Highgui.imread("n_num.jpg",Imgproc.COLOR_BGR2GRAY);


        src_grey=new Mat(src_img.size(), Core.DEPTH_MASK_8U);
        src_blur=new Mat(src_img.size(), Core.DEPTH_MASK_8U);
        src_thresh=new Mat(src_img.size(), Core.DEPTH_MASK_8U);
        src_dilate=new Mat(src_img.size(), Core.DEPTH_MASK_8U);
        dest_img=Mat.zeros(640,480, CvType.CV_8UC3);
        Core.bitwise_not(dest_img, dest_img);
        Highgui.imwrite("dest.jpg", dest_img);

        Imgproc.cvtColor(src_img, src_grey, Imgproc.COLOR_BGR2GRAY);
        Imgproc.GaussianBlur(src_grey, src_blur, new Size(3, 3), 0);
        Imgproc.threshold(src_blur, src_thresh, 80, 255, Imgproc.THRESH_BINARY_INV);
        Imgproc.dilate(src_thresh, src_dilate, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2, 2)));

        Highgui.imwrite("Threshold.jpg", src_thresh);
        Highgui.imwrite("Dilate.jpg", src_dilate);




          List<MatOfPoint> contours = new ArrayList<MatOfPoint>();  
          Mat heirarchy= new Mat();
          Point shift=new Point(150,0);
          Imgproc.findContours(src_dilate, contours,heirarchy, Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE,shift);
          double[] cont_area =new double[contours.size()]; 

             for(int i=0; i< contours.size();i++)
             { 
                Rect rect = Imgproc.boundingRect(contours.get(i));
                cont_area[i]=Imgproc.contourArea(contours.get(i));

                System.out.println("Hight: "+rect.height);
                System.out.println("WIDTH: "+rect.width);
                System.out.println("AREA: "+cont_area[i]);
              //System.out.println(rect.x +","+rect.y+","+rect.height+","+rect.width);

                  Core.rectangle(src_img, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255));
                  Imgproc.drawContours(dest_img, contours, i, new Scalar(0,0,0),-1,8,heirarchy,2,shift);
                  Core.rectangle(dest_img, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,255,0));
         }

             Highgui.imwrite("Final.jpg", dest_img);
             Highgui.imwrite("Original.jpg", src_img);
    }

}
Run Code Online (Sandbox Code Playgroud)

小智 7

我认为你只能使用erode/dilate选项.问题在于噪音不仅仅是噪音,而是包含的伪像不一定与您试图检测的某些角色不同.

我建议解决方案需要涉及检测图像中的轮廓.首先,您应该准备好图像,使其更适合轮廓加工过程.

我过去使用过以下序列:

  • 高斯模糊
  • adaptiveThreshold
  • negativeImage
  • 膨胀

现在你可以找到轮椅.这应该挑出字母和不受欢迎的人工制品.然后你需要消除人工制品,你可能需要一些策略,例如:

  • 弄清楚边界框的区域,并消除区域太小而不是字母的区域
  • 检查边界框的宽度与高度:消除高度太小的那些

可能有更复杂的方法,例如试图找到穿过较大轮廓中间的轴,这将给出角色的位置和方向(比如旋转的Rect); 您可以使用该信息忽略不在区域中的所有其他像素.

对不起,这不是一个简单的解决方案,但它是一个复杂的问题,所以你可能需要进行一些实验,并建立多种策略来删除不需要的人工制品.