使用openCV比对任意两张图片的相似度(亲测较准确)

方案:使用openCV中的直方图算法做对比。测试效果较好。

步骤(在java中使用openCV):

1.引入openCV的依赖

      <!-- https://mvnrepository.com/artifact/org.openimaj/core -->
        <dependency>
            <groupId>org.openpnp</groupId>
            <artifactId>opencv</artifactId>
            <version>4.5.5-1</version>
        </dependency>

2.代码

代码中提供了均方差算法(MSE)、结构相似性指数算法(SSIM)、峰值信噪比(PSNR)、直方图算法。其中直方图效果最好

package com.angus.temp;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;
import java.util.List;
/**
 * @author angus
 * @version 1.0.0
 * @Description
 * @createTime 2023年06月01日 19:15:00
 */
public class OpenCVImageSimilarity {
    public static void main(String[] args) {
        // 加载OpenCV库
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // 读取两张图像。准备比对的图片
        Mat image1 = Imgcodecs.imread("C:\\Users\\Pictures\\0009.jpg");
        Mat image2 = Imgcodecs.imread("C:\\Users\\Pictures\\0011.jpg");


        // 将图片处理成一样大
        Imgproc.resize(image1, image1, image2.size());
        Imgproc.resize(image2, image2, image1.size());

        // 计算均方差(MSE)
        double mse = calculateMSE(image1, image2);
        System.out.println("均方差(MSE): " + mse);

        // 计算结构相似性指数(SSIM)
        double ssim = calculateSSIM(image1, image2);
        System.out.println("结构相似性指数(SSIM): " + ssim);

        // 计算峰值信噪比(PSNR)
        double psnr = calculatePSNR(image1, image2);
        System.out.println("峰值信噪比(PSNR): " + psnr);

        // 计算直方图
        final double similarity = calculateHistogram(image1, image2);
        System.out.println("图片相似度(直方图): " + similarity);

        // 计算归一化交叉相关(NCC)
//        double ncc = calculateNCC(image1, image2);
//        System.out.println("归一化交叉相关(NCC): " + ncc);
    }

    // 计算均方差(MSE)
    private static double calculateHistogram(Mat image1, Mat image2) {
        // 计算直方图
        Mat hist1 = calculateHistogram(image1);
        Mat hist2 = calculateHistogram(image2);

        // 计算相似度
        final double similarity = Imgproc.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL);
        return similarity;
    }


    // 计算均方差(MSE)
    private static double calculateMSE(Mat image1, Mat image2) {
        Mat diff = new Mat();
        Core.absdiff(image1, image2, diff);
        Mat squaredDiff = new Mat();
        Core.multiply(diff, diff, squaredDiff);
        Scalar mseScalar = Core.mean(squaredDiff);
        return mseScalar.val[0];
    }

    // 计算结构相似性指数(SSIM)
    private static double calculateSSIM(Mat image1, Mat image2) {
        Mat image1Gray = new Mat();
        Mat image2Gray = new Mat();
        Imgproc.cvtColor(image1, image1Gray, Imgproc.COLOR_BGR2GRAY);
        Imgproc.cvtColor(image2, image2Gray, Imgproc.COLOR_BGR2GRAY);
        MatOfFloat ssimMat = new MatOfFloat();
        Imgproc.matchTemplate(image1Gray, image2Gray, ssimMat, Imgproc.CV_COMP_CORREL);
        Scalar ssimScalar = Core.mean(ssimMat);
        return ssimScalar.val[0];
    }

    // 计算峰值信噪比(PSNR)
    private static double calculatePSNR(Mat image1, Mat image2) {
        Mat diff = new Mat();
        Core.absdiff(image1, image2, diff);
        Mat squaredDiff = new Mat();
        Core.multiply(diff, diff, squaredDiff);
        Scalar mseScalar = Core.mean(squaredDiff);
        double mse = mseScalar.val[0];
        double psnr = 10.0 * Math.log10(255.0 * 255.0 / mse);
        return psnr;
    }

    // 计算归一化交叉相关(NCC)
//    private static double calculateNCC(Mat image1, Mat image2) {
//        Mat image1Gray = new Mat();
//        Mat image2Gray = new Mat();
//        Imgproc.cvtColor(image1, image1Gray, Imgproc.COLOR_BGR2GRAY);
//        Imgproc.cvtColor(image2, image2Gray, Imgproc.COLOR_BGR2GRAY);
//        MatOfInt histSize = new MatOfInt(256);
//        MatOfFloat ranges = new MatOfFloat(0, 256);
//        Mat hist1 = new Mat();
//        Mat hist2 = new Mat();
//
//        Core.normalize(hist1, hist1, 0, 1, Core.NORM_MINMAX);
//        Core.normalize(hist2, hist2, 0, 1, Core.NORM_MINMAX);
//        double ncc = Core.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL);
//        return ncc;
//    }

    private static Mat calculateHistogram(Mat image) {
        Mat hist = new Mat();

        // 设置直方图参数
        MatOfInt histSize = new MatOfInt(256);
        MatOfFloat ranges = new MatOfFloat(0, 256);
        MatOfInt channels = new MatOfInt(0);
        List<Mat> images = new ArrayList<>();
        images.add(image);

        // 计算直方图
        Imgproc.calcHist(images, channels, new Mat(), hist, histSize, ranges);

        return hist;
    }
}

3.会遇到一个问题

Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java455 in java.library.path

Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java455 in java.library.path: [C:\Program Files\Java\jdk-14.0.2\bin, C:\Windows\Sun\Java\bin, C:\Windows\system32, C:\Windows, C:\Windows\system32, C:\Windows, C:\Windows\System32\Wbem, C:\Windows\System32\WindowsPowerShell\v1.0\, C:\Windows\System32\OpenSSH\, D:\angus\soft\Xshell 7\, D:\angus\soft\Xftp 7\, C:\Program Files\Git\cmd, C:\Program Files\Java\jdk-14.0.2\bin, C:\Users\angus\AppData\Local\Microsoft\WindowsApps, ., D:\angus\soft\Microsoft VS Code\bin, .]
	at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2680)
	at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:807)
	at java.base/java.lang.System.loadLibrary(System.java:1907)
	at com.angus.easyes.temp.OpenCVImageSimilarity.main(OpenCVImageSimilarity.java:17)

5.运行效果

6.相似性效果对比

https://blog.csdn.net/star1210644725/article/details/131005052?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22131005052%22%2C%22source%22%3A%22star1210644725%22%7Dicon-default.png?t=N4P3https://blog.csdn.net/star1210644725/article/details/131005052?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22131005052%22%2C%22source%22%3A%22star1210644725%22%7D

  • 1
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
使用JavaOpenCV计算两张图片相似度,可以采用以下步骤: 1. 加载图片使用OpenCVJava接口,加载两张比较图片,可以使用Imgcodecs.imread方法读取图片。 2. 提取特征:使用OpenCV的FeatureDetector和DescriptorExtractor等类,对图片进行特征提取和描述。 3. 计算相似度使用OpenCV的DescriptorMatcher类,将提取的特征进行匹配,并计算相似度。 下面是一个简单的Java代码示例: ``` import org.opencv.core.*; import org.opencv.features2d.*; import org.opencv.imgcodecs.Imgcodecs; public class ImageMatcher { public static void main(String[] args) { // 加载图片 Mat img1 = Imgcodecs.imread("image1.jpg"); Mat img2 = Imgcodecs.imread("image2.jpg"); // 提取ORB特征 ORB orb = ORB.create(); MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); Mat descriptors1 = new Mat(); Mat descriptors2 = new Mat(); orb.detectAndCompute(img1, new Mat(), keypoints1, descriptors1); orb.detectAndCompute(img2, new Mat(), keypoints2, descriptors2); // 计算相似度 DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); MatOfDMatch matches = new MatOfDMatch(); matcher.match(descriptors1, descriptors2, matches); // 输出相似度 double maxDist = 0; double minDist = 100; DMatch[] matchArray = matches.toArray(); for (int i = 0; i < matchArray.length; i++) { double dist = matchArray[i].distance; if (dist < minDist) minDist = dist; if (dist > maxDist) maxDist = dist; } double similarity = (1 - minDist / maxDist) * 100; System.out.println("相似度:" + similarity + "%"); } } ``` 在这个例子中,我们使用OpenCV的ORB算法进行特征提取,使用了Hamming距离进行特征匹配,计算出了两张图片相似度。请注意,在实际应用中可能需要根据具体情况选择不同的算法和参数,以获得更准确的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值