如何使用Java和OpenCV进行模板匹配,识别和裁剪出手指图像。

116 阅读2分钟

首先,我们需要在计算机上安装OpenCV,并且配置Java项目以便能够正确加载OpenCV库文件。接下来,我们将使用Java的Imgcodecs类来加载图像并将其转换为OpenCV的Mat对象。

Mat bigMat = Imgcodecs.imread(big);
Mat templateMat = Imgcodecs.imread(small);

之后,我们需要选择合适的模板匹配方法,这里我们使用了TM_CCORR_NORMED方法。然后,根据大图像和模板图像的尺寸,创建结果矩阵result

int method = Imgproc.TM_CCORR_NORMED;
int width = bigMat.cols() - templateMat.cols() + 1;
int height = bigMat.rows() - templateMat.rows() + 1;
Mat result = new Mat(width, height, CvType.CV_32FC1);

接下来,我们使用Imgproc.matchTemplate()方法执行模板匹配,并对结果矩阵进行归一化处理:

Imgproc.matchTemplate(bigMat, templateMat, result, method);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());

通过调用Core.minMaxLoc()方法,我们可以找到结果矩阵中最佳匹配的位置:

Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
Point point = (method == Imgproc.TM_SQDIFF_NORMED || method == Imgproc.TM_SQDIFF) ? mmr.minLoc : mmr.maxLoc;

如果你只是想要找到匹配位置并将其显示在大图像上。

Imgproc.rectangle(bigMat, new Rect((int) point.x, (int) point.y, templateMat.cols(), templateMat.rows()), new Scalar(0, 255, 0));
MatKit.showImage(bigMat);

匹配区域裁剪并保存。

Mat croppedMat = new Mat(bigMat, new Rect((int) point.x, (int) point.y, templateMat.cols(), templateMat.rows()));
Imgcodecs.imwrite("D://cropped_image.jpg", croppedMat);
Mat palmMat = Imgcodecs.imread(palmImage);
Mat fingerMat = Imgcodecs.imread(fingerImage);

然后,我们设置模板匹配的方法、计算结果矩阵的宽度和高度,并执行模板匹配:

int method = Imgproc.TM_CCORR_NORMED;
int width = palmMat.cols() - fingerMat.cols() + 1;
int height = palmMat.rows() - fingerMat.rows() + 1;
Mat result = new Mat(width, height, CvType.CV_32FC1);
Imgproc.matchTemplate(palmMat, fingerMat, result, method);

我们对结果矩阵进行归一化处理,并找到最佳匹配的位置:

Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
Point point = (method == Imgproc.TM_SQDIFF_NORMED || method == Imgproc.TM_SQDIFF) ? mmr.minLoc : mmr.maxLoc;

最后,我们从手掌图像中裁剪出五个手指,并将它们保存到一个List<Mat>中,并将裁剪出的手指图像保存

List<Mat> croppedFingers = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    int fingerX = (int) point.x + (i * (fingerMat.cols() / 5));
    Mat croppedFingerMat = new Mat(palmMat, new Rect(fingerX, (int) point.y, fingerMat.cols() / 5, fingerMat.rows()));
    croppedFingers.add(croppedFingerMat);
    Imgcodecs.imwrite("D://cropped_finger_" + (i + 1) + ".jpg", croppedFingerMat);
}

如果你只想裁剪出手掌图像中的五个手指,而不是通过模板匹配找到它们,可以使用以下代码:

Mat palmMat = Imgcodecs.imread(palmImage);
int fingerWidth = palmMat.cols() / 5;
int fingerHeight = palmMat.rows();
for (int i = 0; i < 5; i++) {
    int fingerX = i * fingerWidth;
    Mat croppedFingerMat = new Mat(palmMat, new Rect(fingerX, 0, fingerWidth, fingerHeight));
    croppedFingers.add(croppedFingerMat);
    Imgcodecs.imwrite("D://cropped_finger_" + (i + 1) + ".jpg", croppedFingerMat);
}