图片过程
在这里插入图片描述
模板图库制作
Mat image, gray_image, threshold_image;
image = imread("C:/Users/clg2021/Desktop/ocr_a_reference.png");
if (!image.data) {cout << "failed to read" << endl;system("pause");}
show("image", image);
cvtColor(image, gray_image, CV_BGR2GRAY);
show("gray_image", gray_image);
threshold(gray_image, threshold_image, 10, 255, CV_THRESH_BINARY_INV);
show("threshold_image", threshold_image);
//-----------------------------------------------------------------------
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(threshold_image.clone(), contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
drawContours(image, contours, -1, Scalar(0, 255, 0), 3);
imshow("draw_image", image);
cout << contours.size() << endl;
vector<Rect>srcRect(contours.size());
for (unsigned int i = 0; i < contours.size(); ++i)
{
srcRect[i] = boundingRect(contours[i]);
}
sorted_image(srcRect, contours.size());
vector<Mat>image_roi;
Mat roi;
for (unsigned int i = 0; i < contours.size(); ++i)
{
roi = threshold_image(Rect(srcRect[i].x, srcRect[i].y, srcRect[i].width, srcRect[i].height));
resize(roi, roi, Size(57, 88));
image_roi.push_back(roi);
//---------------------------------
char window[220];
sprintf_s(window, "%s%d%s", "C:\\Users\\clg2021\\Desktop\\temple\\", i, ".jpg"); //指定保存路径//"..\\Image\\image",
imwrite(window, roi);
}
//显示模板图像
for (int i = 0; i < image_roi.size(); ++i)
{
imshow("images", image_roi[i]);
waitKey(0);
}
加载测试图片
//导入测试图片
Mat bank_image, bank_gray, bank_tophat;
bank_image = imread("C:/Users/clg2021/Desktop/images/credit_card_01.png");
if (!bank_image.data) { cout << "failed to read" << endl; system("pause"); }
resize(bank_image, bank_image, Size(300, bank_image.rows));
show("bane_image", bank_image);
cvtColor(bank_image, bank_gray, CV_BGR2GRAY);
Mat element1 = getStructuringElement(MORPH_RECT, Size(9, 3));
Mat element2 = getStructuringElement(MORPH_RECT, Size(7, 5));
morphologyEx(bank_gray, bank_tophat, MORPH_TOPHAT, element1);
show("bank_tophat", bank_tophat);
Mat grad_x,close_image,th_image;
Sobel(bank_tophat, grad_x, CV_16S, 1, 0, 3);
convertScaleAbs(grad_x, grad_x);
show("absgrad_x", grad_x);
morphologyEx(grad_x, close_image, MORPH_CLOSE, element1);
morphologyEx(close_image, close_image, MORPH_CLOSE, element2);
threshold(close_image, th_image, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
imshow("th_image", th_image);
//绘制轮廓
vector<vector<Point>>contoures; vector<Vec4i>hierarchy1;
findContours(th_image.clone(), contoures, hierarchy1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
float rate;vector<vector<Point>>::iterator itr;
itr = contoures.begin(); Rect srcRect1;
while (itr != contoures.end())
{
srcRect1 = boundingRect(*itr);
rate = srcRect1.width / float(srcRect1.height);
if (rate < 1.72 || rate > 1.8)
{
if (srcRect1.width < 45 || srcRect1.width > 55 || srcRect1.height<25 || srcRect1.height > 33)
{
itr = contoures.erase(itr);
}
}
else { itr++; }
}
Mat new_image=bank_image,clone();
drawContours(new_image, contoures, -1, Scalar(0, 0, 255), 1);
imshow("new_image", new_image);
//-------------------------------------------------------------
vector<Mat>image_roi1; Mat roi1; vector<Rect>srcRect2(contoures.size());
Mat roi_th;
for (unsigned int i = 0; i < contoures.size(); ++i)
{
srcRect2[i] = boundingRect(contoures[i]);
roi1 = bank_gray(Rect(srcRect2[i].x, srcRect2[i].y, srcRect2[i].width, srcRect2[i].height));
threshold(roi1, roi_th, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
show("roi_th", roi_th);
vector<vector<Point>>c; vector<Vec4i>h;
findContours(roi_th, c, h, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
vector<Rect>R(c.size()); Mat small_roi; int serise_unm = 0;
vector<int>num123;
for (unsigned int j = 0; j < c.size(); ++j)
{
R[j] = boundingRect(c[j]);
small_roi = roi_th(Rect(R[j].x, R[j].y, R[j].width, R[j].height));
resize(small_roi, small_roi, Size(57, 88));
show("small_roi", small_roi);
//模板匹配
serise_unm=temple_image(small_roi);
num123.push_back(serise_unm);
}
char groupOutput[300];
for (int t = 0; t < num123.size(); ++t)
{
cout << num123.at(t) << " ";
}
putText(bank_image, groupOutput, Point(srcRect2[i].x, srcRect2[i].y - 20),
FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2);
show("putText", bank_image);
num123.clear();
}
其他的辅助函数
void show(string name, Mat img)//显示函数
{
imshow(name, img);
waitKey(0);
destroyAllWindows();
}
void sorted_image(vector<Rect>&img, unsigned int n)//轮廓排序
{
Rect temp;
bool flage;
for (unsigned int i = 0; i < n - 1; ++i)
{
flage = false;
for (unsigned int j = 0; j < n - i - 1; ++j)
{
if (img[j].x > img[j + 1].x)
{
temp = img[j]; img[j] = img[j + 1]; img[j + 1] = temp;
flage = true;
}
}
if (flage)
{
flage = false;
for (unsigned int t = n - i - 2; t > 0; t--)
{
if (img[t-1].x > img[t].x)
{
temp = img[t-1]; img[t-1] = img[t]; img[t] = temp;
flage = true;
}
}
}
if (flage == false) { break; }
}
}
Mat substract(Mat &src, Mat&dst)//两幅图像相减
{
int sum = 0; Mat result = Mat::zeros(src.rows, src.cols, CV_8UC1);
for (int i = 0; i < src.rows; ++i)
{
uchar *data1 = src.ptr<uchar>(i);
uchar*data2 = dst.ptr<uchar>(i);
uchar*data3 = result.ptr<uchar>(i);
for (int j = 0; j < src.cols; ++j)
{
data3[j] = abs(data1[j] - data2[j]);
}
}
return result;
}
int get_One(Mat image)
{
threshold(image, image, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU);
int sum_one = 0;
for (int i = 0; i < image.rows; ++i)
{
uchar*data = image.ptr<uchar>(i);
for (int j = 0; j < image.cols; ++j)
{
if (data[j] > 0) { sum_one += 1; }
}
}return sum_one;
}
//-----------------------------------------------------
int temple_image(Mat img)//模板匹配
{
Mat src_image; int temp = 0; float sum = 0; float max = 200000000; int seriesNum = 0;
float c = 0.0; float n1 = 0.0; float n2 = 0.0; Mat result;
for (int i = 0; i < 10; ++i)
{
char name[520];
sprintf_s(name, "C:\\Users\\clg2021\\Desktop\\temple\\%d.jpg", i);
src_image = imread(name);
if (!src_image.data) { cout << "failed to read" << endl; system("pause"); }
//n2 = get_One(img)+get_One(src_image);
//n1=substract(img, src_image);
//c = n1 / n2;
result = substract(img, src_image);
c = get_One(result);
if (c < max) {
max = c; seriesNum
= i;
}
}
return seriesNum;
}