我试图找到与直线和椭圆相交的点。我可以如代码中所示手动找到该点,但如何自动找到它。此外,当红点位于椭圆内部时,延伸直线时绿点也应投影到椭圆上。我该如何解决这个问题?代码示例表示赞赏!谢谢!
import cv2
import numpy as np
# Parameters
ellipse_center = np.array([238, 239])
ellipse_axes = np.array([150, 100]) # Semi-major and semi-minor axes
ellipse_angle = np.radians(70) # Angle of rotation (in radians)
line_point1 = ellipse_center # Point on the line
line_point2 = np.array([341, 125]) # Another point on the line (moving point)
# Initialize OpenCV window
window_name = "Projecting Point on Rotated Ellipse"
cv2.namedWindow(window_name)
canvas = np.zeros((400, 400, 3), dtype=np.uint8)
while True:
# Clear canvas
canvas.fill(0)
# Draw the rotated ellipse
cv2.ellipse(canvas, tuple(ellipse_center), tuple(ellipse_axes), np.degrees(ellipse_angle), 0, 360, (255, 255, 255), 2)
# Draw the moving point
cv2.circle(canvas, (int(line_point2[0]), int(line_point2[1])), 5, (0, 0, 255), -1)
# Draw the center point of the ellipse
cv2.circle(canvas, tuple(ellipse_center), 5, (0, 255, 255), -1)
# Draw the line between moving point and the center of the ellipse
cv2.line(canvas, (int(line_point2[0]), int(line_point2[1])), tuple(ellipse_center), (0, 0, 255), 1)
intersection_points = (310, 159) # <- How to find this?
cv2.circle(canvas, intersection_points, 5, (0, 255, 0), -1)
# Show canvas
cv2.imshow(window_name, canvas)
# Exit if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Close OpenCV window
cv2.destroyAllWindows()
当使用椭圆方程和直线方程时,我得到:
import cv2
import numpy as np
from scipy.optimize import fsolve
# Parameters
ellipse_center = np.array([238, 239])
ellipse_axes = np.array([150, 100]) # Semi-major and semi-minor axes
ellipse_angle = np.radians(70) # Angle of rotation (in radians)
line_point1 = ellipse_center # Point on the line
line_point2 = np.array([341, 125]) # Another point on the line (moving point)
# Ellipse equation: (x - h)^2 / a^2 + (y - k)^2 / b^2 = 1, where (h, k) is the center of the ellipse
def ellipse_eq(params):
x, y = params
h, k = ellipse_center
a, b = ellipse_axes
return ((x - h) ** 2 / a ** 2) + ((y - k) ** 2 / b ** 2) - 1
# Line equation: y = mx + c
def line_eq(x):
m = (line_point2[1] - line_point1[1]) / (line_point2[0] - line_point1[0])
c = line_point1[1] - m * line_point1[0]
return m * x + c
# Intersection of the ellipse and the line
def intersection_point():
x_intercept = fsolve(lambda x: ellipse_eq([x, line_eq(x)]), line_point2[0])
y_intercept = line_eq(x_intercept)
return x_intercept[0], y_intercept[0]
# Initialize OpenCV window
window_name = "Projecting Point on Rotated Ellipse"
cv2.namedWindow(window_name)
canvas = np.zeros((400, 400, 3), dtype=np.uint8)
while True:
# Clear canvas
canvas.fill(0)
# Draw the rotated ellipse
cv2.ellipse(canvas, tuple(ellipse_center), tuple(ellipse_axes), np.degrees(ellipse_angle), 0, 360, (255, 255, 255), 2)
# Draw the moving point
cv2.circle(canvas, (int(line_point2[0]), int(line_point2[1])), 5, (0, 0, 255), -1)
# Draw the center point of the ellipse
cv2.circle(canvas, tuple(ellipse_center), 5, (0, 255, 255), -1)
# Draw the line between moving point and the center of the ellipse
cv2.line(canvas, (int(line_point2[0]), int(line_point2[1])), tuple(ellipse_center), (0, 0, 255), 1)
# Find and draw the intersection point
intersection_points = intersection_point()
cv2.circle(canvas, (int(intersection_points[0]), int(intersection_points[1])), 5, (0, 255, 0), -1)
# Show canvas
cv2.imshow(window_name, canvas)
# Exit if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Close OpenCV window
cv2.destroyAllWindows()
这并不能解决我的问题。我在这里做错了什么?
编辑: 使用 MBo 的方法和代码:
import cv2
import numpy as np
# Parameters
ellipse_center = np.array([238, 239])
ellipse_axes = np.array([150, 100]) # Semi-major and semi-minor axes
ellipse_angle = np.radians(70) # Angle of rotation (in radians)
line_point1 = ellipse_center # Point on the line (ellipse center)
line_point2 = np.array([341, 125]) # Another point on the line (moving point)
# Initialize OpenCV window
window_name = "Projecting Point on Rotated Ellipse"
cv2.namedWindow(window_name)
canvas = np.zeros((400, 400, 3), dtype=np.uint8)
while True:
# Clear canvas
canvas.fill(0)
# Draw the rotated ellipse
cv2.ellipse(canvas, tuple(ellipse_center), tuple(ellipse_axes), np.degrees(ellipse_angle), 0, 360, (255, 255, 255), 2)
# Draw the moving point
cv2.circle(canvas, (int(line_point2[0]), int(line_point2[1])), 5, (0, 0, 255), -1)
# Draw the center point of the ellipse
cv2.circle(canvas, tuple(ellipse_center), 5, (0, 255, 255), -1)
# Draw the line between moving point and the center of the ellipse
cv2.line(canvas, (int(line_point2[0]), int(line_point2[1])), tuple(ellipse_center), (0, 0, 255), 1)
# Calculate the intersection point
t = np.arctan2(line_point2[1] - ellipse_center[1], line_point2[0] - ellipse_center[0]) - np.arctan2(np.sin(ellipse_angle) * ellipse_axes[0], np.cos(ellipse_angle) * ellipse_axes[1])
x_intersection = ellipse_center[0] + ellipse_axes[0] * np.cos(t) * np.cos(ellipse_angle) - ellipse_axes[1] * np.sin(t) * np.sin(ellipse_angle)
y_intersection = ellipse_center[1] + ellipse_axes[0] * np.cos(t) * np.sin(ellipse_angle) + ellipse_axes[1] * np.sin(t) * np.cos(ellipse_angle)
intersection_point = (int(x_intersection), int(y_intersection))
# Draw the intersection point
cv2.circle(canvas, intersection_point, 5, (0, 255, 0), -1)
# Show canvas
cv2.imshow(window_name, canvas)
# Exit if 'q' is pressed
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Close OpenCV window
cv2.destroyAllWindows()
让我明白:
当第一个线点始终是椭圆中心
cx, cy
,第二个线点是px, py
时,我们可以在交点处找到椭圆参数:
t = atan2(py - cy, px - cx) - atan2(a * Sin(theta), b * Cos(theta))
其中
theta
是椭圆旋转角度,您的 ellipse_angle
、a
和 b
是椭圆半轴(更多数学细节这里)
所以交点是:
x = cx + a * Cos(t) * Cos(theta) - b * Sin(t) * Sin(theta)
y = cy + a * Cos(t) * Sin(theta) + b * Sin(t) * Cos(theta)
将直线方程 (y=mx+c) 代入椭圆方程 (x-h)2/a2+(y-k)2/b2=1(y)。这将给出 x 的二次方程,可以通过通常的二次方程公式求解。
二次方为 Ax2+Bx+C=0,其中,在重新排列时,
A=a2m2+b2
B=2a2(c-k)-2b2h
C=b2h2+a2(c-k)2-a2b2
求解 x 并从直线方程中得到 y。
与任何二次方程一样,您可能会遇到具有单根(直线刚刚接触椭圆)和无根(直线错过椭圆)的情况。