0.功能
function : 计算一组数组(通常是图像或图像平面)的直方图,此处将R、G、B三个通道平面分别进行计算;
theory : 图像直方图不仅可以计算颜色强度,还可以计算任何图像特征;
函数 : cv:calcHist()
/*计算直方图
void cv::calcHist ( const Mat * images,//具有相同depth的源数组/图像
int nimages, //源数组/图像的数量
const int * channels, //用于计算直方图的通道序号,可以是dims多维数组
InputArray mask, //可选,当值为0时意味着像素值被忽略;没定义则没有作用
OutputArray hist, //输出直方图,是一个稠密或者稀疏的dims多维数组
int dims, //直方图的维度数
const int * histSize, //每个维度上直方图数组大小
const float ** ranges, //每个维度上直方图数组边界
bool uniform = true, //指示直方图是否均匀的标志
bool accumulate = false //累计标志。如果设置,则直方图在分配时不会在开始时清除;可以从多组数组计算单个直方图或及时更新直方图
)
*/
1.工作空间准备
在任意非中文目录下创建如下工作空间:
mkdir -p opencv_hc/src
cd opencv_hc/src
catkin_create_pkg image_processing cv_bridge roscpp rospy std_msgs
cd ..
tree
得目录结构如下所示:
[meng@meng ~/opencv_hc]$ tree
.
└── src
└── image_processing
├── CMakeLists.txt
├── include
│ └── image_processing
├── package.xml
└── src
5 directories, 2 files
2.程序准备与解读
修改opencv_hc/src/image_processing/CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.0.2)
project(image_processing)
find_package(catkin REQUIRED COMPONENTS
cv_bridge
roscpp
rospy
std_msgs
)
find_package(OpenCV REQUIRED)
catkin_package()
include_directories(
# include
${catkin_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS}
)
add_executable(histogram_calculation_node src/histogram_calculation.cpp)
target_link_libraries(histogram_calculation_node
${catkin_LIBRARIES} ${OpenCV_LIBS}
)
在opencv_hc/src/image_processing/src/下添加文件:histogram_calculation.cpp,如下所示:
/*
reference link : https://docs.opencv.org/master/d8/dbc/tutorial_histogram_calculation.html
*/
#include "opencv2/highgui.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
//CommandLineParser parser( argc, argv, "{@input | lena.jpg | input image}" );
//Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ), IMREAD_COLOR );
Mat src = imread("/home/meng/my_learning/opencv/data/lena.jpg", IMREAD_COLOR );
if( src.empty() )
{
return EXIT_FAILURE;//程序返回值
}
vector<Mat> bgr_planes;
split( src, bgr_planes );//将图像的通道分离
int histSize = 256;//直方图分格数量
//设置值的范围
float range[] = { 0, 256 }; //the upper boundary is exclusive //两个元素的数组
const float* histRange[] = { range };//一个元素的数组
bool uniform = true, accumulate = false;
Mat b_hist, g_hist, r_hist;
/*计算直方图
void cv::calcHist ( const Mat * images,//具有相同depth的源数组/图像
int nimages, //源数组/图像的数量
const int * channels, //用于计算直方图的通道序号,可以是dims多维数组
InputArray mask, //可选,当值为0时意味着像素值被忽略;没定义则没有作用
OutputArray hist, //输出直方图,是一个稠密或者稀疏的dims多维数组
int dims, //直方图的维度数
const int * histSize, //每个维度上直方图数组大小
const float ** ranges, //每个维度上直方图数组边界
bool uniform = true, //指示直方图是否均匀的标志
bool accumulate = false //累计标志。如果设置,则直方图在分配时不会在开始时清除;可以从多组数组计算单个直方图或及时更新直方图
)
*/
calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, histRange, uniform, accumulate );
calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, histRange, uniform, accumulate );
calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, histRange, uniform, accumulate );
//创建一个图像去显示直方图
int hist_w = 512, hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );//cvRound()使浮点数靠近最近的整数
Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
/*
NORM_MINMAX : 归一化类型,NORM_MINMAX调整两个限制中间的值
-1 : 归一化输出数组与输入数组同类型
*/
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(r_hist, r_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(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 );
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(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 );
}
imshow("Source image", src );
imshow("calcHist Demo", histImage );
waitKey();
return EXIT_SUCCESS;
}
3.程序编译与运行
到opencv_hc/目录下
catkin_make
source devel/setup.bash
rosrun image_processing histogram_calculation_node
即可看到图像B、G、R三个通道分别的直方图如下
注:原图像如下