我用JAVA做了個簡易圖像相似度計算器


簡單說兩句:

筆主利用這個七夕前后兩天的寂寞時光,用JAVA磨了一個簡單的圖像相似度計算小程序,就在剛才終於糾結完畢,輸出了1.0版本,小小的滿足了一下可憐的虛榮心..→_→

使用最簡單最基礎的感知哈希算法,算法原理戳這里,絕對比筆主講的要好:

http://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html

 

UI設計圖:

 

實際運行效果圖:

 

關鍵算法:

 1 // 全流程
 2 public static void main(String[] args) throws IOException {
 3     // 獲取圖像
 4     File imageFile = new File("c:/1.jpg");
 5     Image image = ImageIO.read(imageFile);
 6     // 轉換至灰度
 7     image = toGrayscale(image);
 8     // 縮小成32x32的縮略圖
 9     image = scale(image);
10     // 獲取灰度像素數組
11     int[] pixels = getPixels(image);
12     // 獲取平均灰度顏色
13     int averageColor = getAverageOfPixelArray(pixels);
14     // 獲取灰度像素的比較數組(即圖像指紋序列)
15     pixels = getPixelDeviateWeightsArray(pixels, averageColor);
16     // 獲取兩個圖的漢明距離(假設另一個圖也已經按上面步驟得到灰度比較數組)
17     int hammingDistance = getHammingDistance(pixels, pixels);
18     // 通過漢明距離計算相似度,取值范圍 [0.0, 1.0]
19     double similarity = calSimilarity(hammingDistance);
20 }
21 
22 // 將任意Image類型圖像轉換為BufferedImage類型,方便后續操作
23 public static BufferedImage convertToBufferedFrom(Image srcImage) {
24     BufferedImage bufferedImage = new BufferedImage(srcImage.getWidth(null),
25             srcImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
26     Graphics2D g = bufferedImage.createGraphics();
27     g.drawImage(srcImage, null, null);
28     g.dispose();
29     return bufferedImage;
30 }
31 
32 // 轉換至灰度圖
33 public static BufferedImage toGrayscale(Image image) {
34     BufferedImage sourceBuffered = convertToBufferedFrom(image);
35     ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
36     ColorConvertOp op = new ColorConvertOp(cs, null);
37     BufferedImage grayBuffered = op.filter(sourceBuffered, null);
38     return grayBuffered;
39 }
40 
41 // 縮放至32x32像素縮略圖
42 public static Image scale(Image image) {
43     image = image.getScaledInstance(32, 32, Image.SCALE_SMOOTH);
44     return image;
45 }
46 
47 // 獲取像素數組
48 public static int[] getPixels(Image image) {
49     int width = image.getWidth(null);
50     int height = image.getHeight(null);
51     int[] pixels = convertToBufferedFrom(image).getRGB(0, 0, width, height,
52             null, 0, width);
53     return pixels;
54 }
55 
56 // 獲取灰度圖的平均像素顏色值
57 public static int getAverageOfPixelArray(int[] pixels) {
58     Color color;
59     long sumRed = 0;
60     for (int i = 0; i < pixels.length; i++) {
61         color = new Color(pixels[i], true);
62         sumRed += color.getRed();
63     }
64     int averageRed = (int) (sumRed / pixels.length);
65     return averageRed;
66 }
67 
68 // 獲取灰度圖的像素比較數組(平均值的離差)
69 public static int[] getPixelDeviateWeightsArray(int[] pixels,final int averageColor) {
70     Color color;
71     int[] dest = new int[pixels.length];
72     for (int i = 0; i < pixels.length; i++) {
73         color = new Color(pixels[i], true);
74         dest[i] = color.getRed() - averageColor > 0 ? 1 : 0;
75     }
76     return dest;
77 }
78 
79 // 獲取兩個縮略圖的平均像素比較數組的漢明距離(距離越大差異越大)
80 public static int getHammingDistance(int[] a, int[] b) {
81     int sum = 0;
82     for (int i = 0; i < a.length; i++) {
83         sum += a[i] == b[i] ? 0 : 1;
84     }
85     return sum;
86 }
87 
88 // 通過漢明距離計算相似度
89 public static double calSimilarity(int hammingDistance){
90     int length = 32*32;
91     double similarity = (length - hammingDistance) / (double) length;
92 
93     // 使用指數曲線調整相似度結果
94     similarity = java.lang.Math.pow(similarity, 2);
95     return similarity;
96 }


UI部分的代碼就不公開了,成品下載地址如下(使用JDK1.5):

http://download.csdn.net/detail/u011088871/7711833

 

解壓后打開 run.bat 批處理文件就可以跑起來了 :)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM