opencv图像直方图的计算及绘制
2017-01-29 13:32
477 查看
OpenCV 中提供了 calcHist 函数来计算图像直方图,其函数原型是:
images:输入的图像的指针,可以是多幅图像,但要求所有的图像必须有同样的深度(CV_8U or CV_32F)。
nimages:输入的图像的个数。
channels:计算直方图的 channels 的数组。
mask:掩码,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和输入的图像的大小相同,值非 0 的点将用来计算直方图。
hist:输出参数,计算出来的直方图。
dims:直方图的维数,不能大于 CV_MAX_DIMS 。
histSize:在每一维上直方图的元素个数。
ranges:直方图每一维的范围,ranges 是指向数组的数组,它指向的那些数组为 ranges 的元素,元素大小也就是这些数组的长度。
如果参数uniform为 true,这此时的ranges 里元素的大小为 2(也就是说 ranges 指向一系列长度为 2 的数组);如果参数 uniform 为 false,则此时每一维的坐标值不一定是均匀的,需要人为指定。
uniform: 如果为 true 的话,则说明所需计算的直方图的每一维按照它的范围和尺寸大小均匀取值;如果为 false 的话,说明直方图的每一维不是均匀分布取值的,参考参数 ranges 的解释。
accumulate: 表示是否对传入的 hist 清零。不清零的话可以将多幅图像的直方图累加。
实例二:将计算和绘制直方图写成函数
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
// 得到图像的直方图
MatND getHistogram(Mat &image)
{
MatND hist;
int channels[] = {0};
int dims = 1;
int histSize[] = {256};
float granges[] = {0, 255};
const float *ranges[] = {granges};
calcHist(&image, 1, channels, Mat(), hist, dims, histSize, ranges);
return hist;
}
// 将图像直方图展示出来
Mat getHistogramImage(Mat &image)
{
MatND hist = getHistogram(image);
Mat showImage(256,256, CV_8U,Scalar(0));
int i;
double maxValue = 0;
minMaxLoc(hist, 0, &maxValue, 0, 0);
for(i = 0; i < 256; i++)
{
float value = hist.at<float>(i);
int intensity = saturate_cast<int>(256 - 256* (value/maxValue));
rectangle(showImage, Point(i,256 - 1), Point((i+1)-1, intensity), Scalar(255));
}
return showImage;
}
//主函数
int main()
{
Mat image = imread("E://IM_VIDEO//kobe.jpg");
if(!image.data)
{
cout << "fail to load the image" << endl;
return 0;
}
Mat showImage = getHistogramImage(image);
namedWindow("image");
imshow("image", image);
namedWindow("showImage");
imshow("showImage", showImage);
waitKey(0);
return 0;
} 运行结果:
实例三:计算和绘制多通道图像的直方图
参考:
http://blog.csdn.net/liyuanbhu/article/details/50708912 http://blog.csdn.net/qq_23880193/article/details/49669297 http://blog.csdn.net/zhouzhouzf/article/details/9272299 http://blog.csdn.net/lu597203933/article/details/17061173
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)。
nimages:输入的图像的个数。
channels:计算直方图的 channels 的数组。
mask:掩码,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和输入的图像的大小相同,值非 0 的点将用来计算直方图。
hist:输出参数,计算出来的直方图。
dims:直方图的维数,不能大于 CV_MAX_DIMS 。
histSize:在每一维上直方图的元素个数。
ranges:直方图每一维的范围,ranges 是指向数组的数组,它指向的那些数组为 ranges 的元素,元素大小也就是这些数组的长度。
如果参数uniform为 true,这此时的ranges 里元素的大小为 2(也就是说 ranges 指向一系列长度为 2 的数组);如果参数 uniform 为 false,则此时每一维的坐标值不一定是均匀的,需要人为指定。
uniform: 如果为 true 的话,则说明所需计算的直方图的每一维按照它的范围和尺寸大小均匀取值;如果为 false 的话,说明直方图的每一维不是均匀分布取值的,参考参数 ranges 的解释。
accumulate: 表示是否对传入的 hist 清零。不清零的话可以将多幅图像的直方图累加。
#include<opencv2/opencv.hpp> #include<iostream> #include<vector> using namespace cv; using namespace std; int main() { Mat srcImage = imread("E://IM_VIDEO//kobe.jpg"); imshow("ScrImage", srcImage); int channels = 0; MatND dstHist; int histSize[] = { 256 }; //如果写成int histSize = 256;调用计算直方图的函数的时,该变量需写成&histSize float midRanges[] = { 0, 256 }; const float *ranges[] = { midRanges }; calcHist(&srcImage, 1, &channels, Mat(), dstHist, 1, histSize, ranges, true, false); //绘制直方图,首先先创建一个黑底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像 Mat drawImage = Mat::zeros(Size(256, 256), CV_8UC3); //任何一个图像的某个像素的总个数有可能会很多,甚至超出所定义的图像的尺寸, //所以需要先对个数进行范围的限制,用minMaxLoc函数来得到计算直方图后的像素的最大个数 double g_dHistMaxValue; minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0); //将像素的个数整合到图像的最大范围内 for (int i = 0; i < 256; i++) { int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue); line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(0, 0, 255)); } imshow("hist", drawImage); waitKey(0); return 0; }运行结果如下:
实例二:将计算和绘制直方图写成函数
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
// 得到图像的直方图
MatND getHistogram(Mat &image)
{
MatND hist;
int channels[] = {0};
int dims = 1;
int histSize[] = {256};
float granges[] = {0, 255};
const float *ranges[] = {granges};
calcHist(&image, 1, channels, Mat(), hist, dims, histSize, ranges);
return hist;
}
// 将图像直方图展示出来
Mat getHistogramImage(Mat &image)
{
MatND hist = getHistogram(image);
Mat showImage(256,256, CV_8U,Scalar(0));
int i;
double maxValue = 0;
minMaxLoc(hist, 0, &maxValue, 0, 0);
for(i = 0; i < 256; i++)
{
float value = hist.at<float>(i);
int intensity = saturate_cast<int>(256 - 256* (value/maxValue));
rectangle(showImage, Point(i,256 - 1), Point((i+1)-1, intensity), Scalar(255));
}
return showImage;
}
//主函数
int main()
{
Mat image = imread("E://IM_VIDEO//kobe.jpg");
if(!image.data)
{
cout << "fail to load the image" << endl;
return 0;
}
Mat showImage = getHistogramImage(image);
namedWindow("image");
imshow("image", image);
namedWindow("showImage");
imshow("showImage", showImage);
waitKey(0);
return 0;
} 运行结果:
实例三:计算和绘制多通道图像的直方图
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; int main( int argc, char** argv ) { Mat src, dst; src = imread("E://IM_VIDEO//kobe.jpg"); if( !src.data ) { return -1; } vector<Mat> rgb_planes; split( src, rgb_planes ); int histSize = 255; float range[] = { 0, 255 } ; const float* histRange = { range }; bool uniform = true; bool accumulate = false; Mat r_hist, g_hist, b_hist; // 计算直方图: calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); // 创建直方图画布 int hist_w = 400; int hist_h = 400; int bin_w = cvRound( (double) hist_w/histSize ); Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) ); // 将直方图归一化到范围 [ 0, histImage.rows ] normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); // 在直方图画布上画出直方图 for( int i = 1; i < histSize; i++ ) { line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ), Scalar( 0, 0, 255), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ), Scalar( 0, 255, 0), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ), Scalar( 255, 0, 0), 2, 8, 0 ); } /// 显示直方图 namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE ); imshow("calcHist Demo", histImage ); waitKey(0); return 0; }运行结果如下:
参考:
http://blog.csdn.net/liyuanbhu/article/details/50708912 http://blog.csdn.net/qq_23880193/article/details/49669297 http://blog.csdn.net/zhouzhouzf/article/details/9272299 http://blog.csdn.net/lu597203933/article/details/17061173
相关文章推荐
- opencv学习之(五)-直方图计算和绘制图像直方图
- opencv学习之(五)-直方图计算和绘制图像直方图
- OpenCV之imgproc 模块. 图像处理(4)直方图均衡化 直方图计算 直方图对比 反向投影 模板匹配
- opencv-python绘制图像颜色直方图
- Opencv绘制灰度/彩色图像的直方图及直方图的均衡化实例及源代码
- opencv学习(三十七)之图像直方图计算calcHist()
- opencv 绘制图像直方图
- 【OpenCV学习笔记】二十二、直方图计算及绘制(二)
- 图像相似度计算之直方图方法OpenCV实现
- OpenCV入门(二十一)-- 绘制彩色图像的直方图
- 利用opencv函数对图像旋转后,按旋转偏移新计算新的图像外接四边形绘制
- OpenCV环境下计算并绘制灰度直方图的源码!
- OpenCV【4】---calcHist 计算图像的直方图
- 图像相似度计算之直方图方法OpenCV实现
- OpenCV绘制图像的水平和竖直方向直方图
- OpenCV绘制图像的水平和竖直方向直方图
- 计算并绘制单通道图像的直方图
- 【OpenCV3图像处理】统计图像的直方图 ,绘制直方图
- opencv 绘制图像直方图
- 有关opencv的学习(9)—计算图像直方图