java利用直方图实现图片对比

需求

  实现两张图对比,找出其中不同的部分。

分析

  首先将大图切片,分成许多小图片。然后进行逐个对比,并设定相似度阈值,判断是否是相同。最后整理,根据生成数组标记不同部分。如果切片足够小,便越能精确找出不同点。

  本例使用1024x1024图片,切片大小为32x32。

实现

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

public class PicTest {
    public final static int THRESHOLD = 90;//阈值百分比
    public static void main(String[] args) throws Exception {
		//用于记录不同点
        int[][] comparyArray = new int[32][32];
		//两张图片
        BufferedImage img1 = ImageIO.read(new File("G:\\1.jpg"));
        BufferedImage img2 = ImageIO.read(new File("G:\\2.jpg"));
		//两张图片的切片
        BufferedImage img1Sub;
        BufferedImage img2Sub;
        float percent;
		//双循环用来取图片的切片坐标
        for(int i = 0;i<32;i++){
            for(int j = 0;j<32;j++){
				//取相同点的坐标
                img1Sub = img1.getSubimage(j*32, i*32, 32, 32);
                img2Sub = img2.getSubimage(j*32, i*32, 32, 32);
				//比较获得相似度
                percent = compare(getData(img1Sub), getData(img2Sub));
                if(percent>THRESHOLD){//比阈值大,则记录1表示相同
                    comparyArray[i][j] = 1;
                    System.out.print(1+" ");
                }else{//比阈值小,则记录0表示不同
                    comparyArray[i][j] = 0;
                    System.out.print(0+" ");
                }
            }
            System.out.println();
        }
        
    }
    
	//直方图作对比返回相似度
    public static float compare(int[] s, int[] t) {
        float result = 0F;
        for (int i = 0; i < 256; i++) {
            int abs = Math.abs(s[i] - t[i]);
            int max = Math.max(s[i], t[i]);
            result += (1 - ((float) abs / (max == 0 ? 1 : max)));
        }
        return (result / 256) * 100;
    }
    //根据图片获取直方图数据
    public static int[] getData(BufferedImage img) throws Exception {
        BufferedImage slt = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
        slt.getGraphics().drawImage(img, 0, 0, 100, 100, null);
        // ImageIO.write(slt,"jpeg",new File("slt.jpg"));
        int[] data = new int[256];
        for (int x = 0; x < slt.getWidth(); x++) {
            for (int y = 0; y < slt.getHeight(); y++) {
                int rgb = slt.getRGB(x, y);
                Color myColor = new Color(rgb);
                int r = myColor.getRed();
                int g = myColor.getGreen();
                int b = myColor.getBlue();
                data[(r + g + b) / 3]++;
            }
        }
        // data 就是所谓图形学当中的直方图的概念
        return data;
    }
}

 效果

两张图片分别为

    

运行程序后,输出1和0的数组,与第二张图相比较得到

可以看出不同的地方显示为0.据此,便可以根据数组显示画框突出了。

posted @ 2017-07-26 22:29  Adam_Jin  阅读(1093)  评论(0编辑  收藏  举报