1、主程序
#include "utility.h"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat srcImage; // 待测图像
Mat templImage; // 匹配模板
// 【1】载入待测图片,模板
srcImage = imread("../images/n004.png", CV_LOAD_IMAGE_GRAYSCALE);
templImage = imread("../images/template/t0.png", CV_LOAD_IMAGE_GRAYSCALE);
double time0 = static_cast<double>(getTickCount());
// 【2】预处理
Mat sizeImage;
sizeImage = srcImage(Rect(0, 300, srcImage.size().width, srcImage.size().height - 500));
Mat filterImage;
blur(sizeImage, sizeImage, Size(3, 3));
Canny(sizeImage, filterImage, 100, 100 * 2, 3);
// 【3】图像校正
vector<Vec2f> lines; // 存放线段的矢量集合
HoughLines(filterImage, lines, 1, CV_PI / 180, 300, 0, 0);
double theta = lines[0][1] * 180 / CV_PI - 90.0;
Mat rotaImage = Mat::zeros(sizeImage.size(), CV_8UC1);
rotateImage(sizeImage, rotaImage, theta);
// 【4】匹配模块
Mat dstImage = Mat::zeros(templImage.size(), templImage.type());
inspectLabel(rotaImage, templImage, dstImage);
time0 = ((double)getTickCount() - time0) / getTickFrequency();
cout<< "Time: "<< time0 << "s" << endl;
//imshow("【1】模板", templImage);
imshow("【3】结果", dstImage);
waitKey(0);
return 0;
}
2、逆时针旋转图像角度
#include "utility.h"
using namespace cv;
using namespace std;
// 逆时针旋转图像角度(原尺寸)
void rotateImage(InputArray srcImage, OutputArray dstImage, double angle)
{
int rowNumber = srcImage.size().height;
int colNumber = srcImage.size().width;
// 旋转中心为图像中心
CvPoint2D32f center;
center.x = float(colNumber / 2.0);
center.y = float(rowNumber / 2.0);
// 计算二维旋转的仿射变换矩阵
Mat rotmat = getRotationMatrix2D(center, angle, 1);
// 变换图像,并用黑色填充其余值
warpAffine(srcImage, dstImage, rotmat, srcImage.size(), CV_INTER_CUBIC);
}
3、nspectLabel
#include "utility.h"
using namespace cv;
using namespace std;
void inspectLabel(Mat& srcImage, Mat& templImage, Mat& dstImage)
{
// 【1】匹配模块
Mat matchImage = Mat::zeros(templImage.size(), templImage.type());
matchingTempl(srcImage, templImage, matchImage);
// 【2】差分
Mat resultImage;
resultImage = abs(matchImage - templImage);
// 【3】去轮廓伪影
Mat morTempImage;
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(templImage, morTempImage, MORPH_GRADIENT, element);
Mat morSrcImage;
morphologyEx(matchImage, morSrcImage, MORPH_GRADIENT, element);
Mat noiseImage;
noiseImage = morSrcImage & morTempImage;
element = getStructuringElement(MORPH_RECT, Size(5, 5));
morphologyEx(noiseImage, noiseImage, MORPH_DILATE, element);
Mat maskImage;
threshold(noiseImage, maskImage, 200, 255, THRESH_BINARY + THRESH_OTSU);
seqMask(resultImage, maskImage);
// 【4】阈值
threshold(resultImage, dstImage, 55, 255, THRESH_BINARY);
}
4、匹配和标准化
#include "utility.h"
using namespace cv;
using namespace std;
void matchingTempl(Mat& srcImage, Mat& templImage, Mat& dstImage)
{
// 创建输出结果的矩阵
Mat resultImage;
int result_cols = srcImage.cols - templImage.cols + 1;
int result_rows = srcImage.rows - templImage.rows + 1;
resultImage.create(result_cols, result_rows, CV_32FC1);
// 进行匹配和标准化
matchTemplate(srcImage, templImage, resultImage, TM_CCOEFF);
normalize(resultImage, resultImage, 0, 1, NORM_MINMAX, -1, Mat());
// 通过函数 minMaxLoc 定位最匹配的位置
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc(resultImage, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
matchLoc = maxLoc;
Mat matchImage;
matchImage = srcImage(Rect(matchLoc, templImage.size()));
matchImage.copyTo(dstImage);
}