【计算机视觉】OpenCV中直方图处理函数简述

计算直方图calcHist

直方图是对数据集合的统计 ,并将统计结果分布于一系列预定义的bins中。这里的数据不仅仅指的是灰度值 ,统计数据可能是任何能有效描述图像的特征。

假设有一个矩阵包含一张图像的信息 (灰度值 0-255):

gray

既然已知数字的范围包含256个值, 我们可以将这个范围分割成子区域(称作 bins),如:

bins

然后再统计掉入每一个bin_{i}的像素数目。采用这一方法来统计上面的数字矩阵,我们可以得到下图( x轴表示 bin, y轴表示各个bin中的像素个数)。

hist1

直方图可以统计的不仅仅是颜色灰度,它可以统计任何图像特征(如梯度,方向等等)。

直方图具体细节

dims: 需要统计的特征的数目,在上例中,dims = 1因为我们仅仅统计了灰度值(灰度图像)

bins: 每个特征空间子区段的数目,在上例中,bins = 16

range: 每个特征空间的取值范围,在上例中,range = [0,255]

OpenCV的直方图计算

OpenCV提供了一个简单的计算数组集(通常是图像或分割后的通道)的直方图函数calcHist。支持高达32维的直方图。

void calcHist(
const Mat* arrays,            // 图像源数组,同样深度(CV_8U or CV_32F),同样大小
int narrays,                 // 图片个数
const int* channels,         // 通道
InputArray mask,             // 掩码图像
OutputArray hist,             // 返回的直方图
int dims,                     // 直方图的维数
const int* histSize,         // 每一维上直方图的个数
const float** ranges,        // 像素值的范围
bool uniform=true,
bool accumulate=false );

说明:

channels - 用来计算直方图的channels的数组

mask - 掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算

dim - 直方图的维数。必须为正,并且不大于CV_MAX_DIMS(当前的OpenCV版本中为32,即最大可以统计32维的直方图)

histSize - 在每一维上直方图的个数。简单把直方图看作一个一个的竖条的话,就是每一维上竖条的个数

ranges - 用来进行统计的范围

反投影直方图

反向投影是一种记录给定图像中的像素点如何适应直方图模型像素分布的方式。

简单的讲,所谓反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征。

void calcBackProject(
const Mat* arrays,
int narrays,
const int* channels,
InputArray hist,
OutputArray backProject,
const float** ranges,
double scale=1, bool uniform=true );

hist - 输入直方图

backProject - 反投影向量,这是一个单通道的向量,和arrays[0]具有相同的大小和深度

下面使用肤色直方图为例来解释反向投影的工作原理:

使用模型直方图(代表手掌的皮肤色调)来检测测试图像中的皮肤区域,

  • 对测试图像中的每个像素 ( p(i,j) ),获取色调数据并找到该色调( h(i,j), s(i,j) )在直方图中的bin的位置
  • 查询 模型直方图 中对应的bin( h(i,j), s(i,j) )并读取该bin的数值
  • 将此数值储存在新的图像中(BackProjection)。 你也可以先归一化 模型直方图 ,这样测试图像的输出就可以在屏幕显示了
  • 通过对测试图像中的每个像素采用以上步骤, 得到 BackProjection 结果图

    backProjection

  • 使用统计学的语言, BackProjection 中储存的数值代表了测试图像中该像素属于皮肤区域的概率。比如以上图为例, 亮起的区域是皮肤区域的概率更大(事实确实如此),而更暗的区域则表示更低的概率

阈值化

阈值是最简单的图像分割的方法。

应用举例:从一副图像中利用阈值分割出我们需要的物体部分(当然这里的物体可以是一部分或者整体)。这样的图像分割方法是基于图像中物体与背景之间的灰度差异,而且此分割属于像素级的分割。

为了从一副图像中提取出我们需要的部分,应该用图像中的每一个像素点的灰度值与选取的阈值进行比较,并作出相应的判断。(注意:阈值的选取依赖于具体的问题。即:物体在不同的图像中有可能会有不同的灰度值。)

一旦找到了需要分割的物体的像素点,我们可以对这些像素点设定一些特定的值来表示。(例如:可以将该物体的像素点的灰度值设定为:‘0’(黑色),其他的像素点的灰度值为:‘255’(白色);当然像素点的灰度值可以任意,但最好设定的两种颜色对比度较强,方便观察结果)。

Threshold_Example

阈值类型

Threshold Type 1

Threshold Type 2

Threshold Type 3

Threshold Type 4

Threshold Type 5

阈值API

double threshold(
InputArray src,
OutputArray dst,
double thresh,
double maxVal,
int thresholdType);

均值漂移(Mean Shift)算法函数

该函数利用了迭代物体搜索算法,它要以一个物体的反射直方图(back projection)和初始位置作为输入。

搜索窗口的重心向反射直方图的质心(mass center)移动,该过程不断的重复,直到达到了迭代的次数(criteria.maxCount),或者窗口中心小于一个阈值(criteria.epsilon)。

int meanShift(
InputArray probImage,         // Back projection of the object histogram
Rect& window,                 // Initial search window
TermCriteria criteria        // Stop criteria for the iterative search algorithm.
);

Camshift算法函数

该函数首先利用meanShift()函数找到物体的中心,然后调整窗口的大小并找到最优的旋转角度。该函数返回一个rotated rectangle数据结构(包含物体的位置,大小和旋转角度)。下一次搜索窗口的位置可以通过RotatedRect::boundingRect()得到。

RotatedRect CamShift(
InputArray probImage,         // Back projection of the object histogram
Rect& window,                 // Initial search window
TermCriteria criteria        // Stop criteria for the underlying meanShift()
);

TermCriteria模板类

该类是作为迭代算法的终止条件使用的,其构造函数需要三个参数:一个是类型,第二个参数为迭代的最大次数,最后一个是特定的阈值。

TermCriteria(int type, int maxCount, double epsilon);

类型有CV_TERMCRIT_ITER、CV_TERMCRIT_EPS、CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,分别代表着迭代终止条件为达到最大迭代次数终止,迭代到阈值终止,或者两者都作为迭代终止条件。

参考资料

OpenCV Histograms API文档

直方图之calcHist使用

直方图之calcHist使用(补)

OpenCV 教程 imgproc模块

反向投影

阈值操作

转载请注明作者Jason Ding及其出处

Github主页(http://jasonding1354.github.io/)

CSDN博客(http://blog.csdn.net/jasonding1354)

简书主页(http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)

时间: 2024-11-07 05:21:24

【计算机视觉】OpenCV中直方图处理函数简述的相关文章

Opencv中直方图函数calcHist

calcHist函数在Opencv中是极难理解的一个函数,一方面是参数说明晦涩难懂,另一方面,说明书给出的实例也不足以令人完全搞清楚该函数的使用方式.最难理解的是第6,7,8个参数dims.histSize和ranges.以前一直都是想当然认为,该函数可以一次统计多张图片每个通道的灰度值数据,实际上calcHist函数一次只能统计一个通道上的直方图.我估计许多同学都犯过和我类似的错误,认为第5个参数hist,可以根据dims设定维度,比如dims=3,则输出的hist的维度就是3,并且会想当然的

openCV中的findHomography函数分析以及RANSAC算法的详解

本文将openCV中的RANSAC代码全部挑选出来,进行分析和讲解,以便大家更好的理解RANSAC算法.代码我都试过,可以直接运行. 在计算机视觉和图像处理等很多领域,都需要用到RANSAC算法.openCV中也有封装好的RANSAC算法,以便于人们使用.关于RANSAC算法的一些应用,可以看我的另一篇博客: 利用SIFT和RANSAC算法(openCV框架)实现物体的检测与定位,并求出变换矩阵(findFundamentalMat和findHomography的比较) 但是前几天师弟在使用op

OpenCV中的常用函数

1.cvLoadImage:将图像文件加载至内存: 2.cvNamedWindow:在屏幕上创建一个窗口: 3.cvShowImage:在一个已创建好的窗口中显示图像: 4.cvWaitKey:使程序暂停,等待用户触发一个按键操作: 5.cvReleaseImage:释放图像文件所分配的内存: 6.cvDestroyWindow:销毁显示图像文件的窗口: 7.cvCreateFileCapture:通过参数设置确定要读入的AVI文件: 8.cvQueryFrame:用来将下一帧视频文件载入内存:

(转)OpenCV中的常用函数

1.cvLoadImage:将图像文件加载至内存: 2.cvNamedWindow:在屏幕上创建一个窗口: 3.cvShowImage:在一个已创建好的窗口中显示图像: 4.cvWaitKey:使程序暂停,等待用户触发一个按键操作: 5.cvReleaseImage:释放图像文件所分配的内存: 6.cvDestroyWindow:销毁显示图像文件的窗口: 7.cvCreateFileCapture:通过参数设置确定要读入的AVI文件: 8.cvQueryFrame:用来将下一帧视频文件载入内存:

5、opencv中的绘图函数

1.目标 a.学习使用 OpenCV 绘制不同几何图形 b. 你将会学习到这些函数: cv2.line(), cv2.circle(), cv2.rectangle(),cv2.ellipse(),cv2.putText() 等. 2.代码 上面所有的这些绘图函数需要设置下面这些参数: img:你想要绘制图形的那幅图像. color: 形状的颜色. 以 RGB 为例, 需要传入一个元组, 例如: (255,0,0)代表蓝色.对于灰度图只需要传入灰度值. thickness:线条的粗细.如果给一个

OpenCV中的新函数connectedComponentsWithStats使用

主要内容:对比新旧函数,用于过滤原始图像中轮廓分析后较小的区域,留下较大区域. 关键字    :connectedComponentsWithStats 在以前,常用的方法是"是先调用 cv::findContours() 函数(传入cv::RETR_CCOMP 标志),随后在得到的连通区域上循环调用 cv::drawContours() " 比如,我在GOCVHelper中这样进行了实现 //寻找最大的轮廓 VP FindBigestContour(Mat src){ int ima

OpenCV中的绘图函数

OpenCV可以用来绘制不同的集合图形,包括直线,矩形,圆,椭圆,多边形以及在图片上添加文字.用到的绘图函数包括 cv2.line(),cv2.circle(),cv2.rectangle() ,cv2.putText() 等等. 这些绘图函数需要设置参数如: ? img:你想要绘制图形的那幅图像.? color:形状的颜色.以 RGB 为例,需要传入一个元组,例如: (255,0,0 )代表蓝色.对于灰度图只需要传入灰度值.? thickness:线条的粗细.如果给一个闭合图形设置为 -1,那

OpenCV中使用cvResize函数或resize函数进行图象放缩

//cvResize函数原型void cvResize( const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR ); src:输入图像.(IplImage) dst:输出图像.(IplImage) interpolation:差值方法: CV_INTER_NN - 最近邻差值 CV_INTER_LINEAR - 双线性差值 (缺省使用) CV_INTER_AREA - 使用象素关系重采样.当图像缩小时候,该方法可以避免波纹

opencv中自适应阈值函数的实现(c++)

根据<面向飞机蒙皮接缝的线结构光检测技术研究_张卡>论文中的原理,编写了自适应阈值函数 原理: 1 //计算灰度最大最小值 2 void MaxGrayValue(Mat image,int &max,int &min) 3 { 4 max = 0; 5 min = 255; 6 Mat *im = reinterpret_cast<Mat*>((void*)&image); 7 int height = image.rows; 8 int width =