Add getClosestEllipsePoints() function to get the closest point on an ellipse#26299
Merged
asmorkalov merged 3 commits intoopencv:4.xfrom Jun 3, 2025
Merged
Conversation
6 tasks
291c1cf to
a5f19d2
Compare
Contributor
Author
|
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
6 tasks
Contributor
Author
|
Additional information if it can help someone. In
|
…int belonging to a considered ellipse equation.
f817d9f to
d4114dc
Compare
vpisarev
reviewed
May 30, 2025
Contributor
|
@s-trinh, sorry for late reply. The functionality is useful. Except for the very slow and unnecessary Mat allocation, PR looks good. |
sturkmen72
reviewed
May 30, 2025
vpisarev
approved these changes
Jun 3, 2025
Contributor
vpisarev
left a comment
There was a problem hiding this comment.
Looks good! Thank you for the contribution!
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.orgFollowing #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.