分割带有结合字符的图像

时间:2019-04-04 14:37:15

标签: java opencv image-processing text-segmentation

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

我正在使用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);

之前:

https://i.imgur.com/qiTwfnx.png

之后:

https://i.imgur.com/ekjbWNs.png

1 个答案:

答案 0 :(得分:0)

一种可行的方法(您可以尝试)是:如果您知道字符数,例如: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();

这是结果:

enter image description here

现在图像清晰得足以识别。