(图像大小不一致缺陷) 方法1图像处理库 java.awt 和 javax.imageio,通过将图片转换为灰度图像,然后比较像素值来计算相似度
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageSimilarityUtils {
public static double compareImages(String imagePath1, String imagePath2) {
try {
BufferedImage image1 = ImageIO.read(new File(imagePath1));
BufferedImage image2 = ImageIO.read(new File(imagePath2));
int width = Math.min(image1.getWidth(), image2.getWidth());
int height = Math.min(image1.getHeight(), image2.getHeight());
int samePixelCount = 0;
int totalPixelCount = width * height;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb1 = image1.getRGB(x, y);
int rgb2 = image2.getRGB(x, y);
int gray1 = getGrayValue(rgb1);
int gray2 = getGrayValue(rgb2);
if (gray1 == gray2) {
samePixelCount++;
}
}
}
return (double) samePixelCount / totalPixelCount;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
private static int getGrayValue(int rgb) {
Color color = new Color(rgb);
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
return (r + g + b) / 3;
}
public static void main(String[] args) {
String imagePath1 = "C:\\Users\\Downloads\\20250313-111643.jpg";
String imagePath2 = "C:\\Users\\Downloads\\20250313-111638.jpg";
double similarity = compareImages(imagePath1, imagePath2);
System.out.printf("两张图片的相似度为: %.2f%%\n", similarity * 100);
}
}
(解决图像大小不一致对比)方法2:使用感知哈希算法(Perceptual Hash Algorithm),其中比较常用的是均值哈希(Average Hash)和感知哈希(pHash)
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageSimilarityUtils {
public static double compareImages(String imagePath1, String imagePath2) {
try {
String hash1 = calculateAverageHash(imagePath1);
String hash2 = calculateAverageHash(imagePath2);
int hammingDistance = hammingDistance(hash1, hash2);
return 1 - (double) hammingDistance / hash1.length();
} catch (IOException e) {
e.printStackTrace();
return 0;
}
}
private static String calculateAverageHash(String imagePath) throws IOException {
BufferedImage image = ImageIO.read(new File(imagePath));
BufferedImage resizedImage = resizeImage(image, 8, 8);
int[] grayPixels = convertToGray(resizedImage);
int average = calculateAverage(grayPixels);
StringBuilder hash = new StringBuilder();
for (int pixel : grayPixels) {
if (pixel >= average) {
hash.append("1");
} else {
hash.append("0");
}
}
return hash.toString();
}
private static BufferedImage resizeImage(BufferedImage originalImage, int width, int height) {
BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
resizedImage.getGraphics().drawImage(originalImage, 0, 0, width, height, null);
return resizedImage;
}
private static int[] convertToGray(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
int[] grayPixels = new int[width * height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = image.getRGB(x, y);
Color color = new Color(rgb);
int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3;
grayPixels[y * width + x] = gray;
}
}
return grayPixels;
}
private static int calculateAverage(int[] pixels) {
int sum = 0;
for (int pixel : pixels) {
sum += pixel;
}
return sum / pixels.length;
}
private static int hammingDistance(String s1, String s2) {
int distance = 0;
for (int i = 0; i < s1.length(); i++) {
if (s1.charAt(i) != s2.charAt(i)) {
distance++;
}
}
return distance;
}
public static void main(String[] args) {
String imagePath1 = "C:\\Users\\Downloads\\20250313-111643.jpg";
String imagePath2 = "C:\\Users\\Downloads\\20250313-111638.jpg";
double similarity = compareImages(imagePath1, imagePath2);
System.out.printf("两张图片的相似度为: %.2f%%\n", similarity * 100);
}
}