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);

}

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

相关推荐
全栈胖叔叔-瓜州2 分钟前
关于llamasharp 大模型多轮对话,模型对话无法终止,或者输出角色标识User:,或者System等角色标识问题。
前端·人工智能
坚果派·白晓明22 分钟前
AI驱动的命令行工具集x-cmd鸿蒙化适配后通过DevBox安装使用
人工智能·华为·harmonyos
GISer_Jing36 分钟前
前端营销技术实战:数据+AI实战指南
前端·javascript·人工智能
Dekesas96951 小时前
【深度学习】基于Faster R-CNN的黄瓜幼苗智能识别与定位系统,农业AI新突破
人工智能·深度学习·r语言
大佐不会说日语~1 小时前
Spring AI Alibaba 的 ChatClient 工具注册与 Function Calling 实践
人工智能·spring boot·python·spring·封装·spring ai
CeshirenTester2 小时前
Playwright元素定位详解:8种定位策略实战指南
人工智能·功能测试·程序人生·单元测试·自动化
棒棒的皮皮2 小时前
【OpenCV】Python图像处理几何变换之翻转
图像处理·python·opencv·计算机视觉
无能者狂怒2 小时前
YOLO C++ Onnx Opencv项目配置指南
c++·opencv·yolo
劈星斩月2 小时前
OpenCV 学习9-灰度转黑白二值图像
opencv·转二值图像·threshold函数
世岩清上2 小时前
AI驱动的智能运维:从自动化到自主化的技术演进与架构革新
运维·人工智能·自动化