OpenCV实现多角度多尺度模板匹配(基于形状)

89 篇文章 88 订阅 ¥69.90 ¥99.00

1 前言

模板匹配最终输出搜索图像的位置,匹配尺度,匹配角度。下面是Shiju PK开源出来的基于OpenCV实现的代码,如下:

Edge-Based-Template-Matching

运行效果:

模板图像:

匹配效果:

 

 本文末将提供win10 64位 + VS2015 + OpenCV4.5.1版本的代码实现,代码亲测可编译运行。

2 多角度,多尺度的形状匹配原理


1.根据原始模板图像生成多个模板并特征提取、存储

多角度变换模板图像(旋转)并进行特征提取,再对各个多角度变

  • 2
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
OpenCV提供了多种图像匹配算法,其中包括多尺度模板匹配(Multi-Scale Template Matching)算法。下面介绍如何使用Java实现多角度多尺度模板匹配。 1. 导入OpenCV库 首先需要导入OpenCV库,可以在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.openpnp</groupId> <artifactId>opencv</artifactId> <version>3.4.1-1</version> </dependency> ``` 2. 加载图像 使用OpenCV的Java API,可以通过以下代码加载待匹配的图像和模板图像: ```java // 加载待匹配的图像和模板图像 Mat img = Imgcodecs.imread("image.jpg"); Mat template = Imgcodecs.imread("template.jpg"); ``` 其中,`Imgcodecs`是OpenCV提供的用于读写图像的类。 3. 多角度匹配 为了实现多角度匹配,可以对模板图像进行旋转,然后在旋转后的图像上进行匹配。以下是旋转图像的代码: ```java // 旋转图像 Mat rotate(Mat src, double angle) { Point center = new Point(src.cols() / 2, src.rows() / 2); Mat rotMat = Imgproc.getRotationMatrix2D(center, angle, 1.0); Mat dst = new Mat(); Imgproc.warpAffine(src, dst, rotMat, src.size()); return dst; } ``` 其中,`src`是待旋转的图像,`angle`是旋转角度。 接下来,在旋转后的图像上进行匹配,可以得到每个匹配结果的位置和得分。以下是代码: ```java double minScore = 0.8; // 最小匹配得分 double maxScore = 0.0; // 最大匹配得分 Point maxLoc = null; // 最大匹配得分的位置 double angleStep = 10.0; // 旋转角度步长 double angleStart = 0.0; // 起始旋转角度 double angleEnd = 360.0; // 终止旋转角度 double angle = angleStart; // 当前旋转角度 while (angle <= angleEnd) { // 旋转模板图像 Mat rotatedTemplate = rotate(template, angle); // 多尺度匹配 Mat result = new Mat(); Imgproc.matchTemplate(img, rotatedTemplate, result, Imgproc.TM_CCOEFF_NORMED); Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1); // 找到最大匹配得分和位置 Core.MinMaxLocResult mmr = Core.minMaxLoc(result); double score = mmr.maxVal; if (score >= minScore && score > maxScore) { maxScore = score; maxLoc = mmr.maxLoc; } // 更新旋转角度 angle += angleStep; } ``` 在上述代码中,`minScore`是最小匹配得分,如果匹配得分低于这个值,则认为没有匹配成功。`angleStep`是旋转角度步长,`angleStart`和`angleEnd`分别是旋转角度的起始值和终止值。在每次旋转后,使用`Imgproc.matchTemplate`函数进行多尺度匹配,找到最大匹配得分和位置,然后更新旋转角度。最终得到的`maxLoc`就是最大匹配得分的位置。 4. 显示匹配结果 最后,可以在原图像上标记匹配结果。以下是代码: ```java // 在原图像上标记匹配结果 if (maxLoc != null) { Point topLeft = new Point(maxLoc.x, maxLoc.y); Point bottomRight = new Point(topLeft.x + template.cols(), topLeft.y + template.rows()); Imgproc.rectangle(img, topLeft, bottomRight, new Scalar(0, 0, 255), 2); } // 显示匹配结果 HighGui.imshow("Result", img); HighGui.waitKey(); ``` 在上述代码中,如果找到了匹配结果,则使用`Imgproc.rectangle`函数在原图像上画出匹配框。最后,使用`HighGui.imshow`函数显示匹配结果。 完整代码如下: ```java import org.opencv.core.Core; import org.opencv.core.Core.MinMaxLocResult; import org.opencv.core.Mat; import org.opencv.core.Point; import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.highgui.HighGui; public class MultiScaleTemplateMatching { // 旋转图像 static Mat rotate(Mat src, double angle) { Point center = new Point(src.cols() / 2, src.rows() / 2); Mat rotMat = Imgproc.getRotationMatrix2D(center, angle, 1.0); Mat dst = new Mat(); Imgproc.warpAffine(src, dst, rotMat, src.size()); return dst; } public static void main(String[] args) { // 加载待匹配的图像和模板图像 Mat img = Imgcodecs.imread("image.jpg"); Mat template = Imgcodecs.imread("template.jpg"); double minScore = 0.8; // 最小匹配得分 double maxScore = 0.0; // 最大匹配得分 Point maxLoc = null; // 最大匹配得分的位置 double angleStep = 10.0; // 旋转角度步长 double angleStart = 0.0; // 起始旋转角度 double angleEnd = 360.0; // 终止旋转角度 double angle = angleStart; // 当前旋转角度 while (angle <= angleEnd) { // 旋转模板图像 Mat rotatedTemplate = rotate(template, angle); // 多尺度匹配 Mat result = new Mat(); Imgproc.matchTemplate(img, rotatedTemplate, result, Imgproc.TM_CCOEFF_NORMED); Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1); // 找到最大匹配得分和位置 MinMaxLocResult mmr = Core.minMaxLoc(result); double score = mmr.maxVal; if (score >= minScore && score > maxScore) { maxScore = score; maxLoc = mmr.maxLoc; } // 更新旋转角度 angle += angleStep; } // 在原图像上标记匹配结果 if (maxLoc != null) { Point topLeft = new Point(maxLoc.x, maxLoc.y); Point bottomRight = new Point(topLeft.x + template.cols(), topLeft.y + template.rows()); Imgproc.rectangle(img, topLeft, bottomRight, new Scalar(0, 0, 255), 2); } // 显示匹配结果 HighGui.imshow("Result", img); HighGui.waitKey(); } } ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

thequitesunshine007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值