openCV1-2 图像的直方图相关

通道合并与分离

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    Mat src = imread("D:\\souse\\opencv_tutorial_data-master\\images\\WindowsLogo.jpg");
    if (src.empty()) {
		return -1;
    }
	namedWindow("input", WINDOW_AUTOSIZE);
	imshow("input", src);
	vector<Mat> mv;
	//分离
	split(src, mv);
	imshow("input1", mv.at(0));
	imshow("input2", mv.at(1));
	imshow("input3", mv.at(2));
	Mat des;
	mv.at(0) = Scalar(0);
	//合并操作
	merge(mv, des);
	imshow("des",des);

	waitKey(0);
    std::cout << "Hello World!\n";
	return 0;
}

图像直方图统计

Bin:是直方图的基本统计单元,用于统计图像中特定范围内像素值的出现频率。

calcHist

cpp 复制代码
CV_EXPORTS 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 );

函数cv::calcHist用于计算一个或多个数组的直方图。用于增加直方图 bin 的元组元素取自相应输入数组中相同位置的元素。下面的示例展示了如何为彩色图像计算二维色调 - 饱和度直方图:

@include snippets/imgproc_calcHist.cpp

@param images 源数组。它们都应该具有相同的深度,即CV_8U、CV_16U或CV_32F ,并且大小相同。每个数组可以有任意数量的通道。

@param nimages 源图像的数量。

@param channels 用于计算直方图的维度通道列表。第一个数组的通道从0到images[0].channels() - 1编号,第二个数组的通道从images[0].channels()到images[0].channels() + images[1].channels() - 1编号,依此类推。

@param mask 可选掩码。如果该矩阵不为空,它必须是与images[i]大小相同的8位数组。非零掩码元素标记在直方图中统计的数组元素。

@param hist 输出直方图,它是一个密集或稀疏的dims维数组。

@param dims 直方图维度,必须为正且不大于CV_MAX_DIMS(在当前OpenCV版本中等于32)。

@param histSize 每个维度的直方图大小数组。

@param ranges 每个维度的直方图 bin 边界的dims个数组的数组。

@param uniform 指示直方图是否均匀的标志。

@param accumulate 累加标志。如果设置了该标志,在分配直方图时,开始时不会将其清空。此功能使您能够从几组数组中计算单个直方图,或者及时更新直方图。

normalize

cv::normalize() 是 OpenCV 中用于归一化数组元素的函数,它可以将数组的值缩放到指定范围。以下是对该函数的详细解析:

cpp 复制代码
void cv::normalize(
    InputArray src,            // 输入数组(如Mat)
    InputOutputArray dst,      // 输出数组(可与src相同,实现原地操作)
    double alpha = 1,          // 归一化后的最小值(或范数值,取决于norm_type)
    double beta = 0,           // 归一化后的最大值(仅用于NORM_MINMAX)
    int norm_type = NORM_L2,   // 归一化类型(如NORM_MINMAX、NORM_L1、NORM_L2等)
    int dtype = -1,            // 输出数组的类型(-1表示与输入相同)
    InputArray mask = noArray() // 可选掩码,非零元素参与计算
);

参数详解
src 输入数组(如直方图数据 b),通常是 Mat 类型。
dst 输出数组,可与 src 相同(原地操作)。若不同,需保证尺寸和通道数一致。
alpha 对于 NORM_MINMAX:归一化后的最小值。

对于其他归一化类型(如 NORM_L2):目标范数值。
beta 仅用于 NORM_MINMAX,表示归一化后的最大值。
norm_type 常用取值:

NORM_MINMAX:线性映射到 [alpha, beta] 范围。

NORM_L1:L1 范数(绝对值之和)归一化。

NORM_L2:L2 范数(欧几里得距离)归一化。

NORM_INF:无穷范数(最大值)归一化。
dtype

输出数组的类型。-1 表示与输入类型相同。
mask

可选掩码,仅掩码中非零元素参与计算。

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    Mat src = imread("D:\\souse\\opencv_tutorial_data-master\\images\\sp_noise.png");
    if (src.empty()) {
        cout << "读取失败"<<endl;
        return -1;
    }
	namedWindow("src", WINDOW_AUTOSIZE);
	imshow("src", src);
    //分离通道
    vector<Mat> mv;
    split(src, mv);
    //计算直方图
    int histSize=256;
    float range[] = { 0,255 };
    const float* hisRanges = range;
    Mat b, g, r;
    //原图像 原图像数量 通道 掩码 输出 维度  每个维度的bin数量  每个维度的取值范围 bin是否均匀分布 是否累积计算
    calcHist(&mv[0],1,0,Mat(),b,1,&histSize, &hisRanges);
    calcHist(&mv[1], 1, 0, Mat(), g, 1, &histSize, &hisRanges);
    calcHist(&mv[2], 1, 0, Mat(), r, 1, &histSize, &hisRanges);
    //绘制直方图
    Mat result= Mat::zeros(Size(600, 500), CV_8UC3);
    int margin = 50;//边缘大小
    int h = result.rows-2*margin;//最大高
    normalize(b, b, 0, h, NORM_MINMAX, -1, Mat());
    normalize(g, g, 0, h, NORM_MINMAX, -1, Mat());
    normalize(r, r, 0, h, NORM_MINMAX, -1, Mat());
    float step = 500.0 / 256;
    for (int i = 0; i < 255; i++) {
        // 绘制蓝色通道
        line(result,
            Point(step * i+50, 50 + h - b.at<float>(i, 0)),
            Point(step * (i + 1)+50, 50 + h - b.at<float>(i + 1, 0)),
            Scalar(255, 0, 0), 2, 8, 0);

        // 修复:添加绿色和红色通道的绘制(颜色参数修正)
        line(result,
            Point(step * i+50, 50 + h - g.at<float>(i, 0)),
            Point(step * (i + 1)+50, 50 + h - g.at<float>(i + 1, 0)),
            Scalar(0, 255, 0), 2, 8, 0);  // 绿色:(0,255,0)

        line(result,
            Point(step * i+50, 50 + h - r.at<float>(i, 0)),
            Point(step * (i + 1)+50, 50 + h - r.at<float>(i + 1, 0)),
            Scalar(0, 0, 255), 2, 8, 0);  // 红色:(0,0,255)
    }

    imshow("result", result);
	waitKey(0);
}

图像直方图均衡化

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
    Mat src = imread("D:\\souse\\opencv_tutorial_data-master\\images\\age_gender.jpg");
    if (src.empty()) {
        cout << "读取失败" << endl;
        return -1;
    }
    namedWindow("src", WINDOW_AUTOSIZE);
    imshow("src", src);
    //=========================//
    //转灰度图像
    Mat gray, des;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    imshow("gray", gray);
    //均衡化
    equalizeHist(gray, des);
    imshow("des", des);
    //=========================//
    //分离通道
    vector<Mat> mv;
    split(src, mv);
    //计算直方图
    int histSize = 256;
    float range[] = { 0,255 };
    const float* hisRanges = range;
    Mat b, g, r,g_z,d_z;
    //原图像 原图像数量 通道 掩码 输出 维度  每个维度的bin数量  每个维度的取值范围 bin是否均匀分布 是否累积计算
    calcHist(&mv[0], 1, 0, Mat(), b, 1, &histSize, &hisRanges);
    calcHist(&mv[1], 1, 0, Mat(), g, 1, &histSize, &hisRanges);
    calcHist(&mv[2], 1, 0, Mat(), r, 1, &histSize, &hisRanges);
    calcHist(&gray, 1, 0, Mat(), g_z, 1, &histSize, &hisRanges);
    calcHist(&des, 1, 0, Mat(), d_z, 1, &histSize, &hisRanges);

    //绘制直方图
    Mat result = Mat::zeros(Size(600, 500), CV_8UC3);
    Mat result1 = Mat::zeros(Size(600, 500), CV_8UC3);
    int margin = 50;//边缘大小
    int h = result.rows - 2 * margin;//最大高
    normalize(b, b, 0, h, NORM_MINMAX, -1, Mat());
    normalize(g, g, 0, h, NORM_MINMAX, -1, Mat());
    normalize(r, r, 0, h, NORM_MINMAX, -1, Mat());
    normalize(g_z, g_z, 0, h, NORM_MINMAX, -1, Mat());
    normalize(d_z, d_z, 0, h, NORM_MINMAX, -1, Mat());
    float step = 500.0 / 256;
    for (int i = 0; i < 255; i++) {
        // 绘制蓝色通道
        line(result,
            Point(step * i + 50, 50 + h - b.at<float>(i, 0)),
            Point(step * (i + 1) + 50, 50 + h - b.at<float>(i + 1, 0)),
            Scalar(255, 0, 0), 2, 8, 0);

        // 修复:添加绿色和红色通道的绘制(颜色参数修正)
        line(result,
            Point(step * i + 50, 50 + h - g.at<float>(i, 0)),
            Point(step * (i + 1) + 50, 50 + h - g.at<float>(i + 1, 0)),
            Scalar(0, 255, 0), 2, 8, 0);  // 绿色:(0,255,0)

        line(result,
            Point(step * i + 50, 50 + h - r.at<float>(i, 0)),
            Point(step * (i + 1) + 50, 50 + h - r.at<float>(i + 1, 0)),
            Scalar(0, 0, 255), 2, 8, 0);  // 红色:(0,0,255)
        line(result1,
            Point(step * i + 50, 50 + h - g_z.at<float>(i, 0)),
            Point(step * (i + 1) + 50, 50 + h - g_z.at<float>(i + 1, 0)),
            Scalar(0, 0, 255), 2, 8, 0);  // 红色:(0,0,255)
        line(result1,
            Point(step * i + 50, 50 + h - d_z.at<float>(i, 0)),
            Point(step * (i + 1) + 50, 50 + h - d_z.at<float>(i + 1, 0)),
            Scalar(0, 255, 0), 2, 8, 0);  // 红色:(0,0,255)
    }
    imshow("result", result);
    imshow("result1", result1);
    waitKey(0);

}

绿色是灰度图,红色是均衡化处理之后的

相关推荐
拓端研究室TRL几秒前
MATLAB贝叶斯超参数优化LSTM预测设备寿命应用——以航空发动机退化数据为例
开发语言·人工智能·rnn·matlab·lstm
__Benco19 分钟前
OpenHarmony外设驱动使用 (五),Fingerprint_auth
人工智能·驱动开发·harmonyos
桃花键神31 分钟前
从 0 到 1:用 Trae 插件 Builder 模式开发端午包粽子小游戏
人工智能·trae
庞德公2 小时前
PARSCALE:大语言模型的第三种扩展范式
人工智能·计算机视觉·大模型·并行计算·moe
AI.NET 极客圈2 小时前
AI与.NET技术实操系列(六):实现图像分类模型的部署与调用
人工智能·分类·.net
geneculture2 小时前
《黄帝内经》数学建模与形式化表征方式的重构
人工智能·算法·机器学习·数学建模·重构·课程设计·融智学的重要应用
渝欢意2 小时前
机器学习——逻辑回归
人工智能·机器学习·逻辑回归
EasyDSS2 小时前
EasyRTC嵌入式音视频通信SDK一对一音视频通信,打造远程办公/医疗/教育等场景解决方案
人工智能·音视频
www_pp_3 小时前
# 深入解析BERT自然语言处理框架:原理、结构与应用
人工智能·自然语言处理·bert
jndingxin3 小时前
OpenCV CUDA模块图像过滤------用于创建一个最小值盒式滤波器(Minimum Box Filter)函数createBoxMinFilter()
人工智能·opencv·计算机视觉