Сегментация изображений с символами, которые объединены - PullRequest
0 голосов
/ 04 апреля 2019

Я пытаюсь нарисовать границу вокруг символов на изображении ниже. Однако, поскольку некоторые персонажи объединены, я не могу нарисовать прямоугольник. Я пробовал несколько вещей, таких как; расширяя, размывая и пробуя разные пятна, но я не могу их разделить. Разрушение, кажется, лучший способ приблизиться, но если я продолжу размывать, символы не могут быть распознаны.

Я использую библиотеку OpenCV в Java для достижения этой цели.

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 голосов
/ 04 апреля 2019

Один из возможных способов (вы можете попробовать) сработает, если вы знаете количество символов, например: 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

Теперь изображение достаточно четкое для распознавания.

...