目录 大学时候,曾经暑假在学校值班,当时一个学长在准备考研,学长是我在计算机视觉的引路人,当时我们要做一件事,就是监控火警灯,因为火警报警器出故障了,当时学长跟我说,可以做一个自动识别然后进行报警的装置。这样就不用每时每刻都盯着它,就可以把精力放在其他事情上。 这个项目化简一下,我们就可以变成如下这个项目,用我们最近学习的读写像素就可以完成啦。 下面是火警等一系列监控界面,监控正常情况如下: 火警只有在有地方的烟感设备监测到有烟出现,才会亮灯并且报警。 当监控出现问题时,故障就会亮灯。 但是监控器出故障之后: 火警预警灯就会定期闪亮,并且没有报警; 故障灯一直常亮状态; 为了防患于未然,学校的要求是,只要有火警灯亮起,就必须到报警地查看情况,如果没有问题,回到监控室,手动关闭火警灯。 现在我们要做的就是通过摄像头自动监控火警灯,如果亮起,发出警报! 我们目前学习了几个最基本的内容: 图像输入、输出、保存 Mat类 基本数据类型 像素基本操作(获取像素指针、控制像素范围、读写像素) 我们就要用上面的来完成该项目。 我们分析一下这个项目,主要分为如下步骤: 原项目是通过视频流获取图像,现在我们没有具体得环境,就只能用图片,检测原理是一样的。我们要先获取图像,保证图像能够正确读取,才能完成后续操作。 遍历所有图像的运算速度是非常慢的,为了加快运算效率,我们要选择缩小区域进行检测。所以我们要选择如下区域: 因为只有上面的几个基本内容,那我们就没有办法使用更多的东西进行定位,我们定位的方式就是通过反复检测,然后找到一个合适的区域: (1)尽可能只包含火警区域; (2)不受摄像头抖动影响,所以摄像头轻微抖动,火警灯依然在范围内; 获取火警灯位置的像素,并根据像素值选定亮灯及灭灯像素范围。 但是我们发现,灭灯状态,和火警外面的圆角矩形边框的颜色是类似的,所以检测灭灯容易出现误报。而亮灯的灯光像素应该是很明显的,再加上灯只有灯亮和灯灭两种状态,所以我们只需要检测亮灯的像素范围就好。在像素范围内,就说明亮灯,不在像素范围内,就说明灭灯。 当我们确定了亮灯的像素范围后,我们就需要实时监测我们选择的区域像素,并判断是否有像素在我们上面规定好的范围之内。 一旦出现有大量的像素点满足在范围之内,那我们就报警。所以我们要设定一个阈值,达到多少时,我们认为是火警灯亮。 为什么我们要检测到大量呢? 因为根据环境光线不同,一旦出现反光,也会导致出现部分点满足范围。 首先我们要获取图像。这个用到我们最开始的图像的读入,理论上我们是要使用摄像头,然后获取帧,在这里,我们就直接读入图片吧!这并不影响后续的操作,也没有改变检测原理。代码如下: 然后需要我们获取区域,最直接的方法就是凭感觉去设定,然后不断调整找到一个合适的区域。 当然如果我们学的更多的话,我们可以用到更多的功能去获得区域,比如当时我尝试了如下方式: (1)给那个区域贴上红纸,检测红纸; (2)使用文字识别模块,检测火警文字,然后获取区域。 现在我们学的内容比较少,就用最简单、最直接的方式吧! 代码如下: 区域如下: 获取火警灯位置的像素,并根据像素值选定亮灯及灭灯像素范围。 我们要检测的区域为: 这是一个22×22的正方形区域,因为亮灯区域是一个圆形区域,所以,我们考虑准确度,那我们在检测像素,应该是检测到图像中心距离为11像素范围内的图像: 检测的结果如下: 如果想让精度更高,我们可以缩小范围,比如到图像中心距离为10那么检测到的结果如下: 我们可以根据上面我们获得的范围,来选择我们的范围,比如我们的像素范围可以是: B : ≥125;G : ≥ 155;R : ≥ 228; 一个半径为10的圆形中间的像素点的个数肯定大于边长为10的正方形中间的像素点的个数。 边长为10的正方形有100个像素点。那我们的阈值,可以设为100,只要我们检测到满足上面的范围的像素点的个数大于100时,就认为火警灯亮起。为了查看哪些点被检测出来,我们将这些点的像素值修改为黑色。 火警灯亮起,我们给出提示。 结果如下: 全部代码如下: 如果我们更换一下图片,我们使用未亮灯图片,没有提示,也没有任何改变:
前言
一、项目要求
二、项目分析
1、获取图像
2、选择区域
3、区域像素检测
4、报警
三、实战
1、获取图像
Mat src = imread("./image/1.png"); //1.png 是亮灯, 2.png 是灭灯 if (!src.data) { cout << "ERROR : could not load image.n"; return -1; }
2、选择区域
//不断调整Rect,找到对于我的比较合适为Rect(70, 60, 150, 60)。 Mat src_ROI = Mat(src, Rect(70, 60, 150, 60)); imshow("src_ROI", src_ROI);
3、区域像素检测
int max_B = 0, max_G = 0, max_R = 0; int min_B = 255, min_G = 255, min_R = 255; //半径为9的圆区域像素 for (int i = 0; i < light.rows; i++) { for (int j = 0; j < light.cols; j++) { if ((i - 11)*(i - 9) + (j - 9)*(j - 9) <= 81) { Vec3b BGR = light.at<Vec3b>(i, j); int B = BGR.val[0]; int G = BGR.val[1]; int R = BGR.val[2]; cout << "[" << B << ", " << G << ", " << R << "]t"; if (B > max_B) max_B = B; else if (B < min_B) min_B = B; if (G > max_G) max_G = G; else if (G < min_G) min_B = G; if (R > max_R) max_R = R; else if (R < min_R) min_R = R; } } cout << endl << endl; } cout << "B: [" << min_B << ", " << max_B << "]" << endl; cout << "G: [" << min_G << ", " << max_G << "]" << endl; cout << "R: [" << min_R << ", " << max_R << "]" << endl;
4、报警
int num = 0; //按列遍历,效率更高 for (int i = 0; i < src_ROI.cols; i++) { for (int j = 0; j < src_ROI.rows; j++) { BGR = src_ROI.at<Vec3b>(j, i); if (BGR.val[0] >= min_B && BGR.val[1] >= min_G && BGR.val[2] >= min_R) { src_ROI.at<Vec3b>(j, i)[0] = 0; src_ROI.at<Vec3b>(j, i)[1] = 0; src_ROI.at<Vec3b>(j, i)[2] = 0; num++; //cout << "num = " << num << endl; } } } if (num > 100) { cout << "亲,疑似火警,请亲临现场查看!" << endl; } imshow("new_src_ROI", src_ROI);
5、全部代码
/* 作者:水亦心 内容:core-像素基本操作实战之报警灯检测 时间:2020年5月20日 */ #define INPUT_TITLE "input image" #include<iostream> #include<opencv2opencv.hpp> using namespace std; using namespace cv; int main() { //////////////////////////////// 获取图像 //////////////////////////////// Mat src = imread("./image/1.png"); //1.png 是亮灯, 2.png 是灭灯 if (!src.data) { cout << "ERROR : could not load image.n"; return -1; } //////////////////////////////// 选择区域 //////////////////////////////// //不断调整Rect,找到对于我的比较合适为Rect(70, 60, 150, 60)。 Mat src_ROI = Mat(src, Rect(70, 60, 150, 60)); imshow("src_ROI", src_ROI); ////////////////////////////// 区域像素检测 ////////////////////////////// Mat light = imread("./image/3.png"); //光区域 if (!light.data) { cout << "ERROR : could not load light image.n"; return -1; } int max_B = 0, max_G = 0, max_R = 0; int min_B = 255, min_G = 255, min_R = 255; int B, G, R; Vec3b BGR; //半径为9的圆区域像素 int k = 0; for (int i = 0; i < light.rows; i++) { for (int j = 0; j < light.cols; j++) { if ((i - 11)*(i - 11) + (j - 11)*(j - 11) <= 100) { BGR = light.at<Vec3b>(i, j); B = BGR.val[0]; G = BGR.val[1]; R = BGR.val[2]; //cout << "[" << B << ", " << G << ", " << R << "]t"; //light.at<Vec3b>(i, j)[0] = 0; //light.at<Vec3b>(i, j)[1] = 0; //light.at<Vec3b>(i, j)[2] = 0; //imshow("new light", light); if (B > max_B) max_B = B; if (B < min_B) min_B = B; if (G > max_G) max_G = G; if (G < min_G) min_G = G; if (R > max_R) max_R = R; if (R < min_R) min_R = R; } } //cout << endl << endl; } cout << "B: [" << min_B << ", " << max_B << "]" << endl; cout << "G: [" << min_G << ", " << max_G << "]" << endl; cout << "R: [" << min_R << ", " << max_R << "]" << endl; cout << endl; //Mat test = Mat(100, 100, CV_8UC3, Scalar(min_B, min_G, min_R)); //imshow("test", test); //////////////////////////////// 监测及报警 /////////////////////////////// int num = 0; //按列遍历,效率更高 for (int i = 0; i < src_ROI.cols; i++) { for (int j = 0; j < src_ROI.rows; j++) { BGR = src_ROI.at<Vec3b>(j, i); if (BGR.val[0] >= min_B && BGR.val[1] >= min_G && BGR.val[2] >= min_R) { src_ROI.at<Vec3b>(j, i)[0] = 0; src_ROI.at<Vec3b>(j, i)[1] = 0; src_ROI.at<Vec3b>(j, i)[2] = 0; num++; //cout << "num = " << num << endl; } } } if (num > 100) { cout << "亲,疑似火警,请亲临现场查看!" << endl; } imshow("new_src_ROI", src_ROI); waitKey(0); return 0; }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算