当前位置: 代码迷 >> 综合 >> 基于opencv的图像亮度异常检测
  详细解决方案

基于opencv的图像亮度异常检测

热度:50   发布时间:2024-02-24 04:59:22.0

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

/***************************************************************************
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 < 85.00)//过暗,过暗图片测试值是85-95,阈值设置成85,那么就只有很暗的才检测为过暗。//else if(da < 25.00)//上面阈值设置了85之后,有很多正常的图片被检测成了过暗,其中一张图片是信号灯熄灭,计算出是35,因此修改该阈值为25.else if(da < darkThresh){//printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ guoan+++++\n");return 22;}else//正常{  //printf("--------------------------------------------------------------------------------------liang-du-zheng-chang\n");//cv::imwrite(debugName, inputMat);return 20;}
}

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