最近因为毕业课题的需要,初学OPENCV,钻研一周,终于有一点点小小的收获。
编译环境:VS2013+OpenCV.4.9
任务:摄像头识别电梯中已亮的按钮数字
目的:框选图中已亮的3和5号按钮。话不多说,上代码。
#include "stdafx.h"
#include "CharacterRecognize.h"
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
Mat frame = imread("C:/Users/FAN/Desktop/Elevator button/all_35light.jpg");
namedWindow("frame", 0);
Mat gray, bin, rbgThresholded;
//rgb直方图
//把r通道分为32个bin
int rbins = 32;
//int histsize[] = {rbins,bbins};
int histsize[] = { rbins };
//r的取值范围 0-255
float rranges[] = { 0, 255 };
//const float* ranges [] = {rranges,granges};
const float* ranges[] = { rranges };
MatND hist;
//我们根据图像第一个通道一维直方图
int channels[] = { 0 };
calcHist(&frame, 1, channels, Mat(), hist, 1, histsize, ranges, true, false);
//输出直方图
cout << hist << endl;输出hist矩阵值
//对上述矩阵处理得到我们需要的矩阵区间,处理目的是找出矩阵空间的陡变区间
int one,two,m;
int j;
float k[27];
for (int i = 5,j=0; i < hist.rows-1; i++)
{
float a = max(hist.at<float>(i, 0), hist.at<float>(i + 1, 0));
float b = min(hist.at<float >(i, 0), hist.at<float>(i + 1, 0));
float c = a / b;
k[j] = c;
//cout << c << endl;
cout << k[j] << endl;
j++;
}
for ( one = 0, m = 0; m < 27;m++)
{
if (k[one] < k[m])
{
one = m;
}
}
for ( two = 0,m= 0; m < 27 &&m != one;m++)
{ if (k[two]<k[m])
{
two = m;
}
}
one = max(one, two);
two = min(one, two);
cout << one << two << endl;
int LowB = 8*(two-3)+1;//对得到的矩阵区间进行系数纠正,得到阈值范围;(在这里我只对R通道的矩阵区间进行处理其他两个通道同样的处理方式)
int HighB = 8*(one+10)-1;
int LowG = 230;
int HighG = 255;
int LowR = 230;
int HighR =255;
inRange(frame, Scalar(LowB, LowG, LowR), Scalar(HighB, HighG, HighR), rbgThresholded); //阈值化原图
cvtColor(rbgThresholded, gray, CV_BGRA2GRAY);//RGB图转换成灰度图
imshow("灰度图", gray);//输出灰度图
//对灰度图进行一系列的处理
//开运算(去掉噪点)
Mat element = getStructuringElement(MORPH_RECT, Size(5,5 ));
morphologyEx(gray, gray, MORPH_OPEN, element);
//闭运算 (连接部分连通域)
morphologyEx(gray, gray, MORPH_CLOSE, element);
threshold(gray, bin, 120, 255, CV_THRESH_BINARY);二值化
medianBlur(bin, bin, 3);//中值滤波
imshow("二值图", bin);
//寻找像素点,绘制轮廓
vector<vector<Point> > contours;
vector<Vec4i> hiers;
Mat bin_con;
bin.copyTo(bin_con);//拷贝数据
findContours(bin_con, contours, hiers, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
Mat bin_conContours = Mat::zeros(bin_con.size(), CV_8UC1);
Mat Contours = Mat::zeros(bin_con.size(), CV_8UC1); //绘制
for (int i = 0; i < contours.size(); i++)
{
//contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
for (int j = 0; j < contours[i].size(); j++)
{
//绘制出contours向量内所有的像素点
Point P = Point(contours[i][j].x, contours[i][j].y);
Contours.at
<uchar>(P) = 255;
}
//绘制轮廓
drawContours(bin_conContours, contours, i, Scalar(255), 1, 8, hiers);
}
imshow("轮廓图", bin_conContours); /
最终得到效果如图,完美!
依次对其他几个样图检测: