JAVA圖片類似度判斷(1)顏色分佈法

每張圖片均可以生成顏色分佈的直方圖(color histogram)。若是兩張圖片的直方圖很接近,就能夠認爲它們很類似。java

任何一種顏色都是由紅綠藍三原色(RGB)構成的,因此上圖共有4張直方圖(三原色直方圖 + 最後合成的直方圖)。函數

若是每種原色均可以取256個值,那麼整個顏色空間共有1600萬種顏色(256的三次方)。針對這1600萬種顏色比較直方圖,計算量實在太大了,所以須要採用簡化方法。能夠將0~255分紅四個區:0~63爲第0區,64~127爲第1區,128~191爲第2區,192~255爲第3區。這意味着紅綠藍分別有4個區,總共能夠構成64種組合(4的3次方)。this

任何一種顏色必然屬於這64種組合中的一種,這樣就能夠統計每一種組合包含的像素數量。code

上圖是某張圖片的顏色分佈表,將表中最後一欄提取出來,組成一個64維向量(7414, 230, 0, 0, 8, …, 109, 0, 0, 3415, 53929)。這個向量就是這張圖片的特徵值或者叫」指紋」。圖片

因而,尋找類似圖片就變成了找出與其最類似的向量。這裏用皮爾遜相關係數算出。get

下面貼出代碼it

package com;

import java.util.Map;
import java.util.HashMap;
import java.awt.image.BufferedImage;

public class ImageColorHistogramSimilarity {

    public double colorHistogramSimilarity(BufferedImage src1, BufferedImage src2) {
        int[] array1 = this.colorHistogramSimilarity(src1);
        int[] array2 = this.colorHistogramSimilarity(src2);
        double sumX = 0.0;
        double sumY = 0.0;
        double sumX_Sq = 0.0;
        double sumY_Sq = 0.0;
        double sumXY = 0.0;
        int N = 64;
        for (int i = 0; i < 64; i++) {
            int x = array1[i];
            int y = array2[i];
            sumX += x;
            sumY += y;
            sumX_Sq += Math.pow(x, 2);
            sumY_Sq += Math.pow(y, 2);
            sumXY += x * y;
        }

        double numerator = sumXY - sumX * sumY / N;
        double denominator = Math.sqrt((sumX_Sq - sumX * sumX / N)
                * (sumY_Sq - sumY * sumY / N));

        // 分母不能爲0
        if (denominator == 0) {
            return 0;
        }

        return numerator / denominator;
    }

    private String getRange(int color) {
        if (color >= 0 && color <= 63) {
            return "0";
        } else if (color >= 64 && color <= 127) {
            return "1";
        } else if (color >= 128 && color <= 191) {
            return "2";
        } else if (color >= 192 && color <= 255) {
            return "3";
        }
        return null;
    }

    public int[] colorHistogramSimilarity(BufferedImage src) {
        int width = src.getWidth();
        int height = src.getHeight();
        Map<String, Integer> imageHistogram = new HashMap<String, Integer>();
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int rgb = src.getRGB(j, i);
                int r = (rgb >> 16) & 0xff;//取出次高位(16-23)紅色份量的信息
                int g = (rgb >> 8) & 0xff;//取出中位(8-15)綠色份量的信息
                int b = rgb & 0xff;//取出低位(0-7)藍色份量的信息
                String key = this.getRange(r) + this.getRange(g) + this.getRange(b);

                Integer count = imageHistogram.get(key);
                if (count == null) {
                    imageHistogram.put(key, 1);
                } else {
                    imageHistogram.put(key, count + 1);
                }
            }
        }
        int[] result = new int[64];
        String key = "";
        int idx = 0;
        for (int r = 0; r < 4; r++) {
            for (int g = 0; g < 4; g++) {
                for (int b = 0; b < 4; b++) {
                    key = String.valueOf(r) + String.valueOf(g) + String.valueOf(b);
                    Integer count = imageHistogram.get(key);
                    if (count == null) {
                        result[idx] = 0;
                    } else {
                        result[idx] = count;
                    }
                    idx++;
                }
            }
        }
        return result;
    }
}

獲得相關係數的值介於–1與+1之間,即–1≤r≤+1。其性質以下:io

當r>0時,表示兩變量正相關,r<0時,兩變量爲負相關。
當|r|=1時,表示兩變量爲徹底線性相關,即爲函數關係。
當r=0時,表示兩變量間無線性相關關係。
當0<|r|<1時,表示兩變量存在必定程度的線性相關。且|r|越接近1,兩變量間線性關係越密切;|r|越接近於0,表示兩變量的線性相關越弱。
通常可按三級劃分:|r|<0.4爲低度線性相關;0.4≤|r|<0.7爲顯著性相關;0.7≤|r|<1爲高度線性相關。class

調用代碼以下import

public class Test {


    public static void main(String[] args) throws IOException {
        BufferedImage image1 = ImageIO.read(new File("C:/timg.jpg"));
        BufferedImage image2 = ImageIO.read(new File("C:/timg4.jpg"));
        ImageColorHistogramSimilarity is = new ImageColorHistogramSimilarity();
        double rate = is.colorHistogramSimilarity(image1,image2);
        System.out.println(rate);
    }


}

你能夠用下面幾張圖片試試哦:)

相關文章
相關標籤/搜索