Vision Assistance

Hello,

I am a programmer for 4534, The Wired Wizards.

We are a 3rd year team, and are looking into getting into vision for real this year. We have an axis cam and a Microsoft 3000. We plan on running OpenCV on a Raspberry Pi as a coprocessor to the RoboRio. I have been toying with OpenCV, using Python, but I haven’t been able to figure out a good process to locate the vision target. We have a light ring, but I haven’t been able to use that yet.

Any advice from teams who have done vision tracking in the past?

The traditional method is to define ranges for color values that match your target, then use algorithms such as convex hull to pick out the objects. We did that last season with LabVIEW, and it worked pretty reliably. It’s not perfect, however. It took a good 5 minutes to get the values zeroed in for each competition. Also, by the time our bot made it to the finals, either the axis camera re-calibrated itself, or the lighting had changed just enough to render the color ranges ineffective.

Over the off season, we bought a Raspberry Pi and Camera to try with an alternative algorithm I had come up with (using Python and OpenCV). Rather than using static color values to isolate the retroreflective tape, we tried taking two pictures - one with the tape lit and one unlit - and subtract the images to get the target.

When held rock-steady, the algorithm worked beautifully. The trouble came when you tried to move your targets. An ever-so-slight shift in the image between pictures caused all sorts of chaos. If I were to do it again, I would probably do a hybrid of the two methods.

What processes have you tried?

I have been working with contours and I have just gotten into detection of colors via HSV. The python implementation has missing methods however, but I do not know how to code in C++.

Unfortunately I do not have code in Python for the following algorithm…

This was my presentation I gave at various academic competitions. This was the 2013 challenge. Ignore the math at the beginning, it is irrelevant.

Basically, the steps are as follows:

  1. acquire the image
  2. apply a binary threshold (white is 255, black is 0, pixels are either 255 or 0, white or black)
  3. Reduce noise using morphological functions such as erode, dilate, and (Gaussian) blur.
  4. Convert your binary image with reduced noise to a different type of data, a contour (the c++ function is findcontours). (This is my all time favorite algorithm of all time) What this does is organizes your white pixels into a hierarchy of contours. The algorithm was developed in the 1980s.
  5. Do tests on your contours to make sure you are left with what you want.
    Some common ones: area test (get rid of contours too small or too big), concavity test.
  6. You can also do things like bound a rectangle around your contour, which in itself isn’t very cool, but it provides something that will come in handy this year, a ratio. Take the area of your contour / area of bounding rectangle. The contours this year are L’s, so the ratio might be something like .6, but if you get a false positive through all your tests (say a reflective piece of metal on a robot), it will return a number close to one.

If anyone has any questions, shoot me a pm or comment a question. I’m on ivs right now so I have nothing but time :smiley:

edit: 2073 developed in python last year and used opencv. Here is their code:

Edit 2: Spoiler: To differentiate between left and right vision tape, take the moment of the contour and test it vs the center of the bounding rectangle.

if (moment.x < center.x)
contour = right;
else
contour = left;

Then you can match lefts to rights to group them to “create” a yellow tote. How I would match them: take a left contour, double the height of the bounding rect, and if a center for a right height*2 pixels away or closer to the center of the left, they are a pair, match them, and save them off to a struct or class for yellow totes.

If you really want to get fancy, and if your camera is less than the height of the totes, you can check to see if an element of your array of yellow totes are stacked by a simple checking of their center.x values. You have to check all your yellow totes to every other yellow tote. If they are stacked, you can push them to an array, if they aren’t, push them to another array. This might be needed in case you try to grab at the closest yellow tote but it has a tote on top of it.

The last problem is a geometric problem. How do you tell if you’re aligned with box and looking at it’s center. The latter is easy, is the yellowtote.center.x = center of screen (the origin in opencv is the top left. For this calculation I would remap the center to the bottom of the center of the screen, but that’s just me). You can do a proportion of image width/fov_x = center.x/unknown x rotation to center of target.

But that simply lines you up with the center, you could still be looking at the box when it is at an angle to the camera. I haven’t thought about this problem much, but you could “cheat” and simply check the areas of the left and right tape, and if they are about the same (area left/area right ~=1), you know you are lined up. I haven’t thought of a method to explicitly return the degree of offset the tote is to the camera.

That information will really help! Thanks!

I currently have a Odroid c1 running my vision solution on python, my question is

  1. what is the best way to send data to the roborio
  2. Is there any way to use more then 1 core to speed up the image processing?

I am learning python just for the vision so any help is much apreciated

Glad to hear you got it working.

The way my team sends it to the cRio, now roborio, is through the network on the robot via udp.

Crude diagram found here: http://ratchetrockers1706.org/team/technical-division/robot-control/

Sample c++ code that @cmastudios wrote for this year that sends the values we want to the roborio can be found here: https://github.com/rr1706/vision2015

more precisely: udpsender.cpp and .hpp.

I have not personally looked at his code for this year. He is a brilliant student and one day when I was lecturing to the new programmers about c++ basics, he said he has a working udp sender and I have full faith that it works.

Our team uses a serial connection, our computer supports RS232 using the main slot on the roboRIO, but you can also use the second serial port through the modular expansion port (MXP.)