我的图像处理课程的一个实验。
一.任务
识别字符:
二.使用平台
Windows10专业版
VS2015企业版
C++ opencv3.2
三.图像处理的思路
1.先定位感兴趣区域(字符区域)
定位有两种方法,一种是定位圆,另一种是定位直线
2.然后模版匹配(matchTemplate)
模版匹配需要做好模版。将感兴趣区域找出后,可以采用像素投影分割法,将每个字符分割出来保存到本地文件夹做样本。
四.图像处理
整个流程:
1.读入图像
2.转为灰度
3.中值滤波
4.固定阈值二值化。(因为我定位的是圆)
5.霍夫圆检测找到圆心
6.根据圆心剪裁感兴趣区域
7.读取本地文件夹样本
8.进行模版匹配
9.标出模板匹配结果
图像:
1.转为灰度中值滤波
2.二值化后霍夫圆检测
3.根据圆心坐标裁出字符区域
3.模版匹配后标记结果
代码:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <string>
using namespace cv;
using namespace std;
Mat src, dst, gray, binImg;
Mat eImage;
int main(int argc, char** argv)
{
src = imread("G:\\U_lesson\\图像处理\\实验\\zf1.bmp");
if (src.empty())
{
printf("can not load image....\n");
return -1;
}
// 窗口命名
namedWindow("test", CV_WINDOW_AUTOSIZE);
imshow("test", src);
//中值滤波
Mat moutput;
medianBlur(src, moutput, 11);
imshow("moutput", moutput);
cvtColor(moutput, gray, CV_BGR2GRAY);
// 固定阈值二值化
threshold(gray, binImg, 15, 255, THRESH_BINARY);
imshow("binImg", binImg);
// 霍夫圆检测
vector<Vec3f> pcircles;
HoughCircles(binImg, pcircles, CV_HOUGH_GRADIENT, 1, 50, 15, 15, 25, 80);
src.copyTo(dst);
// 画圆与圆心
for (size_t i = 0; i < pcircles.size(); i++)
{
Vec3f cc = pcircles[i];
circle(dst, Point(cc[0], cc[1]), cc[2], Scalar(0, 0, 255), 2, LINE_AA);
circle(dst, Point(cc[0], cc[1]), 2, Scalar(98, 23, 255), 2, LINE_AA);
cout << cc << endl;
}
imshow("dst", dst);
// 简陋判断有无圆心坐标
if (pcircles[0][0] > 0 && pcircles[0][1] > 0)
{
// 剪裁出字符区域
int start_x = pcircles[0][0] - 280;
int start_y = pcircles[0][1] + 80;
int rect_width = 500;
int rect_height = 140;
Rect rect(start_x, start_y, rect_width, rect_height);
Mat ROI = src(rect);
imshow("rect", ROI);
Mat dst_gray, dst_bin;
cvtColor(ROI, dst_gray, CV_BGR2GRAY);
int height = dst_gray.rows;
int width = dst_gray.cols;
// 取出本地文件的样本
vector<Mat> character_image;
char tempstr[12] = { '2','0','1','8','1','2','0','7','2','5','1','C'};
for (int i = 0; i <= 11; i++)
{
string ImgName = "character";
ImgName = ImgName + to_string(i);
ImgName = "G:\\U_lesson\\图像处理\\实验\\match\\" + ImgName + ".bmp";
Mat temp = imread(ImgName);
character_image.push_back(temp);
}
Mat tmp_dst;
Mat find_dst;
dst_gray.copyTo(find_dst);
cvtColor(find_dst, find_dst, CV_GRAY2BGR);
// 模版匹配
for (int i = 0; i <= 11; i++)
{
Mat temp;
cvtColor(character_image[i],temp, CV_BGR2GRAY);
width = dst_gray.cols - temp.cols + 1;
height = dst_gray.rows - temp.rows + 1;
Mat result(width, height, CV_32FC1);
Point minLoc;
Point maxLoc;
double min, max;
Point temLoc;
dst_gray.copyTo(tmp_dst);
matchTemplate(dst_gray, temp, result, CV_TM_CCORR_NORMED, Mat());
// 找到匹配的最大最小坐标
minMaxLoc(result, &min, &max, &minLoc, &maxLoc, Mat());
temLoc = maxLoc;
cout << temLoc << endl;
// 画出矩形框
rectangle(find_dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
string str(1, tempstr[i]);
putText(find_dst, str, Point(temLoc.x, temLoc.y), FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 255, 0), 1, 8, 0);
cout << tempstr[i] << endl;
//rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255), 2, 8);
}
imshow("AAA", find_dst);
}
waitKey(0);
return 0;
}
被抛弃的写随笔公众号改写技术文章了,感兴趣的可以关注公众号:王崇卫