تشخیص رنگ در اپن سی وی
Lets start by thresholding the input image for anything that is not red. Instead of the usual RGB color space we are going to use the HSV space, which has the desirable property that allows us to identify a particular color using a single value, the hue, instead of three values. As a side note, in OpenCV H has values from 0 to 180, S and V from 0 to 255. The red color, in OpenCV, has the hue values approximately in the range of 0 to 10 and 160 to 180.
Next piece of code converts a color image from BGR (internally, OpenCV stores a color image in the BGR format rather than RGB) to HSV and thresholds the HSV image for anything that is not red:
1 ...
2 // Convert input image to HSV
3 cv::Mat hsv_image;
4 cv::cvtColor(bgr_image, hsv_image, cv::COLOR_BGR2HSV);
5
6 // Threshold the HSV image, keep only the red pixels
7 cv::Mat lower_red_hue_range;
8 cv::Mat upper_red_hue_range;
9 cv::inRange(hsv_image, cv::Scalar(0, 100, 100), cv::Scalar(10, 255, 255), lower_red_hue_range);
10 cv::inRange(hsv_image, cv::Scalar(160, 100, 100), cv::Scalar(179, 255, 255), upper_red_hue_range);
11 ...
Preprocess the image using cv::inRange() with the necessary color bounds to isolate red. You may want to transform to a color-space like HSV or YCbCr for more stable color bounds because chrominance and luminance are better separated. You can use cvtColor() for this. Check out my answer here for a good example of using inRange()
with createTrackbar()
.
So, the basic template would be:
Mat redColorOnly;
inRange(src, Scalar(lowBlue, lowGreen, lowRed), Scalar(highBlue, highGreen, highRed), redColorOnly);
detectSquares(redColorOnly);
EDIT : Just use the trackbars to determine the color range you want to isolate, and then use the color intervals you find that work. You don't have to constantly use the trackbars.
EXAMPLE :
So, for a complete example of the template here you go,
I created a simple (and ideal) image in GIMP, shown below:
Then I created this program to filter all but the red squares:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat redFilter(const Mat& src)
{
assert(src.type() == CV_8UC3);
Mat redOnly;
inRange(src, Scalar(0, 0, 0), Scalar(0, 0, 255), redOnly);
return redOnly;
}
int main(int argc, char** argv)
{
Mat input = imread("colored_squares.png");
imshow("input", input);
waitKey();
Mat redOnly = redFilter(input);
imshow("redOnly", redOnly);
waitKey();
// detect squares after filtering...
return 0;
}
NOTE : You will not be able to use these exact same filter intervals for your real imagery; I just suggest you tune the intervals with trackbars to see what is acceptable.
The output looks like this:
Viola! Only the red square remains :)
Enjoy :)