OpenCV实战——使用直方图比较相似图像

Posted 盼小辉丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV实战——使用直方图比较相似图像相关的知识,希望对你有一定的参考价值。

OpenCV实战——使用直方图比较相似图像

0. 前言

基于内容的图像检索是计算机视觉中的一个重要问题,用于查询与给定图像具有相似内容的图像。我们知道直方图是表征图像内容的一种有效方式,因此它们可用于解决基于内容的图像检索问题。

1. 基于直方图衡量图像相似性

使用直方图进行图像检索的关键是通过比较图像的直方图来衡量两个图像之间的相似性,因此需要定义一个测量函数,用于估计两个直方图的相似程度。有多种方法可以衡量图像间的相似度,在 OpenCV 中可以使用 cv::compareHist 函数进行计算。

(1) 为了将给定图像与一组图像进行比较并找到与该查询图像最相似的图像,我们创建 ImageComparator 类,此类包含对查询图像和一组输入图像及它们直方图的引用。此外,我们使用颜色直方图进行比较,因此可以使用 ColorHistogram 类:

class ImageComparator 
    private:
        cv::Mat refH;       // 参考直方图
        cv::Mat inputH;     // 输入图像直方图
        ColorHistogram hist;
        int nBins;          // 每个通道使用的 bin 数量
    public:
        ImageComparator() : nBins(8) 

(2) 要获得可靠的相似性度量,应在减少 bin 数量后的直方图上进行计算。因此,ImageComparator 类需要可以指定要在每个 BGR 通道中使用的 bin 数量:

// 设置 bin 数量
void setNumberOfBins(int bins) 
    nBins = bins;

(3) 使用适当的 setter 指定查询图像,该 setter 也需要计算给定图像的直方图:

// 计算参考图像直方图
void setReferenceImage(const cv::Mat& image) 
    hist.setSize(nBins);
    refH = hist.getHistogram(image);

(4) 最后,compare 方法将查询图像与给定的输入图像进行比较,并返回一个分数表示两个图像的相似程度:

// 使用 BGR 直方图比较图像
double compare(const cv::Mat& image) 
    inputH = hist.getHistogram(image);
    return cv::compareHist(refH, inputH, cv::HISTCMP_INTERSECT);

(5) ImageComparator 类可用于检索与给定查询图像相似的图像:

ImageComparator c;
c.setReferenceImage(image);
  1. 我们使用的查询图像是人像图像,此图像与一组图像进行比较:

比较结果如下图所示,图像按相似度从大到小顺序排列显示:

2. 其它测量方法

大多数直方图的相似性度量都是基于逐个 bin 的比较,因此在测量两个颜色直方图的相似性时使用减少 bin 数量的直方图能够在保证准确率的同时提高比较效率。调用 cv::compareHist 函数,只需输入两个直方图,该函数就会返回两个直方图间距离。通过使用标志位可以指定不同的的测量方法,在 ImageComparator 类中,我们使用了相交方法 (CV_COMP_INTERSECT)。这种方法只是简单地比较两个直方图中每个 bin 的值并保留两者中的最小值,因此,相似性度量是这些最小值之和;因此,如果两个图像没有共同颜色,它们的直方图的交集值为 0,而两个相同的直方图间的距离等于图像中的总像素数。
也可以使用其他测量方法:卡方测量 (HISTCMP_CHISQR),对 bin 之间的归一化平方差求和;相关方法 (HISTCMP_CORREL),基于信号处理中使用的归一化互相关算子测量两个信号之间的相似性;以及 Bhattacharyya 测量 (HISTCMP_BHATTACHARYYA),在统计学中用于估计两个概率分布之间的相似性。

3. 完整代码

头文件 imageComparator.h 代码如下:

#if !defined ICOMPARATOR
#define ICOMPARATOR

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "colorhistogram.h"

class ImageComparator 
    private:
        cv::Mat refH;       // 参考直方图
        cv::Mat inputH;     // 输入图像直方图
        ColorHistogram hist;
        int nBins;          // 每个通道使用的 bin 数量
    public:
        ImageComparator() : nBins(8) 
        // 设置 bin 数量
        void setNumberOfBins(int bins) 
            nBins = bins;
        
        int getNumberOfBins() 
            return nBins;
        
        // 计算参考图像直方图
        void setReferenceImage(const cv::Mat& image) 
            hist.setSize(nBins);
            refH = hist.getHistogram(image);
        
        // 使用 BGR 直方图比较图像
        double compare(const cv::Mat& image) 
            inputH = hist.getHistogram(image);
            return cv::compareHist(refH, inputH, cv::HISTCMP_INTERSECT);
        
;

#endif

主函数代码 retrieve.cpp 如下所示:

#include <iostream>
using namespace std;

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

#include "imageComparator.h"

int main() 
    // 读取参考图像
    cv::Mat image = cv::imread("12.png");
    if (!image.data) return 0;
    // 显示图像
    cv::namedWindow("Query Image");
	cv::imshow("Query Image",image);
	ImageComparator c;
	c.setReferenceImage(image);
    // 读取图像并进行对比
    cv::Mat input = cv::imread("2.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("3.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("4.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("5.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("6.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("7.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("8.png");
    cout << " vs " << c.compare(input) << endl;
    input = cv::imread("9.png");
    cout << " vs " << c.compare(input) << endl;
    cv::waitKey();
    return 0;

相关链接

OpenCV实战(1)——OpenCV与图像处理基础
OpenCV实战(2)——OpenCV核心数据结构
OpenCV实战(3)——图像感兴趣区域
OpenCV实战(4)——像素操作
OpenCV实战(5)——图像运算详解
OpenCV实战(6)——OpenCV策略设计模式
OpenCV实战(7)——OpenCV色彩空间转换
OpenCV实战(8)——直方图详解
OpenCV实战——基于均值漂移算法检测图像内容

以上是关于OpenCV实战——使用直方图比较相似图像的主要内容,如果未能解决你的问题,请参考以下文章

opencv:图像直方图相似性比较

OpenCV进行图像相似度对比的几种办法

如何使用opencv比较存储在文件中的两个图像

匹配 OpenCV 中相似直方图的对应峰/谷

从 OpenCv 图像比较中获取比较分数

java版 opencv 图像对比相似度怎么实现