OpenCV图像处理之直方图比较方法详解

 更新时间:2022年09月06日 10:21:09   作者:肖爱Kun  
直方图比较是对输入的两张图像进行计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度,进而比较图像本身的相似程度。本文将为大家详细讲讲直方图比较的实现方法,需要的可以参考一下

一、直方图比较

直方图比较是对输入的两张图像进行计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度(每张图像都有唯一的直方图与之对应),进而比较图像本身的相似程度。Opencv提供的比较方法有四种:

Correlation 相关性比较

Chi-Square 卡方比较

Intersection 十字交叉性

Bhattacharyya distance 巴氏距离。

(1)直方图比较方法-相关性计算(CV_COMP_CORREL)

其中:      

其中N是直方图的BIN个数,是均值。

(2)直方图比较方法-相关性计算(CV_COMP_CORREL)

H1,H2分别表示两个图像的直方图数据

(3)直方图比较方法-十字交叉性计算(CV_COMP_INTERSECT)

H1,H2分别表示两个图像的直方图数据

(4)直方图比较方法-巴氏距离计算(CV_COMP_BHATTACHARYYA )

H1,H2分别表示两个图像的直方图数据,

二、图像直方图比较方法

加载原图像

将图像色彩空间由BGR三通道转换为HSV空间(由于直方图对亮度和灰度比较敏感,色彩空间转换就是突出这两个因素尽量去除其他因素)

计算直方图进行归一化处理,归一化到0到1之间,调用calcHist和normalize

直方图比较,使用上述四种方法之一,调用compareHist

直方图比较API函数接口

API接口

double compareHist(InputArray h1,InputArray H2,int method)

参数说明:

第一个参数InputArray类型 h1,直方图数据

第二个参数InputArray类型 h2,直方图数据

第三个参数int类型 method比较方法,上述四种方法之一

返回值:采用上述四中方法之一计算后的两个直方图相关系数

关于 int method 的取值:

enum HistCompMethods {
    HISTCMP_CORREL        = 0,    //相关性比较
    HISTCMP_CHISQR        = 1,    //卡方比较
    HISTCMP_INTERSECT     = 2,    //十字交叉性
    HISTCMP_BHATTACHARYYA = 3,    //巴氏距离
    HISTCMP_HELLINGER     = HISTCMP_BHATTACHARYYA, 
    HISTCMP_CHISQR_ALT    = 4,    //替代卡方:通常用于纹理比较。
    HISTCMP_KL_DIV        = 5     //KL散度
};

不同直方图相关性比较方法的特点:

Correlation相关性比较(CV_COMP_CORREL)值越大,相关度越高,最大值为1,最小值为0,越接近1越相似

Chi-Square卡方比较(CV_COMP_CHISQR) 值越小,相关度越高,最大值无上界,最小值0,越接近0越相似

Intersection十字交叉性(CV_COMP_INTERSECT)对于相似度比较,值越大,表明相关度越高,最大值无上界;完美匹配为1,完全不匹配为0;

Bhattacharyya distance巴氏距离(CV_COMP_BHATTACHARYYA)值越小,相关度越高,最大值为1,最小值为0,越接近1越相似

三、代码实现

#include"stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
 
using namespace std;
using namespace cv;
 
string convertToString(double d);
int main(int argc, char** argv) {
	Mat base, test1, test2;          //RGB图像
	Mat hsvbase, hsvtest1, hsvtest2; //HSV图像
	base = imread("F:/photo/zx.jpg");
	if (!base.data) {
		printf("could not load image...\n");
		return -1;
	}
	test1 = imread("F:/photo/a.jpg");
	test2 = imread("F:/photo/c.jpg");
	//转化为HSV图像
	cvtColor(base, hsvbase, COLOR_BGR2HSV);
	cvtColor(test1, hsvtest1, COLOR_BGR2HSV);
	cvtColor(test2, hsvtest2, COLOR_BGR2HSV);
 
	int h_bins = 50; int s_bins = 60;
	int histSize[] = { h_bins, s_bins };
	// hue varies from 0 to 179, saturation from 0 to 255     
	float h_ranges[] = { 0, 180 };
	float s_ranges[] = { 0, 256 };
	const float* ranges[] = { h_ranges, s_ranges };
	// Use the o-th and 1-st channels     
	int channels[] = { 0, 1 };
	MatND hist_base;
	MatND hist_test1;
	MatND hist_test2;
 
	calcHist(&hsvbase, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false);
	normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());
 
	calcHist(&hsvtest1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
	normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());
 
	calcHist(&hsvtest2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);
	normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());
 
	double basebase = compareHist(hist_base, hist_base, 2);//zx
	double basetest1 = compareHist(hist_base, hist_test1,2);//zx and a
	double basetest2 = compareHist(hist_base, hist_test2, 2);//zx and c
	double tes1test2 = compareHist(hist_test1, hist_test2, 2);//a and c
	printf("test1 compare with test2 correlation value :%f", tes1test2);
 
	Mat test12;
	test2.copyTo(test12);
	putText(base, convertToString(basebase), Point(50, 50), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);  //zx
	putText(test1, convertToString(basetest1), Point(50, 50), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);//zx and a
	putText(test2, convertToString(basetest2), Point(50, 50), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);//zx and c
	putText(test12, convertToString(tes1test2), Point(50, 50), FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);//a and c
 
	namedWindow("base", 0);
	resizeWindow("base", base.cols / 2, base.rows / 2);
	namedWindow("test1", 0);
	resizeWindow("test1", test1.cols / 2, test1.rows / 2);
	namedWindow("test2", 0);
	resizeWindow("test2", test2.cols / 2, test2.rows / 2);
 
	imshow("base", base);
	imshow("test1", test1);
	imshow("test2", test2);
	imshow("test12", test12);
 
	waitKey(0);
	return 0;
}
 
string convertToString(double d) {
	ostringstream os;
	if (os << d)
		return os.str();
	return "invalid conversion";
}

四、图像处理效果

代码中,车道线图片base自行十字交叉性比较,basebase = 36.8538,数值越大,图像相关性程度越高 

base图片与test1图片进行十字交叉性比较,test1base = 9.55181,数值较小,图像相识度较低

下面图像是test1图像与test2图像直方图对比,test2base = 7.98399,相识度较小

到此这篇关于OpenCV图像处理之直方图比较方法详解的文章就介绍到这了,更多相关OpenCV直方图比较内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于C语言实现简单扫雷游戏

    基于C语言实现简单扫雷游戏

    这篇文章主要为大家详细介绍了基于C语言实现简单扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • C++详细讲解引用类型

    C++详细讲解引用类型

    引用指的是对一个对象的引用。那么什么是对象?在c++中狭义的对象指的是用类,结构,联合等复杂数据类型来声明的变量,如 MyClass myclass,CDialog mydlg,等等
    2022-07-07
  • Matlab实现绘制高阶版本韦恩图(upset图)

    Matlab实现绘制高阶版本韦恩图(upset图)

    韦恩图随着阶数升高会越来越复杂,当阶数达到7或者以上时几乎没办法绘制,但是使用upset图却可以比较轻易的绘制。本文就来用Matlab实现绘制upset图,需要的可以参考一下
    2023-01-01
  • C++中取余运算的实现

    C++中取余运算的实现

    这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 深入了解C++异常处理

    深入了解C++异常处理

    任何东西都可以认为是异常,错误只是异常的一种。本文将带大家了解C++中异常是什么,是如何捕获和处理的等相关知识。文中示例代码简洁易懂,感兴趣的小伙伴可以了解一下
    2021-12-12
  • 使用QT连接USB摄像头的方法

    使用QT连接USB摄像头的方法

    这篇文章主要为大家详细介绍了使用QT连接USB摄像头的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C语言编程中实现二分查找的简单入门实例

    C语言编程中实现二分查找的简单入门实例

    这篇文章主要介绍了C语言编程中实现二分查找的简单入门实例,需要的朋友可以参考下
    2015-12-12
  • strtok函数的使用示例

    strtok函数的使用示例

    今天小编就为大家分享一篇关于strtok函数的使用示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • C语言 90后怀旧游戏超级玛丽的实现流程

    C语言 90后怀旧游戏超级玛丽的实现流程

    90后最风靡的游戏是什么?第一个联想到的肯定是插卡游戏机或者VCD加光盘运行在电视机上的超级玛丽了,它的经典绝对可以排在第一位,长大后的我们今天来用C语言重温一下
    2021-11-11
  • C语言顺序查找算法介绍及示例

    C语言顺序查找算法介绍及示例

    顺序查找又称线性查找,主要用于在线性表中进行查找。顺序查找通常分为对一般的无序线性表的顺序查找和对按关键字有序的顺序表的顺序查找,下面我们来一探究竟
    2022-08-08

最新评论