Histogram-灰度直方图

前言

什么是直方图?

直方图是对数据的集合做统计,并将统计结果分布于一系列预定义的bins中。

例如: 

图片通道化

如果我按照某种方式去统计通道中的这些数字,会发生什么情况呢?既然以知数字的范围是包含256个色值(这里是8bit无符号四通道图像 2^8 = 256),我们可以将这个范围分割成子区域(称作 bins), 如:

[0, 255] = { [0, 15] U [16, 31]U ....U[240,255] } 

range = { bin_{1} U bin_{2} U ....U bin_{n = 15} }

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

直方图

以上只是一个说明直方图如何工作以及它的用处的简单示例。直方图可以统计的不仅仅是颜色灰度, 它可以统计任何图像特征 (如 梯度, 方向等等)。

让我们再来搞清楚直方图的一些具体细节:

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

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

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

怎样去统计两个特征呢? 在这种情况下, 直方图就是3维的了,x轴和y轴分别代表一个特征, z轴是掉入 (bin_{x}, bin_{y}) 组合中的样本数目。 同样的方法适用于更高维的情形 (当然会变得很复杂。

OpenCV的直方图计算

OpenCV提供了一个简单的计算数组集(通常是图像或分割后的通道)的直方图函数 calcHist 。 支持高达 32 维的直方图。下面的代码演示了如何使用该函数计算直方图!

基本的逻辑就是将一张图像通道化,计算各通道图像的直方图并返回显示。

首先将UIImage对象转成OpenCV Mat 数据结构:

Mat img = [FaceDetection CVMatFromUIImage:image];//这段代码OpenCV已经写好了

然后我们需要将Mat图像数据通道化:

cv::split(img, img_channels);

CV_EXPORTS void split(const Mat& src, Mat* mvbegin);

@param src input multi-channel array.

@param mvbegin output array; the number of arrays must match src.channels(); the arrays themselves arereallocated, if needed.

意思就是传一个多通道图像,传出一个装载各通道的数组。

第一步-图像通道化

接着就需要通过直方图CvHistogram类来处理每一个通道数据。

CVAPI(CvHistogram*)  cvCreateHist( int dims, int* sizes, int type,float** ranges CV_DEFAULT(NULL),int uniform CV_DEFAULT(1));API是有这个函数😓

@param dims Number of histogram dimensions.这参数前言中已经提到过。

@param sizes Array of the histogram dimension sizes. 就相当于 bins 

@param type Histogram representation format. CV_HIST_ARRAY means that the histogram data is represented as a multi-dimensional dense array CvMatND. CV_HIST_SPARSE means that histogram data is represented as a multi-dimensional sparse array CvSparseMat.直方图疏密程度

@param ranges Array of ranges for the histogram bins. Its meaning depends on the uniform parameter value. The ranges are used when the histogram is calculated or backprojected to determine which .

@param uniform.....这里看都不用看了😅因为通过我的实验OpenCV 3.2里只有下边这个函数

创建直方图类

那我说如果我几就需要用Range uniform这些呢?

CVAPI(void)  cvSetHistBinRanges( CvHistogram* hist, float** ranges,int uniform CV_DEFAULT(1));

cvSetHistBinRanges(CvHistogram *hist, float **ranges)

又骗我?😄。我感觉它这些函数有规律的,只要有CV_DEFAULT的这些参数的,就不需要填,它知道你也填DEFAULT,就帮你填好了,当然你填了就调用的你填的参数,很强!

接下来就需要调用Histogram类的计算直方图方法:

CVAPI(void)  cvCalcArrHist( CvArr** arr, CvHistogram* hist,int accumulate CV_DEFAULT(0),const CvArr* mask CV_DEFAULT(NULL) );/** @overload */

CV_INLINE  void  cvCalcHist( IplImage** image, CvHistogram* histint accumulate CV_DEFAULT(0),const CvArr* mask CV_DEFAULT(NULL) ){

cvCalcArrHist( (CvArr**)image, hist, accumulate, mask );

}

给了一个重载方法。我们用重载函数就好了。需要说的是 CvArr,IplImage,CvMat,其实是一个东西,它自己没说,但确实有人说了😄:

§ CvArr -This is the "metatype" used only as a function parameter.

It denotes that the function accepts arrays of multiple types, such as IplImage*, CvMat* or even CvSeq* sometimes. The particular array type is determined at runtime by analyzing the first 4 bytes of the header. In C++ interface the role of CvArr is played by InputArray and OutputArray.

我们就可以这样想:到这里channel里的图像数据已经被Histogram做好Collection了,现在需要做的就是拿出bins绘制图像。需要注意的是,在IplImage结构体中有这样一个属性int origin.

int  origin;            /**< 0 - top-left origin,1 - bottom-left origin (Windows bitmaps style).  */我是这样理解的:你给我的图片有可能是从下边开始计算的,不一定所有的IplImage都是从左上角开始计算的。

然后就比如我现在创建一个画布:

IplImage *image = cvCreateImage(cvSize(256, 80), 8, 1);cvSetZero(image);

获取bins开始绘图。

float histValue    = cvGetReal1D(hist->bins, i);

float histNextVable = cvGetReal1D(hist->bins, i+1);

灰度直方图

这个画出来的图像如果使用cvFillConvexPoly填充的时候就是蓝色线条上半部分。

cvFillConvexPoly(image, points, numPts, cvScalar(255));

那画下半部分就很简单了,将得到第i个点 使用size Max y - i.bins 就是相反的图像么。😄 

直方图

OpenCV的直方图均衡化

直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。

使用起来很简单

直方图均衡化

那么效果怎样呢?

均衡化和没有均衡化直方图

基本逻辑:将一张图像均衡化,然后输出显示。

图像均衡化

po:我突然发现,只要代码思路清晰,写起代码很舒服😌。

OpenCV的直方图对比

其实对于直方图对比,就是按照enum cv::HistCompMethods标准取相似度。拿出待比对的bins与基准图像的bins求交集嘛😄。

就单单两张相同的图片,如果调整一下亮度,相似度就下来了。

需要注意的是相关性不能证明因果关系,尽管它可能符合因果关系。下面就介绍一下这几个Methods👇。

HISTCMP_CORREL

Correlation (co-relation) refers to the degree of relationship (or dependency) between two variables.

Linear correlation refers to straight-line relationships between two variables.

A correlation can range between -1 (perfect negative relationship) and +1 (perfect positive relationship), with 0 indicating no straight-line relationship. -出处 学术文档看起来总是很清晰。

相关系数是用以反映变量之间相关关系密切程度的统计指标.

说是给了四张图,correlation = 0.816

👇解释一下吧

卡尔·皮尔逊 相关性

HISTCMP_CHISQR

A Pearson's chi-square test can be used as an inferential test of the independence of two nominal variables.出处 这个屌,尤其是对例子的解析👇。

用来监测实际观测值与理论推断值之间的偏离程度。其根本思想就是在于比较理论频数和实际频数的吻合程度或拟合优度问题。

If you wanted to test a die to see whether it’s a fair die, what would you do?

Class Answers: Roll it over and over and see what kind of distribution you get

此处很经典,我叫我王牌翻译来翻译一下:

王牌翻译说:如果你想要测试一个死之人是否害怕死亡你会怎么做?😄一遍一遍去实验。

我觉得我得把文档中的这个example用我的语言Roll一次。

如果你要推测一场死亡属于正常死亡,你会怎么做?让他再活一次?

假设我们使他复活了60次,那你会用什么样的理由去接受其中的一次死亡属于正常死亡?对数据分组 1/6 ?取其中的10次?很显然这个方法很愚蠢。本来60次就不怎么可靠,然后你再去随机取其中的10次?

👇解释一下吧:

一维卡方检测

我觉得我解释明白了,如果你还没有看明白,点这里吧

HISTCMP_INTERSECT

这个就不用说了,单单就这个英文单词就能解释:交集么。

HISTCMP_BHATTACHARYYA

在统计中,Bhattacharyya距离测量两个离散或连续概率分布的相似性。它与衡量两个统计样品或种群之间的重叠量的Bhattacharyya系数密切相关。原文点这里

计算方法

HISTCMP_HELLINGER

在概率论和统计理论中,Hellinger距离被用来度量两个概率分布的相似度。它是f散度的一种(f散度——度量两个概率分布相似度的指标)

我现在都不敢解释这些算法了😄

总之,这些属性都是来判断两组数据的相关性。

总结

那么图像直方图有什么用?其实我也是百度了好多的文章,说的意思很多。

对图像进行分析、观察,形成一个有效的处理方法

就我的理解:

1.对于纯色图像来说,在直方图中只显示一条柱状,一个bins。

2.对于图像来说,如果图像的峰值偏左,bins 集合会偏向0;相反,如果图像的峰值偏右,图像bins集合偏向255;

3.直方图具有二峰性,这表明这个图像有较亮和较暗的区域。

最重要的一点是这个可以做特征提取。

我感觉检测某个图像中: 是真实的人脸、还是照片中的人脸,判断背景区域的直方图就好了。如果拿着照片去充当人脸,那么直方图中会出现多个峰值。

对于前景图像和背景图像比较接近的图像可以使用直方图均衡化,修改对比度。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容