下边是代码部分
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