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

来源:互联网 发布:外国法制史 知乎 编辑:程序博客网 时间:2024/06/05 05:39
程序功能,将一张彩色图片转为灰度图后,分析其各灰度值(0-255)的像素个数以直方图的方式显示出来.

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

#include"stdafx.h"#include<iostream>#include<highgui.hpp>#include<cv.hpp>#include<imgproc.hpp>using namespace std;using namespace cv;Mat getHistImage(const MatND& hist){double maxValue = 0;double minValue = 0;int a = 0;for (int i = 0; i < hist.rows; i++){for (int j = 0; j < hist.cols; j++){float b = hist.at<float>(i, j);a += 1;cout << b << endl;}}minMaxLoc(hist, &minValue, &maxValue, 0, 0);//找到全局最小、最大的像素值数目cout << "max: " << maxValue << "min: " << minValue << endl;int histSize = hist.rows;Mat histImage(histSize, histSize, CV_8UC3, Scalar(255,255,255));int hpt = static_cast<int>(0.9*histSize);int total = 0;Scalar color(172, 172, 150);//BGRfor (int h = 0; h < histSize; h++){float binVal = hist.at<float>(h);//读取对应灰度级的像素个数,一共1000000个cout << h<<": "<<binVal << endl;total += binVal;int intensity = static_cast<int>(binVal*hpt /maxValue);//按比例运算,当前数目*230/最大数目,与除以总数只是比例不同line(histImage, Point(h, histSize), Point(h, histSize - intensity),color);//rectangle(histImage, Point(h, histSize), Point(h + 1, histSize - intensity), color);}cout << total << endl;//total = 1000000return histImage;}int main(int argc, _TCHAR* argv[]){Mat src = imread("D:/2.jpg",-1);//IplImage* image = cvLoadImage("D:/timg.jpg");int a = src.channels();//a = 3通道imshow("b", src);if (!src.data){cout << "no picture!\n";exit(1);}cvtColor(src, src, CV_BGR2GRAY, 0);a = src.channels();//a = 1通道imshow("d", src);int image_count = 1;//要计算直方图的图像的个数int channels[1] = { 0};//图像的通道'Mat out;//计算所得直方图int dims = 1;//得到直方图的维数int histsize[1] = { 256 };//直方图横坐标的子区间数float hrange[2] = { 0, 255 };//区间的总范围const float *ranges[1] = { hrange };//指针数组calcHist(&src, image_count,channels, Mat(), out, dims, histsize, ranges);Mat last = getHistImage(out);imshow("ddd", last);waitKey();return 0;}



几个关键函数介绍:

void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, booluniform=true, bool 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参数表明直方图是否等距,最后一个参数与多图像下直方图的显示与存储有关。


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.
掩码


Mat(int rows, int cols, int type, const Scalar& s)
Mat的构造函数,行,列,类型,每一元素值


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 线条。
第六个参数:坐标点的小数点位数。


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是三


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

for (int i = 0; i < hist.rows; i++){for (int j = 0; j < hist.cols; j++){float b = hist.at<float>(i, j);//这里at函数里的必须是float类型,如果是int的话,就相当于(int&)float,输出的数没有意义,数值很大a += 1;cout << b << endl;}}结果如下:0: 01: 02: 03: 04: 05: 06: 07: 08: 09: 010: 011: 012: 013: 014: 015: 016: 017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032: 033: 034: 135: 136: 037: 038: 239: 340: 341: 842: 1343: 1944: 1845: 2846: 3847: 5248: 5849: 7650: 8151: 10552: 13253: 17554: 20155: 26956: 25757: 34458: 41359: 52860: 59861: 89862: 104263: 133064: 158065: 243166: 13554767: 250368: 161269: 123370: 101271: 68872: 56273: 39874: 28775: 24076: 17377: 14178: 12079: 7680: 7781: 10082: 5883: 5984: 6185: 6186: 7287: 9688: 11189: 12190: 13191: 16392: 21793: 30594: 42595: 57496: 74197: 108498: 152099: 2191100: 2985101: 4345102: 6866103: 11409104: 25454105: 171666106: 10226107: 4380108: 2887109: 1814110: 1257111: 860112: 649113: 437114: 430115: 348116: 345117: 341118: 309119: 296120: 310121: 273122: 336123: 282124: 277125: 285126: 289127: 252128: 347129: 285130: 283131: 287132: 259133: 280134: 265135: 243136: 288137: 294138: 258139: 292140: 294141: 285142: 279143: 254144: 276145: 274146: 261147: 281148: 318149: 268150: 347151: 291152: 351153: 382154: 450155: 545156: 647157: 825158: 1146159: 1506160: 2344161: 3881162: 6737163: 122569164: 6361165: 4283166: 6113167: 12657168: 144433169: 3991170: 1631171: 932172: 566173: 406174: 235175: 174176: 191177: 176178: 161179: 136180: 130181: 136182: 164183: 135184: 137185: 123186: 119187: 130188: 160189: 145190: 129191: 142192: 149193: 138194: 134195: 129196: 159197: 164198: 156199: 169200: 195201: 225202: 216203: 208204: 245205: 300206: 307207: 433208: 485209: 663210: 816211: 1117212: 1579213: 2227214: 3199215: 4209216: 6493217: 210867218: 5713219: 3937220: 2781221: 1980222: 1400223: 979224: 702225: 514226: 351227: 217228: 260229: 168230: 129231: 107232: 80233: 75234: 62235: 55236: 37237: 28238: 27239: 13240: 13241: 13242: 8243: 6244: 1245: 1246: 1247: 0248: 1249: 0250: 0251: 0252: 0253: 0254: 0255: 0total:1000000

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


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


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


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

                                                                         

     划线显示 划矩形显示





原创粉丝点击