1:由于calhist()函数求得的直方图返回值也是一个一维或三维等等的矩阵,因此可以采用可视化的方式将结果显示出来;为此我们将计算和显示的功能封装到一个类中来实现:
class Histogram1D
{
private:
int histSize[1]; //项的数量;保存了维数和分块的信息;
float histRange[2]; //灰度最大值和最小值;
const float *range[1]; //指针数组,
int channels[1]; //通道数目;
public:
Histogram1D()
{
histSize[0] = 255;
histRange[0] = 0;
histRange[1] = 255;
range[0] = histRange; //range[0]是一个指针,range就是指针的指针
channels[0] = 0;
}
MatND getHistorgram(const Mat& image) //计算直方图数组
{
MatND hist;
calcHist(&image,1,channels,Mat(),hist,1,histSize,range);
return hist;
}
Mat GetHistoImage(const Mat &image); //直方图数组的show;
};
Mat Histogram1D::GetHistoImage(const Mat &image)
{
MatND hist = getHistorgram(image);
double maxVal=0;
double minVal=0;
minMaxLoc(hist,&minVal,&maxVal,0,0);
int histSize=hist.rows;
Mat histImage(histSize,histSize,CV_8U,Scalar(255));
int hpt=static_cast<int>(0.9*histSize);
for(int h=0;h<histSize;h++)
{
float binVal=hist.at<float>(h);
int intensity=static_cast<int>(binVal*hpt/maxVal);
line(histImage,Point(h,histSize),Point(h,histSize-intensity),Scalar::all(0));
}
return histImage;
}
然后在主函数中定义一个对象,就可以直接实现直方图的可视化了
int _tmain(int argc, _TCHAR* argv[])
{
Mat image = imread("meng.jpg",1);
cvtColor(image,image,CV_RGB2GRAY);
Histogram1D h;
namedWindow("直方图");
imshow("直方图",h.GetHistoImage(image));
waitKey(0);
return 0;
}
得到的结果:
但是需要注意的是,在显示的过程中用到了line函数,该函数的原型:
C: void cvLine(CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color, int thickness=1, int line_type=8, int shift=0 )
第一个参数为需要划线的图像指针,第二第三为起始点终点,color表示画笔颜色;默认的坐标体系为:原点在window的左上角,向下为y轴正方向,向右为x轴正方向;