CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 56.2k
Add getClosestEllipsePoints() function to get the closest point on an ellipse #26299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
291c1cf
to
a5f19d2
Compare
I have added additional tests to check the code correctness when handling "minor/major axes swapping" cases. Python code to validate ellipse points sampling: code#!/usr/bin/env python3
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def getEllipsePointsCV(ellipse):
center, axes, angle = ellipse
ellipse_points = cv.ellipse2Poly((int(center[0]), int(center[1])), (int(axes[0] // 2), int(axes[1] // 2)), int(angle), 0, 360, 1)
return ellipse_points
# https://github.com/opencv/opencv/pull/26299
def main():
(xc, yc) = (1442.97900390625, 662.1879272460938)
(a, b) = (579.5570678710938/2, 730.834228515625/2)
theta_deg = 20.190902709960938
theta = np.deg2rad(theta_deg)
ellipse_params = ((float(xc), float(yc)),(float(a*2), float(b*2)), float(theta_deg))
ellipse_points = getEllipsePointsCV(ellipse_params)
xs = []
ys = []
ts = np.linspace(0, 360, 60)
for t in ts:
# https://fr.wikipedia.org/wiki/Ellipse_(math%C3%A9matiques)#%C3%89quation_param%C3%A9trique
ax = a * np.cos(theta)
ay = a * np.sin(theta)
bx = -b * np.sin(theta)
by = b * np.cos(theta)
cos_t = np.cos(np.deg2rad(t))
sin_t = np.sin(np.deg2rad(t))
x = xc + ax*cos_t + bx*sin_t
y = yc + ay*cos_t + by*sin_t
xs.append(x)
ys.append(y)
xs_ = np.expand_dims(np.array(xs), axis=1)
ys_ = np.expand_dims(np.array(ys), axis=1)
input_pts = np.hstack((xs_, ys_)).astype(np.float32)
closest_pts = cv.getClosestEllipsePoints(ellipse_params, input_pts).reshape((input_pts.shape[0], 2))
error_pts = closest_pts - input_pts
print(f"input_pts={input_pts}")
print(f"closest_pts={closest_pts}")
print(f"error_pts={error_pts}")
mse = (error_pts**2).mean(axis=1).mean()
print(f"mse={mse}")
_, axs = plt.subplots(figsize=(8, 8))
axs.scatter(xs, ys, c='blue', label='Points')
axs.scatter(closest_pts[:,0], closest_pts[:,1], c='red', label='Closest points')
ellipse_polygon = plt.Polygon(ellipse_points, fill=None, edgecolor='green', \
label='Ellipse from points')
axs.add_patch(ellipse_polygon)
axs.set_aspect('equal', adjustable='box')
axs.legend()
plt.show()
if __name__ == '__main__':
main() |
c25415c
to
35fb4ea
Compare
Additional information if it can help someone. In
|
β¦int belonging to a considered ellipse equation.
f817d9f
to
d4114dc
Compare
@s-trinh, sorry for late reply. The functionality is useful. Except for the very slow and unnecessary Mat allocation, PR looks good. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thank you for the contribution!
Sorry, for some reason the GitHub CI was not run in the previous PR #26237
I have opened this one to have at least results from the GitHub CI +
pullrequest.opencv.org
Following #26078, I was thinking that a function to get for a considered 2d point the corresponding closest point (or maybe directly the distance?) on an ellipse could be useful.
This would allow computing the fitting error with
fitEllipse()
for instance.Code is based from:
Demo code:
code
Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.