The algorithm is as follows:
- Convert an input image to a YCbCr color space that detects blue (as well as red) color well: To convert an image to a different color space, use cvtColor .
- Remove the blue channel from it: Use the
extractChannel
function to retrieve the desired channel. - Detection of areas with the highest value [0-255] in blue. I used the minMaxIdx function, and then just multiplied a maximum of 0.8 (this is the threshold). You can use more sophisticated methods such as histogram analysis.
- Make a blue mask: For this, I used the threshold function with the step 3 calculated in the threshold (as a parameter).
- Find all the blue contours in the mask. In OpenCV, this is easy - just use findContours .
- And finally, we find the contour with the largest square and find its coordinates (in the center). To calculate the contour with the largest square, you can use the contourArea function.
Also, instead of steps 1-4, you can convert the image to HSV and using inRange detects a blue color.
Here is my C ++ impementation:
Mat inMat = imread("input.jpg"), blueMat, threshMat; cvtColor(inMat, blueMat, CV_BGR2YCrCb);//convert to YCrCb color space extractChannel(blueMat, blueMat, 2);//get blue channel //find max value of blue color //or you can use histograms //or more complex mathod double blueMax; minMaxIdx(blueMat, 0, &blueMax); blueMax *= 0.8; //make binary mask threshold(blueMat, threshMat, blueMax, 255, THRESH_BINARY); //finding all blue contours: vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours(blueMat, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); double maxSquare = 0; vector<Point> maxContour; //finding contours with biggest square: for (size_t i=0; i<contours.size(); i++) { double square = contourArea(contours[i]); if (square > maxSquare) { maxContour = contours[i]; maxSquare = square; } } //output results: Point center = centerPolygon(maxContour); cout << "square = " << maxSquare << endl; cout << "position: x: " << center.x << ", y: " << center.y << endl;
Here's the centerPolygon
function:
Point centerPolygon(const vector<Point>& points) { int x=0, y=0; for (size_t i=0; i<points.size(); i++) { x += points[i].x; y += points[i].y; } return Point(x/points.size(), y/points.size()); }
The result of the program is as follows:
square = 263525 position: x: 318, y: 208
You can convert this code to JavaCV - see this tutorial .
source share