calcHist() 计算直方图实现(C++、opencv)

1.作用:

       图像直方图是对数据集合的一种统计方法,将统计结果分布于一系列预定义的bin中,bin是直方图中经常用到的一个概念,其数值是从数据中计算出的特征统计量,这些数据不仅仅指的灰度值,统计数据可能是任何能有效描述图像的特征包括梯度、方向、色彩或任何其他特征。直方图获得的是数据分布的统计图,通常直方图的维数要低于原始数据。
图像直方图是用以表示数字图像中亮度分布的直方图,标绘了图像中亮度值的像素数。可以借助观察该直方图调整亮度分布,这种直方图中横坐标的左侧为纯黑或较暗区域,右侧为较亮纯白的区域。可用于实现图像的二值化
假设有一个矩阵包含一张图像信息(灰度值0-255),如下:

2.函数原型 

void calcHist( const Mat* images, int nimages,
               const int* channels, InputArray mask,
               OutputArray hist, int dims, const int* histSize,
               const float** ranges, bool uniform=true, bool accumulate=false );
//1.输入的图像数组   2.输入数组的个数             3.通道数              4.掩码                5.直方图         
//6.直方图维度       7.直方图每个维度的尺寸数组   8.每一维数组的范围    9.直方图是否是均匀   10.累加标志

参数详解:

 images:输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度(CV_8U or CV_32F)。同时一副图像可以有多个channes。

nimages:输入图像的个数

 channels:需要统计直方图的第几通道。用来计算直方图的channes的数组。比如输入是2副图像,第一副图像有0,1,2共三个channel,第二幅图像只有0一个channel,那么输入就一共有4个channes,如果int channels[3] = {3, 2, 0},那么就表示是使用第二副图像的第一个通道和第一副图像的第2和第0个通道来计算直方图。

mask:掩膜,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算掩膜内的直方图  ...Mat()

hist:输出的直方图数组

dims:需要统计直方图通道的个数

histSize:指的是直方图分成多少个区间,就是 bin的个数。在每一维上直方图的个数。简单把直方图看作一个一个的竖条的话,就是每一维上竖条的个数。

const float** ranges: 统计像素值得区间。比如: 

        float rang1[] = {0, 20};

        float rang2[] = {30, 40};

        const float *rangs[] = {rang1, rang2};那么就是对0,20和30,40范围的值进行统计。

uniform=true::是否对得到的直方图数组进行归一化处理

accumulate=false:在多个图像时,是否累计计算像素值得个数

1.图像数组              2.图像数组个数      3.图像的通道数    4.图像掩码       5.计算得到的直方图

6.直方图的维度(灰度直方图为1维)      7.直方图每一维度上的数组个数(bin 的个数)

8.每一维进行直方图统计的数组的范围  范围如 0~256 表示统计 0~255的数组 这里注意 (0,256) 包含0而不包含256 包含的是256-1

9.是否均匀的统计

10.累加标志   在多幅图像输入时,对其中数据进行累加,单幅图像不进行累计所以例子中为false

void cv::normalize  (   InputArray      src,
        InputOutputArray    dst,
        double      alpha = 1,
        double      beta = 0,
        int     norm_type = NORM_L2,
        int     dtype = -1,
        InputArray      mask = noArray() 
    )

参数解释
. src: 输入数组
. dst: 输出数组,与src有相同的尺寸
. alpha: 将数组归一化范围的最大值,有默认值1
. beta: 归一化的最小值,有默认值0
. norm_type: 归一化方式,可以查看NormTypes()函数查看详细信息,有默认值NORM_L2
. dtype: 当该值取负数时,输出数组与src有相同类型,否则,与src有相同的通道并且深度为CV_MAT_DEPTH(dtype)
. mask: 可选的掩膜版

3.实现:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

int main()
{
    Mat srcImage;
    srcImage = imread("E:\\workspace\\opencv_study\\example\\1.jpg");
    if (srcImage.empty())
    {
        cout << "图像加载失败!" << endl;
        return -1;
    }
    else
        cout << "图像加载成功!" << endl << endl;
    //分割成三通道图像
    vector<Mat> channels;
    split(srcImage, channels);

    Mat gray_color;
    cvtColor(srcImage, gray_color, COLOR_RGB2GRAY);

    //设定bin数目
    int histBinNum = 255;

    //设定取值范围
    float range[] = { 0, 255 };
    const float* histRange = { range };

    bool uniform = true;
    bool accumulate = false;

    //声明三个通道的hist数组
    Mat red_hist, green_hist, blue_hist,gray_hist;

    //计算直方图
    calcHist(&channels[0], 1, 0, Mat(), red_hist, 1, &histBinNum, &histRange, uniform, accumulate);
    calcHist(&channels[1], 1, 0, Mat(), green_hist, 1, &histBinNum, &histRange, uniform, accumulate);
    calcHist(&channels[2], 1, 0, Mat(), blue_hist, 1, &histBinNum, &histRange, uniform, accumulate);
    calcHist(&gray_color, 1, 0, Mat(), gray_hist, 1, &histBinNum, &histRange, uniform, accumulate);

    //创建直方图窗口
    int hist_w = 400;
    int hist_h = 400;
    int bin_w = cvRound((double)srcImage.cols / histBinNum);

    Mat histImage(srcImage.cols, srcImage.rows, CV_8UC3, Scalar(0, 0, 0));

    //将直方图归一化到范围[0, histImage.rows]
    normalize(red_hist, red_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(green_hist, green_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(blue_hist, blue_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
    normalize(gray_hist, gray_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

    //循环绘制直方图
    for (int i = 1; i < histBinNum+1; i++)
    {
        line(histImage, Point(bin_w * (i - 1), srcImage.rows - cvRound(red_hist.at<float>(i - 1))),
            Point(bin_w * (i), srcImage.rows - cvRound(red_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
        line(histImage, Point(bin_w * (i - 1), srcImage.rows - cvRound(green_hist.at<float>(i - 1))),
            Point(bin_w * (i), srcImage.rows - cvRound(green_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
        line(histImage, Point(bin_w * (i - 1), srcImage.rows - cvRound(blue_hist.at<float>(i - 1))),
            Point(bin_w * (i), srcImage.rows - cvRound(blue_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
        line(histImage, Point(bin_w * (i - 1), srcImage.rows - cvRound(blue_hist.at<float>(i - 1))),
            Point(bin_w * (i), srcImage.rows - cvRound(gray_hist.at<float>(i))), Scalar(255, 255, 255), 2, 8, 0);
    }

   /* namedWindow("原图像", WINDOW_AUTOSIZE);
    imshow("原图像", srcImage);*/

    namedWindow("图像直方图", WINDOW_AUTOSIZE);
    imshow("图像直方图", histImage);

    waitKey(0);

    return 0;
}
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/video/background_segm.hpp>
#include "opencv2/calib3d/calib3d.hpp"
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(int argc, char** argv) {
	cv::Mat temp_thin = cv::imread("../example/2.jpg", CV_LOAD_IMAGE_UNCHANGED);
	//cv::imshow("temp_thin",temp_thin);
	cv::Mat gray_image, dst, temp_thin_image, binary_image, edge_image;
	
	cvtColor(temp_thin, gray_image, CV_RGB2GRAY);

	GaussianBlur(gray_image, edge_image, Size(3, 3), 0, 0);
	//blur(gray, edge, Size(3, 3));
	Canny(edge_image, edge_image, 10, 150, 3, false);
	cv::imshow("edge_image", edge_image);

	std:; string anme_pic = "..\\example\\edge_image.bmp";
	cv::imwrite(anme_pic, edge_image);

	cv::waitKey(0);
	return 0;
}

4.效果

 

 

5.原理


  •  

6.参考

【1】 https://blog.csdn.net/nanguazhuo/article/details/53509695

【2】https://blog.csdn.net/wolfcsharp/article/details/85945491?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2

【3】https://blog.csdn.net/keith_bb/article/details/56680997

【4】https://blog.csdn.net/keith_bb/article/details/56680997

GitHub 加速计划 / opencv31 / opencv
144
15
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:3 个月前 )
d9a139f9 Animated WebP Support #25608 related issues #24855 #22569 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 2 天前
09030615 V4l default image size #25500 Added ability to set default image width and height for V4L capture. This is required for cameras that does not support 640x480 resolution because otherwise V4L capture cannot be opened and failed with "Pixel format of incoming image is unsupported by OpenCV" and then with "can't open camera by index" message. Because of the videoio architecture it is not possible to insert actions between CvCaptureCAM_V4L::CvCaptureCAM_V4L and CvCaptureCAM_V4L::open so the only way I found is to use environment variables to preselect the resolution. Related bug report is [#25499](https://github.com/opencv/opencv/issues/25499) Maybe (but not confirmed) this is also related to [#24551](https://github.com/opencv/opencv/issues/24551) This fix was made and verified in my local environment: capture board AVMATRIX VC42, Ubuntu 20, NVidia Jetson Orin. ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [X] I agree to contribute to the project under Apache 2 License. - [X] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [X] The PR is proposed to the proper branch - [X] There is a reference to the original bug report and related work - [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ ] The feature is well documented and sample code can be built with the project CMake 2 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐