OpenCV 图像直方图

一、知识点
1、图像直方图

(1)、图像直方图(Histogram)是图像像素值的统计报告图。

(2)、由一系列高度不等的纵向条纹或线段表示数据分布的情况,一般横轴表示数据类型,纵轴表示分布情况。

(3)、计算代价较小,具有图像平移、旋转、缩放不变性等众多优点。

(4)、广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类、反向投影跟踪。

(5)、常见的分为灰度直方图、颜色直方图。

(6)、例如灰度直方图,横坐标是0到255,纵坐标表示灰度值在像素点出现的次数。

2、Bins

(1)、bin,英文翻译为箱子,我理解为直方图的一个条纹、柱子。

(2)、Bins指直方图柱子的个数,即把数据划分为连续区间的个数,用于统计每个区间内数据出现的频次。

(3)、对于像素值在0-255之间的,可以有256个bin,可以有16、32、48、128等,256除以bin应该是整数倍。

3、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)、参数说明:

images: 源图像数组。 它们应具有相同的深度(CV_8U、CV_16U、CV_32F)、相同的尺寸,但它们每一个可以有任意数量的通道。

nimages: 源图像的数量。

channels: 需要统计的通道索引数组。第一个图像的通道索引为0到images[0].channels() - 1,第二个图像通道索引为images[0].channels()到images[0].channels() + images[1].channels() - 1,依次类推。

mask: 可选掩码。 若不为空,则它必须和源图像大小相同且像素深度为8位。 非零元素对应的图像元素才计算直方图。

hist: 输出的统计直方图结果,它是一个dims维度的数组。

dims: 需要计算直方图的维度,必须是整数,不能大于CV_MAX_DIMS。

histSize: 每个维度的直方图bins数组。

ranges: 每个图像通道中灰度值的取值范围。

uniform: 直方图是否均匀的标志,默认为均匀。

accumulate: 是否累计统计直方图的标志。 该参数主要用于统计多个图像整体的直方图。

(3)、因此函数参数较多且复杂,建议将彩色图像先分离通道再计算直方图。

4、int cvRound(double value)

(1)、对浮点数进行四舍五入。

二、示例代码

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>


int main()
{
    //1.读取源彩色图像
    cv::Mat src = cv::imread("../images/img08.png");
    if (src.empty())
    {
        std::cout << "load src image error..." << std::endl;
        return -1;
    }

    //2.三通道分离
    std::vector<cv::Mat> bgr_plane;
    cv::split(src, bgr_plane);

    //3.定义参数变量
    const int bins[1] = { 256 };
    float hrange[2] = { 0, 255 };
    const float* ranges[1] = { hrange };
    cv::Mat b_hist;
    cv::Mat g_hist;
    cv::Mat r_hist;

    //4.计算Blue、Green、Red通道的直方图
    cv::calcHist(&bgr_plane[0], 1, nullptr, cv::Mat(), b_hist, 1, bins, ranges);
    cv::calcHist(&bgr_plane[1], 1, nullptr, cv::Mat(), g_hist, 1, bins, ranges);
    cv::calcHist(&bgr_plane[2], 1, nullptr, cv::Mat(), r_hist, 1, bins, ranges);

    //5.创建画布
    int hist_w = 512;
    int hist_h = 400;
    int bin_w = cvRound((double)hist_w / bins[0]);
    cv::Mat histImage = cv::Mat::zeros(hist_h, hist_w, CV_8UC3);

    //6.归一化直方图数据
    cv::normalize(b_hist, b_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
    cv::normalize(g_hist, g_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());
    cv::normalize(r_hist, r_hist, 0, histImage.rows, cv::NORM_MINMAX, -1, cv::Mat());

    //7.绘制直方图曲线
    for (int i = 1; i < bins[0]; i++)
    {
        cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
            cv::Point(bin_w * i, hist_h - cvRound(b_hist.at<float>(i))), cv::Scalar(255, 0, 0), 2, 8, 0);
        cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
            cv::Point(bin_w * i, hist_h - cvRound(g_hist.at<float>(i))), cv::Scalar(0, 255, 0), 2, 8, 0);
        cv::line(histImage, cv::Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
            cv::Point(bin_w * i, hist_h - cvRound(r_hist.at<float>(i))), cv::Scalar(0, 0, 255), 2, 8, 0);
    }

    //8.显示直方图
    cv::namedWindow("Hisogram Demo", cv::WINDOW_AUTOSIZE);
    cv::imshow("Hisogram Demo", histImage);

    cv::waitKey(0);

    return 0;
}

输出结果:

相关推荐
OAFD.5 小时前
机器学习之线性回归:原理、实现与实践
人工智能·机器学习·线性回归
SHIPKING3937 小时前
【机器学习&深度学习】LMDeploy的分布式推理实现
人工智能·深度学习
mit6.8247 小时前
[RestGPT] docs | RestBench评估 | 配置与环境
人工智能·python
CareyWYR7 小时前
每周AI论文速递(250818-250822)
人工智能
门思科技8 小时前
LoRaWAN 的网络拓扑全解析:架构、原理与应用实践
服务器·网络·人工智能·科技·物联网·架构
兔子的倔强8 小时前
Transformer在文本、图像和点云数据中的应用——经典工作梳理
人工智能·深度学习·transformer
lxmyzzs9 小时前
【图像算法 - 21】慧眼识虫:基于深度学习与OpenCV的农田害虫智能识别系统
人工智能·深度学习·opencv·算法·yolo·目标检测·计算机视觉
Gloria_niki9 小时前
机器学习之K 均值聚类算法
人工智能·机器学习
AI人工智能+9 小时前
表格识别技术:通过图像处理与深度学习,将非结构化表格转化为可编辑结构化数据,推动智能化发展
人工智能·深度学习·ocr·表格识别
深圳多奥智能一卡(码、脸)通系统9 小时前
智能二维码QR\刷IC卡\人脸AI识别梯控系统功能设计需基于模块化架构,整合物联网、生物识别、权限控制等技术,以下是多奥分层次的系统设计框架
人工智能·门禁·电梯门禁·二维码梯控·梯控·电梯