比尔云BierYun--阿里云最新优惠活动
阿里云优惠码丨阿里云代金券

计算灰度图的像素直方图,并显示(c++)

计算灰度图的像素直方图,并显示(c++)http://www.bieryun.com/2897.html

程序功能,将一张彩色图片转为灰度图后,分析其各灰度值(0-255)的像素个数以直方图的方式显示出来.

这次是用c++写的,很多函数都很陌生,花了我很长时间。

[cpp] view plain copy

  1. #include”stdafx.h”
  2. #include<iostream>
  3. #include<highgui.hpp>
  4. #include<cv.hpp>
  5. #include<imgproc.hpp>
  6. using namespace std;
  7. using namespace cv;
  8. Mat getHistImage(const MatND& hist)
  9. {
  10.     double maxValue = 0;
  11.     double minValue = 0;
  12.     int a = 0;
  13.     for (int i = 0; i < hist.rows; i++)
  14.     {
  15.         for (int j = 0; j < hist.cols; j++)
  16.         {
  17.             float b = hist.at<float>(i, j);
  18.             a += 1;
  19.             cout << b << endl;
  20.         }
  21.     }
  22.     minMaxLoc(hist, &minValue, &maxValue, 0, 0);//找到全局最小、最大的像素值数目
  23.     cout << “max: “ << maxValue << “min: “ << minValue << endl;
  24.     int histSize = hist.rows;
  25.     Mat histImage(histSize, histSize, CV_8UC3, Scalar(255,255,255));
  26.     int hpt = static_cast<int>(0.9*histSize);
  27.     int total = 0;
  28.     Scalar color(172, 172, 150);//BGR
  29.     for (int h = 0; h < histSize; h++)
  30.     {
  31.         float binVal = hist.at<float>(h);//读取对应灰度级的像素个数,一共1000000个
  32.         cout << h<<“: “<<binVal << endl;
  33.         total += binVal;
  34.         int intensity = static_cast<int>(binVal*hpt /maxValue);//按比例运算,当前数目*230/最大数目,与除以总数只是比例不同
  35.         line(histImage, Point(h, histSize), Point(h, histSize – intensity),color);
  36.         //rectangle(histImage, Point(h, histSize), Point(h + 1, histSize – intensity), color);
  37.     }
  38.     cout << total << endl;//total = 1000000
  39.     return histImage;
  40. }
  41. int main(int argc, _TCHAR* argv[])
  42. {
  43.     Mat src = imread(“D:/2.jpg”,-1);
  44.     //IplImage* image = cvLoadImage(“D:/timg.jpg”);
  45.     int a = src.channels();//a = 3通道
  46.     imshow(“b”, src);
  47.     if (!src.data)
  48.     {
  49.         cout << “no picture!\n”;
  50.         exit(1);
  51.     }
  52.     cvtColor(src, src, CV_BGR2GRAY, 0);
  53.     a = src.channels();//a = 1通道
  54.     imshow(“d”, src);
  55.     int image_count = 1;//要计算直方图的图像的个数
  56.     int channels[1] = { 0};//图像的通道’
  57.     Mat out;//计算所得直方图
  58.     int dims = 1;//得到直方图的维数
  59.     int histsize[1] = { 256 };//直方图横坐标的子区间数
  60.     float hrange[2] = { 0, 255 };//区间的总范围
  61.     const float *ranges[1] = { hrange };//指针数组
  62.     calcHist(&src, image_count,channels, Mat(), out, dims, histsize, ranges);
  63.     Mat last = getHistImage(out);
  64.     imshow(“ddd”, last);
  65.     waitKey();
  66.     return 0;
  67. }

几个关键函数介绍:

[cpp] view plain copy

  1. void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, booluniform=truebool accumulate=false )

计算直方图,统计各灰度的像素个数,其输出为多维矩阵
const Mat* images:
为输入图像的指针。
int nimages:
要计算直方图的图像的个数。此函数可以为多图像求直方图,我们通常情况下都只作用于单一图像,所以通常nimages=1。
const int* channels:
图像的通道,它是一个数组,如果是灰度图像则channels[1]={0};如果是彩色图像则channels[3]={0,1,2};如果是只是求彩色图像第2个通道的直方图,则channels[1]={1};
IuputArray mask:
是一个遮罩图像用于确定哪些点参与计算,实际应用中是个很好的参数,默认情况我们都设置为一个空图像,即:Mat()。
OutArray hist:
计算得到的直方图
int dims:
得到的直方图的维数,灰度图像为1维,彩色图像为3维。
const int* histSize:
直方图横坐标的区间数。如果是10,则它会横坐标分为10份,然后统计每个区间的像素点总和。
const float** ranges:
这是一个二维数组,用来指出每个区间的范围。后面两个参数都有默认值,uniform参数表明直方图是否等距,最后一个参数与多图像下直方图的显示与存储有关。

[cpp] view plain copy

  1. void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())

找出矩阵中最大和最小的值以及他们的坐标
src – Source single-channel array.
单通道数组
minVal – Pointer to the returned minimum value. NULL is used if not required.
指向最小值的指针
maxVal – Pointer to the returned maximum value. NULL is used if not required.
指向最大值的指针
minLoc – Pointer to the returned minimum location (in 2D case). NULL is used if not required.
最小值的二维坐标
maxLoc – Pointer to the returned maximum location (in 2D case). NULL is used if not required.
最大值得二维坐标
mask – Optional mask used to select a sub-array.
掩码

[cpp] view plain copy

  1. Mat(int rows, int cols, int type, const Scalar& s)

Mat的构造函数,行,列,类型,每一元素值

[cpp] view plain copy

  1. void cvLine( CvArr* img,CvPoint pt1, CvPoint pt2, CvScalar color,int thickness=1, int line_type=8, int shift=0 );

第一个参数img:要划的线所在的图像;
第二个参数pt1:直线起点
第二个参数pt2:直线终点
第三个参数color:直线的颜色 e.g:Scalor(0,0,255)
第四个参数thickness=1:线条粗细
第五个参数line_type=8,
8 (or 0) – 8-connected line(8邻接)连接 线。
4 – 4-connected line(4邻接)连接线。
CV_AA – antialiased 线条。
第六个参数:坐标点的小数点位数。

[cpp] view plain copy

  1. static_cast

用法:static_cast < type-id > ( expression_r_r )
该运算符把expression_r_r转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有如下几种用法:
用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。
用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
把空指针转换成目标类型的空指针。
把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression_r_r的const、volitale、或者__unaligned属性。
注意:static_cast不能转换掉expression_r_r的const、volitale、或者__unaligned属性。
更详细的:http://blog.sina.com.cn/s/blog_4a84e45b0100f57m.html

值得注意的是:
c++中Mat类的rows和cols与c中image的height和width一样
dim表示维度,一般都是2为,channels为维度,c++中是通过Mat::channels()函数来查看。
注意,彩色图dim也是二,channels是三

为了测试计算直方图函数的效果,我把计算后的矩阵里的每一个元素的出来

[cpp] view plain copy

  1. for (int i = 0; i < hist.rows; i++)
  2. {
  3.     for (int j = 0; j < hist.cols; j++)
  4.     {
  5.         float b = hist.at<float>(i, j);//这里at函数里的必须是float类型,如果是int的话,就相当于(int&)float,输出的数没有意义,数值很大
  6.         a += 1;
  7.         cout << b << endl;
  8.     }
  9. }
  10. 结果如下:
  11. 0: 0
  12. 1: 0
  13. 2: 0
  14. 3: 0
  15. 4: 0
  16. 5: 0
  17. 6: 0
  18. 7: 0
  19. 8: 0
  20. 9: 0
  21. 10: 0
  22. 11: 0
  23. 12: 0
  24. 13: 0
  25. 14: 0
  26. 15: 0
  27. 16: 0
  28. 17: 0
  29. 18: 0
  30. 19: 0
  31. 20: 0
  32. 21: 0
  33. 22: 0
  34. 23: 0
  35. 24: 0
  36. 25: 0
  37. 26: 0
  38. 27: 0
  39. 28: 0
  40. 29: 0
  41. 30: 0
  42. 31: 0
  43. 32: 0
  44. 33: 0
  45. 34: 1
  46. 35: 1
  47. 36: 0
  48. 37: 0
  49. 38: 2
  50. 39: 3
  51. 40: 3
  52. 41: 8
  53. 42: 13
  54. 43: 19
  55. 44: 18
  56. 45: 28
  57. 46: 38
  58. 47: 52
  59. 48: 58
  60. 49: 76
  61. 50: 81
  62. 51: 105
  63. 52: 132
  64. 53: 175
  65. 54: 201
  66. 55: 269
  67. 56: 257
  68. 57: 344
  69. 58: 413
  70. 59: 528
  71. 60: 598
  72. 61: 898
  73. 62: 1042
  74. 63: 1330
  75. 64: 1580
  76. 65: 2431
  77. 66: 135547
  78. 67: 2503
  79. 68: 1612
  80. 69: 1233
  81. 70: 1012
  82. 71: 688
  83. 72: 562
  84. 73: 398
  85. 74: 287
  86. 75: 240
  87. 76: 173
  88. 77: 141
  89. 78: 120
  90. 79: 76
  91. 80: 77
  92. 81: 100
  93. 82: 58
  94. 83: 59
  95. 84: 61
  96. 85: 61
  97. 86: 72
  98. 87: 96
  99. 88: 111
  100. 89: 121
  101. 90: 131
  102. 91: 163
  103. 92: 217
  104. 93: 305
  105. 94: 425
  106. 95: 574
  107. 96: 741
  108. 97: 1084
  109. 98: 1520
  110. 99: 2191
  111. 100: 2985
  112. 101: 4345
  113. 102: 6866
  114. 103: 11409
  115. 104: 25454
  116. 105: 171666
  117. 106: 10226
  118. 107: 4380
  119. 108: 2887
  120. 109: 1814
  121. 110: 1257
  122. 111: 860
  123. 112: 649
  124. 113: 437
  125. 114: 430
  126. 115: 348
  127. 116: 345
  128. 117: 341
  129. 118: 309
  130. 119: 296
  131. 120: 310
  132. 121: 273
  133. 122: 336
  134. 123: 282
  135. 124: 277
  136. 125: 285
  137. 126: 289
  138. 127: 252
  139. 128: 347
  140. 129: 285
  141. 130: 283
  142. 131: 287
  143. 132: 259
  144. 133: 280
  145. 134: 265
  146. 135: 243
  147. 136: 288
  148. 137: 294
  149. 138: 258
  150. 139: 292
  151. 140: 294
  152. 141: 285
  153. 142: 279
  154. 143: 254
  155. 144: 276
  156. 145: 274
  157. 146: 261
  158. 147: 281
  159. 148: 318
  160. 149: 268
  161. 150: 347
  162. 151: 291
  163. 152: 351
  164. 153: 382
  165. 154: 450
  166. 155: 545
  167. 156: 647
  168. 157: 825
  169. 158: 1146
  170. 159: 1506
  171. 160: 2344
  172. 161: 3881
  173. 162: 6737
  174. 163: 122569
  175. 164: 6361
  176. 165: 4283
  177. 166: 6113
  178. 167: 12657
  179. 168: 144433
  180. 169: 3991
  181. 170: 1631
  182. 171: 932
  183. 172: 566
  184. 173: 406
  185. 174: 235
  186. 175: 174
  187. 176: 191
  188. 177: 176
  189. 178: 161
  190. 179: 136
  191. 180: 130
  192. 181: 136
  193. 182: 164
  194. 183: 135
  195. 184: 137
  196. 185: 123
  197. 186: 119
  198. 187: 130
  199. 188: 160
  200. 189: 145
  201. 190: 129
  202. 191: 142
  203. 192: 149
  204. 193: 138
  205. 194: 134
  206. 195: 129
  207. 196: 159
  208. 197: 164
  209. 198: 156
  210. 199: 169
  211. 200: 195
  212. 201: 225
  213. 202: 216
  214. 203: 208
  215. 204: 245
  216. 205: 300
  217. 206: 307
  218. 207: 433
  219. 208: 485
  220. 209: 663
  221. 210: 816
  222. 211: 1117
  223. 212: 1579
  224. 213: 2227
  225. 214: 3199
  226. 215: 4209
  227. 216: 6493
  228. 217: 210867
  229. 218: 5713
  230. 219: 3937
  231. 220: 2781
  232. 221: 1980
  233. 222: 1400
  234. 223: 979
  235. 224: 702
  236. 225: 514
  237. 226: 351
  238. 227: 217
  239. 228: 260
  240. 229: 168
  241. 230: 129
  242. 231: 107
  243. 232: 80
  244. 233: 75
  245. 234: 62
  246. 235: 55
  247. 236: 37
  248. 237: 28
  249. 238: 27
  250. 239: 13
  251. 240: 13
  252. 241: 13
  253. 242: 8
  254. 243: 6
  255. 244: 1
  256. 245: 1
  257. 246: 1
  258. 247: 0
  259. 248: 1
  260. 249: 0
  261. 250: 0
  262. 251: 0
  263. 252: 0
  264. 253: 0
  265. 254: 0
  266. 255: 0
  267. total:1000000

由此可见,最大值210867,最小值0
总像素个数1000000,因为原图是1000*1000 的

若像素值4567980,则化为16进制为45b3ac,每两位化成十进制为:69 176 172 对应RGB

直方图中各个灰度值的高度是  该灰度的像素个数/图中最多像素个数*230 计算而得,它的比例是对于最多数来算的,其实这与对于总数来算是一样的,总数永远都是
1000000。 用于显示直方图的高度为 256,因此要给他一个最高限制0.9 * 256 = 230.

最后用画矩形的方式显示也可以

                                                                         

划线显示 划矩形显示

未经允许不得转载:阿里云代金券 » 计算灰度图的像素直方图,并显示(c++)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

强烈推荐

高性能SSD云服务器ECS抗攻击,高可用云数据库RDS