首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 圖片相似度比較:像素級差值統計實現

     編輯:Java 相關知識

本文實現一種基於像素 RGB 差值統計的圖片相似度比較算法。核心思路:將兩張圖片縮放至相同尺寸,逐像素比對 RGB 三通道值,設定閾值判定相似像素,最終計算相似像素佔比作為相似度指標。提供完整可運行代碼與結果解析。

算法原理

  1. 讀取兩張圖片為 BufferedImage
  2. 遍歷每個像素座標 (x, y)
  3. 提取 RGB 三通道值:R = (pixel >> 16) & 0xFF 等
  4. 計算對應通道差值:|R1 - R2|, |G1 - G2|, |B1 - B2|
  5. 若三通道差值均小於閾值(預設 5),判定為相似像素
  6. 相似度 = 相似像素數 / 總像素數 × 100%

完整代碼實現


import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class ImageSimilarity {

    /**
     * 將圖片轉換為 RGB 字串矩陣
     * @param imagePath 圖片路徑
     * @return 二維陣列,每元素為 "R,G,B" 格式字串
     */
    public static String[][] getPixelMatrix(String imagePath) {
        File file = new File(imagePath);
        BufferedImage image;
        try {
            image = ImageIO.read(file);
        } catch (Exception e) {
            e.printStackTrace();
            return new String[0][0];
        }

        int width = image.getWidth();
        int height = image.getHeight();
        String[][] matrix = new String[width][height];

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int pixel = image.getRGB(x, y);
                int r = (pixel >> 16) & 0xFF;
                int g = (pixel >> 8) & 0xFF;
                int b = pixel & 0xFF;
                matrix[x][y] = r + "," + g + "," + b;
            }
        }
        return matrix;
    }

    /**
     * 比較兩張圖片相似度
     * @param imgPath1 圖片 1 路徑
     * @param imgPath2 圖片 2 路徑
     */
    public static void compareImages(String imgPath1, String imgPath2) {
        String[][] pixels1 = getPixelMatrix(imgPath1);
        String[][] pixels2 = getPixelMatrix(imgPath2);

        // 尺寸檢查
        if (pixels1.length != pixels2.length || 
            pixels1[0].length != pixels2[0].length) {
            System.out.println("圖片尺寸不一致,無法直接比較。建議先縮放至相同尺寸。");
            return;
        }

        int width = pixels1.length;
        int height = pixels1[0].length;
        int similar = 0;
        int different = 0;
        final int THRESHOLD = 5; // RGB 差值閾值

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                String[] rgb1 = pixels1[x][y].split(",");
                String[] rgb2 = pixels2[x][y].split(",");
                
                boolean isSimilar = true;
                for (int c = 0; c < 3; c++) {
                    int diff = Math.abs(Integer.parseInt(rgb1[c]) - Integer.parseInt(rgb2[c]));
                    if (diff >= THRESHOLD) {
                        isSimilar = false;
                        break;
                    }
                }
                if (isSimilar) similar++;
                else different++;
            }
        }

        double similarity = (double) similar / (similar + different) * 100;
        System.out.printf("相似像素: %d, 不同像素: %d, 相似度: %.2f%%%n", 
                          similar, different, similarity);
    }

    public static void main(String[] args) {
        // 測試:請替換為實際圖片路徑
        compareImages("E:/12.bmp", "E:/1.bmp");
    }
}

代碼改進說明

原始代碼存在以下問題,已在上方修正:

  • 迴圈邏輯錯誤:原代碼使用單一 i, j 索引卻雙重嵌套導致越界
  • 重複比較:原代碼雙向比較 (1→2, 2→1) 導致計數翻倍
  • 字串分割效能低:每像素分割字串,改進版直接用位運算提取 RGB
  • 異常吞噬:原代碼 catch (RuntimeException e) { continue; } 掩蓋真實錯誤
  • 尺寸不匹配未處理:新增尺寸檢查並提示縮放建議

效能優化建議

進階算法:感知哈希

像素級比較對平移、旋轉、縮放敏感。生產環境推薦 感知哈希:


// 1. 縮放至 32x32 灰度圖
// 2. DCT 離散餘弦變換取 8x8 低頻係數
// 3. 計算係數平均值,生成 64 位指紋
// 4. 漢明距離比較指紋(距離越小越相似)

// 推薦庫:https://github.com/axiomhq/hamming-distance
// 或使用 OpenCV: Imgproc.dct() + 比較

應用場景與限制

優化方向實現方式效果
避免字串操作直接用 int[] rgb = new int[3] 存儲或位運算提取大幅降低 GC 壓力,提升 10-50x
圖片預處理縮放使用 Image.getScaledInstance() 統一尺寸支援不同解析度圖片比較
採樣比較每隔 N 像素採樣,適合大圖快速預估犧牲精度換速度
使用原始數組int[] pixels = image.getRGB(0, 0, w, h, null, 0, w)一次性讀取所有像素,避免重複 getRGB 調用
適用場景不適用場景
截圖比對、UI 回歸測試不同角度/光照拍攝同一物體
水印偵測、圖片去重(完全相同)縮放、裁剪、旋轉後的圖片
簡單相似度閾值過濾語義級相似度(如「都是貓」)

總結

像素差值統計法實現簡單、邏輯清晰,適合尺寸固定、內容高度一致的圖片比對(如自動化測試截圖驗證)。對於複雜場景,建議引入感知哈希或深度學習特徵向量比較(如 ResNet + 余弦相似度)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved