OpenCV计算得到摄像头视野内灯源数目

目标:判断是否有灯源

环境: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<N;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<vector<Point>> contours;
	vector<Vec4i> 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<contours.size(); i++)
	{
		//绘制轮廓  
		drawContours(drawing, contours, i, Scalar(255), 1, 8, hierarchy);
 
		//绘制轮廓的最小外结矩形  
		RotatedRect rect = minAreaRect(contours[i]);
		//Rect rect = minAreaRect(contours[i]);
		//rectangle(画布,rect.boundingRect(),Scalar(55));
		Point2f P[4];
 
		rect.points(P);
		for (int j = 0; j <= 3; j++)
		{
			line(img, P[j], P[(j + 1) % 4], Scalar(0,0,255), 1);
			line(drawing, P[j], P[(j + 1) % 4], Scalar(111), 2);
		}
 
		/*
		//绘制轮廓的最小外结圆  
		Point2f center; float radius;
		minEnclosingCircle(contours[i], center, radius);
		circle(画布1, center, radius, Scalar(255), 2);
		*/

		// 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);
		
		imshow("rotated", rotated);
        if (!cropped.data)
            continue;
		
		
		cvtColor(cropped, cropped_gray , COLOR_BGR2GRAY  );
		cropped_LumAvg = GetGrayImagAvg(cropped_gray);
		cropped_LumSd  = GetGrayImagStandardDeviation(cropped_gray, cropped_LumAvg);
		cout << "cropped.LumAvg: " << cropped_LumAvg<< endl;
		cout << "cropped.LumSd: " << cropped_LumSd<< endl;

		if( ( cropped_LumAvg > 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;
}

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值