The algorithm is the following:
- Convert input image to YCbCr color space which is good to detect blue (and also red) color:
To convert some image to another color space use cvtColor.
- Extract blue channel from it:
Use function extractChannel
to extract needed channel.
- Detect regions with biggest value [0-255] of blue color. I used function minMaxIdx and then just multiplied maximum on 0.8 (this is threshold). You can use more complex methods like histogram analysation.
- Make a mask of blue color:
For this I used threshold function with calculated in step 3 threshold (as parameter).
- Find all blue contours in mask. In OpenCV it's easy - just use findContours.
- And, finally, detect contour with biggest square and find its coordinates (center). To calculate contour with biggest square you can use function contourArea.
Also instead of steps 1-4 you can convert image to HSV and using inRange detect blue color.
Here's 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 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 output of program is next:
square = 263525
position: x: 318, y: 208
You can convert this code to JavaCV - see this tutorial.