Checkerboard Pattern Recognition

Hello,

I’m working on a simple project that will be used for a bigger project. The simple problem at hand is that I’m trying to have my M7 see and recognize black/white checkerboard from any rotation angle, know that it is what it is (and not other random rectangles in a picture), and turn an LED on. To do this, I’ll be outputting 1s and 0s depending on if it recognizes the checkerboard. I figured I could do a histogram equalization on the image, set it to binary with a threshold of around (250, 255), and use erode(1), the same way it’s used for the “Donkey Car”. From here, I thought about just using the find_rectangle method, but it ended up seeing other rects where there wasn’t checkerboard. I also considered having it learn the checkerboard as a basic QR code or April tag.

Does this seem like a good approach to my problem at hand? Any tips for my plan or adjustments I ought to make? Should I consider a different method? I’d be grateful for any help. Thanks!

Weston

Hi, using find_rectangle is the right approach. Just filter the rectangle output. So, use the filter() method in python and use a call back to cut down the list of rectangle. In general, find_rectangle() is just going to give you a bunch of rectangles that you then need to look at and determine to use or not use them.

Anyway… a simple trick to determine the rotation angle would be to use the edge points of each rectangle (from the corners() method) and computer the cross variance.

Um, describing what I’m taking about in this thread is hard. Just read this code here:

https://github.com/openmv/openmv/blob/master/src/omv/img/blob.c#L162

Maybe read the link in the code to the computer vision book. Anyway, the output of the math is the rotation angle of the point spread.

Alternatively, there find_rectangles() I think gives you an angle for each rect that’s not too accurate. Could combine those.

Anyway, you’re going to have to write some complex code.

I haven’t bothered with any rotation code yet. This is what I’m doing to filter it:

    
    for r in img.find_rects(threshold = 500):
        print('Rect: [{}, {}, {}, {}]; Mag: {}'.format(r.x(), r.y(), r.w(), r.h(), r.magnitude()))
        
        # Filter image to ignore errors in image
        rmvOriginErr   = filter(lambda x: x.x() == 0 and x.y() == 0, r)
        filterToMag    = filter(lambda x: x.magnitude() > 100000, rmvOriginErr)
        filterToWidth  = filter(lambda x: x.w() > 50 and x.w() < 65, filterToMag)
        filterToHeight = filter(lambda x: x.h() > 50 and x.h() < 65, filterToWidth)

        img.draw_rectangle(filterToHeight.rect(), color = (255, 0, 0))
        for p in filterToHeight.corners(): img.draw_circle(p[0], p[1], 5, color = (0, 255, 0))

I think I’m using filter correctly, but I’m getting the error: “TypeError: ‘rect’ object is not iterable” from the “rmvOriginErr” line. Any ideas as to what is wrong with the code or how to fix it? I feel like I’m very close here

Hi, you have to move your code outside of the for loop. You’re trying to filter on one object. filter works on a list of objects which is what find_rect() returns.

Also, note that filter sometimes outputs things in a weird format and you have to wrap filter with list() if you want a list object again.