#include<iostream>
#include<opencv2/opencv.hpp>
//#include<cv.h>
#include<ctime>
using namespace cv;
using namespace std;
//ROI区域的位置信息
#define xx 100//300// //横坐标
#define yy 100//80//240// //纵坐标
#define zz 300//400// //正方形ROI区域的边长
#define PI 3.14159267989
#define ModelPATH "..\\ConsoleApplication1\\picture\\my Logo.bmp"//模板图像路径
#define SearchPATH "..\\ConsoleApplication1\\picture\\my Logo.bmp"//待检测图像路径
int nThresh = 80;//二值化处理的控制阈值,最大值为255
//图片旋转函数
void imrotate(Mat &img, Mat &newIm, double angle)//img:输入图片;newIm:输出图片;angle:旋转角度(°)
{
//int len = max((img.cols), (img.rows));
//Point2f pt(len / 2.0, len / 2.0);
//Mat r = getRotationMatrix2D(pt, angle, 1.0);
//warpAffine(img, newIm, r, Size(len, len));
//better performance :
Point2f pt(img.cols / 2., img.rows / 2.);
Mat r = getRotationMatrix2D(pt, angle, 1.0);
warpAffine(img, newIm, r, img.size());
}
//取圆形ROI区域函数:具体实现功能为输入原图,取原图最大可能的原型区域输出
Mat circle_tr(Mat src)
{
Mat dst = Mat::zeros(src.size(), src.type());
Mat mask = Mat::zeros(src.size(), CV_8U);
Point circleCenter(mask.cols / 2, mask.rows / 2);
int radius = min(mask.cols, mask.rows) / 2;
circle(mask, circleCenter, radius, Scalar(255), -1);
src.copyTo(dst, mask);
return dst;
}
//旋转匹配函数(输入参数分别为匹配区域的左上角坐标、匹配角度、模板图像的ROI区域、待匹配图像)
void RatationMatch(Point &location, double &angle, Mat modelpicture, Mat searchpicture)
{
Mat modeltmp, searchtmp;
//对模板ROI区域和待检测图像分别进行三层图像金字塔下采样
pyrDown(modelpicture, modeltmp, Size(modelpicture.cols / 2, modelpicture.rows / 2));
pyrDown(searchpicture, searchtmp, Size(searchpicture.cols / 2, searchpicture.rows / 2));
pyrDown(modeltmp, modeltmp, Size(modeltmp.cols / 2, modeltmp.rows / 2));
pyrDown(searchtmp, searchtmp, Size(searchtmp.cols / 2, searchtmp.rows / 2));
pyrDown(modeltmp, modeltmp, Size(modeltmp.cols / 2, modeltmp.rows / 2));
pyrDown(searchtmp, searchtmp, Size(searchtmp.cols / 2, searchtmp.rows / 2));
Mat newIm;//临时储存每个旋转角度对应的图片
//定义图片匹配所需要的参数
int result_cols = searchtmp.cols - modeltmp.cols;
int result_rows = searchtmp.rows - modeltmp.rows;
Mat result = Mat(result_cols, result_rows, CV_32FC1);
double minVal, maxVal, temp;//minVal:当前匹配计算的最小值
Point minLoc, maxLoc, matchLoc1;//minLoc:当前最佳匹配区域的左上角坐标
//在没有旋转的情况下进行第一次匹配计算
newIm = circle_tr(modeltmp);
matchTemplate(searchtmp, newIm, result, CV_TM_SQDIFF);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
location = minLoc;
temp = minVal;
angle = 0;//当前旋转角度记录为0
//以步长为5进行第一次粗循环匹配
for (int i = -20; i < 21; i = i + 5)
{
double start = (double)clock();
imrotate(modeltmp, newIm, i);
newIm = circle_tr(newIm);
matchTemplate(searchtmp, newIm, result, CV_TM_SQDIFF);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
double finish = (double)clock();
if (minVal < temp)
{
location = minLoc;
temp = minVal;
angle = i;
}
cout << minVal << " " << temp << " " << finish - start << endl;
}
//在当前最优匹配角度周围10的区间以1为步长循环进行循环匹配计算
for (int j = angle - 5; j < angle + 6; j++)
{
imrotate(modeltmp, newIm, j);
newIm = circle_tr(newIm);
matchTemplate(searchtmp, newIm, result, CV_TM_SQDIFF);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (minVal < temp)
{
location = minLoc;
temp = minVal;
angle = j;
}
cout << minVal << " " << temp << endl;
}
//在当前最优匹配角度周围2的区间以0.1为步长进行循环匹配计算
double k_angle = angle - 0.9;
for (int k = 0; k < 19; k = k + 1)
{
k_angle = k_angle + 0.1;
imrotate(modeltmp, newIm, k_angle);
newIm = circle_tr(newIm);
matchTemplate(searchtmp, newIm, result, CV_TM_SQDIFF);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (minVal < temp)
{
location = minLoc;
temp = minVal;
angle = k_angle;;
}
cout << minVal << " " << temp << endl;
}
//用下采样前的图片来进行精匹配计算
result_cols = searchpicture.cols - modelpicture.cols;
result_rows = searchpicture.rows - modelpicture.rows;
result = Mat(result_cols, result_rows, CV_32FC1);
k_angle = angle - 0.1;
imrotate(modelpicture, newIm, k_angle);
newIm = circle_tr(newIm);
matchTemplate(searchpicture, newIm, result, CV_TM_SQDIFF);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
location = minLoc;
temp = minVal;
angle = k_angle;
for (int k = 1; k < 3; k = k + 1)
{
k_angle = k_angle + 0.1;
imrotate(modelpicture, newIm, k_angle);
newIm = circle_tr(newIm);
matchTemplate(searchpicture, newIm, result, CV_TM_SQDIFF);
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (minVal < temp)
{
location = minLoc;
temp = minVal;
angle = k_angle;;
}
cout << minVal << " " << temp << endl;
}
location.x = location.x+50;
location.y = location.y+50;
//前面得到的是在待检测图片中的匹配区间的左上角坐标,下面将这个坐标换算到待检测图片旋转后的坐标中
int tmpx, tmpy;
tmpx = (zz / 2)*(1 - cos(angle*PI / 180) - sin(angle*PI / 180));
tmpy = (zz / 2)*(1 - cos(angle*PI / 180) + sin(angle*PI / 180));
location.x = location.x + tmpx;
location.y = location.y + tmpy;
//前面得到的旋转角度是匹配时模板图像旋转的角度,后面需要的角度值是待检测图像应该旋转的角度值,故需要做相反数变换
angle = -angle;
}
int main()
{
//读入模板图像
Mat ModelImage = imread(ModelPATH);
//将图片缩放到合适的大小(这一步是因为笔记本屏幕比较小才进行的)
//resize(ModelImage, ModelImage, Size((ModelImage.cols) / 2, (ModelImage.rows) / 2));
//显示模板图像
cout << "显示模板图像" << endl;
imshow("模板图像", ModelImage);
waitKey(0);
//定义ROI区域(起始点横坐标,纵坐标,长度,宽度)
Mat ROIPart = ModelImage(Rect(xx, yy, zz, zz));
//将ROI区域标记为蓝色
for (int i = 0; i < ROIPart.rows; i++)
{
for (int j = 0; j < ROIPart.cols; j++)
{
ROIPart.at<Vec3b>(i, j)[0] = 255;
}
}
cout << "选择ROI区域" << endl;
imshow("模板图像", ModelImage);
waitKey(0);
//重新读入模板图像并进行边缘提取处理
ModelImage = imread(ModelPATH);
//resize(ModelImage, ModelImage, Size((ModelImage.cols) / 2, (ModelImage.rows) / 2));//将图片缩放到合适的比例
//高斯滤波
GaussianBlur(ModelImage, ModelImage, Size(5, 5), 0, 0, BORDER_DEFAULT);
//边缘提取
Mat ModelImage_edge = Mat(ModelImage);
Canny(ModelImage, ModelImage_edge, 15, 100, 3);
//定义边缘提取后的模板图像上的ROI区域
ROIPart = ModelImage_edge(Rect(xx, yy, zz, zz));//定义ROI区域(起始点横坐标,纵坐标,长度,宽度)
//显示形状模板
destroyWindow("模板图像");
cout << "形状模板" << endl;
imshow("形状模板", ROIPart);
waitKey(0);
//读入待检测图像
Mat SearchImage = imread(SearchPATH);
//resize(SearchImage, SearchImage, Size((SearchImage.cols) / 2, (SearchImage.rows) / 2));//将图片缩放到合适的比例
//高斯滤波
GaussianBlur(SearchImage, SearchImage, Size(5, 5), 0, 0, BORDER_DEFAULT);
//显示待检测图片
destroyWindow("形状模板");
cout << "检测图像" << endl;
imshow("检测图像", SearchImage);
waitKey(0);
//待检测图像做边缘提取
Mat SearchImage_edge = Mat(SearchImage);
Canny(SearchImage, SearchImage_edge, 10, 100, 3);
//取待检测图像边缘的一部分来进行匹配以加快匹配速度
Mat serch_ROIPart = SearchImage_edge(Rect(50, 50, SearchImage_edge.cols - 100, SearchImage_edge.rows-100));
//显示待检测图片边缘提取后的结果
waitKey(0);
//用ROI区域做匹配,找到在检测图像中的匹配坐标location
double angle;
Point location;
double start = (double)clock();
RatationMatch(location, angle,ROIPart,serch_ROIPart );
double finish = (double)clock();
cout<<"匹配所花时间为:"<< finish - start << endl;
cout << "匹配的最优区域的起点坐标为:(" << location.x <<
没有合适的资源?快使用搜索试试~ 我知道了~
基于OpenCV的的图像旋转匹配算法模板(C++实现)
共30个文件
obj:8个
tlog:6个
pdb:2个
1星 需积分: 41 356 下载量 132 浏览量
2020-01-02
16:59:43
上传
评论 46
收藏 7.52MB ZIP 举报
温馨提示
1.基于OpenCv的旋转匹配 基于OpenCv实现了模板图像的旋转匹配,此代码基于matchTemplate函数封装实现可以得知旋转角度的模板匹配(vs2013+opencv2.4.9) 2.带旋转的模板匹配的原理及算法实现(c++) 带旋转的模板匹配算法,能够匹配带旋转角度的模板。(VS 2015+OPENCV C++)
资源推荐
资源详情
资源评论
收起资源包目录
基于OpenCV的的图像旋转匹配算法模板(C++实现).zip (30个子文件)
基于OpenCV的的图像旋转匹配算法模板(C++实现)
Match.cpp 8KB
基于Opencv实现的旋转匹配
ConsoleApplication1.v12.suo 40KB
ConsoleApplication1
picture
my Logo.jpg 41KB
my Logo.bmp 1.17MB
ConsoleApplication1.vcxproj 4KB
Debug
vc120.pdb 1.79MB
RotationMatch.obj 265KB
On_TreshChange.obj 348KB
GetArea.obj 332KB
Gauss_test.obj 222KB
ConsoleA.7D2ACBDB.tlog
CL.write.1.tlog 9KB
CL.read.1.tlog 205KB
cl.command.1.tlog 9KB
link.write.1.tlog 2KB
link.command.1.tlog 15KB
link.read.1.tlog 15KB
ConsoleApplication1.lastbuildstate 230B
vc120.idb 1.74MB
源.obj 304KB
Match.obj 286KB
ConsoleApplication1.log 4KB
imageRatation.obj 258KB
multi_ROI.obj 334KB
Match.cpp 8KB
ConsoleApplication1.vcxproj.filters 946B
ConsoleApplication1.sdf 13.44MB
ConsoleApplication1.sln 1003B
Debug
ConsoleApplication1.exe 92KB
ConsoleApplication1.pdb 3.78MB
ConsoleApplication1.ilk 776KB
共 30 条
- 1
资源评论
- 思不凉2021-04-23与这里的https://blog.csdn.net/iamqianrenzhan/article/details/105040587里面一模一样,连个标点符号的不带差的
- 伍粟2022-03-04好垃圾的代码,替换图片就没办法检测了
- 逆_流2022-05-03水得一匹。
伤感666
- 粉丝: 86
- 资源: 108
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功