Java比较两张图片的相似度

2021-01-05 32点热度 0人点赞 0条评论

先准备好工具类:

新建HistogramFilter.java
package com.terrynow.test.imagecompare;

import java.awt.image.BufferedImage;

public class HistogramFilter {
    
    private int redBins;
    private int greenBins;
    private int blueBins;
    
    public HistogramFilter() {
        redBins = greenBins = blueBins = 4;
    }
    
    public void setRedBinCount(int redBinCount) {
        this.redBins = redBinCount;
    }

    public void setGreenBinCount(int greenBinCount) {
        this.greenBins = greenBinCount;
    }

    public void setBlueBinCount(int blueBinCount) {
        this.blueBins = blueBinCount;
    }

    public float[] filter(byte[] imageBytes) {
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes);
            BufferedImage bufferedImage = ImageIO.read(bais);
            return filter(bufferedImage, null);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    @SuppressWarnings("unused")
    public float[] filter(BufferedImage src, BufferedImage dest) {
        int width = src.getWidth();
        int height = src.getHeight();
        
        int[] inPixels = new int[width*height];
        float[] histogramData = new float[redBins * greenBins * blueBins];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        int redIdx = 0, greenIdx = 0, blueIdx = 0;
        int singleIndex = 0;
        float total = 0;
        for(int row=0; row<height; row++) {
        	int ta = 0, tr = 0, tg = 0, tb = 0;
        	for(int col=0; col<width; col++) {
        		index = row * width + col;
        		ta = (inPixels[index] >> 24) & 0xff;
                tr = (inPixels[index] >> 16) & 0xff;
                tg = (inPixels[index] >> 8) & 0xff;
                tb = inPixels[index] & 0xff;
                redIdx = (int)getBinIndex(redBins, tr, 255);
                greenIdx = (int)getBinIndex(greenBins, tg, 255);
                blueIdx = (int)getBinIndex(blueBins, tb, 255);
                singleIndex = redIdx + greenIdx * redBins + blueIdx * redBins * greenBins;
                histogramData[singleIndex] += 1;
                total += 1;
        	}
        }
        
        // start to normalize the histogram data
        for (int i = 0; i < histogramData.length; i++)
        {
        	histogramData[i] = histogramData[i] / total;
        }
        
        return histogramData;
    }

    private float getBinIndex(int binCount, int color, int colorMaxValue) {
        float binIndex = (((float)color)/((float)colorMaxValue)) * ((float)binCount);
        if(binIndex >= binCount)
            binIndex = binCount  - 1;
        return binIndex;
    }
    
    public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
        int type = image.getType();
        if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
            return (int [])image.getRaster().getDataElements( x, y, width, height, pixels );
        return image.getRGB( x, y, width, height, pixels, 0, width );
    }

}
如何使用
public static void main(String[] args) throws Exception {
        //从文件读取图片的bytes或者从BufferedImage读取都可以
        byte[] imageBytes1 = FileUtils.readFileToByteArray(new File("/path/to/image1.jpg"));
        byte[] imageBytes2 = FileUtils.readFileToByteArray(new File("/path/to/image2.jpg"));

        HistogramFilter hfilter = new HistogramFilter();
        float[] sourceData = hfilter.filter(imageBytes1);
        float[] candidateData = hfilter.filter(imageBytes2);

        System.out.println(calcImageSimilarity(sourceData, candidateData));
    }

    //相似度从0-1之间的double
    public static double calcImageSimilarity(float[] sourceData, float[] candidateData) {
        double[] mixedData = new double[sourceData.length];
        for (int i = 0; i < sourceData.length; i++) {
            mixedData[i] = Math.sqrt(sourceData[i] * candidateData[i]);
        }

        double similarity = 0;
        for (int i = 0; i < mixedData.length; i++) {
            similarity += mixedData[i];
        }

        return similarity;
    }

 

Terry

文章评论

*

code