-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Geometry utils update polygon center getter #1084
Geometry utils update polygon center getter #1084
Conversation
Hi @sharingan000 👋🏻 Could you give us a bit more context? Why the previous solution was not enough? |
Okay, the essence of the algorithm appears when the distribution of points is uneven (if you want to see the code for generating this picture, I can send you a link) |
Oh! This makes a lot of sense. 🔥 It seems the new implementation performs significantly more operations. Have you measured the execution time? Since we use this function in annotators, people expect the code to execute quickly. |
Hi @sharingan000 👋🏻 Interjecting briefly to ask for more details. What's Your example was fantastic in illustrating the problem. If there's no downsides to a faster algo and the performance is comparable to ours then by all means - please post it :) |
k in my table means how many times my algorithm worked more than yours, and the header of the table is the number of points in one polygon. my algorithm has exactly the same asymptotics as yours - O(n), but with a greater constant :) |
Thank you, that makes sense. The slowdown seems small enough to not be an issue. Please, send it over and we'll review it, do some tests of our own :) |
…nter-getter' into geometry-utils-update-polygon-center-getter
I pushed a new algorithm |
Hi @sharingan000, Found a test case where this doesn't give good results, unfortunately. Example 1We'd expect the center of mass to be slightly above the y=50 line, but it's slightly higher at 45: Example 2Continuing with the trend, while we'd expect to see the center of mass move upwards, it, in fact, moved downwards even more, to 40: Test code:import numpy as np
import matplotlib.pyplot as plt
def get_polygon_center(polygon: np.ndarray) -> tuple[float, float]:
polygon = polygon.astype(np.float32)
shifted_polygon = np.roll(polygon, 1, axis=0)
points = (shifted_polygon + polygon) / 2
vectors = shifted_polygon - polygon
mass = np.sum(vectors**2, axis=1) ** 0.5
center = (mass @ points) / np.sum(mass)
return center[1], center[0]
def vertices_concave(size: int, thick: int, thin: int) -> np.ndarray:
assert size > thick > 0
assert size > thin > 0
return np.array([
# ->
[0, 0], [0, size], [thin, size],
# <-
[thin, thin],
# up
[size - thick, thin], [size - thick, size], [size, size],
# down
[size, 0]])
# verts = vertices_concave(100, 25, 2)
verts = vertices_concave(100, 55, 2)
print(verts)
center = get_polygon_center(verts)
center2 = get_polygon_center_2(verts)
print(center)
plt.fill(verts[:, 1], verts[:, 0])
plt.plot(center[0], center[1], 'ro')
plt.show() |
@sharingan000, I was wondering - perhaps there was a more commonly known center of mass algorithm for polygons that we could adapt? It would be really good to integrate it now, especially if we have a benchmark close-at-hand |
Okay man, i see the problem, but I have a few questions:
Text me, if you want to see best algorithm :) |
the best algorithm is implemented using triangulation, I will need some time to implement it, maybe tomorrow, I just have 01:14 on the clock |
By the way, if in your code, in the fill method, you swap the coordinates, then my algorithm in the second example will move along X closer to the “heavy” part, yours, on the contrary, will move away |
Good point about the swapped |
I like your proposal of the two options. We're all short on time, so let's find the best of both worlds. Here's an algo I found on SO: Is this what you had in mind when you mentioned triangulation? It would need an augmentation for the case when all points are on the same line. def get_polygon_center_2(polygon: np.ndarray) -> tuple[float, float]:
polygon2 = np.roll(polygon, -1, axis=0)
signed_areas = 0.5 * np.cross(polygon, polygon2)
if signed_area.sum() == 0:
signed_area = None # Equal weights. Could just return here instead.
centroids = (polygon + polygon2) / 3.0
center = np.average(centroids, axis=0, weights=signed_areas)
return center[0], center[1] Do you think that is correct? If so, would you have some time to test how it compares in terms of runtime, with your proposal? I don't know which of the two is better to keep yet - maybe both is the answer. |
You won’t believe it, but I implemented the same algorithm in parallel with you and it works the same way, I made all the time measurements (a table is attached below, where mean is the old algorithm, frame is my first accelerated algorithm, solid is the last algorithm) I came to the conclusion that you can implement 3 algorithms at once, but choose which one to use depending on the number of points in the polygon (for example: if there are less than 100 points, then use mean, since it is often sufficient for a small number of points and for a small number of points it is much faster than others, but if the number of points exceeds 100 and less than 10000, then you can use solid, since the running time is slightly different from frame, but it is better, and in other cases use frame) (in fact, it is better to check whether the figure is convex and based on this choose frame or solid, but this is an unnecessary operation, so I prefer the option above) |
Oh wow, thank you very much! I'll have a word with the team and see what's best; hopefully merge in soon |
if you like this idea I can merge it in about 12 hours |
ok, thanks, I'll wait for news :) |
can I write you a private message about developing some algorithms for your repository (geometry)? |
…nter-getter' into geometry-utils-update-polygon-center-getter # Conflicts: # supervision/geometry/utils.py
Feel free to reach out on LinkedIn. |
I am having problems registering on this platform :( (it is probably impossible or very difficult to implement), are there other ways to contact you? |
Hi @sharingan000, Apologies for the delay. I've thought about the next steps and this is what I feel is most optimal for us:
# This is one of the 3 candidate algorithms considered for centroid calculation.
# For a more detailed discussion, see PR #1084 and commit eb33176 (The reason it's not in the dosctring is that it's a message for the devs - not the users)
|
…nter-getter' into geometry-utils-update-polygon-center-getter
supervision/geometry/utils.py
Outdated
The center is calculated as center of frame. | ||
polygon -> polygon, where p[i] = p[i + 1] + p[i] / 2, | ||
with mass = length of vector p[i + 1] - p[i] | ||
Еhe center is calculated as the center |
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.
Typo "Ehe"
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.
Typo "Ehe"
sorry, I was in a hurry :)
Regarding your comments, I thought about it, and yes, you are right, it can easily happen that in the polygon of the same object there will be a different number of points on different frames of the video, I also agree that it is better to use the “solid” algorithm, since it is universal, but it doesn’t lose much in speed
(I solved the problem with the condition in this algorithm, if the sum is equal to zero, then the algorithm returns the average of all points, this is a sufficient approximation, since this condition can only be satisfied if there are very few points or they form a straight line)
and I wanted to write to you in private messages because I have a couple of ideas related to the 'geometry' module, but not with this function specifically
Thank you very much! I can take it from here :) |
ok, X didn't fit either for political reasons, so I won't talk about it anymore |
@SkalskiP, I ran the tests - ready to merge. |
Hi @sharingan000 and @LinasKo 👋🏻, I just read the whole conversation. It's so informative, and I'm glad that, in the end, you were able to come up with an optimal solution. 🔥 I'm merging this PR! I plan to highlight this change in our upcoming |
Hi, thanks for the reply. Of course I can, tell me what time to cook please |
Hey @sharingan000, appreciate your eagerness to contribute :) If it helps, here's some roughly hacked-together code I had for testing. main.py - import algorithms, define polygons, run results
algos.py - algorithms, though it's better to use a local version of supervision instead
segment.py - alternative to main, does segmentation on an image, plots that
Note that I've adjusted the Thanks again for helping us out! |
Thank you very much, I’ll try to do a couple more visual tests soon if necessary, but here I want to leave a couple of questions that interest me, since I can’t register anywhere else)
|
Hi @sharingan000, With respect to your questions:
You could also look at new issues and PRs popping up, see how other contributors engage with those. If a contributor says they'd like to take on it, we'd assign it to them to make sure there's not clashes, and they can do it. Do note that your case was a bit of an exception in how much time I could dedicate to it - normally it's a bit less 😄 There are also some paid positions, but I myself am new, so I'll refer your to the careers page: https://roboflow.com/careers.
I hope that answers your questions. |
Description
I updated the function for finding the center of the frame (geometry/utils), before it found the center of mass of the points, and now it finds the center of mass of the frame of points, which allows you to more accurately find the center in case of uneven distribution of points, I also added tests to this function.
(also this function had a slightly incorrect example)
Type of change
Please delete options that are not relevant.
How has this change been tested, please provide a testcase or example of how you tested the change?
write new tests (test/geometry/test_utils.py)
Any specific deployment considerations
more accurate determination of the polygon center using the same asymptotics
Docs
no changes