OpenCV直方图与反向投影

20 篇文章 0 订阅

OpenCV直方图与反向投影

前言

在计算机视觉中,直方图的有着很广泛的的应用,通常用来统计图像中的某些特征,比如边缘特征、色彩特征、梯度特征等等。直方图通过一种统计的方法,来表征图形的特征。这篇文章简单来探讨一下直方图以及它的一个应用–反向投影。

直方图

直返图的计算其实很简单,和我们数学中的直方图差不多,就是统计某一特征,在这里我们用统计灰度值举例子。
首先来看一段画直方图的代码:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{
    Mat img = imread("football2.png");
    cout << "img size " << img.size() << endl;
    cvtColor(img, img, COLOR_BGR2GRAY);
    imshow("img", img);

    Rect rect(330, 270, 160, 160); //lofated of football
    Mat img_obj = img(rect);
    imshow("img_obj", img_obj);

    int bin = 4;
    int channels = 0;
    int size = 256 / bin;
    float hranges[] = {0, 256};
    const float *ranges[] = {hranges};
    const float *ranges_back = {hranges};

    // 计算直方图
    MatND hist;
    calcHist(&img_obj, 1, &channels, Mat(), hist, 1, &size, ranges);

	double minValue = 0;
	double maxValue = 0;
	minMaxLoc(hist, &minValue, &maxValue, 0, 0);
    cout << "maxValue: " << maxValue << endl;

    Mat img_hist(maxValue, size, CV_8UC3, Scalar(0, 0, 0));
	for (int i = 0; i < size; i++)
	{
        float bin_value = hist.at<float>(i);
        rectangle(img_hist,Point(i, maxValue), Point(i+1, maxValue-bin_value), Scalar(0, 255, 0));
	}
    imshow("img_hist", img_hist);

    ......
    waitKey(0);
    return 0;
}

直方图有个一概念,就是bin,其实是组距的意思,代码中是4,就是按照[0, 4)、[4, 8)、[8, 12)…[251,255)为x轴来做统计的。
整个代码其实简单,OpenCV画直方图的函数是calcHist,我们要了解函数的用法以及每个参数的意思,在这了不在赘述。另外,它的原理其实不难,如果想自己实现一下,应该也是比较简单的。

反向投影

在这篇博客https://blog.csdn.net/zhangjunp3/article/details/79862424是这样说的

反向投影其实是直方图运算的逆过程。直方图运算是统计每个灰度值对应的像素个数,而反向投影则是将像素个数回送到该像素个数对应灰度区间的像素位置。
反向投影是直方图运算的逆过程,这个是最最要的内容,上面讲的已经差不多了,下面我们自己来实现一下反向投影。

接着上面直方图的代码继续:

	......
	//将直方图归一化为[0, 255]区间,方面下面可视化
    normalize(hist, hist, 0, 255, NORM_MINMAX, -1, Mat());

    Mat img_back_proj = img.clone();
    for (int i = 0; i < img_back_proj.rows; i++)
    {
        uchar *p = img_back_proj.ptr<uchar>(i);
        for (int j = 0; j < img_back_proj.cols; j++)
        {
            p[j] = hist.at<float>(p[j] / bin);
        }
    }
    imshow("img_back_proj", img_back_proj);

    waitKey(0);
	return 0;
}

代码的核心就是这句话:p[j] = hist.at(p[j] / bin);
将p[j]位置的像素值带到直放图的x轴,得到该像素值在直方图中的个数,用统计的个数取代原先的像素值。
代码的运行结果如下:
在这里插入图片描述
可以看出来,在这个例子中足球的匹配效果还是很好的,
在这个例子中,我们用的是灰度值做的直方图,另外的一些特征,比如颜色,边缘都是可以用来做统计的。

与我联系

微信公众号,扫二维码即可关注:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

chasentech

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

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

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

打赏作者

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

抵扣说明:

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

余额充值