View Single Post
  #4   Spotlight this post!  
Unread 04-08-2013, 11:37
faust1706's Avatar
faust1706 faust1706 is offline
Registered User
FRC #1706 (Ratchet Rockers)
Team Role: College Student
 
Join Date: Apr 2012
Rookie Year: 2011
Location: St Louis
Posts: 498
faust1706 is infamous around these partsfaust1706 is infamous around these parts
Re: Help with Locating Disks with Vision

Quote:
Originally Posted by Greg McKaskle View Post
I'm sure that you can write simple color threshold code to locate a frisbee, and you can do a few additional particle measurements to see if it is round. This approach will be more forgiving in varied lighting conditions. Even then, make sure to follow the recommendations in the white paper regarding camera white balance setting, compressions, focus, etc.
this is exactly what we did this year (though we had to scrap the project due to weight issues which causes us to turn into a FCS only).

The steps:

Acquire image

Convert it to HSV (hue, saturation, and value)

(Binary) Threshold image to locate only the desired colour (red, white blue)

This is where vision programming has a lot of diversity...

We found the contour of an image, that is, where black meets white.

Approximate a polygon (I promise I will make this better before next build season for squares for teams that want to do pose)

then I said

if (result > 5))
[
it's a circle;
}

result being the amount of sides of the contour.

From then, you ideally should have located the circle.

To find the center:

// Calculate the moments to estimate the position of the frisbee
CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));
cvMoments(*yourcontourhere*, moments, 1);

// The actual moment values
double moment10 = cvGetSpatialMoment(moments, 1, 0);
double moment01 = cvGetSpatialMoment(moments, 0, 1);
double area = cvGetCentralMoment(moments, 0, 0);

posX = moment10/area;
posY = moment01/area;

This gives subpixel accuracy for the center

Now you have the center of a frisbee based off the specified colour. Congrats. BUT, what if there was more than 1 of the same coloured frisbee?

This simple algorithm solves this problem (keep in mine that I used opencv and changed the center from the top left to the center of the screen to make the logic easier)

Int prevclosestfrisbee = 300 (arbitary pixel value that is high on the screen. *note the greater the y pixel value, the further it will be away.)

if (frisbee.y < prevclosestfrisbee)
{ prevclosestfrisbee = frisbee.y
}
else
{
contours = contours ->h_next:
}

after you go through all the contours (the frisbees that passed the threshold test and the approximate polygon test, then you're left with one with the lowest y value.

**note, you can do this with all 3 coloured frisbees, I posted an image on here of a frame while tracking all 3 disks. It does take a fairly large amount of processing power (this program ran ~13 fps while the program that tracked the alliance wall ran at ~27, but it is do able!)

Hope this helped!
__________________
"You're a gentleman," they used to say to him. "You shouldn't have gone murdering people with a hatchet; that's no occupation for a gentleman."
Reply With Quote