• 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.据此,便可以根据数组显示画框突出了。

  • 相关阅读:
    剔除数组中重复对象
    2018湖南省高中数学联赛(A)试题
    向量与三角
    阿波罗尼斯圆
    2019高考理科数学(天津卷)
    转载Android常见错误(http://www.cnblogs.com/oklanyan/archive/2011/10/12/2208378.html)
    TCP/IP网络层谜云
    bitmap 设置图片尺寸,避免 内存溢出 OutOfMemoryError的优化方法(转载:http://tonyyu.iteye.com/blog/713256)
    ArcGIS for Android 离线数据编辑原理
    Android环境搭建(XP/Win7)转载http://www.cnblogs.com/oklanyan/archive/2011/10/14/2207339.html
  • 原文地址:https://www.cnblogs.com/adamJin/p/6935385.html
Copyright © 2020-2023  润新知