图像亮度异常检测主要就是求一张图片的平均亮度,如果大于阈值则判断为过亮,小于阈值则判断为过暗,实际使用时可能不是对整张图片进行检测,而是只检测图片的某个区域,这时候可以根据传入的坐标对特定区域进行检测。

另外下面的代码中是验证了几种方法,最终用的就是平均值的方法,也就是代码中的da。

/***************************************************************************
Description:根据传入的信号灯结构体,求出左上角和右下角的坐标
parameter:
    lightStr:图像中包含的信号灯坐标;
	lightNum:信号灯框的数量,
    minNum:左上角点在数组中的下标,
    maxNum:右下角点在数组中的下标
return:
    0:success;
    1:fail
***************************************************************************/
int minAndMax(tlight::LightClock *lightStr, unsigned int lightNum, int &minNum, int &maxNum)
{
    
    int xmin = lightStr[0].xmin;
	int xmax = lightStr[0].xmax;
	
    //求出左上角点在数组中的下标
    for(int i = 0; i < lightNum; i++)
    {
         if(lightStr[i].xmin < xmin )
         {
             printf("i=%d,lightStr[i].xmin:%d,xmin:%d\n", i, lightStr[i].xmin, xmin);
             xmin = lightStr[i].xmin;
			 minNum = i;
         }
    }
 
    //求出右下角点在数组中的下标
	for(int i = 0; i < lightNum; i++)
    {
         if(lightStr[i].xmax > xmax )
         {
             printf("i=%d,lightStr[i].xmax:%d, xmax:%d\n", i, lightStr[i].xmax, xmax);
             xmax = lightStr[i].xmax;
			 maxNum = i;
         }
    }
 
	return 1;
 
 
}
 
 
 
/*****************************************************************************
Description:判断图像是否逆光,过亮;
parameter:
    inputImage:要检测的输入图像;
	lightStr:图像中包含的信号灯坐标;
	lightNum:信号灯框的数量,
return:
    21:图像过亮
    22:图像过暗
	20:图像正常
******************************************************************************/
int isBackLight(IplImage *inputImage, tlight::LightClock *lightStr, uint32_t lightNum)
{
    float da = 0.0;
	float cast = 0.0;
	float Ma = 0.0;
 
    int xmin = 0;
	int ymin = 0;
	int xmax = 0;
	int ymax = 0;
    int minNum = 0;
	int maxNum = 0;
	
    //首先把IplImage转化为Mat格式,并且转换为灰度图,
    cv::Mat inputMat = cv::cvarrToMat(inputImage);
	printf("inputMat.rows:%d\n", inputMat.rows);
	printf("inputMat.cols:%d\n", inputMat.cols);
 
	for(int i  = 0; i < lightNum;i++)//调试,记得删除
	{
	    printf("lightStr[%d].xmin:%d;\n", i, lightStr[i].xmin);
		printf("lightStr[%d].ymin:%d;\n", i, lightStr[i].ymin);
		printf("lightStr[%d].xmax:%d;\n", i, lightStr[i].xmax);
		printf("lightStr[%d].ymax:%d;\n", i, lightStr[i].ymax);
	}
 
	cv::Mat inputRec;
 
    if(0 == lightNum)//没有框的坐标,只检测上半部分
    {
        inputRec = inputMat(cv::Rect(0, 0, inputMat.cols, (inputMat.rows)/2 ));
     	printf("inputRec.rows:%d\n", inputRec.rows);
	    printf("inputRec.cols:%d\n", inputRec.cols);
        
    }
	else//有坐标信息的,按照坐标进行检测,
	{
        //找出xmin的最小值,和xmax的最大值,这两个点对应的就是相应的左上角和右下角。
        minAndMax(lightStr, lightNum, minNum, maxNum);
	    xmin = lightStr[minNum].xmin;
		ymin = lightStr[minNum].ymin;
		xmax = lightStr[maxNum].xmax;
		ymax = lightStr[maxNum].ymax;
        printf("lightNum:%d, minNum:%d, maxNum:%d\n", lightNum, minNum, maxNum);
		printf("xmin:%d, ymin:%d,xmax:%d,ymax:%d\n", xmin, ymin, xmax, ymax);
		//然后把矩形框外扩.
		xmin = ((xmin - 100) < 0) ? 0: (xmin - 100);
		ymin = ((ymin - 20) < 0) ? 0: (ymin - 20);
		xmax = ((xmax + 100) > inputMat.cols)? inputMat.cols : (xmax + 100);
		ymax = ((ymax + 300) > inputMat.rows)? inputMat.rows : (ymax + 300);
 
		printf("xmin:%d, ymin:%d,xmax:%d,ymax:%d\n", xmin, ymin, xmax, ymax);
 
		inputRec = inputMat(cv::Rect(xmin, ymin, (xmax - xmin), (ymax - ymin)));
		//printf("");
		
	}
 
	
	//cv::rectangle(inputMat, cvPoint(722, 28), cvPoint(813, 67), cvScalar(255, 0, 0), 2, 1, 0);//调试,记得删除
	//cv::imwrite("./test.jpg", inputMat);//调试,记得删除
	
	cv::Mat GRAYimg;
	cv::cvtColor(inputRec, GRAYimg, CV_BGR2GRAY);
	
	float a = 0;
	int Hist[256];
	for (int i = 0; i < 256; i++)
	{
		Hist[i] = 0;
	}
 
	float ave = 0.0;
	long sum = 0.0;
	for (int i = 0; i < GRAYimg.rows; i++)
	{
		for (int j = 0; j < GRAYimg.cols; j++)
		{
			//printf("GRAYimg.at<uchar>(i, j):%d\n", GRAYimg.at<uchar>(i, j));
			sum += GRAYimg.at<uchar>(i, j);
 
		}
	}
	printf("function:%s,sum:%d\n", __FUNCTION__, sum);
	ave = sum / (GRAYimg.rows * GRAYimg.cols);
	//printf("ave:%f\n", ave);
 
	int para = ave;
	int aveHigh = 0;
	for (int i = 0; i < GRAYimg.rows; i++)
	{
		for (int j = 0; j < GRAYimg.cols; j++)
		{
			a += float(GRAYimg.at<uchar>(i, j));
			//a += float(GRAYimg.at<uchar>(i, j) - para);
			//a += float(GRAYimg.at<uchar>(i, j) - ave);
			int x = GRAYimg.at<uchar>(i, j);
			if (x > ave)
			{
				aveHigh++;
				Hist[x]++;
			}
		}
	}
	da = a / float(GRAYimg.rows * GRAYimg.cols);//da是平均值
	printf("function:%s,da:%f\n", __FUNCTION__, da);
	float D = abs(da);
	//float Ma = 0;
	for (int i = 0; i < 256; i++)
	{
		if (i > ave)
		{
			Ma += abs(i - ave) * Hist[i];
		}
		//Ma += abs(i - para - da) * Hist[i];
		//Ma += abs(i - ave - da) * Hist[i];
	}
	Ma /= float(aveHigh);
	//Ma /= float((GRAYimg.rows * GRAYimg.cols));
	float M = abs(Ma);
	float K = D / M;
	cast = K;
 
	//调试,记得删除
	char debugName[20] = {};
 
 
	//if(da > 210.00)//过亮
	if(da > lightThresh)
	{
	    sprintf(debugName, "./%f.jpg", da);
	    //cv::imwrite(debugName, inputMat);//调试,记得删除。
	    return 21;
	}
	//else if(da < 25.00)
	else if(da < darkThresh)
	{
	    //printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ guoan+++++\n");
	    return 22;
	}
	else//正常
	{  
	    //printf("--------------------------------------------------------------------------------------liang-du-zheng-chang\n");
	    //cv::imwrite(debugName, inputMat);
	    return 20;
	}
}

项目中实际使用时可以把lightThresh写到配置文件中,上电初始化时读取配置文件。

GitHub 加速计划 / opencv31 / opencv
142
15
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:3 个月前 )
d9a139f9 Animated WebP Support #25608 related issues #24855 #22569 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 1 天前
09030615 V4l default image size #25500 Added ability to set default image width and height for V4L capture. This is required for cameras that does not support 640x480 resolution because otherwise V4L capture cannot be opened and failed with "Pixel format of incoming image is unsupported by OpenCV" and then with "can't open camera by index" message. Because of the videoio architecture it is not possible to insert actions between CvCaptureCAM_V4L::CvCaptureCAM_V4L and CvCaptureCAM_V4L::open so the only way I found is to use environment variables to preselect the resolution. Related bug report is [#25499](https://github.com/opencv/opencv/issues/25499) Maybe (but not confirmed) this is also related to [#24551](https://github.com/opencv/opencv/issues/24551) This fix was made and verified in my local environment: capture board AVMATRIX VC42, Ubuntu 20, NVidia Jetson Orin. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [X] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 1 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐