0

After I process the canny edge detection, I get the edge image. But I just want to keep short edges (edges came from the characters). And there are some long edges (here I define long as cross more than half the height of the picture). The sample picture looks like: sample picture

So how can I remove edges that cross more than half of the height of the picture?

Related questions: remove horizontal/vertical long edges

Community
  • 1
  • 1
Zieng
  • 453
  • 1
  • 7
  • 17

1 Answers1

3

You can apply some constraint on the minAreaRect containing the edge. You can find an example here, but since your edges touch the border, you need an additional trick to make findContours work correctly, so below the improved code.

With a simple constraint on the aspect ratio, you get:

enter image description here

where you removed the red edges:

enter image description here

You can add additional contraint, e.g. on the height, to fit your specific purposes.

Here the code:

#include<opencv2/opencv.hpp>
using namespace cv;


int main()
{
    // Load image
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    // Remove JPG artifacts
    img = img > 200;

    Mat1b result = img.clone();

    // Create output image
    Mat3b out;
    cvtColor(img, out, COLOR_GRAY2BGR);

    // Find contours
    Mat1b padded;
    copyMakeBorder(img, padded, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(0));
    vector<vector<Point>> contours;
    findContours(padded, contours, RETR_LIST, CHAIN_APPROX_NONE, Point(-1, -1));

    for (const auto& contour : contours)
    {
        // Find minimum area rectangle
        RotatedRect rr = minAreaRect(contour);

        // Compute aspect ratio
        float aspect_ratio = min(rr.size.width, rr.size.height) / max(rr.size.width, rr.size.height);

        // Define a threshold on the aspect ratio in [0, 1]
        float thresh_ar = 0.05f;

        // Define other constraints

        bool remove = false;
        if (aspect_ratio < thresh_ar) {
            remove = true;
        }

        // if(some_other_constraint) { remove = true; }

        Vec3b color;
        if (remove) {
            // Almost straight line
            color = Vec3b(0, 0, 255); // RED

            // Delete edge
            for (const auto& pt : contour) {
                result(pt) = uchar(0);
            }
        }
        else {
            // Curved line
            color = Vec3b(0, 255, 0); // GREEN
        }

        // Color output image
        for (const auto& pt : contour) {
            out(pt) = color;
        }
    }

    imshow("Out", out);
    imshow("Result", result);
    waitKey();

    return 0;
}
Community
  • 1
  • 1
Miki
  • 40,887
  • 13
  • 123
  • 202
  • Great! Thanks for your solution. And can you give me some advice on how to remove the other edges that I don't need (such as edges on the right, but they not long enough)? – Zieng Oct 19 '16 at 12:57
  • Slightly increase the `thresh_ar`, e.g. to 0.075 or 0.1. Put some contraint on the max height a letter can be... Something like this.. It's really specific to your context. With edges only you can remove some noise, but you need something more powerful to remove all but your letters – Miki Oct 19 '16 at 13:00
  • Thanks a lot. I will give it a try! – Zieng Oct 19 '16 at 13:35