当前位置:网站首页>opencv 直方图比较
opencv 直方图比较
2022-08-03 17:24:00 【小魔王降临】
函数
CV_EXPORTS_W double compareHist( InputArray H1, InputArray H2, int method );
//! compares two histograms stored in sparse arrays
CV_EXPORTS double compareHist( const SparseMat& H1, const SparseMat& H2, int method );标志参数 | 简记 | 作用 |
|---|---|---|
HISTCMP_CORREL | 0 | 相关法 |
HISTCMP_CHISQR | 1 | 卡方法 |
HISTCMP_INTERSECT | 2 | 直方图相交法 |
HISTCMP_BHATTACHARYYA | 3 | 巴塔恰里雅距离(巴氏距离)法 |
HISTCMP_HELLINGER | 3 | 与HISTCMP_BHATTACHARYYA方法相同 |
HISTCMP_CHISQR_ALT | 4 | 替代卡方法 |
HISTCMP_KL_DIV | 5 | 相对熵法(Kullback-Leibler散度) |
用途
- 利用直方图的方式进行批量的图片缺陷检测(方法简单)
- 图像相似度比较
如果我们有两张图像,并且这两张图像的直方图一样,或者有极高的相似度,那么在一定程度上,我们可以认为这两幅图是一样的,这就是直方图比较的应用之一。
- 分析图像之间关系
两张图像的直方图反映了该图像像素的分布情况,可以利用图像的直方图,来分析两张图像的关系。
步骤
a.加载图像
b.将图像从BGR空间转化为HSV空间
cvtColor()把图像从RGB色彩空间转换到HSV色彩空间
c.计算直方图并归一化处理,
计算图像的直方图,然后归一化到[0~1]之间,用到函数 calcHist() 和 normalize() ;
d.直方图比较
HISTCMP_CORREL 相关性比较 值越大,相关度越高,最大值为1,最小值为0
HISTCMP_CHISQR 卡方法 值为0最好,值越小,相关度越高,最大值无上界,最小值0
HISTCMP_INTERSECT 十字交叉性 (计算公式为取两个直方图每个相同位置的值的最小值,然后求和,这个比较方式不是很好,不建议使用)
HISTCMP_BHATTACHARYYA 巴氏距离(比较结果是很准的,计算结果范围为 0-1 ,0表示两个直方图非常相关,1最不相似) 在直方图相似度计算时,巴氏距离获得的效果最好,但计算是最为复杂的。
HISTCMP_HELLINGER
HISTCMP_CHISQR_ALT
该方法与巴氏距离法相同,常用于替代巴氏距离法用于纹理比较
HISTCMP_KL_DIV
该方法名为相对熵法,又名Kullback-Leibler散度法,在该方法中如果两个图像直方图完全一致,则计算数值为0,两个图像的相似性越小,计算数值越大。
使用上述方法之一进行比较,用到函数compareHist()。

std::array<char, 256> cwd;
std::cout << "exe 路径: " << _getcwd(cwd.data(), (int)cwd.size()) << std::endl;
size_t pos = (std::string(cwd.data())).find_last_of("\\");
std::string path = std::string(cwd.data()).substr(0, pos) + "\\image";
std::vector<std::string> paths;
cv::glob(path, paths);
cv::Mat src1 = cv::imread(paths[0], cv::IMREAD_COLOR);
cv::Mat src2 = cv::imread(paths[1], cv::IMREAD_COLOR);
//计算相似度
if (src2.channels() == 1)
{
//单通道时
std::vector<cv::Mat>(src1);
std::vector<int> channels{ 0 }; //单通道索引
std::vector<int> histSizes{ 256 }; //直方图横轴大小
std::vector<float> ranges{ 0, 256 }; //统计范围 像素值
cv::MatND hist1;
cv::calcHist(std::vector<cv::Mat>(src1), channels, cv::Mat(), hist1, histSizes, ranges);
cv::normalize(hist1, hist1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
cv::Mat hist2;
cv::calcHist(std::vector<cv::Mat>(src2), channels, cv::Mat(), hist1, histSizes, ranges);
cv::normalize(hist2, hist2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
double correl = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL);
double chisqr = cv::compareHist(hist1, hist2, cv::HISTCMP_CHISQR);
double intersect = cv::compareHist(hist1, hist2, cv::HISTCMP_INTERSECT);
double bhattacharyya = cv::compareHist(hist1, hist2, cv::HISTCMP_BHATTACHARYYA);
cout << "correl = " << correl << endl;
cout << "chisqr = " << chisqr << endl;
cout << "intersect = " << intersect << endl;
cout << "bhattacharyya = " << bhattacharyya << endl;
}
else
{
//三通道时
cv::cvtColor(src2, src1, cv::COLOR_BGR2HSV);
cv::cvtColor(src1, src2, cv::COLOR_BGR2HSV);
int h_bins = 50, s_bins = 60;
int histSize[] = { h_bins, s_bins }; //柱状个数(横轴)
float h_ranges[] = { 0, 180 };
float s_ranges[] = { 0, 256 };//像素值 统计范围
const float* ranges[] = { h_ranges, s_ranges };
int channels[] = { 0, 1 };
cv::MatND hist1;
cv::calcHist(&src2, 1, channels, cv::Mat(), hist1, 2, histSize, ranges);
cv::normalize(hist1, hist1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
//计算二维
cv::MatND hist2;
cv::calcHist(&src1, 1, channels, cv::Mat(), hist2, 2, histSize, ranges);
cv::normalize(hist2, hist2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
//只比较二维
double correl = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL);
double chisqr = cv::compareHist(hist1, hist2, cv::HISTCMP_CHISQR);
double intersect = cv::compareHist(hist1, hist2, cv::HISTCMP_INTERSECT);
double bhattacharyya = cv::compareHist(hist1, hist2, cv::HISTCMP_BHATTACHARYYA);
cout << "3 channels correl = " << correl << endl;
cout << "3 channels chisqr = " << chisqr << endl;
cout << "3 channels intersect = " << intersect << endl;
cout << "3 channels bhattacharyya = " << bhattacharyya << endl;
}
边栏推荐
- 掌握Redis的Sentinel哨兵原理,可助你拿到25k的offer
- JVS低代码-多数据模型与数据联动配置举例
- TypeScript的配置文件tsconfig.json
- 使用o.execute_sql 查询很很很小的表, 要7/8秒钟, 这个怎么解决
- 星巴克输血赶不上流血
- 怎么在opengauss中进行测试自己添加的新函数的性能(循环n次的运行时间)?
- 【Metaverse系列一】元宇宙的奥秘
- [Unity Starter Plan] Making RubyAdventure01 - Player Creation & Movement
- 11. Container With Most Water
- Which thread pool does Async use?
猜你喜欢
随机推荐
ASP.NET Core依赖注入之旅:3.Service Locator和依赖注入
Web3 安全风险令人生畏?应该如何应对?
Cool open technology x StarRocks: unified OLAP analysis engine, comprehensive building digital model of OTT
Huawei, Lenovo, BAIC, etc. were selected as the first batch of training bases for "Enterprise Digital Transformation and Security Capability Improvement" by the Ministry of Industry and Information Te
关于oracle表空间在线碎片整理
JS 字符串转 GBK 编码超精简实现
持续投入商品研发,叮咚买菜赢在了供应链投入上
error:Illegal instruction (core dumped),离线下载安装这个other版本numpy
怎么在opengauss中进行测试自己添加的新函数的性能(循环n次的运行时间)?
华为、联想、北汽等入选工信部“企业数字化转型和安全能力提升”首批实训基地
[Unity Getting Started Plan] Basic Concepts (7) - Input Manager & Input Class
【指针初解】
SwinIR combat: record the training process of SwinIR in detail
Async的线程池使用的哪个?
被误解的 MVC 和被神化的 MVVM(二)
并查集模板及思想
[Unity Starter Plan] Making RubyAdventure01 - Player Creation & Movement
C# 构造函数如人之影子
security加密解密
使用deepstream消息发送功能的时候,检测框没有检测标签,No text labels of bboxes displayed with osd for deepstream-test5








