OpenCV学习实践(6) Histogram Calculation

该博客介绍了如何使用OpenCV库计算和显示图像的直方图,包括R、G、B三个通道。通过`cv::calcHist`函数,计算图像的直方图,并使用`normalize`进行归一化处理,最后绘制直方图图像。程序展示了从读取图像到显示直方图的完整流程。
摘要由CSDN通过智能技术生成

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三个通道分别的直方图如下

 注:原图像如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值