【问题标题】:Segmentation of images with characters that are joined用连接的字符分割图像
【发布时间】:2019-08-26 08:54:46
【问题描述】:

我正在尝试在下图中的不同字符周围绘制一个边界框。但是,由于某些字符已加入,我无法绘制框。我尝试了一些事情,例如;扩张、侵蚀和尝试不同的模糊,但我似乎无法将它们分开。腐蚀似乎是最好的接近方法,但如果我继续腐蚀,字符将无法识别。

我正在使用 Java 中的 OpenCV 库来实现这一点。

Mat img = Imgcodecs.imread("test.jpg");

        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchy = new Mat();
        Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2GRAY);
        Imgproc.threshold(img, img, 220, 255, 0);
        Imgproc.erode(img, img, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3)));
        Imgproc.findContours(img, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);


        MatOfPoint2f approxCurve = new MatOfPoint2f();

        //For each contour found
        for (int i = 0; i < contours.size(); i++) {
            MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
            double approxDistance = Imgproc.arcLength(contour2f, true) * 0.02;
            Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);

            MatOfPoint points = new MatOfPoint(approxCurve.toArray());

            Rect rect = Imgproc.boundingRect(points);
            Imgproc.rectangle(img, rect.tl(), rect.br(), new Scalar(255, 255, 255), 1, 8, 0);
        }
        System.out.println(img);
        Imgcodecs.imwrite("o.jpg", img);

之前:

之后:

【问题讨论】:

  • 如果数字共享这么多像素,您的方法将无法正常工作。建议另一种方法需要更多关于字体、比例、旋转等变化的知识......
  • 尝试用更大的结构尺寸进行腐蚀,大到足以区分数字。我认为你正在做 3x3。那太小了,可能是7x7。然后用相同的大小进行膨胀以恢复原始形状(种类)。组合的腐蚀+膨胀被称为形态开放。类似Imgproc.erode(img, img, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(7, 7)));Imgproc.dilate(img, img, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(7, 7)));
  • @Piglet 是的,它们确实共享不少像素。我正在使用库来生成这些图像。该库名为:simplecaptcha ([link]simplecaptcha.sourceforge.net ) 我不知道如何检查字体、比例等
  • @Tetix 我刚刚尝试过并将其设置为 7 完全消除了问题。我已经调整了值,5 是我能达到的最好值。 i.imgur.com/gW0UNbs.png
  • 如果连接的组件可以很好地解决验证码,验证码完全没用。我想你必须更深入地挖掘;)就像,嘿,我想打开这把锁,但我的手指进不去。你能帮我吗?

标签: java opencv image-processing text-segmentation


【解决方案1】:

一种可能的方法(您可以尝试)是如果您知道字符数,例如:5,那么您可以先在分段轮廓周围绑定一个矩形,然后将宽度除以 5,然后绘制图像上带有黑色的矩形,然后图像将被成功分割。

按照以下步骤操作:

cv::namedWindow("result", cv::WINDOW_FREERATIO);
cv::Mat img = cv::imread(R"(D:\A49d6.png)");

// to gray
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
// remove unvisible noise
cv::threshold(gray, gray, 20, 255, cv::THRESH_BINARY);

// this is to make sure to get the correct bounding rect
cv::morphologyEx(gray, gray, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(5, 1)));

std::vector<std::vector<cv::Point> > contours;
cv::findContours(gray, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

// because we know that there is only one contour, so get the first posittion (0 index) from the list
cv::Rect rect = cv::boundingRect(contours[0]);

// calculate the width for each character
int width = int(round(rect.width/5.0));
for(int i(0); i<5; i++) {
    cv::Rect r(rect.x+(width*i), rect.y, width, rect.height);
    cv::rectangle(img, r, cv::Scalar(0));
}

cv::imshow("result", img);
cv::waitKey();

结果如下:

现在图像已经足够清晰,可以识别了。

【讨论】:

    猜你喜欢
    • 2018-11-18
    • 2012-12-22
    • 2011-08-29
    • 2013-12-10
    • 1970-01-01
    • 2014-12-03
    • 2017-11-25
    • 2014-07-31
    • 2013-10-23
    相关资源
    最近更新 更多