How to get area size in JavaCV

In my project, I want to get the size from the largest uniform area of ​​a certain color (in my example, there is a blue sky underneath).

My first idea is to convert the original image:

original image

to the binary image, define skycolor and create a mask with this area: mask image

But how can I get the size and position of these white pixels? I want an effective method that tells the truth if the image has a blue sky at the top 1/3 of the image. Any ideas? Should I create a "global mask" (see Image 3 in the comment) and compare it with the binary image? Or is there an easier way?

Thanks.

+6
source share
1 answer

The algorithm is as follows:

  • Convert an input image to a YCbCr color space that detects blue (as well as red) color well: YCrCb image To convert an image to a different color space, use cvtColor .
  • Remove the blue channel from it: Blue image 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: binary 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 .

+6
source

Source: https://habr.com/ru/post/919056/


All Articles