Java-OpenCV中drawContours无法填充轮廓的OCR预处理问题
我正在开发一款基于Tesseract OCR的文档文本提取应用,目前处理的示例图片如下:
待提取文本的图片
因为后续需要单独分析每个矩形区域,所以必须保留线条坐标,同时要去除图片中的干扰线条。我用Java结合OpenCV写了下面这段预处理代码:
package formRecog; import java.io.File; import java.util.ArrayList; import java.util.List; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.core.Size; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import static org.opencv.core.Core.bitwise_not; import org.opencv.core.MatOfPoint; public class testMat { public static void main(String[] args) { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); Mat source = Imgcodecs.imread("./image.png",Imgcodecs.CV_LOAD_IMAGE_ANYCOLOR); Mat destination = new Mat(source.rows(), source.cols(), source.type()); Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2GRAY); Imgcodecs.imwrite("gray.jpg", destination); Imgproc.GaussianBlur(destination, destination, new Size(3, 3), 0, 0, Core.BORDER_DEFAULT); Imgproc.Canny(destination, destination, 30, 90); Imgcodecs.imwrite("postcanny.jpg", destination); Mat houghlines = new Mat(); Imgproc.HoughLinesP(destination, houghlines, 1, Math.PI / 180, 250, 185,5); //绘制线条 Mat result = new Mat(source.rows(), source.cols(), source.type()); for (int i = 0; i < houghlines.rows(); i++) { double[] val = houghlines.get(i, 0); Imgproc.line(destination, new Point(val[0], val[1]), new Point(val[2], val[3]), new Scalar(0, 0, 255), 5); Imgproc.line(result, new Point(val[0], val[1]), new Point(val[2], val[3]), new Scalar(0, 0, 255),5); } Imgcodecs.imwrite("lines.jpg", result); Mat contourImg = new Mat(source.rows(), source.cols(), source.type()); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Mat hierarchy = new Mat(); //Point offset = new Point(); Imgproc.findContours(destination, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE ); Imgproc.drawContours(contourImg, contours, -1, new Scalar(255, 0, 0),-1); Imgcodecs.imwrite("contour.jpg", contourImg); bitwise_not(destination,destination); Imgcodecs.imwrite("final.jpg", destination); } }
处理后的最终图片是:
处理后的最终图片
但现在遇到了问题:Tesseract无法正确识别图片里的文本,识别结果全是乱码:11m ËEZË@ÜDS@ 7 C@mpû@ 515 îf@5@??ûäû ©©m@@@ @@ vësw??a? PF©@MÜGS @"@X@Ü©ÜÎÊQÜ©IÏÙ 1111 175515
我分析下来觉得是字母没有被填充导致的——之前用其他去线方法时,Tesseract的识别效果是正常的。但我调用Imgproc.drawContours(contourImg, contours, -1, new Scalar(255, 0, 0),-1);这段代码并没有实现填充效果,不过findContours本身是正常工作的,导出的结果和原图片一致。我搜了很多相关问题,但都没找到能用的解决方案。我今年9月才开始学编程,算是纯新手,但这个任务必须完成,实在没办法了才来求助。
编辑:感谢Rick.M的帮助!我把findContours的参数改成CHAIN_APPROX_SIMPLE,并且遍历索引绘制轮廓后,效果有所改善,新的最终图片是:
优化后的最终图片
不过我还是想问问有没有进一步优化的方法?我感觉现在Tesseract应该还是没法正常识别,希望各位能给我一些建议。另外附上Canny处理后的图片:
Canny处理后的图片
内容的提问来源于stack exchange,提问作者DSt

