I have an image with the size of W * H
, I want to draw a line on this and the line should be automatically fit to the image,
for example if I draw it:
I want this:
How can I do this in Python and OpenCV? Thanks
CodePudding user response:
Before ->
After
Here's a function given points p1
and p2
, will calculate the resulting new extended points p3
and p4
. There is also a distance
parameter to determine how far to draw from the original starting point or until the line hits the border of the image.
import cv2
import numpy as np
"""
@param: p1 - starting point (x, y)
@param: p2 - ending point (x, y)
@param: distance - distance to extend each side of the line
"""
def extend_line(p1, p2, distance=10000):
diff = np.arctan2(p1[1] - p2[1], p1[0] - p2[0])
p3_x = int(p1[0] distance*np.cos(diff))
p3_y = int(p1[1] distance*np.sin(diff))
p4_x = int(p1[0] - distance*np.cos(diff))
p4_y = int(p1[1] - distance*np.sin(diff))
return ((p3_x, p3_y), (p4_x, p4_y))
# Create blank black image using Numpy
original = np.zeros((500,500,3), dtype=np.uint8)
image1 = original.copy()
p1 = (250, 100)
p2 = (375, 250)
cv2.line(image1, p1, p2, [255,255,255], 2)
# Second image, calculate new extended points
image2 = original.copy()
p3, p4 = extend_line(p1, p2)
cv2.line(image2, p3, p4, [255,255,255], 2)
cv2.imshow('image1', image1)
cv2.imshow('image2', image2)
cv2.waitKey()
CodePudding user response:
I assumed you meant the following:
You have 2 points - e.g. p1
, p2
within the image.
Instead of drawing a line between p1 and p2 you want the line that contains these points but streches till the edge of the image.
You will need to handle several cases, depending on which edges the line should reach. This depends on the location and angle of the original line segment.
Below is a code example of how to handle one of the cases - where the line should reach the top and right edges. You will need to modify it to handle the other cases similarly and also to determine which case should be applied.
import cv2
import numpy as np
# At the moment only a line that hits the top and right edges is handled.
# You need to handle the rest of the cases in a similar way.
def draw_line_fit_topright(img, p1, p2, color, thinkness):
h = img.shape[0]
w = img.shape[1]
dx = float(p2[0]-p1[0])
dy = float(p2[1]-p1[1])
p1new = (int(p1[0] - dx/dy*p1[1]), 0)
p2new = (w-1, int(p2[1] dy/dx*(w-p2[0]-1)))
cv2.line(img, p1new, p2new, color, thickness=thinkness)
cv2.line(img, p1, p2, (0,0,255), thickness=thinkness-3)
w = 1024
h = 768
p1 = (240,50)
p2 = (440,150)
img1 = np.zeros((h, w, 3), dtype = "uint8")
draw_line_fit_topright(img1, p1, p2, (255, 0, 0), 5)
cv2.imshow("img1", img1)
cv2.waitKey(0)
Note: I am aware that my code does not solve the problem entirely. But I thought it will steer you in the right direction.