每张图片均可以生成颜色分布的直方图(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); } }
你能够用下面几张图片试试哦:)