openCV1-2 图像的直方图相关
通道合并与分离
#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
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 中用于归一化数组元素的函数,它可以将数组的值缩放到指定范围。以下是对该函数的详细解析:
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
可选掩码,仅掩码中非零元素参与计算。
#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);
}
图像直方图均衡化
#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);}
绿色是灰度图,红色是均衡化处理之后的