OpenCV 学习(计算图像的直方图)
2016-02-21 18:11
441 查看
OpenCV 计算图像的直方图
计算图像的直方图是图像处理领域一个非常常见的基本操作。 OpenCV 中提供了 calcHist 函数来计算图像直方图。不过这个函数说实话挺难用的,研究了好久才掌握了些基本的用法。calcHist 函数 C++ 的函数原型如下:
[code]void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, SparseMat& hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
各个参数的含义如下:
images:输入的图像的指针,可以是多幅图像,但是所有的图像必须有同样的深度(CV_8U or CV_32F)。一副图像可以有多个 channels。
nimages:输入的图像的个数。
channels:用来计算直方图的 channels 的数组。
mask:掩码,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和输入的图像的大小相同,值非 0 的点将用来计算直方图。
hist:输出参数,计算出来的直方图。
dims:直方图的维数,不能大于 CV_MAX_DIMS (在现有版本中是 32)。
histSize: 在每一维上直方图的元素个数。
ranges: 所需计算直方图的每一维的范围。ranges 是个指向数组的数组。我们称它指向的那些数组为 ranges 的元素,元素大小也就是这些数组的长度。
如果参数 uniform 为 true,这此时的ranges 里元素的大小为 2(也就是说 ranges 指向一系列长度为 2 的数组),存储的是每一维的上下限这两个数字;如果参数 uniform 为 false,则此时的 ranges 的元素大小为 bin 的个数,存储的是一个个颜色值,即每一维的坐标值不一定是均匀的,需要人为指定。
uniform: 如果为 true 的话,则说明所需计算的直方图的每一维按照它的范围和尺寸大小均匀取值;如果为 false 的话,说明直方图的每一维不是均匀分布取值的,参考参数 ranges 的解释。
accumulate: 表示是否对传入的 hist 清零。不清零的话可以将多幅图像的直方图累加。
看上面这个解释大家应该就能感觉出这个函数有多麻烦了吧。不过好在我们一般只会用到一些最基本的功能。比如计算个单通道灰度图像的直方图。直方图的取值范围一般来说也会是 0 到 255。 这时我们可以把这个函数再进行一次封装,使其更好用一些。
下面的代码来自 《OpenCV 2 Computer Vision Application Programming Cookbook》。 书的作者写了一个类,叫做 Histogram1D。
这个类的声明如下:
[code]class Histogram1D { public: Histogram1D() { // Prepare arguments for 1D histogram histSize[0] = 256; hranges[0] = 0.0; hranges[1] = 255.0; ranges[0] = hranges; channels[0] = 0; // by default, we look at channel 0 } ~Histogram1D(); // Computes the 1D histogram and returns an image of it. cv::Mat getHistogramImage(const cv::Mat &image); // Computes the 1D histogram. cv::MatND getHistogram(const cv::Mat &image); private: int histSize[1]; // number of bins float hranges[2]; // min and max pixel value const float* ranges[1]; int channels[1]; // only 1 channel used here };
getHistogram 函数用来计算直方图。实现如下:
[code]// Computes the 1D histogram. cv::MatND Histogram1D::getHistogram(const cv::Mat &image) { cv::MatND hist; // Compute histogram cv::calcHist(&image, 1, // histogram from 1 image only channels, // the channel used cv::Mat(), // no mask is used hist, // the resulting histogram 1, // it is a 1D histogram histSize, // number of bins ranges // pixel value range ); return hist; }
getHistogramImage 函数用来生成直方图的图像:
[code]// Computes the 1D histogram and returns an image of it. cv::Mat Histogram1D::getHistogramImage(const cv::Mat &image) { // Compute histogram first cv::MatND hist = getHistogram(image); // Get min and max bin values double maxVal = 0; double minVal = 0; cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0); // Image on which to display histogram cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255)); // set highest point at 90% of nbins int hpt = static_cast<int>(0.9 * histSize[0]); // Draw a vertical line for each bin for( int h = 0; h < histSize[0]; h++ ) { float binVal = hist.at<float>(h); int intensity = static_cast<int>(binVal * hpt / maxVal); // This function draws a line between 2 points cv::line(histImg, cv::Point(h, histSize[0]), cv::Point(h,histSize[0]-intensity), cv::Scalar::all(0)); } return histImg; }
还有另外一个类可以计算彩色图像的直方图。不过这个用途不是很大。因为彩色图像的颜色空间太大了。而且形成的直方图是个三维的数组。用起来也不方便。为了完整,这里还是把代码列了出来。
[code]class ColorHistogram { public: ColorHistogram() { // Prepare arguments for a color histogram histSize[0] = histSize[1] = histSize[2] = 256; hranges[0] = 0.0; // BRG range hranges[1] = 255.0; ranges[0] = hranges; // all channels have the same range ranges[1] = hranges; ranges[2] = hranges; channels[0] = 0; // the three channels channels[1] = 1; channels[2] = 2; } cv::MatND getHistogram(const cv::Mat &image) ; cv::SparseMat getSparseHistogram(const cv::Mat &image) ; private: int histSize[3]; float hranges[2]; const float* ranges[3]; int channels[3]; };
这里实现了两个函数 getHistogram 和 getSparseHistogram。 唯一的区别就是 getSparseHistogram 返回的是个稀疏矩阵。
[code]cv::MatND ColorHistogram::getHistogram(const cv::Mat &image) { cv::MatND hist; // Compute histogram cv::calcHist(&image, 1, // histogram of 1 image only channels, // the channel used cv::Mat(), // no mask is used hist, // the resulting histogram 3, // it is a 3D histogram histSize, // number of bins ranges // pixel value range ); return hist; } cv::SparseMat ColorHistogram::getSparseHistogram(const cv::Mat &image) { cv::SparseMat hist(3,histSize,CV_32F); // Compute histogram cv::calcHist(&image, 1, // histogram of 1 image only channels, // the channel used cv::Mat(), // no mask is used hist, // the resulting histogram 3, // it is a 3D histogram histSize, // number of bins ranges // pixel value range ); return hist; }
相关文章推荐
- linux 下mysql安装
- OpenCV实践之路——像素初探
- 使用HYPER-V搭建linux虚拟机
- Linux apt命令
- linux 下常见的文件内字符串替换命令
- linux内核装载vfs过程
- linux 环境下Apache+PHP+Mysql 源码安装
- Apache shiro 笔记整理之HelloWorld
- Linux学习笔记(持续更新)
- openstack常用命令
- Linux下串口通信详解(上)打开串口和串口初始化详解
- POJ 2115 C Looooops 扩展gcd的应用 及其 gcd exgcd的讲解
- 第五项修炼与架构师感想
- ubuntu 添加开机启动项
- CentOS7下Firewall防火墙配置用法详解
- linux常用命令2--权限管理命令
- 大型网站技术架构读书笔记03—大型网站架构核心要素
- Linux 常用命令集合
- CentOS 7 上systemctl 的用法
- linux下定时重启tomcat