Ask Your Question
2

Draw lines from centroid of contour at given angle till edge of contour

asked 2015-02-24 20:55:03 -0600

samkhan gravatar image

updated 2015-08-22 04:11:39 -0600

I have a contour named 'cnt' obtained from the image below:

image description

for which I am able to find the centroid like this:

M = cv2.moments(cnt)
centroid_x = int(M['m10']/M['m00'])
centroid_y = int(M['m01']/M['m00'])

I now want to draw N number of lines, each 360/N degrees apart, starting from the centroid and passing through all possible points of intersection with the contour. The cv2.line() function requires start point and end point but I don't have the end point.

If I had drawn a line passing through centroid with a slope of Tan(360/N) I would have found the intersection of the line with the contour using bitwise_and but I'm not able to figure out a way to draw that line.

Any help would be much appreciated.

edit retag flag offensive close merge delete

3 answers

Sort by ยป oldest newest most voted
10

answered 2015-02-26 05:41:23 -0600

berak gravatar image

updated 2015-02-26 06:27:07 -0600

it's a bit of a shame, that you can't access the LineIterator from python, as it saves you from finding the intersection point manually, you'd just walk on with your line, until you reach a border pixel (or the image bounds) :

Mat ocv = imread("k4eIlCQ.png");
Mat gray; cvtColor(ocv,gray,COLOR_BGR2GRAY);
threshold(gray,gray,100,255,0);

Moments M = moments(gray);
Point cen( int(M.m10/M.m00), int(M.m01/M.m00) );

for (int i=0; i<360; i+=20)
{
    double s = sin(i*CV_PI/180);
    double c = cos(i*CV_PI/180);
    Point p2(cen.x+s*150, cen.y+c*150); // any radius will do, we just want the direction

    LineIterator it(ocv, cen, p2, 8);
    Rect bounds(0, 0, ocv.cols, ocv.rows);
    while(bounds.contains(it.pos()))
    {
        Vec3b & pixel = ocv.at<Vec3b>(it.pos());
        // if you stare really hard, you'll see the cheat ;)
        if (pixel[0] > 50) // non dark(it's not really black in the image!)
           pixel[1] = pixel[2] = 0; // set g and b to 0, leaves blue line
        else
           break;
        it++;
    }
}
imshow("lines", ocv);

image description

edit flag offensive delete link more

Comments

1

perfect!!!! I like it ;-).

theodore gravatar imagetheodore ( 2015-02-26 06:12:57 -0600 )edit
1

i think there must be a marker (maybe a new special tag like "Perfect_Solution" ) to mark all questions like this one. by this way newcomers easily find such good answers. @StevenPuttemans, @berak what is your opinion.

sturkmen gravatar imagesturkmen ( 2015-08-22 03:26:45 -0600 )edit

actually regarding to what we were talking about making some changes in the form of the forum it would be nice answers with high voting rate to be marked as sticky in addition with some other threads like faq, rules, maybe job openings, etc...

theodore gravatar imagetheodore ( 2015-08-23 15:19:19 -0600 )edit

@both be patient. I passed on this concerns to the dev team and they told me they would get back with answers mid september.

StevenPuttemans gravatar imageStevenPuttemans ( 2015-08-31 08:17:26 -0600 )edit

Hello. What does it means C and S variaibles?

adrianaioanei gravatar imageadrianaioanei ( 2019-05-31 09:19:04 -0600 )edit

It stands for the cosinus and sinus signals.

StevenPuttemans gravatar imageStevenPuttemans ( 2019-06-26 04:35:55 -0600 )edit
1

answered 2015-02-25 04:07:36 -0600

Altough the approach by @Balaji will probably work without any problems, I do think this can be done much easier. From an angle and a starting point one can use mathematics to derive the function that represents the line. Once you have done that the following steps are quite easy.

  • Define for each border (edge of mat) the value of the function. For example if your top border equals the equation x = 0, then you can define the y value of your line equation and see if that still falls within the range of your top edge.
  • For each line you want to draw there will be only 2 points possible on your matrix. This also allows you only to draw lines for 180 degrees and get all 360 degree segments. Then use those two matching points to draw your line.

Necessary equation: http://stackoverflow.com/questions/15...

edit flag offensive delete link more

Comments

1

Yes that is correct! Step 1 is unnecessary.

Balaji R gravatar imageBalaji R ( 2015-02-25 05:48:10 -0600 )edit
1

that assumes, you have a function for the outline. if not, all you probably got there is a contour, a vector of points, and you'd have to do an intersection check for each consecutive pairs/lines

berak gravatar imageberak ( 2015-02-26 06:23:32 -0600 )edit

Well I was going to split the image segments over the complete image :D Not only the contour :P

StevenPuttemans gravatar imageStevenPuttemans ( 2015-02-26 06:28:25 -0600 )edit
1

answered 2015-02-24 23:57:17 -0600

Hi @samkhan !

I think you are trying to find contour points that are at certain angle from centroid of that contour. Please follow the above steps:

  1. Find minenclosing circle of that contour.
  2. Find Point on the circle on a given angle. You can refer this Answer
  3. Find all the Points on the Line segment using Line Iterator.
  4. Loop through all the contour points & find the Distance between two points(Contour Point & Point on the Line).
  5. Find the Point with minimum distance which is the Intersection Point P.
  6. Draw a Line from Centroid C to Point P.

Hope you understand this simple explanation & I'll leave the code part for you!

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2015-02-24 20:25:12 -0600

Seen: 8,244 times

Last updated: Feb 26 '15