目标:判断是否有灯源
环境:XP OpenCV3.1.0 VS2010
步骤说明:
1、cvtColor获得灰度图img_gray
2、blur模糊化
3、threshold获得二值图img_thres
4、再次blur模糊化
5、canny边缘检测得到img_canny
6、findContours轮廓检测获得N个包围
7、得到每个轮廓的最小外接矩阵
for(int i=0;i
7.1 绘制轮廓的最小矩阵,得到旋转矩阵
7.2 根据旋转矩阵的角度,将图片整体旋转
7.3 提取图片旋转后的ROI
7.4 计算ROI的亮度和亮度的标准差,通过阀值判断是否灯源
}
缺点:只通过判断平均亮度和亮度的标准差,阀值选择不合适的话,会把反光的白色墙面都当成灯源。
程序:
程序段1:
主函数循环体:功能:获取摄像头图像,转换为灰度图,计算图像平均亮度和亮度的标准差,并实时显示在图像中。
while (true)
{
cap >> img,img_gray;
if (!img.data)
continue;
GetLightSource(img);
cvtColor(img, img_gray , COLOR_BGR2GRAY );
imshow("img_gray", img_gray);
LumAvg = GetGrayImagAvg(img_gray);
LumSd = GetGrayImagStandardDeviation(img_gray, LumAvg);
cv::Mat image_1 = img.clone();
IplImage tmp = IplImage(image_1);
//CvArr* arr = (CvArr*)&tmp;
//the font variable
CvFont font;
double hScale=0.7;
double vScale=0.7;
int lineWidth=4;// 相当于写字的线条
//char showMsg[10]="hello image!";
// sprintf(showMsg, "avg: %d", LumAvg); // 将整数转换成字符串
char showMsg[14];
showMsg[0]='a';
showMsg[1]='v';
showMsg[2]='g';
showMsg[3]=':';
showMsg[4]='0'+(int)LumAvg/100;
showMsg[5]='0'+(int)LumAvg%100/10;
showMsg[6]='0'+(int)LumAvg%10;
showMsg[7]=' ';
showMsg[8]='s';
showMsg[9]=':';
showMsg[10]='0'+(int)LumSd/100;
showMsg[11]='0'+(int)LumSd%100/10;
showMsg[12]='0'+(int)LumSd%10;
showMsg[13]='\0';
// 初始化字体
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);//初始化字体,准备写到图片上的
// cvPoint 为起笔的x,y坐标
cvPutText(&tmp,showMsg,cvPoint(10,20),&font,CV_RGB(255,0,0));//在图片中输出字符
cv::imshow ( "image_1", image_1 );
cv::imshow ("img_gray", img_gray);
imshow("video capture", img);
imshow("标注出矩形", img);
//waitKey(0);
if (waitKey(20) >= 0)
break;
}
程序段2:全部复制自http://answers.opencv.org/question/905/roi-region-of-interest/
功能是contour得到了包围住目标的旋转后的矩阵,使用这个矩阵获得ROI。
// rect is the RotatedRect (I got it from a contour...)
RotatedRect rect;
// matrices we'll use
Mat M, rotated, cropped, cropped_gray;
// get angle and size from the bounding box
float angle = rect.angle;
Size rect_size = rect.size;
// thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
if (rect.angle < -45.) {
angle += 90.0;
swap(rect_size.width, rect_size.height);
}
// get the rotation matrix
M = getRotationMatrix2D(rect.center, angle, 1.0);
// perform the affine transformation
warpAffine(img, rotated, M, img.size(), INTER_CUBIC);
// crop the resulting image
getRectSubPix(rotated, rect_size, rect.center, cropped);
程序段3:平均亮度超过阀值或者亮度的标准差小于阀值,当作是光源。
if( ( cropped_LumAvg > 200)&& ( cropped_LumSd < 40))
{
lightSrcDetectCnt++;
cout << "lightSrcDetectCnt++ "<< endl;
}
程序段4:函数代码。输出参数就是有效的光源数目。
int GetLightSource(cv::Mat img)
{
int lightSrcDetectCnt;
vector> contours;
vector hierarchy;
double cropped_LumAvg, cropped_LumSd;
Mat img_gray, img_canny, img_thres;
cvtColor(img, img_gray , COLOR_BGR2GRAY );
img_thres = img_gray.clone();
blur( img_gray, img_gray, Size(3,3) );
threshold(img_gray,img_thres,250,253,THRESH_BINARY_INV);
blur(img_thres,img_thres,Size(3,3));
Canny(img_thres, img_canny, 0, 30, 3);
findContours(img_canny, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
lightSrcDetectCnt = 0;
Mat drawing = Mat::zeros(img_thres.size(), CV_8UC1); //最小外接矩形画布
for (int i = 0; i 200)&& ( cropped_LumSd < 40))
{
lightSrcDetectCnt++;
cout << "lightSrcDetectCnt++ "<< endl;
}
imshow("cropped", cropped);
//waitKey(0);
}
//imshow("最小外接矩形", 画布);
//Mat B=A(Rect(0,0,100,100));
cout << "contours.size(): " << contours.size()<< endl;
cout << "lightSrcDetectCnt: " << lightSrcDetectCnt<< endl;
cv::imshow ("img_canny", img_canny);
imshow("drawing", drawing);
imshow("img_thres", img_thres);
return lightSrcDetectCnt;
}