Skip to content

Commit

Permalink
添加 直方图算法计算图片相识度
Browse files Browse the repository at this point in the history
  • Loading branch information
nivance committed Jun 29, 2017
1 parent c4da065 commit e33fa75
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 0 deletions.
111 changes: 111 additions & 0 deletions src/main/java/image/similarity/ImageHistogram.java
@@ -0,0 +1,111 @@
package image.similarity;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;

/**
* @desc 相似图片识别(直方图)
*/
public class ImageHistogram {

private int redBins;
private int greenBins;
private int blueBins;

public ImageHistogram() {
redBins = greenBins = blueBins = 4;
}

private float[] filter(BufferedImage src) {
int width = src.getWidth();
int height = src.getHeight();

int[] inPixels = new int[width * height];
float[] histogramData = new float[redBins * greenBins * blueBins];
getRGB(src, 0, 0, width, height, inPixels);
int index = 0;
int redIdx = 0, greenIdx = 0, blueIdx = 0;
int singleIndex = 0;
float total = 0;
for (int row = 0; row < height; row++) {
int tr = 0, tg = 0, tb = 0;
for (int col = 0; col < width; col++) {
index = row * width + col;
tr = (inPixels[index] >> 16) & 0xff;
tg = (inPixels[index] >> 8) & 0xff;
tb = inPixels[index] & 0xff;
redIdx = (int) getBinIndex(redBins, tr, 255);
greenIdx = (int) getBinIndex(greenBins, tg, 255);
blueIdx = (int) getBinIndex(blueBins, tb, 255);
singleIndex = redIdx + greenIdx * redBins + blueIdx * redBins * greenBins;
histogramData[singleIndex] += 1;
total += 1;
}
}

// start to normalize the histogram data
for (int i = 0; i < histogramData.length; i++) {
histogramData[i] = histogramData[i] / total;
}

return histogramData;
}

private float getBinIndex(int binCount, int color, int colorMaxValue) {
float binIndex = (((float) color) / ((float) colorMaxValue)) * ((float) binCount);
if (binIndex >= binCount)
binIndex = binCount - 1;
return binIndex;
}

private int[] getRGB(BufferedImage image, int x, int y, int width, int height, int[] pixels) {
int type = image.getType();
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB)
return (int[]) image.getRaster().getDataElements(x, y, width, height, pixels);
return image.getRGB(x, y, width, height, pixels, 0, width);
}

/**
* Bhattacharyya Coefficient
* http://www.cse.yorku.ca/~kosta/CompVis_Notes/bhattacharyya.pdf
*
* @return 返回值大于等于0.8可以简单判断这两张图片内容一致
* @throws IOException
*/
public double match(File srcFile, File canFile) throws IOException {
float[] sourceData = this.filter(ImageIO.read(srcFile));
float[] candidateData = this.filter(ImageIO.read(canFile));
return calcSimilarity(sourceData, candidateData);
}

/**
* @return 返回值大于等于0.8可以简单判断这两张图片内容一致
* @throws IOException
*/
public double match(URL srcUrl, URL canUrl) throws IOException {
float[] sourceData = this.filter(ImageIO.read(srcUrl));
float[] candidateData = this.filter(ImageIO.read(canUrl));
return calcSimilarity(sourceData, candidateData);
}

private double calcSimilarity(float[] sourceData, float[] candidateData) {
double[] mixedData = new double[sourceData.length];
for (int i = 0; i < sourceData.length; i++) {
mixedData[i] = Math.sqrt(sourceData[i] * candidateData[i]);
}

// The values of Bhattacharyya Coefficient ranges from 0 to 1,
double similarity = 0;
for (int i = 0; i < mixedData.length; i++) {
similarity += mixedData[i];
}

// The degree of similarity
return similarity;
}

}
61 changes: 61 additions & 0 deletions src/test/java/image/similarity/ImgHistogramTest.java
@@ -0,0 +1,61 @@
package image.similarity;

import java.io.File;
import java.io.IOException;
import java.net.URL;

import org.junit.Assert;

import junit.framework.TestCase;

public class ImgHistogramTest extends TestCase {

ImageHistogram histogram = null;

public void setUp() {
histogram = new ImageHistogram();
}

public void testImageHistogram() {
try {
double score = histogram.match(new File("doc/imgs/1.jpg"), new File("doc/imgs/1.jpg"));
System.out.println("img1-->img1::::score : " + score);
Assert.assertTrue(score >= 0.8);

score = histogram.match(new File("doc/imgs/1.jpg"), new File("doc/imgs/2.jpg"));
System.out.println("img1-->img2::::score : " + score);
Assert.assertTrue(score >= 0.8);

score = histogram.match(new File("doc/imgs/1.jpg"), new File("doc/imgs/3.jpg"));
System.out.println("img1-->img3::::score : " + score);
Assert.assertTrue(score >= 0.8);

score = histogram.match(new File("doc/imgs/1.jpg"), new File("doc/imgs/4.jpg"));
System.out.println("img1-->img4::::score : " + score);
Assert.assertTrue(score < 0.8);

score = histogram.match(new File("doc/imgs/5.jpg"), new File("doc/imgs/6.jpg"));
System.out.println("img5-->img6::::score : " + score);
Assert.assertTrue(score < 0.8); // incorrect

score = histogram.match(new File("doc/imgs/1.jpg"), new File("doc/imgs/6.jpg"));
System.out.println("img1-->img6::::score : " + score);
Assert.assertTrue(score < 0.8);

String srcUrl = "http://oarfc773f.bkt.clouddn.com/100000094nzslsdnswbb_1_1_r.jpg";
score = histogram.match(new URL(srcUrl), new URL("https://img3.doubanio.com/lpic/s27140981.jpg"));
System.out.println("url::::score:" + score);
Assert.assertTrue(score < 0.8); // incorrect

score = histogram.match(new URL(srcUrl), new URL("https://img3.doubanio.com/lpic/s8966044.jpg"));
System.out.println("url::::score:" + score);
Assert.assertTrue(score < 0.8); // incorrect

} catch (IOException e) {
e.printStackTrace();
Assert.assertFalse(false);
}

}

}

0 comments on commit e33fa75

Please sign in to comment.