以图搜图实现

该博客介绍了相似图片搜索的实现方法,通过缩小图片、转换为灰度图、计算平均值、构建指纹编码及使用汉明距离判断图片相似度。还提及了感知哈希算法(phash)的升级版,并展示了Java代码示例,用于计算图片指纹和比较汉明距离,从而找出相似图片。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相似图片搜索原理:

实现步骤:

  • 1:将图片缩小为同等规格尺寸 8*8
  • 2:将图片转为灰度图
  • 3:计算灰度平均值
  • 4:遍历灰度矩阵
    • 大于平均值记作1
    • 小于平均值记作0
  • 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;
	}
		
	}

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值