创建灰度图像直方图(c)

来源:互联网 发布:怎么剔除异常数据 编辑:程序博客网 时间:2024/06/18 12:20
#include"stdafx.h"#include<cv.h>#include<highgui.h>#include<stdlib.h>int main(int argc, _TCHAR* argv[]){IplImage* image = cvLoadImage("D:/3.jpg");IplImage* gray_image = cvCreateImage(cvGetSize(image), image->depth, 1);cvCvtColor(image, gray_image, CV_BGR2GRAY);cvShowImage("ddd", gray_image);int dims = 1;//灰度图像为一维int size[] = { 256 };float range[] = { 0, 255 };float* ranges[] = { range };CvHistogram* gray = cvCreateHist(dims, size, CV_HIST_ARRAY, ranges, 1);cvCalcHist(&gray_image, gray, 0,NULL);IplImage* show = cvCreateImage(cvSize(256, 256), 8, 3);cvZero(show);float max_value = 0;cvGetMinMaxHistValue(gray, 0, &max_value, 0, 0);float max = 256*0.9;CvScalar color = cvScalar(10, 50, 256);for (int i = 0; i < 256; i++){float* value = cvGetHistValue_1D(gray, i);CvPoint p0 = cvPoint(i, 256);float out = 256 - (*value)*max / max_value;//printf("%d : %f\n",i, out);CvPoint p1 = cvPoint(i + 1, out);cvRectangle(show, p0, p1, color, 1, 8, 0);}cvShowImage("last", show);char c = cvWaitKey();if (c == 27){cvReleaseImage(&image);cvReleaseImage(&gray_image);cvReleaseImage(&show);return 0;}}

原图转灰度图:


测试每一灰度的高度:

0 : 255.8870541 : 253.7411802 : 251.7082373 : 250.2400054 : 247.1905825 : 245.2705846 : 242.8988197 : 241.6564648 : 239.2846989 : 237.13882410 : 237.70352211 : 234.31529212 : 228.32940713 : 219.29411314 : 209.35530115 : 214.55059816 : 210.48471117 : 204.95059218 : 199.52941919 : 189.02587920 : 171.51998921 : 168.47058122 : 161.46823123 : 160.33882124 : 161.92001325 : 171.18118326 : 178.40942427 : 170.61648628 : 175.92471329 : 179.42587330 : 179.87765531 : 180.55529832 : 183.71765133 : 190.04235834 : 193.65646435 : 197.15765436 : 193.99530037 : 197.72235138 : 194.22117639 : 199.75529540 : 194.44705241 : 198.28706442 : 200.32000743 : 204.27294944 : 202.57882745 : 198.73883146 : 200.43293847 : 205.96705648 : 201.78823949 : 204.04705850 : 204.38588051 : 211.38824552 : 211.16235453 : 209.46823154 : 212.40470955 : 208.56469756 : 205.85412657 : 203.70823758 : 206.87059059 : 214.32470760 : 205.85412661 : 206.64471462 : 204.49882563 : 203.59530664 : 205.85412665 : 205.17646866 : 209.24235567 : 204.04705868 : 200.77175969 : 202.24000570 : 201.78823971 : 205.28941372 : 203.03059473 : 204.83764674 : 203.93411375 : 204.61175576 : 208.45176777 : 210.59765678 : 207.54823379 : 207.20941280 : 208.11294681 : 210.59765682 : 207.88705483 : 212.74353084 : 209.35530185 : 205.74118086 : 200.99765087 : 203.82118288 : 205.06353889 : 202.35293690 : 196.25412091 : 200.77175992 : 194.33412293 : 193.88235594 : 194.10824695 : 197.38353096 : 191.51059097 : 195.68942398 : 189.25177099 : 186.992950100 : 190.042358101 : 192.639999102 : 184.056473103 : 186.654114104 : 185.185883105 : 182.136475106 : 177.392944107 : 176.489410108 : 173.778824109 : 170.051773110 : 162.936462111 : 167.792938112 : 156.047058113 : 160.451767114 : 156.611755115 : 152.320007116 : 152.545883117 : 155.595306118 : 158.531769119 : 162.145889120 : 156.272949121 : 154.014130122 : 146.672943123 : 156.047058124 : 150.964706125 : 162.823532126 : 164.743530127 : 170.503540128 : 169.600006129 : 170.616486130 : 159.209412131 : 148.028229132 : 129.279999133 : 144.188232134 : 156.160004135 : 176.150589136 : 183.604706137 : 191.849411138 : 193.543533139 : 193.769409140 : 198.399994141 : 198.964706142 : 198.174118143 : 203.482361144 : 199.868240145 : 200.207062146 : 204.950592147 : 203.256470148 : 204.950592149 : 204.611755150 : 200.545883151 : 204.950592152 : 203.708237153 : 201.110596154 : 204.837646155 : 203.143524156 : 205.063538157 : 204.724701158 : 205.063538159 : 202.917648160 : 204.272949161 : 202.578827162 : 201.110596163 : 200.884705164 : 199.981171165 : 198.512939166 : 207.435303167 : 200.884705168 : 199.190582169 : 199.642365170 : 197.383530171 : 193.430588172 : 196.141174173 : 192.978821174 : 185.637634175 : 186.428238176 : 183.378815177 : 175.924713178 : 173.778824179 : 173.440002180 : 165.421173181 : 164.743530182 : 164.856476183 : 160.225891184 : 166.211761185 : 161.355301186 : 154.691772187 : 155.143524188 : 148.367065189 : 146.447052190 : 149.044708191 : 150.738831192 : 144.865875193 : 143.058823194 : 150.851776195 : 146.447052196 : 146.898834197 : 140.122360198 : 139.896484199 : 120.696472200 : 116.404709201 : 92.574127202 : 95.058823203 : 90.202362204 : 81.167068205 : 78.343536206 : 73.938828207 : 82.861176208 : 78.569427209 : 97.430588210 : 101.496475211 : 109.854126212 : 96.639999213 : 89.524704214 : 86.249420215 : 64.677643216 : 51.011765217 : 75.858826218 : 60.724716219 : 36.894119220 : 25.600006221 : 31.811768222 : 72.244720223 : 85.120010224 : 98.672943225 : 101.496475226 : 136.734131227 : 149.835297228 : 149.044708229 : 159.435303230 : 168.018829231 : 174.569427232 : 181.797638233 : 194.672943234 : 204.160004235 : 210.936478236 : 221.327057237 : 226.183533238 : 231.378830239 : 231.604706240 : 236.461182241 : 236.687057242 : 239.397644243 : 241.317642244 : 243.576477245 : 245.044708246 : 246.738831247 : 247.755295248 : 250.352936249 : 250.240005250 : 249.901184251 : 250.691772252 : 254.305878253 : 253.063522254 : 254.644699255 : 256.000000


对应结果:



函数解析:

typedef 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. */}
借个图帮助理解,其中也包含二维的使用:http://blog.csdn.net/lu597203933/article/details/14104505这里有该图的解释


第一个成员type:
用来指定第二个成员bins的具体类型。bins的类型是CvArr*,看其定义可以知道,CvArr* 仅仅是被用于作函数的参数,用于指示函数接收的数组类型可以不止一个,如 IplImage*, CvMat* 甚至 CvSeq*,所以需要type来具体指定bins的类型。
第二个成员bins : 
用于存放直方图每个灰度级数目的数组指针,数组在cvCreateHist 的时候创建,其维数由cvCreateHist 确定(一般以一维比较常见)。
bin的含义:计算颜色直方图需要将颜色空间划分为若干小的颜色区间,即直方图的bin,通过计算颜色在每个小区间内德像素得到颜色直方图,bin越多,直方图对颜色的分辨率越强,但增加了计算机的负担。即(学习opencv图7-2中所分成的9个竖条区域,每个竖条区域称为一个bin)
第三个成员thresh:
一个二维数组,CV_MAX_DIM对应直方图的维数。且第二维固定为2。
这个数组比较难理解,首先要理解什么是一维直方图和二维直方图。一维直方图就是单通道图像的直方图,或者彩色图像中某个单独通道的直方图。二维直方图就是2个通道的直方图,比如彩色图像的红-蓝直方图。既然是直方图,必定有上下界,所以thresh的第二维是2,比如[0 255],就是统计[0-255]区间灰度分布的直方图。而二维红-蓝直方图的thresh为[0 255;100 200],就是分别统计红色图像灰度级在[0 255]以及蓝色图像在灰度级[100 200]的分布情况。

第四个成员是thresh2:
一个二维数组指针,用于非均匀直方图的情形。如果是均匀直方图,会自动根据bin的个数均分上下界,每个bin的大小一样。若是非均匀直方图,就要用到thresh2这个参数指定每个区间的上下界,要是多维的直方图,那么就要为每一维的所有bin都设定上下界。
最后一个成员mat:
用来存储数据。


CvHistogram*  cvCreateHist( int dims, int* sizes, int type, float** ranges CV_DEFAULT(NULL),int uniform CV_DEFAULT(1));
创建直方图:
dims:表示直方图的维度
sizes:每一维上直方柱(bin)的数据--创建多大的矩阵,如一维则size[0] =256 二维则size[0]=256,size[1] = 256;
type:创建一个什么样的矩阵,直方图存储数据的方式: 
CV_HIST_ARRAY意味着直方图数据表示为多维密集数组CvMatND;
CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组CvSparseMat.---- 大于0才开设相应的空间存储它<高维的必选它>
Ranges:直方图在每一维度上的范围。
  如果是一维则代码为:
  Floatrange[] = {0,255};
  Float*ranges[]={range};
  如果是二维则代码为:
  Float b_range[] = {0,255};
  Float g_range[] ={0,255};
  Float*ranges[] = {b_range, g_range};
uniform
 该值为0时,表示bin的范围是程序员自由设定的。当该值为非零时,表示bin的划分,是均等划分。
 
cvQueryHistValue_1D 获取对应灰度值上的像素个数,也就是获取对应index上的值,就是cvGetReal1D函数
#define cvQueryHistValue_1D( hist, idx0 ) ((float)cvGetReal1D( (hist)->bins, (idx0)))

他也可以替换为
#define cvGetHistValue_1D( hist, idx0 ) ((float*)cvPtr1D( (hist)->bins, (idx0), 0))
只不过该函数返回的是指针


形象点的讲解:http://blog.csdn.net/dxmgood/article/details/7237437


void  cvCalcHist( IplImage** image,   CvHistogram* hist,                  int accumulate CV_DEFAULT(0),                  const CvArr* mask CV_DEFAULT(NULL)  )

计算直方图:
image:需要计算的图像
hist:存放计算结果的直方图,需要提前通过cvCreateHist创建
accumlate:若为0 ,则在计算此图像的直方图前,将hist先清零,若非0,则在原来的基础上累加
mask:掩码,mask的必须为8位无符号整型 ,单通道图像IplImage 或者CvMat结构 ,将mask看成二值图,非零的地方即为使用(统计)的地方 , 
为0时对应的地方不参与运算操作


直接计算二维的:http://blog.csdn.net/xiaowei_cqu/article/details/7600666


最后怎么确定需要画出来的高度可以参考我用c++写的博客:http://blog.csdn.net/qq_24282081/article/details/73135799


最后总结一下过程:

目的:计算0——255这256个灰度值上的像素个数,最后以直方图的形式显示在256*256的图片上:





阅读全文
0 0
原创粉丝点击