opencv之直方图计算

这里写自定义目录标题

直方图简介

  • 一般来说直方图基于图像像素值,其实对于图像梯度、每个像素的角度、等一切图像的属性值,我们都可以建立直方图,这个才是直方图概念的真正意义,不过是基于图像像素灰度直方图是最常见的。
  • 直方图最常见的几个属性:
    • dims 表示维度,对灰度图像来说只有一个通道值dims=1
    • bins 表示在维度中心区域大小划分,bins=256,划分为256个级别
    • range 表示值的范围,灰度值范围为[0-255]之间

函数API

API
// 把多通道图像分为多个单通道图像 split( const Mat &src, //输入图像 Mat* mvbegin)// 输出的通道图像数组
参数介绍
参数较为简单,这里不做介绍

API
calcHist( const Mat* images,//输入图像指针 int images,// 图像数目 const int* channels,// 通道数 InputArray mask,// 输入mask,可选,不用 OutputArray hist,//输出的直方图数据 int dims,// 维数 const int* histsize,// 直方图级数 const float* ranges,// 值域范围 bool uniform,// true by default bool accumulate// false by defaut )
参数介绍

  • const Mat images*:输入图像
  • int nimages:输入图像的个数
  • const int channels*:需要统计直方图的第几通道
  • InputArray mask:掩膜,,计算掩膜内的直方图 …Mat()
  • OutputArray hist:输出的直方图数组
  • int dims:需要统计直方图通道的个数
  • const int histSize*:指的是直方图分成多少个区间,就是 bin的个数
  • const float ranges**: 统计像素值得区间
  • bool uniform=true::是否对得到的直方图数组进行归一化处理
  • bool accumulate=false:在多个图像时,是否累计计算像素值得个数

代码演示

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

#define Pic_Path "/home/image/Pictures/my_picture/"
#define Pic_Name "model_1.jpeg"

int main(void)
{
    string pic = string(Pic_Path) + string(Pic_Name);
    cout << pic << endl;

    cv::Mat src;
    //读取原始图片
    src = cv::imread(pic.c_str());
    if(src.empty())
    {
        cout << "图片不存在" << endl;
        return -1;
    }

    cv::namedWindow("原始图片",cv::WINDOW_AUTOSIZE);
    cv::imshow("原始图片",src);


    //分通道显示
    vector<Mat> bgr_planes;
    split(src, bgr_planes);

    //设定像素取值范围
    int histSize = 256;
    float range[] = { 0,256 };
    const float *histRanges = { range };

    //三个通道分别计算直方图
    Mat b_hist, g_hist, r_hist;

    //输入图像指针 图像数目 通道数 mask可以不用 输出直方图 直方图维度 直方图级数 值域范围
    calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRanges, true, false);
    calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRanges, true, false);
    calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRanges, true, false);

    //创建直方图画布并归一化处理
    int hist_h = 400;    //绘制图像高度
    int hist_w = 512;    //绘制图像宽度
    int bin_w = hist_w / histSize;  //画点时x坐标的步进长度 因为原图x范围为256

    //创建画布 背景为黑色
    Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));

    //图像归一化 统计像素时某些点数量较大 远远大于图像高度  这里将点的范围全部控制到0-400范围之间
    //normalize参数:输入图像 输出图像 范围低值 范围高值 归一化类型
    //normalize参数:当为负,输出在大小深度通道数都等于输入,当为正,输出只在深度与输如不同,不同的地方游dtype决定;掩膜
    normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
    normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX, -1, Mat());
    normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX, -1, Mat());

    //render histogram chart  在直方图画布上画出直方图
    //cvRound 返回跟参数最接近的整数值;
    //cvFloor 返回不大于参数的最大整数值;
    //cvCeil 返回不小于参数的最小整数值
    for (int i = 0; i < histSize; i++)
    {
        //屏幕坐标系以左上角为00点,向下、向右为正方向,所以高度上不做反转处理,显示出来的直方图是倒立的
        //绘图时用直线描绘 原理是用前一个点做起点 用本身的点做终点  依次绘制
        line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))),
            Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA);
        line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))),
            Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA);
        line(histImage, Point((i - 1)*bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))),
            Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA);


    }
    imshow("直方图", histImage);

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

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值