相似图片搜索原理:
实现步骤:
- 1:将图片缩小为同等规格尺寸 8*8
- 2:将图片转为灰度图
- 3:计算灰度平均值
- 4:遍历灰度矩阵
- 5:拼接为一个“指纹” 64位的一个编码数
- 6:“汉明距离”: 计算两个编码之间的汉明距离
- a 字符串 变换为 b字符串 需要的最小变换个数
- 小于/等于5 看作图片相似
- 超过10 可以认定为没什么关系
- 升级的“汉明距离” : 感知hash算法 phash
项目中:
- 找 N 照片:
- 输入一张新图片:
- 计算指纹
- 对比指纹 计算机 与每个指纹之间的汉明距离
- 找到最接近的图片 (汉明距离<=5)
- 返回图片编号
代码
package com.lqj220403;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class search {
public static void main (String[] args) {
search search =new search();
int[][] huidu1=search.processImage("/Users/cater/Desktop/1.png");
int[][] huidu2=search.processImage("/Users/cater/Desktop/2.png");
String code1=search.finger(huidu1);
String code2=search.finger(huidu2);
String code3=search.finger(search.processImage("/Users/cater/Desktop/3.png"));
String code4=search.finger(search.processImage("/Users/cater/Desktop/4.png"));
String code5=search.finger(search.processImage("/Users/cater/Desktop/5.png"));
String code6=search.finger(search.processImage("/Users/cater/Desktop/6.png"));
String code7=search.finger(search.processImage("/Users/cater/Desktop/7.png"));
int dif1 =search.difference(code7, code1);
int dif2 =search.difference(code7, code2);
int dif3 =search.difference(code7, code3);
int dif4 =search.difference(code7, code4);
int dif5 =search.difference(code7, code5);
int dif6 =search.difference(code7, code6);
System.out.print(code1+"\n");
System.out.print(code2+"\n");
System.out.println(dif1);
System.out.println(dif2);
System.out.println(dif3);
System.out.println(dif4);
System.out.println(dif5);
System.out.println(dif6);
}
public int[][] processImage(String path){
//获取图片路径
File file =new File(path);
BufferedImage buffimg=null;
try {
buffimg=ImageIO.read(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//获取图像数组
int w=buffimg.getWidth();
int h =buffimg.getHeight();
System.out.print(w+" "+h+"\n");
int[][] imagearr=new int[w][h];
for(int i=0;i<w;i++) {
for(int j=0;j<h;j++) {
imagearr[i][j]=buffimg.getRGB(i, j);
}
}
//将图像缩小成8*8并计算灰度平均值
int interw=w/8;
int interh=h/8;
//创建灰度矩阵
int[][] huidu =new int[8][8];
for(int i=0;i<w-interw;i+=interw) {
for(int j=0;j<h-interh;j+=interh) {
int grayend=0;
for(int k = 0; k < interw; k++){
for(int l = 0; l < interh; l++){
int red = (imagearr[i+k][j+l] >> 16) & 0xFF;
int green = (imagearr[i+k][j+l] >> 8) & 0xFF;
int blue = (imagearr[i+k][j+l] >> 0) & 0xFF;
int gray = (red + green + blue) / 3;
grayend += gray;
}
}
huidu[i/interw][j/interh]=grayend;
}
}
return huidu;
}
public String finger (int[][] shuzu) {
//先计算shuzu的平均值
int sum=0;
for(int i = 0;i<shuzu.length;i++){
for(int j = 0; j < shuzu[i].length; j++){
sum+= shuzu[i][j];
}
}
int avg =sum/(shuzu.length*shuzu[0].length);
String code="";
for(int i = 0;i<shuzu.length;i++){
for(int j = 0; j < shuzu[i].length; j++){
int gray = shuzu[i][j];
if(gray > avg){
code += "1";
} else{
code += "0";
}
}}
return code;
}
public int difference(String code1, String code2) {
char [] chararray1 =code1.toCharArray();
char [] chararray2 =code2.toCharArray();
int len =chararray1.length;
int dif=0;
for(int i=0;i<len;i++) {
if(chararray1[i]!=chararray2[i]) {
dif++;
}
}
return dif;
}
}