0

I am trying to recognize curved line from a simple image only containing single curved edge. The line cannot be represented as a formula because the line is generated completely randomly. Thus, the only way to save the curved line is to save pixel positions and connect them using the list (or heap, vector, what else).

Example:

Example with noise:

Is there any algorithm or solution for this problem?

Miki
  • 40,887
  • 13
  • 123
  • 202
Bahamut
  • 33
  • 5
  • You need to implement Bezier Curve fitting on your points! more details here http://stackoverflow.com/questions/785097/how-do-i-implement-a-b%C3%A9zier-curve-in-c & here http://www.codeproject.com/Articles/25237/Bezier-Curves-Made-Simple – Balaji R Feb 17 '16 at 08:58
  • 1
    Can we have an example? – FiReTiTi Feb 17 '16 at 10:33
  • Please post an example image, and the code you tried so far – Miki Feb 17 '16 at 13:56
  • Bezier curve fitting might not be necessary as the OP does not say he needs the curved line to be represented as a Bezier curve. It could be that the OP already knew a collection of pixel positions (not in any particular order) that represents the curved line but just need a way to figure out their correct order. – fang Feb 17 '16 at 20:03
  • Miki, I updated my question but I don't have implemented code yet. For now, I have thought the algorithm but there were too many exceptions. I thought I can know the direction by seeing neighbor pixels, but soon I recognized that it can be different depending on the position of pixel. – Bahamut Feb 18 '16 at 00:54
  • I posted an answer. If that's not what you're looking for, please add more details to your question. (FYI, use @name to notify someone, I came back on this question by accident ;D) – Miki Feb 18 '16 at 02:17

1 Answers1

0

You can use findContours and drawContours for this task. Here's a tutorial from OpenCV

findContours will store the ordered sequence of points for each contour in a std::vector<std::vector<cv::Point>>. You can rebuild the original contour using drawContour.

Or you can collect all the non-zero points in your image with findNonZero, saving points in a std::vector<cv::Point>. You can then set all those points to rebuilt your original image.

Have a look at both methods in the following code:

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

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

    // Get all contours in the image
    vector<vector<Point>> contours;
    findContours(img.clone(), contours, CV_RETR_LIST, CHAIN_APPROX_NONE);

    // Draw all contours in green on a black image
    Mat3b rec(img.rows, img.cols, Vec3b(0,0,0));
    drawContours(rec, contours, -1, Scalar(0,255,0), 1);

    imshow("Original", img);
    imshow("Reconstructed", rec);
    waitKey();


    // Save all non-zero pixel positions
    vector<Point> pts;
    findNonZero(img, pts);

    // Set the pixels to red, according to the points in pts
    Mat3b rec2(img.rows, img.cols, Vec3b(0, 0, 0));
    for (int i = 0; i < pts.size(); ++i)
    {
        rec2(pts[i]) = Vec3b(0,0,255);
    }

    imshow("Reconstructed 2", rec2);
    waitKey();

    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202