opencv第七章-直方图与匹配

本文介绍了OpenCV中直方图的概念及其在图像处理中的应用,包括直方图的统计作用,如边缘和色彩分布。通过创建、设置直方图范围、访问和操作直方图,以及提供示例代码展示了直方图的计算和显示过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

opencv第七章-直方图与匹配

一、基本概念

在分析图像、物体和视频信息的过程中,我们常常想把眼中看到的物体用直方图表示。直方图可以用来描述各种不同的事情,如物体的色彩分布、物体边缘梯度模板,以及表示目标位置的当前假设(目标当前位置的假设?)的概率分布。


设置一个摄像机,该摄像机观察人的各种手势以控制网络视频。在每帧中,从输入的视频中检测感兴趣的色彩区域,然后计算这些感兴趣区域周围的边缘梯度方向,将得到的边缘梯度方向放到一个方向直方图相应的bin中,然后将该直方图与手势模板进行匹配,从而识别出各种手势。


直方图广泛应用于很多计算机视觉应用中。通过标记帧与帧之间显著的边缘和颜色的统计变化,直方图被用来检测视频中场景的变换。通过为每个兴趣点设置一个有相近特征的直方图所构成的“标签”,用以确定图像中的兴趣点。边缘、色彩、角等直方图构成了可以被传递给目标识别分类器的一个通用特征类型。色彩和边缘的直方图序列还可以用来识别网络视频是否被复制等。直方图是计算机视觉中最经典的工具之一。


简单地说,直方图就是对数据进行统计,将统计值组织到一系列事先定义好的bin中。bin中的数值是从数据中计算出的特征的统计量,这些数据可以是诸如梯度、方向、色彩或任何其他特征。无论如何,直方图获得的是数据分布的统计图。通常直方图的维数要低于原始数据。


表示连续分布的直方图通过隐式计算每个网格单元中点的均值来实现前面的功能。这就会产生一个问题。如果网格太宽,则参与计算平均值的点太多,就会丧失分布的结构。如果网格太窄,则没有足够的点来准确表示分布而且我们会得到小而尖锐的单元。


opencv有表征直方图的数据类型。该直方图数据结构能够以一维或者多维的方式表示直方图,并且包含所有可能跟踪的均匀或非均匀的bin中的数据。并且,如我们所期待的,它可以配属各种有用的函数,使得我们能够在直方图上容易地进行各种常见操作。


二、直方图的基本数据结构

(1)CvHistogram   是个直方图数据结构。

(2)cvCreateHist   创建一个直方图

(3)cvSetHistBinRanges   设置直方图中的ranges值

(4)cvClearHist   直方图的bins清0

(5)cvMakeHistHeaderForArray   根据已给出的数据创建直方图


三、访问直方图

cvQueryHistValue_1D

cvQueryHistValue_2D

cvQueryHistValue_3D

cvQueryHistValue_nD


四、直方图的基本操作

cvNormalizeHist   直方图的归一化

cvThreshHist    直方图阈值化

cvCopyHist   复制直方图

cvGetMInMaxHistValue   直方图中最大值最小值

cvCalcHist   计算直方图的总像素点(处理单通道图像)


五、例程

#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <cxcore.h>
using namespace std;
using namespace cv;
int main()
{
IplImage *src=cvLoadImage("f.jpg");
cout<<"total_pixel : "<<src->width*src->height<<endl;
assert(src);
IplImage *hsv=cvCreateImage(cvGetSize(src),8,3);
cvCvtColor(src,hsv,CV_BGR2HSV);//转换为hsv格式
IplImage *h_plane = cvCreateImage(cvGetSize(src),8,1);
IplImage *s_plane = cvCreateImage(cvGetSize(src),8,1);
IplImage *v_plane = cvCreateImage(cvGetSize(src),8,1);
IplImage *planes[] = {h_plane,s_plane};
cvCvtPixToPlane(hsv,h_plane,s_plane,v_plane,0);//分割多通道数组
int h_bins=30,s_bins=40;
int hist_size[]={h_bins,s_bins};
float h_ranges[]={0,256};
float s_ranges[]={0,256};
float *ranges[]={h_ranges,s_ranges};
int scale = 10;
IplImage *hist_img = cvCreateImage(cvSize(h_bins*scale,s_bins*scale),8,3);
CvHistogram *hist;
float max_value = 0;
int h,s;
hist = cvCreateHist(2,hist_size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(planes,hist,0,0);
cvGetMinMaxHistValue(hist,0,&max_value,0,0);
cvZero(hist_img);
float cnt=0;
for(h=0;h<h_bins;h++)
{
for(s=0;s<s_bins;s++)
{
float bin_val=cvQueryHistValue_2D(hist,h,s);
cnt += bin_val;
int intensity = cvRound(bin_val*255/max_value);
cvRectangle(hist_img,cvPoint(h*scale,s*scale),
cvPoint((h+1)*scale - 1,(s+1)*scale - 1),
CV_RGB(intensity,0,0),
CV_FILLED);
}
}
cout<<"cnt = "<<cnt<<endl;
cvShowImage("h_s histogram " ,hist_img);
cvShowImage("src",src);
cvSaveImage("h_s histogram.bmp",hist_img);
cvWaitKey();
cvReleaseHist(&hist);
cvReleaseImage(&src);
cvReleaseImage(&hist_img);
cvDestroyAllWindows();
}

详细过程不细说,总结一下直方图流程:

(1)确定直方图的维数dims(1,2,3,4)。

(2)确定一个整数数组sizes[],数组长度等于dims,数组中的每一个整数表示分配给对应维数的bin的个数。

(3)确定type是密集多维矩阵结构还是稀疏矩阵。

(4)ranges为范围划分,bin里面像素划分

(5)uniform=1






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值