In this tutorial, you are learn how to segment a colored object using a web-cam. We will use inRange() algorithm to segment the moving colored object and draw contour or boundary boxes around the tracked object.
Choose the target window to analyze with mouse click and drag.
See Appendix for the MouseEvent code
Analyze for the standard deviation and mean of the targeted color within the window.
Mat roi_RGB(image, selection); // Set ROI by the selection box
Mat roi_HSV;
cvtColor(roi_RGB, roi_HSV, CV_BGR2HSV);
Scalar means, stddev; meanStdDev(roi_HSV, means, stddev);
cout << "\n Selected ROI Means= " << means << " \n stddev= " << stddev;
Add slidebars to change the InRange values of each R, G, B or H, S, V and segment each colored ball.
/// set dst as the output of InRange
inRange(hsv, Scalar(MIN(hmin, hmax), MIN(smin, smax), MIN(vmin, vmax)),
Scalar(MAX(hmin, hmax), MAX(smin, smax), MAX(vmin, vmax)), dst);
Apply appropriate morphology (i.e. dilation/erosion/fill holes) to the output binary images to cluster the detected objects into meaningful blobs.
Find all contours and select the contour with the largest area
Mat image_disp, hsv, hue, mask, dst;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
…
findContours(dst, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
/// Find the Contour with the largest area ///
int idx = 0, largestComp = 0;
double maxArea = 0;
for (; idx >= 0; idx = hierarchy[idx][0])
{
const vector<Point>& c = contours[idx];
double area = fabs(contourArea(Mat(c)));
if (area > maxArea)
{
maxArea = area;
largestComp = idx;
}
}
Draw the contour and a box over the target object
/// Draw the Contour Box on Original Image ///
drawContours(image_disp, contours, largestComp, Scalar(255, 255, 255), 4, 8, hierarchy);
Rect boxPoint = boundingRect(contours[largestComp]);
rectangle(image_disp, boxPoint, Scalar(255, 0, 255), 3);
Now, segment other color balls
III. Exercise
Drawing the trajectory of a colored object with Webcam
Modify your tutorial program to keep drawing the contour on a white or black background image.
Use your webcam for the source image data.
Use any colored object as the target.
Draw rectangles or circles for the output display.
Appendix
Sample code: On Mouse Event
/// On mouse event
static void onMouse(int event, int x, int y, int, void*)
{
if (selectObject) // for any mouse motion
{
selection.x = MIN(x, origin.x);
selection.y = MIN(y, origin.y);
selection.width = abs(x - origin.x) + 1;
selection.height = abs(y - origin.y) + 1;
selection &= Rect(0, 0, image.cols, image.rows);
// Bitwise AND check selectin is within the image coordinate
}
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
selectObject = true;
origin = Point(x, y);
break;
case CV_EVENT_LBUTTONUP:
selectObject = false;
if (selection.area())
trackObject = true;
break;
}
}