#include"stdafx.h"
#include
#include
#include
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.887054
1 : 253.741180
2 : 251.708237
3 : 250.240005
4 : 247.190582
5 : 245.270584
6 : 242.898819
7 : 241.656464
8 : 239.284698
9 : 237.138824
10 : 237.703522
11 : 234.315292
12 : 228.329407
13 : 219.294113
14 : 209.355301
15 : 214.550598
16 : 210.484711
17 : 204.950592
18 : 199.529419
19 : 189.025879
20 : 171.519989
21 : 168.470581
22 : 161.468231
23 : 160.338821
24 : 161.920013
25 : 171.181183
26 : 178.409424
27 : 170.616486
28 : 175.924713
29 : 179.425873
30 : 179.877655
31 : 180.555298
32 : 183.717651
33 : 190.042358
34 : 193.656464
35 : 197.157654
36 : 193.995300
37 : 197.722351
38 : 194.221176
39 : 199.755295
40 : 194.447052
41 : 198.287064
42 : 200.320007
43 : 204.272949
44 : 202.578827
45 : 198.738831
46 : 200.432938
47 : 205.967056
48 : 201.788239
49 : 204.047058
50 : 204.385880
51 : 211.388245
52 : 211.162354
53 : 209.468231
54 : 212.404709
55 : 208.564697
56 : 205.854126
57 : 203.708237
58 : 206.870590
59 : 214.324707
60 : 205.854126
61 : 206.644714
62 : 204.498825
63 : 203.595306
64 : 205.854126
65 : 205.176468
66 : 209.242355
67 : 204.047058
68 : 200.771759
69 : 202.240005
70 : 201.788239
71 : 205.289413
72 : 203.030594
73 : 204.837646
74 : 203.934113
75 : 204.611755
76 : 208.451767
77 : 210.597656
78 : 207.548233
79 : 207.209412
80 : 208.112946
81 : 210.597656
82 : 207.887054
83 : 212.743530
84 : 209.355301
85 : 205.741180
86 : 200.997650
87 : 203.821182
88 : 205.063538
89 : 202.352936
90 : 196.254120
91 : 200.771759
92 : 194.334122
93 : 193.882355
94 : 194.108246
95 : 197.383530
96 : 191.510590
97 : 195.689423
98 : 189.251770
99 : 186.992950
100 : 190.042358
101 : 192.639999
102 : 184.056473
103 : 186.654114
104 : 185.185883
105 : 182.136475
106 : 177.392944
107 : 176.489410
108 : 173.778824
109 : 170.051773
110 : 162.936462
111 : 167.792938
112 : 156.047058
113 : 160.451767
114 : 156.611755
115 : 152.320007
116 : 152.545883
117 : 155.595306
118 : 158.531769
119 : 162.145889
120 : 156.272949
121 : 154.014130
122 : 146.672943
123 : 156.047058
124 : 150.964706
125 : 162.823532
126 : 164.743530
127 : 170.503540
128 : 169.600006
129 : 170.616486
130 : 159.209412
131 : 148.028229
132 : 129.279999
133 : 144.188232
134 : 156.160004
135 : 176.150589
136 : 183.604706
137 : 191.849411
138 : 193.543533
139 : 193.769409
140 : 198.399994
141 : 198.964706
142 : 198.174118
143 : 203.482361
144 : 199.868240
145 : 200.207062
146 : 204.950592
147 : 203.256470
148 : 204.950592
149 : 204.611755
150 : 200.545883
151 : 204.950592
152 : 203.708237
153 : 201.110596
154 : 204.837646
155 : 203.143524
156 : 205.063538
157 : 204.724701
158 : 205.063538
159 : 202.917648
160 : 204.272949
161 : 202.578827
162 : 201.110596
163 : 200.884705
164 : 199.981171
165 : 198.512939
166 : 207.435303
167 : 200.884705
168 : 199.190582
169 : 199.642365
170 : 197.383530
171 : 193.430588
172 : 196.141174
173 : 192.978821
174 : 185.637634
175 : 186.428238
176 : 183.378815
177 : 175.924713
178 : 173.778824
179 : 173.440002
180 : 165.421173
181 : 164.743530
182 : 164.856476
183 : 160.225891
184 : 166.211761
185 : 161.355301
186 : 154.691772
187 : 155.143524
188 : 148.367065
189 : 146.447052
190 : 149.044708
191 : 150.738831
192 : 144.865875
193 : 143.058823
194 : 150.851776
195 : 146.447052
196 : 146.898834
197 : 140.122360
198 : 139.896484
199 : 120.696472
200 : 116.404709
201 : 92.574127
202 : 95.058823
203 : 90.202362
204 : 81.167068
205 : 78.343536
206 : 73.938828
207 : 82.861176
208 : 78.569427
209 : 97.430588
210 : 101.496475
211 : 109.854126
212 : 96.639999
213 : 89.524704
214 : 86.249420
215 : 64.677643
216 : 51.011765
217 : 75.858826
218 : 60.724716
219 : 36.894119
220 : 25.600006
221 : 31.811768
222 : 72.244720
223 : 85.120010
224 : 98.672943
225 : 101.496475
226 : 136.734131
227 : 149.835297
228 : 149.044708
229 : 159.435303
230 : 168.018829
231 : 174.569427
232 : 181.797638
233 : 194.672943
234 : 204.160004
235 : 210.936478
236 : 221.327057
237 : 226.183533
238 : 231.378830
239 : 231.604706
240 : 236.461182
241 : 236.687057
242 : 239.397644
243 : 241.317642
244 : 243.576477
245 : 245.044708
246 : 246.738831
247 : 247.755295
248 : 250.352936
249 : 250.240005
250 : 249.901184
251 : 250.691772
252 : 254.305878
253 : 253.063522
254 : 254.644699
255 : 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的图片上: