Yonatan
Yonatan

Reputation: 53

OpenCV-Python: Draw Parabolical Line

I'm trying to draw a curved line, but I just can't figure out how to do that.

I've got 3 coordinates to work with - [line_start_x, line_start_y], [clicked_x, clicked_y], and [line_end_x, line_end_y] and my code looks like this:

pts = np.array(
        [
            [line_start_x, line_start_y],
            [clicked_x, clicked_y],
            [line_end_x, line_end_y],
        ], np.int32)
image = cv2.polylines(image, [pts], True, (0, 255, 0), 2)
cv2.imshow(window_name, image)

However, the above code outputs a triangle and not a parabolical line, as I need.

I'd appreciate any help with that matter!

Upvotes: 0

Views: 879

Answers (1)

Ulises Bussi
Ulises Bussi

Reputation: 1725

assuming I understand the problem, 2 points will be ever fixed (line_start,line_end). when you have 3 points an a 2nd grade polinomial you there's only onse solution. you can calculate the expresion using numpy and then draw it evaluating this is a toy example with fixed image an point (change it's coords and try diferent solutions). I didn't put any condition on clicked_point so it could be out of the rect.

  1. create image, rectangle and put bias points

     import cv2
     import numpy as np
    
     width,height = 900,600
     img = np.zeros((height,width,3), np.uint8)
     white_rect = np.array([[100, 100],
                            [width-100, 100],
                            [width-100, height-100],
                            [100, height-100],
                            [100, 100] ], np.int32)
    
     img = cv2.polylines(img, [white_rect], True, (255,255,255), 3)
    
     line_start_x = int(white_rect[0:2,0].mean())
     line_start_y = int(white_rect[0:2,1].mean())
     line_end_x   = int(white_rect[2:4,0].mean())
     line_end_y   = int(white_rect[2:4,1].mean())
     clicked_x    = 555
     clicked_y    = 192
    
     img =cv2.circle(img, (clicked_x, clicked_y), 5, (0,0,255), -1)
     img =cv2.circle(img, (line_start_x, line_start_y), 5, (0,0,255), -1)
     img =cv2.circle(img, (line_end_x, line_end_y), 5, (0,0,255), -1)
    
    
    
     cv2.imshow('fr', img)
     cv2.waitKey(1)
    
  2. Then create point array 'pts' fit parabola and evaluate with numpy.

     pts = np.array([ [line_start_x, line_start_y],
                      [clicked_x, clicked_y],
                      [line_end_x, line_end_y] ], np.int32)
    
     #side parabola coeffs
    
     coeffs = np.polyfit(pts[:,1], pts[:,0], 2)
     poly = np.poly1d(coeffs)
    
     yarr = np.arange(line_start_y, line_end_y)
     xarr = poly(yarr)
    
  3. create parab points as int to draw with polylines (might be other choices but i'm gonna use this for simplicity).

     parab_pts = np.array([xarr, yarr],dtype=np.int32).T
     cv2.polylines(img, [parab_pts], False, (255,0,0), 3)
    
     cv2.imshow('fr', img)
     cv2.waitKey(1)
    

The output !!!

the Output!

Upvotes: 2

Related Questions