Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by z3nth10n · Oct 22, 2018 at 09:32 PM · texture2dshapemathsedges

Find corners/edges on a shape using own implementation

I'm trying to get the corners of the following shape:

enter image description here

By corners I mean this (red dots):

enter image description here

The minimum quantity of points that can define this shape.

And I have implemented the following:

     public Shape Optimize()
     {
         // If the vertices are null or empty this can't be executed
         if (vertices.IsNullOrEmpty())
             return this; // In this case, return the same instance.

         if (!edges.IsNullOrEmpty())
             edges = null; //Reset edges, because a recalculation was requested

         // The corners available on each iteration
         var corners = new Point[] { Point.upperLeft, Point.upperRight, Point.downLeft, Point.downRight };

         //The idea is to know if any of the following or previous vertice is inside of the the array from upside, if it is true then we can add it.

         Point[] vs = vertices.ToArray();

         for (int i = 0; i < vertices.Count - 1; ++i)
         {
             Point backPos = i > 0 ? vs[i - 1] : vs[vertices.Count - 1],
                   curPos = vs[i], //Punto actual
                   nextPos = i < vertices.Count - 1 ? vs[i + 1] : vs[0];

             // We get the difference point between the actual point and the back & next point
             Point backDiff = backPos - curPos,
                   nextDiff = nextPos - curPos,
                   totalDiff = nextPos - backPos;

             if (corners.Contains(backDiff) || corners.Contains(nextDiff) || corners.Contains(totalDiff))
                 AddEdge(curPos, center); // If any of the two points are defined in the corners of the point of before or after it means that the actual vertice is a edge/corner
         }

         return this;
     }

This works rectangled shapes, but rotated shapes are very sharp, so, this code doesn't work well:

enter image description here

  • Blue pixels (in this photo and the following) are the vertices variable processed on Optimize method.

  • Green pixels are the detected corners/edges (on both photos).

But sharpness in a shape only defines the side inclination, so what can I do to improve this?

Also, I have tested Accord.NET BaseCornersDetector inherited classes, but the best result is obtained with HarrisCornersDetector, but:

enter image description here

Many edges/corners are innecesary, and they aren't in the needed place (see first photo).

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by z3nth10n · Oct 23, 2018 at 03:37 PM

Well, after hours of research I found a library called Simplify.NET that internally runs the Ramer–Douglas–Peucker algorithm.

Also, you maybe interested on the Bresenham algorithm, with this algorithm you can draw a line using two Points.

With this algorithm, you can check if your tolerance is too high, comparing the actual points and the points that this algorithm outputs and making some kind of percentage calculator of similarity.

Finally, is interesting to mention Concave Hull and Convex Hull algorithms.

All this is related to Unity3D.

My outputs:

enter image description here

enter image description here

And my implementation.

It's very important to say, that points needs to be sorted forcing them to be sorted. If the shape is concave as you can see on the second photo maybe you need to iterate walls of the shape.

You can see an example of implementation here. Thanks to @Bunny83.

Also answered here: https://stackoverflow.com/a/52952874/3286975

Thanks Bunny83 for guide me !! :)

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by Bunny83 · Oct 22, 2018 at 11:19 PM

This is a quite difficult task as the exact points completely depends on the way the edges of the shape are drawn. They are probably drawn with the popular Bresenham algorithm. However to exactly reproduce a certain pattern in many cases you have to pick the exact right corner points for that line. If it's just one pixel off it won't match the pattern. Analysing a shape like this becomes extremely difficult. If you're happy with a good approximation you may try to first group the border point into straight line segments. Next you try to combine consecutive line segments if their direction angle is "about" the same. As soon as a line segment has a direction that is too far from the original angle you will start a new line segment and basically have found a "necessary" corner. This approach does not necessarily reproduce the exact same shape but it should be a very close approximation depending on how large you set the angle threshold.


Once you found your corners you could re-run bresenham between your corners to see if it fits or not. However the main question is what you do if it doesn't match ^^.

Comment
Add comment · Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image z3nth10n · Oct 23, 2018 at 10:50 AM 0
Share

Thanks again for your answer Bunny83. I have implemented this algorithm in a fiddle so every body can see it: https://dotnetfiddle.net/aPOhPi but I don't make it work. I will do some research about your algorithm. :P

avatar image Bunny83 z3nth10n · Oct 23, 2018 at 11:17 AM 0
Share

Just for detecting the outer bounds of a shape i've written a simple straight forward implementation over here. It just deter$$anonymous$$es all border pixels of a shape in the right order. Though it has some limitations in order to avoid issues with connected shapes it enforces a gap of 1 pixel between shapes. When removing a shape from the source image i just remove a 1 pixel border around it. Of course this question was about finding the outline of a shape, not a filled shape.


The actual concrete implementation i've posted in the comments below my answer. The code is on pastebin and the webgl live example is on github pages.


Though as i said reducing the number of points is not trivial and you can't guarantee a certain solution is the best one unless you literally tested all possible combinations (and for a shape like yours this would take ages).

avatar image Bunny83 Bunny83 · Oct 23, 2018 at 11:18 AM 0
Share

Damn, I just realised the question i just mentioned was your own question x)

Show more comments
avatar image z3nth10n · Oct 23, 2018 at 11:06 AM 0
Share

I think on the following logic.

  • The first point of my shape will always be a corner.

  • Following this, we will get the slope of the following points and we will add them to a global mean.

  • If the global mean changes drastically, we will suppose that the previous point to the actual is a corner.

What do you think?

avatar image Bunny83 z3nth10n · Oct 23, 2018 at 12:00 PM 0
Share

Actually i wouldn't constrain myself to assume the first point is a corner ^^. What you could do is calculate a "bresenham error score" based on all points in between two (potential) corner points. As long as this error score stays within a certain threshold we can just move either the start or end point further to the next point on the shape border. The error score should ensure to get a clear indication when the line goes too much off the trail. With the bresenham algorithm all points / pixels should never have a greater distance from our actual (mathematical) line than "0.5". To calculate an error score you may multiply the measured distance from each point to the line by 2 so we get an error between 0-1 if it's in the "good" range and a value greater than 1 if it's in the "bad" range. Now we can apply a power to that error (probably a higher power like 4 or 8). This will amplify the error greater than 1 and also reduce the error if smaller than 1. Sum up the error score of all points between start and end and divide by the number of points. This score if we get a perfect fit should stay below 1 and would be 0 for an exact fit (only happens for horizontal, vertical or diagonal lines). Now you can just try moving the ends of a line segment outwards and if the score is still within a certain threshold you keep going. However if moving to the next point skyrockets the error you essentially have found a corner. Though it all depends on what threshold you set and how greate the tolerance for errors can be.

avatar image z3nth10n Bunny83 · Oct 23, 2018 at 01:36 PM 0
Share

So, what you mean, is that I have to create a segment where (x1, y1) = actual point && (x2, y2) is the last corner. And compare it's slope with the slope of the previous point (where (x1, y1) = actual point - 1), if the actual slope is different from current slope we can define the previous point as a corner?

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

98 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Cut Texture2D in circle format 2 Answers

Texture2D.Resize and Shader 0 Answers

Create, export, and then load a huge image. 2 Answers

Text Box 2 vs TextMeshPro 0 Answers

Disabling mipmaps for downloaded textures 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges