基于颜色特征提取数字

最近因为毕业课题的需要,初学OPENCV,钻研一周,终于有一点点小小的收获。

编译环境:VS2013+OpenCV.4.9

任务:摄像头识别电梯中已亮的按钮数字


目的:框选图中已亮的35号按钮。话不多说,上代码。

#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通道分为32bin 

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); /

 

最终得到效果如图,完美!

 

依次对其他几个样图检测:

 

猜你喜欢

转载自blog.csdn.net/weixin_43124720/article/details/90293067