首页 > 编程语言 >使用Java语言 利用OpenCV,对两种图片相似度对比

使用Java语言 利用OpenCV,对两种图片相似度对比

时间:2023-10-23 19:32:31浏览次数:45  
标签:Imgproc Java Mat double OpenCV image2 new image1 对比

下边是代码部分

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.opencv.features2d.*;
import org.opencv.core.MatOfDMatch;
import org.opencv.core.DMatch;

public class OpenCVImageSimilarity {

public static void main(String[] args) throws IOException {

// 加载OpenCV库

// 读取两张图像。准备比对的图片
System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 加载OpenCV库NATIVE_LIBRARY_NAME
String imageUrl1 = "https://img/0b653e8b-d306-4e15-8e64-4d2212a7434b.jpg";
String imageUrl2 = "https://img/98845b33-0237-45a1-a91d-714d6aba0c3c.jpg";

Mat image1 = readImageFromUrl(imageUrl1); // 调用方法读取网络图片
Mat image2 = readImageFromUrl(imageUrl2); double rdb=rdbSimilar(image1,image2);
double hash= meanHash(image1, image2);
double hist= histogram(image1, image2);
double result=(rdb+hash+hist)/ 3;
System.out.println("RDB相似度:" +rdb );
System.out.println("均值哈希算法计算相似度:"+hash);
System.out.println("图片相似度(直方图): " + hist);

/* if (image1 != null) {
// 图片读取成功,可以进行后续处理或保存
// 这里只是示例将图片保存到本地
String outputPath = "output.jpg";
Imgcodecs.imwrite(outputPath, image1);
System.out.println("图片保存成功: " + outputPath);
} else {
System.out.println("图片读取失败");
}*/
// 将图片处理成一样大

// 计算归一化交叉相关(NCC)
// double ncc = calculateNCC(image1, image2);
// System.out.println("归一化交叉相关(NCC): " + ncc);
}
private static Mat readImageFromUrl(String imageUrl) {
Mat image = null;
try {
// 使用URL类打开网络图片的输入流
URL url = new URL(imageUrl);
BufferedInputStream inputStream = new BufferedInputStream(url.openStream());

// 将输入流解码为OpenCV的Mat对象
byte[] imageData = inputStream.readAllBytes();
image = Imgcodecs.imdecode(new MatOfByte(imageData), Imgcodecs.IMREAD_COLOR);
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
static double histogram(Mat image1, Mat image2){
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);
return similarity;

}

// 计算均方差(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 images = new ArrayList<>();
images.add(image);

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

return hist;
}
static double rdbSimilar(Mat img1, Mat img2){
// 加载OpenCV库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

// 读取两张图片
/* Mat img1 = Imgcodecs.imread("path/to/your/image1.jpg");
Mat img2 = Imgcodecs.imread("path/to/your/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 v = 1 - minDist / maxDist;
//System.out.println("最小距离:" + minDist);
// System.out.println("最大距离:" + maxDist);
// System.out.println("RDB相似度:" +v );
return v;
}

static double meanHash(Mat img1, Mat img2){
Mat grayImg1 = new Mat();
Mat grayImg2 = new Mat();
Imgproc.cvtColor(img1, grayImg1, Imgproc.COLOR_BGR2GRAY);
Imgproc.cvtColor(img2, grayImg2, Imgproc.COLOR_BGR2GRAY);
// 缩放图像至固定大小
Size targetSize = new Size(8, 8);
Mat resizedImg1 = new Mat();
Mat resizedImg2 = new Mat();
Imgproc.resize(grayImg1, resizedImg1, targetSize);
Imgproc.resize(grayImg2, resizedImg2, targetSize);

// 计算均值哈希值
String hash1 = calculateMeanHash(resizedImg1);
String hash2 = calculateMeanHash(resizedImg2);

// 计算汉明距离并计算相似度
int hammingDistance = calculateHammingDistance(hash1, hash2);
double similarity = 1 - (double) hammingDistance / (targetSize.width * targetSize.height);

return similarity;
}

private static String calculateMeanHash(Mat image) {
double sum = 0;
int totalPixels = image.rows() * image.cols();

for (int i = 0; i < image.rows(); i++) {
for (int j = 0; j < image.cols(); j++) {
double pixelValue = image.get(i, j)[0];
sum += pixelValue;
}
}

double mean = sum / totalPixels;
StringBuilder hash = new StringBuilder();

for (int i = 0; i < image.rows(); i++) {
for (int j = 0; j < image.cols(); j++) {
double pixelValue = image.get(i, j)[0];
if (pixelValue >= mean) {
hash.append("1");
} else {
hash.append("0");
}
}
}

return hash.toString();
}

public static int hammingDistance2(int hash1, int hash2){

int num = hash1 ^ hash2;

int count = 0;

for(; num > 0; count++)

{

num &= (num - 1);

}

return count;

}
private static int calculateHammingDistance(String hash1, String hash2) {
int distance = 0;

for (int i = 0; i < hash1.length(); i++) {
if (hash1.charAt(i) != hash2.charAt(i)) {
distance++;
}
}

return distance;
}

}

下载opencv官方地址:https://opencv.org/releases/ 安装opencv参考地址:https://blog.csdn.net/star1210644725/article/details/131004810?csdn_share_tail={"type"%3A"blog"%2C"rType"%3A"article"%2C"rId"%3A"131004810"%2C"source"%3A"star1210644725"}

如果是linux环境:需要把System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 注释掉。然后在类中加入静态方法 static { OpenCV.LoadShared(); }

标签:Imgproc,Java,Mat,double,OpenCV,image2,new,image1,对比
From: https://blog.51cto.com/u_13017912/7993280

相关文章

  • armsom:为何选择rk3588开发与Jetson Nano引脚兼容的嵌入式产品之规格对比
    下面是JetsonNano模块(以NVIDIAJetsonNano为代表)与armsom开发的AIM5(RockchipRK3588)的主要技术规格的对比,整理成表格:规格JetsonNano(NVIDIA)ArmSoM-AIM5CPU核数四核ARM®Cortex®-A57MPCore处理器四核ARM®Cortex®-A76+四核ARM®Cortex®-A55GPU核数1......
  • Java基础 计算机的存储规则
    在计算机中,任意数据都是以二进制的形式来存储的8个比特为1个字节,字节是计算机最小的存储单元计算机在存储英文的时候,只需一个字节简体中文版Windows默认使用GBK字符集。GBK字符集完全兼容ASCII字符集 GBK编码:规则①:一个汉字用两个字节存储(英文字母占一个字节,二进制......
  • armsom:为何选择rk3588开发与Jetson Nano引脚兼容的嵌入式产品之规格对比
    下面是JetsonNano模块(以NVIDIAJetsonNano为代表)与armsom开发的AIM5(RockchipRK3588)的主要技术规格的对比:规格JetsonNano(NVIDIA)ArmSoM-AIM5CPU核数四核ARM®Cortex®-A57MPCore处理器四核ARM®Cortex®-A76+四核ARM®Cortex®-A55GPU核数128核Maxwell架......
  • IDEA工具第二篇:自定义Java方法注释模板
    网上搜索类似的文章有很多,但是一味的复制粘贴总会出现各种奇葩问题,最后然并卵!今天特意自己研究琢磨一下,将最终结果分享给大家,100%亲测可用。一、说明想必大家都用过Eclipse的方法注释生成,方法上输入/**,回车走你,巴拉巴拉如下的注释便生成了,今天就悄悄告诉大家如何自定义这样的模......
  • javascript: Sorting Algorithms
     /***fileSort.js*ide:vscodeJavaScriptSortingAlgorithms*插件:IntelliSense,JSDoc,CodeLens,DebuggerforChrome,静态代码检查:ESLint,JSHint,FlowLangugaeSupport,StandardJS-JavaScriptStandardStyle,koroFileHeader(文件头注释),测试插件:Mochasidebar,M......
  • y电容和高压瓷片电容区别对比
    多外观上来看,Y电容和高压瓷片电容非常像,有人甚至这样认为,所谓的Y电容,也就是多了个认证的瓷片电容,事实上真的是这样的吗?Y电容和瓷片电容有区别吗?到底有哪些区别?今天KYET小编就来为大家详细讲解一下。Y电容确实也属于高压瓷片电容:y电容也就是常见的安规电容器的一种,也可以叫做安......
  • java实现文件上传到服务器
    本文实例为大家分享了java实现文件上传到服务器的具体代码,供大家参考,具体内容如下1、运行jar包,发送post请求publicstaticvoidmain(String[]args){    //StringfilePath="C:/Users/706293/IT_onDuty.xls";    StringfilePath=args[0];    String......
  • 【文心一言】百度千帆 Python 和 JavaScript 调用上下文 API
    接口为:百度ERNIE-Bot-4(邀测)控制台直达链接JavascriptconstAK="urAK"constSK="urSK"constaxios=require("axios").default;letaccess_token="urtoken"varurl='https://aip.baidubce.com/rpc/2.0/ai_custom/v1/w......
  • nacos启动脚本去除多余的javac
    github上面一个阿里巴巴开源的服务叫nacos,用途在这里不多说了,主要是在启动时他会寻找javac,但是很多服务器可能没有,所以我小小的修改了一下他的startup.sh然后给他打成了rpm包,也不知道网站可不可以直接把包传上来,这里是github的地址,乱放在一个仓库里面的:https://github.com/linux......
  • java8 map过滤 map转字符串
    Map<String,Long>map=newHashMap<>();map.put("aaa",1L);map.put("bbb",2L);map.put("ccc",1L);Map<String,Long>map2=map.entrySet().stream().filter(e->e.getValue().intValue()>1).collect(Coll......