opencv CvHistogram 求直方图的均值
2016-06-19 20:39
411 查看
转载请注明 t1234xy4原创 : http://blog.csdn.net/t1234xy4/article/details/51713895
相关源码下载连接:http://download.csdn.net/detail/t1234xy4/9554431
目标:利用opencv的直方图表示,求出直方图均值。
bins : 用于存放直方图每个灰度级数目的数组指针,数组在cvCreateHist 的时候创建,其维数由cvCreateHist 确定(一般以一维比较常见)
bins:也就是我们对像素的分类形成的容器。这里的CvArr* 内部是void的指针,具体解释成什么类型,与使用有关。
多维、多通道密集数组
创建直方图
dims直方图维数的数目sizes直方图维数尺寸的数组type直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat.ranges图中方块范围的数组. 它的内容取决于参数 uniform 的值。这个范围的用处是确定何时计算直方图或决定反向映射(backprojected ),每个方块对应于输入图像的哪个/哪组值。uniform归一化标识。 如果不为0,则ranges[i](0<=i<cDims,译者注:cDims为直方图的维数,对于灰度图为1,彩色图为3)是包含两个元素的范围数组,包括直方图第i维的上界和下界。在第i维上的整个区域 [lower,upper]被分割成 dims[i] 个相等的块(译者注:dims[i]表示直方图第i维的块数),这些块用来确定输入象素的第 i 个值(译者注:对于彩色图像,i确定R,
G,或者B)的对应的块;如果为0,则ranges[i]是包含dims[i]+1个元素的范围数组,包括lower0, upper0, lower1, upper1 == lower2, ..., upperdims[i]-1, 其中lowerj 和upperj分别是直方图第i维上第 j 个方块的上下界(针对输入象素的第 i 个值)。任何情况下,输入值如果超出了一个直方块所指定的范围外,都不会被 cvCalcHist 计数,而且会被函数 cvCalcBackProject 置零。
函数 cvCreateHist 创建一个指定尺寸的直方图,并且返回创建的直方图的指针。 如果数组的 ranges 是 0, 则直方块的范围必须由函数 cvSetHistBinRanges 稍后指定。虽然 cvCalcHist 和 cvCalcBackProject 可以处理 8-比特图像而无需设置任何直方块的范围,但它们都被假设等分 0..255 之间的空间。
从数组中创建直方图
dims直方图维数.sizes直方图维数尺寸的数组hist为函数所初始化的直方图头data用来存储直方块的数组ranges直方块范围,见 cvCreateHist.uniform归一化标识,见 cvCreateHist.
函数 cvMakeHistHeaderForArray 初始化直方图,其中头和直方块为用户所分配。以后不需要调用 cvReleaseHist 只有稠密直方图可以采用这种方法,函数返回 hist.
1、我使用的测试图片的规格为41×41的jpeg。
2、测试直方图统计是不是按每一个像素来统计的,首先41×41的总像素为1681个,我统计ranges{0,255}范围,也就是整个图片的所有像素。
对于原图我利用以下代码统计:
(1)、直接读取指针内存
为了好看,把对应的直方图画出来:(只帖了红色通道的像素值)
其保存代码如下:
结果说明:数据确实保存在CvHistogram中的CvMatND中的data中的fl指针中。
1、对直方图归一化,读取各个直方图中的数据
2、对两个直方图数据相同bins下的指做均值处理,并保存在float* data中
3、利用cvMakeHistHeaderForArray函数,生成一个新的CvHistogram
3、读取直方图中的值,并做均值处理,保存在float* data中
fish1
fish2
2、原图红色通道直方图
fish1 的红色通道直方图
fish2的红色通道直方图
3、归一化直方图显示与以上无差别
4、均值化两张红色通道之后的比较
第一张为fish1归一化直方图,第二张为fish2直方图,第三张是前两张的均值化后的结果。
源码下载连接:http://download.csdn.net/detail/t1234xy4/9554431
相关源码下载连接:http://download.csdn.net/detail/t1234xy4/9554431
目标:利用opencv的直方图表示,求出直方图均值。
一、理解opencv直方图的数据类型
学习连接:http://wiki.opencv.org.cn/index.php/Cv图像处理#CvHistogramtypedef struct CvHistogram { int type; CvArr* bins; float thresh[CV_MAX_DIM][2]; /* for uniform histograms */ float** thresh2; /* for non-uniform histograms */ CvMatND mat; /* embedded matrix header for array histograms */ } CvHistogram;
bins : 用于存放直方图每个灰度级数目的数组指针,数组在cvCreateHist 的时候创建,其维数由cvCreateHist 确定(一般以一维比较常见)
bins:也就是我们对像素的分类形成的容器。这里的CvArr* 内部是void的指针,具体解释成什么类型,与使用有关。
可以看到CvHistogram 中的数据保存在CvMatND的结构体中,下面我再学习学习CvMatND。
CvMatND
多维、多通道密集数组typedef struct CvMatND { int type; /* CvMatND 标识(CV_MATND_MAGIC_VAL), 元素类型和标号*/ int dims; /* 数组维数 */ int* refcount; /* 数据参考计数 */ union { uchar* ptr; short* s; int* i; float* fl; double* db; } data; /* data 指针*/ /* 每维的数据结构 (元素号,以字节为单位的元素之间的距离)是配套定义的 */ struct { int size; int step; } dim[CV_MAX_DIM]; } CvMatND;
特别注意(一维直方图):CvHistogram结构的直方图数据是保存在CvMatND中的,CvMatND结构中dims与type就不说了,struct中的size与step分别是保存在dim[0](一维直方图),二维、三维保存类推。size保存了数据空间的大小,step保存每一维数据的宽度。union
data中保存了数据,我猜测是根据直方图输入的数据类型来判定使用哪一种数据指针,经过一些测试,我得到的数据保存在float* fl这个指针所指位置。(估计是默认的)如果不在你试试其他指针。
二、学会使用操作cvHistogram的函数
CreateHist
创建直方图CvHistogram* cvCreateHist( int dims, int* sizes, int type, float** ranges=NULL, int uniform=1 );
dims直方图维数的数目sizes直方图维数尺寸的数组type直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat.ranges图中方块范围的数组. 它的内容取决于参数 uniform 的值。这个范围的用处是确定何时计算直方图或决定反向映射(backprojected ),每个方块对应于输入图像的哪个/哪组值。uniform归一化标识。 如果不为0,则ranges[i](0<=i<cDims,译者注:cDims为直方图的维数,对于灰度图为1,彩色图为3)是包含两个元素的范围数组,包括直方图第i维的上界和下界。在第i维上的整个区域 [lower,upper]被分割成 dims[i] 个相等的块(译者注:dims[i]表示直方图第i维的块数),这些块用来确定输入象素的第 i 个值(译者注:对于彩色图像,i确定R,
G,或者B)的对应的块;如果为0,则ranges[i]是包含dims[i]+1个元素的范围数组,包括lower0, upper0, lower1, upper1 == lower2, ..., upperdims[i]-1, 其中lowerj 和upperj分别是直方图第i维上第 j 个方块的上下界(针对输入象素的第 i 个值)。任何情况下,输入值如果超出了一个直方块所指定的范围外,都不会被 cvCalcHist 计数,而且会被函数 cvCalcBackProject 置零。
函数 cvCreateHist 创建一个指定尺寸的直方图,并且返回创建的直方图的指针。 如果数组的 ranges 是 0, 则直方块的范围必须由函数 cvSetHistBinRanges 稍后指定。虽然 cvCalcHist 和 cvCalcBackProject 可以处理 8-比特图像而无需设置任何直方块的范围,但它们都被假设等分 0..255 之间的空间。
MakeHistHeaderForArray
从数组中创建直方图CvHistogram* cvMakeHistHeaderForArray( int dims, int* sizes, CvHistogram* hist, float* data, float** ranges=NULL, int uniform=1 );
dims直方图维数.sizes直方图维数尺寸的数组hist为函数所初始化的直方图头data用来存储直方块的数组ranges直方块范围,见 cvCreateHist.uniform归一化标识,见 cvCreateHist.
函数 cvMakeHistHeaderForArray 初始化直方图,其中头和直方块为用户所分配。以后不需要调用 cvReleaseHist 只有稠密直方图可以采用这种方法,函数返回 hist.
三、测试过程及相关代码
1、我使用的测试图片的规格为41×41的jpeg。2、测试直方图统计是不是按每一个像素来统计的,首先41×41的总像素为1681个,我统计ranges{0,255}范围,也就是整个图片的所有像素。
对于原图我利用以下代码统计:
(1)、直接读取指针内存
float sum = 0; for (int i= 0; i<hist1->mat.dim->size;i++) { float m = (float)(hist1->mat.data.fl[i]); cout << m <<" "; sum+=m; } cout<<"sum: "<<sum <<endl;(2)、利用函数读取
sum = 0; for (int i= 0; i<hist1->mat.dim->size;i++) { float m = cvQueryHistValue_1D(hist1,i); data[i] = m; cout << m <<" "; sum+=m; } cout<<"sum: "<<sum <<endl;结果一样(如下)
为了好看,把对应的直方图画出来:(只帖了红色通道的像素值)
其保存代码如下:
void saveHistogram(string filename,CvHistogram* hist) { if(!hist) return; if(hist->mat.dim->size<=0) return; int scale = 2; int hist_height = 100; IplImage* hist_image = cvCreateImage(cvSize(hist->mat.dim->size*scale,hist_height),8,3); cvZero(hist_image); float max_value = 0; cvGetMinMaxHistValue(hist, 0,&max_value,0,0); for(int i=0;i<hist->mat.dim->size;i++) { float bin_val = cvQueryHistValue_1D(hist,i); int intensity = cvRound(bin_val*hist_height/max_value); cvRectangle( hist_image, cvPoint(i*scale,hist_height-1), cvPoint((i+1)*scale - 1, hist_height - intensity), CV_RGB(255,0,0)); } cvSaveImage(filename.c_str(),hist_image); cvReleaseImage(&hist_image); }
结果说明:数据确实保存在CvHistogram中的CvMatND中的data中的fl指针中。
四、利用opencv CvHistogram求多个直方图均值想法
1、对直方图归一化,读取各个直方图中的数据2、对两个直方图数据相同bins下的指做均值处理,并保存在float* data中
3、利用cvMakeHistHeaderForArray函数,生成一个新的CvHistogram
五、具体实现过程
1、读取图片,将图片分成BGR三通道,并分别生成直方图<span style="white-space:pre"> </span>IplImage* img_source,*img_source2; img_source = cvLoadImage("E:/MFCPlat/MutiTrackingApp/MutiTrackingApp/sequences/fishModel/fish_1/0134.jpeg",1); img_source2 = cvLoadImage("E:/MFCPlat/MutiTrackingApp/MutiTrackingApp/sequences/fishModel/fish_2/0134.jpeg",1); if((!img_source) || (!img_source2)) return; IplImage* RedChannel = cvCreateImage( cvGetSize(img_source), 8, 1); IplImage* GreenChannel = cvCreateImage( cvGetSize(img_source), 8, 1); IplImage* BlueChannel = cvCreateImage( cvGetSize(img_source), 8, 1); //分割为单通道图像 cvCvtPixToPlane(img_source,BlueChannel,GreenChannel,RedChannel,0); cvCvtColor(img_source,gray_plane,CV_BGR2GRAY); //然后为这四幅图创建对应的直方图结构。 int hist_size = 255; in hist_height = 100; float range[] = {0,256}; float* ranges[]={range}; CvHistogram* r_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1); CvHistogram* g_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1); CvHistogram* b_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);2、计算三个通道直方图,并归一化
<span style="white-space:pre"> </span>cvCalcHist(&RedChannel,r_hist,0,0); cvCalcHist(&GreenChannel,g_hist,0,0); cvCalcHist(&BlueChannel,b_hist,0,0); <pre name="code" class="cpp"> cvNormalizeHist(r_hist,1.0); cvNormalizeHist(g_hist,1.0); cvNormalizeHist(b_hist,1.0);
3、读取直方图中的值,并做均值处理,保存在float* data中
bool CalcMeanOfHists(CvHistogram* hist1,CvHistogram* hist2,float* data) { if( !hist1 || !hist2 || !data) return false; if(hist1->mat.dims != hist2->mat.dims) return false; if( (hist1->thresh[0][0]!=hist2->thresh[0][0]) || (hist1->thresh[0][1]!=hist2->thresh[0][1]) ) return false; if(hist1->mat.dim->size != hist2->mat.dim->size) return false; for (int i= 0; i<hist1->mat.dim->size;i++) { float m1 = (float)(hist1->mat.data.fl[i]); float m2 = (float)(hist2->mat.data.fl[i]); data[i] = (m1+m2)/2.0f; } }4、通过float* data 生成新的直方图
<span style="white-space:pre"> </span>float* data = new float[r_hist->mat.dim->size]; CalcMeanOfHists(r_hist,r_hist2,data); CvHistogram* mean_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1); cvMakeHistHeaderForArray(1,&hist_size,mean_hist,data,ranges,1);
六、测试结果
1、使用了两张测试图片如下:fish1
fish2
2、原图红色通道直方图
fish1 的红色通道直方图
fish2的红色通道直方图
3、归一化直方图显示与以上无差别
4、均值化两张红色通道之后的比较
第一张为fish1归一化直方图,第二张为fish2直方图,第三张是前两张的均值化后的结果。
源码下载连接:http://download.csdn.net/detail/t1234xy4/9554431
相关文章推荐
- 一些有用的文章出处
- 图像特征之颜色直方图
- [数字图像处理]灰度变换——直方图处理
- OpenCV提取图像颜色直方图
- opencv提取图片直方图的的波谷的的x值
- 《数字图像处理》--直方图处理
- 颜色直方图opencv c++代码
- 直方图处理(规定化)
- 直方图处理(均衡)
- HSV颜色直方图
- RBG颜色直方图
- 各种硬件设备在linux的文件名及磁盘组成分区
- zookeeper集群在linux上的搭建
- Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
- Linux如何查看进程、杀死进程、启动进程等常用命令
- Windows和Linux下的目标文件、静态库和动态库
- linux系统目录介绍
- 项目相关错误系列之eclipse中配置tomcat问题
- 在Linux上使用的10种云备份方案
- linux kill 关闭进程命令