All: I’m working through some code to detect a rectangle using a Jetson TX2. I have sample code that will find the target (after some tuning) using the cv::boundingRect(cnt) function, but it loses that target when the rectangle is rotated more than a few degrees. Given the angle of the vision targets in the game this year, I’m not sure what I have will find them (not tested yet…).
Is there a better function to use to find the contours in this case? I’m thinking minAreaRect(cnt), but have yet to figure out the exact syntax for this in C++.
Can we see the section of code you are using to find the rectangles. Start right after your inRange checks for HSV.
Until we see that…
Are you also testing for approxPoly? If so, your tuning value may be a bit too stringent.
https://docs.opencv.org/3.0-beta/genindex.html#A
I’m woriking from the JetsonDemo software on Github (https://github.com/JetsonFRC/JetsonDemo/tree/master/ProcessingAndDrawing) , and trying to modify for use to find the vision targets in the game - still early days in the coding. I’m not having issues finding the contours, they are being picked up but when I store and process the contour hulls, I fail when the rectangle rotates at an angle (I’m still testing by how much.
Determining if the contour is “valid” is done with this code snippet:
//store the convex hulls of any valid contours
vector<contour_type> valid_contour_hulls;
for (int i = 0; i < (int)contours.size(); i++) {
contour_type contour = contours[i];
if (is_valid (contour)) {
contour_type hull;
cv::convexHull(contour, hull);
valid_contour_hulls.push_back(hull);
}
}
The is-valid component looks for a rectangle based on the opencv “boundingRect()” function. This is where I believe things fall apart for me.
bool is_valid (contour_type &contour) {
bool valid = true; //start out assuming its valid, disprove this later
//find bounding rect & convex hull
cv::Rect rect = cv::boundingRect(contour);
contour_type hull;
cv::convexHull(contour, hull);
double totalArea = (RES_X * RES_Y);
//calculate relevant ratios & values
double area = cv::contourArea(contour) / totalArea;
//double perim = cv::arcLength(hull, true);
double convex_area = cv::contourArea(hull) / totalArea;
double width = rect.width, height = rect.height;
double area_rat = area / convex_area;
double rect_rat = height / width;
//check ratios & values for validity
if (area < MIN_AREA || area > MAX_AREA) valid = false;
if (area_rat < MIN_AREA_RAT || area_rat > MAX_AREA_RAT) valid = false;
if (rect_rat < MIN_RECT_RAT || rect_rat > MAX_RECT_RAT) valid = false;
if (width < MIN_WIDTH || width > MAX_WIDTH) valid = false;
if (height < MIN_HEIGHT || height > MAX_HEIGHT) valid = false;
return valid;
}
Image examples:
Screen:
Filtered:
Even if I cover the right image, it does not target on the left contour, unless I tilt the camera and bring it back closer to vertical… I’m stuck on this one.
I did a bit more playing, I think I was going too fine with the aspect ratio for the contour. I backed it off to 1.5:1 and it seems to work. Next steps… getting two contours detected at the same time.