1. 需求
利用USB摄像头实时检测一个红色的小球
2. 原料/前期准备
OpenCV2.4.11,VS2010
摄像头模块(可以用罗技的USB摄像头代替)
3. 原理/实施步骤
#include <iostream> #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; using namespace std; int main( int argc, char** argv ) { VideoCapture cap(0); //capture the video from web cam if ( !cap.isOpened() ) // if not success, exit program { cout << "Cannot open the cam" << endl; return -1; } namedWindow("Control", CV_WINDOW_AUTOSIZE); //create a window called "Control" int iLowH = 156; int iHighH = 180; int iLowS = 43; int iHighS = 255; int iLowV = 46; int iHighV = 255; //Create trackbars in "Control" window cvCreateTrackbar("LowH", "Control", &iLowH, 179); //Hue (0 - 179) cvCreateTrackbar("HighH", "Control", &iHighH, 179); cvCreateTrackbar("LowS", "Control", &iLowS, 255); //Saturation (0 - 255) cvCreateTrackbar("HighS", "Control", &iHighS, 255); cvCreateTrackbar("LowV", "Control", &iLowV, 255); //Value (0 - 255) cvCreateTrackbar("HighV", "Control", &iHighV, 255); while (true) { Mat imgOriginal; bool bSuccess = cap.read(imgOriginal); // read a new frame from video if (!bSuccess) //if not success, break loop { cout << "Cannot read a frame from video stream" << endl; break; } Mat imgHSV; vector<Mat> hsvSplit; cvtColor(imgOriginal, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV //因为我们读取的是彩色图,直方图均衡化需要在HSV空间做 split(imgHSV, hsvSplit); equalizeHist(hsvSplit[2],hsvSplit[2]); merge(hsvSplit,imgHSV); Mat imgThresholded; inRange(imgHSV, Scalar(iLowH, iLowS, iLowV), Scalar(iHighH, iHighS, iHighV), imgThresholded); //Threshold the image /* //开操作 (去除一些噪点) Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); morphologyEx(imgThresholded, imgThresholded, MORPH_OPEN, element); //闭操作 (连接一些连通域) morphologyEx(imgThresholded, imgThresholded, MORPH_CLOSE, element); */ vector<Vec3f> circles; HoughCircles( imgThresholded, circles, CV_HOUGH_GRADIENT,1.5, 10, 200, 100, 0, 0 ); //依次在图中绘制出圆 for( size_t i = 0; i < circles.size(); i++ ) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); //绘制圆心 circle( imgThresholded, center, 3, Scalar(0,255,0), -1, 8, 0 ); //绘制圆轮廓 circle( imgThresholded, center, radius, Scalar(155,50,255), 3, 8, 0 ); } imshow("Thresholded Image", img); //show the thresholded image imshow("Original", imgOriginal); //show the original image char key = (char) waitKey(300); if(key == 27) break; } return 0; }
说明:
1.二值化是将彩色图片转换文纯黑纯白,cvCvtColor可以将图片转为灰度图,但是不是二值图。CvThreshold是二值化函数。获得的图片原红色部分是白色,其余部分是黑色。
2.通过控制RGB通道很难找到红色的准确范围,于是我们选用HSV空间。HSV(Hue, Saturation,Value)是根据颜色的直观特性而创建的一种颜色空间, H:色调 S:饱和度 V:明度
imgHSV是将imgOriginal的RGB空间转换为HSV空间后的得到的图像,之后是分离HSV三通道。cvEqualizeHist函数用于将直方图均衡化,可以将比较淡的图像变换为比较深的图像(即增强图像的亮度及对比度)。cvMerge:把几个单通道图像合并为一个多通道图像,这样我们就获得了一个HSV空间的图像。并且通过调节HSV的值基本可以滤掉所有非红色区域。
效果图:
----------------------------------------------------------------------------
---------------------------------------------------------------------------