图像处理直方图匹配-巴氏系数原理及实现

        在图像处理中,巴氏系数可用于进行相似图像匹配。

        巴氏系数公式:BC(p,q) = ∑√p(x)q(x)

        BC为巴氏系数计算结果,p、q分别为两张图像在直方图上同一位置的概率分布,巴氏系数结果范围为(0~1),0为完全不相同,1为完全相同。

        原理:先分别求出两张图像在直方图上的概率分布,对相同位置的概率相乘(如果某一图像在该处分布概率为0,则乘积结果也为0,表示在该处完全不相同),然后进行开方,再对开方后结果进行累加。如果两张图像在某一处分布概率完全一样,那么该处计算结果与任意一张图像在该处分布概率相同,如果两张图像完全相同,那么计算结果就是与任意一张图像在直方图上分布概率完全相同,累加结果必定为1。

        实现步骤:

        1、分别计算两张图像在直方图上概率分布,如果是灰度图,可以直接计算在0~255上分布概率。彩色图像稍微复杂一些,由于彩色图像由RGB三个通道组成,也就是说彩色图像有256*256*256=16777216个灰度级别,显然要对每一个灰度级别进行计算,计算量会非常大,而且计算结果也会因为过度细分而产生较大差异。如果将彩色图像直接转为灰度图,虽然降低了计算量,但会损失掉彩色信息。一般可以将每个通道除以16,从256个灰度级别降低到16个,再将三个通道合并为单一值,将16777216个灰度级别降低到4096个。

        转换代码:

                 int value = (R / 16) * 16 * 15 + (G / 16) * 15 + (B / 16)

        当然也可以采用位运算提速:

                 int value = (R / 16) << 8 | (G / 16) << 4 | (B / 16)

        2、计算图像在每个灰度级别上概率分布,统计每个灰度级别包含多少像素,将像素数量除以图像总像素。

                 P = number / width * height

        3、根据巴氏系数计算公式计算匹配结果。

                 result = Math.sqrt(srcMap.get(i) * destMap.get(i))    

        实现代码:

public class BhattacharyyaCoefficient {
	//singleton 
	private static BhattacharyyaCoefficient instance = new BhattacharyyaCoefficient();
	private BhattacharyyaCoefficient() {}
	public static BhattacharyyaCoefficient getInstance() {
		return instance;
	}
	
	//巴氏系数计算
	public double getBhattacharyyaCoefficient (BufferedImage srcImage, BufferedImage destImage) {
		Map<Integer, Double> srcMap = tranverseImage(srcImage);
		Map<Integer, Double> destMap = tranverseImage(destImage);
		double result = getMatchResult(srcMap,destMap);
		return result;
	}
	
	//计算匹配结果
	private double getMatchResult(Map<Integer, Double> srcMap, Map<Integer, Double> destMap) {
		double result = 0.0;
		for(int i = 0; i < 4096; i++) {
			result += Math.sqrt(srcMap.get(i) * destMap.get(i));
		}
		return result;
	}
	/**
	 * 图像RGB值转换,把255压缩到16,返回map
	 * R = (R / 16) << 8,G = (G / 16) << 4,B = (B / 16)
	 * @param image
	 * @return
	 */
	private Map<Integer, Double> tranverseImage(BufferedImage image){
		int width = image.getWidth();
		int height = image.getHeight();
		Map<Integer, Double> map = new HashMap<>();
		for(int i = 0; i < 4096; i++) {
			map.put(i, 0.0);
		}
		for(int i = 0; i < width; i++) {
			for(int j = 0; j < height; j++) {
				int rgb = image.getRGB(i, j);
				int R = (rgb >> 16) & 0xff;
				int G = (rgb >> 8) & 0xff;
				int B = rgb & 0xff;
				int rgbs = tranverseRGBToInt(R, G, B);
				map.put(rgbs, map.get(rgbs) + 1);
			}
		}
		int totalPix = height * width;
		for(int i = 0; i < 4096; i++) {
			double value = map.get(i) / totalPix;
			map.put(i, value);
		}
		return map;
	}
	
	/**
	 * 将rgb值转为压缩后int
	 * result = (R / 16) << 8 | (G / 16) << 4 | (B / 16)
	 * @param R
	 * @param G
	 * @param B
	 * @return
	 */
	private int tranverseRGBToInt(int R,int G,int B) {
		int value = (R / 16) << 8 | (G / 16) << 4 | (B / 16);
		return value;
	}
}

        测试:

public class BhattacharyyaTest {
	public static void main(String[] args) throws Exception{
		File srcFile = new File("E:\\桌面\\test\\原图\\1.JPG");
		File destFile = new File("E:\\桌面\\test\\原图\\2.JPG");
		BufferedImage srcImage = ImageIO.read(srcFile);
		BufferedImage destImage = ImageIO.read(destFile);
		double result = BhattacharyyaCoefficient.getInstance().getBhattacharyyaCoefficient(srcImage, destImage);
		System.out.println(result);
	}
}

        测试图像:

        运行结果:0.9899107889267019

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TheMatrixs

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值