在 Android 版本的 OpenCV 中,可以使用 matchTemplate 进行模板匹配(Template Matching)。下面是详细的步骤和示例代码:
步骤
- 引入 OpenCV
确保你的 Android 项目已经集成了 OpenCV,可以使用 OpenCV SDK 或者 OpenCV Android 绑定(OpenCV Android SDK)。
- 加载图像
目标图像(需要搜索的图像)和模板图像(要匹配的部分)。
- 模板匹配
使用 Imgproc.matchTemplate() 进行匹配。
- 获取匹配位置
通过 Core.minMaxLoc() 找到最佳匹配位置。
- 绘制匹配结果
在原图上绘制一个矩形框标记匹配位置。
示例代码
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
public class TemplateMatching {
public static Bitmap matchTemplate(Bitmap sourceBitmap, Bitmap templateBitmap) {
// 将 Bitmap 转换为 Mat
Mat sourceMat = new Mat();
Mat templateMat = new Mat();
Utils.bitmapToMat(sourceBitmap, sourceMat);
Utils.bitmapToMat(templateBitmap, templateMat);
// 创建存放匹配结果的 Mat
int resultCols = sourceMat.cols() - templateMat.cols() + 1;
int resultRows = sourceMat.rows() - templateMat.rows() + 1;
Mat result = new Mat(resultRows, resultCols, CvType.CV_32FC1);
// 进行模板匹配 (TM_CCOEFF_NORMED 是常用的一种)
Imgproc.matchTemplate(sourceMat, templateMat, result, Imgproc.TM_CCOEFF_NORMED);
// 获取最佳匹配位置
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
Point matchLoc = mmr.maxLoc; // maxLoc 对应 TM_CCOEFF_NORMED
// 在原图上绘制匹配位置
Imgproc.rectangle(sourceMat, matchLoc,
new Point(matchLoc.x + templateMat.cols(), matchLoc.y + templateMat.rows()),
new Scalar(0, 255, 0), 3);
// 转换回 Bitmap 以便显示
Bitmap outputBitmap = Bitmap.createBitmap(sourceMat.cols(), sourceMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(sourceMat, outputBitmap);
return outputBitmap;
}
}
关键点解析
- 匹配方法选择(Imgproc.matchTemplate)
• Imgproc.TM_CCOEFF_NORMED(推荐,归一化互相关系数)
• Imgproc.TM_SQDIFF(平方差)
• Imgproc.TM_CCORR(相关性)
• Imgproc.TM_CCORR_NORMED(归一化相关性)
• Imgproc.TM_SQDIFF_NORMED(归一化平方差)
一般建议使用 TM_CCOEFF_NORMED,因为它对光照变化影响较小。
- Core.minMaxLoc(result) 解析
• minLoc 和 maxLoc 返回的是匹配值最小和最大的像素坐标。
• TM_CCOEFF_NORMED 选择 maxLoc 作为匹配点。
• TM_SQDIFF 选择 minLoc 作为匹配点。
- 绘制匹配框
• Imgproc.rectangle() 用于在匹配区域画矩形框。
在 Android 上使用 OpenCV
如果你还没有集成 OpenCV,可以按照以下步骤:
- 添加 OpenCV 依赖
• 在 app/build.gradle 中添加:
implementation 'org.opencv:opencv-android:4.5.1'
• 或者使用 OpenCV SDK,并在 CMakeLists.txt 或 gradle 中手动配置。
- 在 MainActivity.java 中初始化 OpenCV
import org.opencv.android.OpenCVLoader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!OpenCVLoader.initDebug()) {
Log.e("OpenCV", "OpenCV 初始化失败!");
} else {
Log.d("OpenCV", "OpenCV 初始化成功!");
}
}
总结
• Imgproc.matchTemplate() 是 OpenCV 提供的标准模板匹配方法,适用于静态目标匹配。
• 使用 Core.minMaxLoc() 找到最佳匹配位置。
• TM_CCOEFF_NORMED 是最常用的匹配方法。
• 适用于简单的匹配任务,不适用于旋转、缩放等复杂情况(可以使用特征匹配如 SIFT/SURF/ORB 进行改进)。
如果你需要更高级的匹配(例如旋转/缩放不变),可以考虑 ORB/SIFT/SURF 特征匹配。