用vue-cli做的网站,国内网站在国外访问很慢,开题报告 网站建设,wordpress get_search_form()操作系统#xff1a;ubuntu22.04OpenCV版本#xff1a;OpenCV4.9IDE:Visual Studio Code编程语言#xff1a;C11
功能描述
图像的直方图是一种统计表示方法#xff0c;用于展示图像中不同像素强度#xff08;通常是灰度值或色彩强度#xff09;出现的频率分布。具体来说…操作系统ubuntu22.04OpenCV版本OpenCV4.9IDE:Visual Studio Code编程语言C11
功能描述
图像的直方图是一种统计表示方法用于展示图像中不同像素强度通常是灰度值或色彩强度出现的频率分布。具体来说它将图像的整个色调范围如0到255对于8位灰度图像划分为若干个离散的bins或区间然后统计每个bin内像素值出现的次数并以柱状图的形式展示出来。
通过图像的直方图我们可以直观地了解到图像的亮度分布、对比度信息以及色彩分布情况。例如如果一个图像的直方图集中在较暗的色调上说明图像整体偏暗如果直方图覆盖了较广的范围且分布均匀表明图像具有良好的动态范围和对比度。
直方图对于图像处理和分析非常重要常用于自动曝光、图像均衡化如直方图均衡化、图像分割、颜色校正等多种图像处理任务中。
calcHist函数
cv::calcHist函数用于计算一个或多个数组的直方图
函数原型1
void cv::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 参数 images 源图像。它们都应该具有相同的深度即CV_8UCV_16U或CV_32F并且具有相同的尺寸. 每个数组可以有任意数量的通道。 参数 nimages 源图像个数. 参数 channels 计算直方图的各个维度上所选择的通道列表.第一个数组的通道编号从0开始一直到images[0].channels()-1第二个数组的通道编号则从images[0].channels()开始一直到images[0].channels() images[1].channels()-1以此类推. 对于第一个图像数组images[0]其通道编号从0开始一直到该数组通道数减一。 第二个图像数组images[1]的通道编号紧接着第一个数组的通道编号之后从images[0].channels()开始直到images[0].channels() images[1].channels()-1。 同样的规则应用于后续的图像数组每个数组的通道编号都是紧接在前一个数组的通道编号之后。 这样的编号方式允许在计算直方图或其他涉及跨多个图像的通道操作时可以统一地引用所有图像的通道而不需要单独考虑每个图像的通道编号。这在处理复杂图像分析任务时特别有用比如计算多图像的联合直方图或特征提取等。 参数 mask 可选参数掩码。如果矩阵不为空它必须是一个与images[i]相同尺寸的8位数组。非零的掩码元素标记出了将在直方图中计数的数组元素。. 参数hist 输出的直方图它是一个稠密或稀疏的dims维数组. 参数dims 直方图的维度必须是正数并且不能超过CV_MAX_DIMS在当前OpenCV版本中等于32). 参数histSize 在每一维度上的直方图大小的数组。 参数ranges 数组ranges包含了dims个数组每个数组表示直方图在对应维度上的bin边界。当直方图是均匀的uniformtrue对于每个维度i只需要指定第0个直方图bin的下界包含 L 0 L_0 L0和最后一个binhistSize[i]-1的上界不包含 U histSize [ i ] − 1 U_{\texttt{histSize}[i]-1} UhistSize[i]−1。也就是说在均匀直方图的情况下ranges[i]是一个包含2个元素的数组分别表示该维度上bin的起始和结束边界。 然而当直方图是非均匀的uniformfalseranges[i]则包含histSize[i]1个元素 L 0 , U 0 L 1 , U 1 L 2 , . . . , U histSize[i] − 2 L histSize[i] − 1 , U histSize[i] − 1 L_0, U_0L_1, U_1L_2, ..., U_{\texttt{histSize[i]}-2}L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1} L0,U0L1,U1L2,...,UhistSize[i]−2LhistSize[i]−1,UhistSize[i]−1。这里的Lj和Uj分别表示第j个bin的下界和上界。在非均匀直方图中数组中的元素若不在 L 0 L_0 L0和 U histSize[i] − 1 U_{\texttt{histSize[i]}-1} UhistSize[i]−1之间则不会被计入直方图. 参数 uniform 这是一个标志指示直方图是否为均匀直方图参见上述说明 参数 accumulate 累积标志。如果设置了这个标志那么在分配直方图时直方图不会在开始时被清零。这个特性使你能够在不同时刻从多组数组中计算单一的直方图或者随时间更新直方图。
函数原型2
这是一个重载成员函数提供是为了方便使用。它与上述函数的不同之处仅在于它接受的参数类型。
此版本的函数使用SparseMat作为输出类型。
在OpenCV中SparseMat是一种专门用于存储稀疏矩阵的容器。与常规的矩阵存储方式相比SparseMat在存储和处理包含大量零值或无效值的大型矩阵时更加高效。它仅存储非零或有效元素及其位置从而显著减少了内存占用和计算成本。
void cv::calcHist
(const Mat * images,int nimages,const int * channels,InputArray mask,SparseMat hist,int dims,const int * histSize,const float ** ranges,bool uniform true,bool accumulate false
) 参数2 参数 images 源图像。它们都应该具有相同的深度即CV_8UCV_16U或CV_32F并且具有相同的尺寸. 每个数组可以有任意数量的通道。 参数 nimages 源图像个数. 参数 channels 计算直方图的各个维度上所选择的通道列表.第一个数组的通道编号从0开始一直到images[0].channels()-1第二个数组的通道编号则从images[0].channels()开始一直到images[0].channels() images[1].channels()-1以此类推. 对于第一个图像数组images[0]其通道编号从0开始一直到该数组通道数减一。 第二个图像数组images[1]的通道编号紧接着第一个数组的通道编号之后从images[0].channels()开始直到images[0].channels() images[1].channels()-1。 同样的规则应用于后续的图像数组每个数组的通道编号都是紧接在前一个数组的通道编号之后。 这样的编号方式允许在计算直方图或其他涉及跨多个图像的通道操作时可以统一地引用所有图像的通道而不需要单独考虑每个图像的通道编号。这在处理复杂图像分析任务时特别有用比如计算多图像的联合直方图或特征提取等。 参数 mask 可选参数掩码。如果矩阵不为空它必须是一个与images[i]相同尺寸的8位数组。非零的掩码元素标记出了将在直方图中计数的数组元素。. 参数hist 输出的直方图使用SparseMat作为输出类型. 参数dims 直方图的维度必须是正数并且不能超过CV_MAX_DIMS在当前OpenCV版本中等于32). 参数histSize 在每一维度上的直方图大小的数组。 参数ranges 数组ranges包含了dims个数组每个数组表示直方图在对应维度上的bin边界。当直方图是均匀的uniformtrue对于每个维度i只需要指定第0个直方图bin的下界包含 L 0 L_0 L0和最后一个binhistSize[i]-1的上界不包含 U histSize [ i ] − 1 U_{\texttt{histSize}[i]-1} UhistSize[i]−1。也就是说在均匀直方图的情况下ranges[i]是一个包含2个元素的数组分别表示该维度上bin的起始和结束边界。 然而当直方图是非均匀的uniformfalseranges[i]则包含histSize[i]1个元素 L 0 , U 0 L 1 , U 1 L 2 , . . . , U histSize[i] − 2 L histSize[i] − 1 , U histSize[i] − 1 L_0, U_0L_1, U_1L_2, ..., U_{\texttt{histSize[i]}-2}L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1} L0,U0L1,U1L2,...,UhistSize[i]−2LhistSize[i]−1,UhistSize[i]−1。这里的Lj和Uj分别表示第j个bin的下界和上界。在非均匀直方图中数组中的元素若不在 L 0 L_0 L0和 U histSize[i] − 1 U_{\texttt{histSize[i]}-1} UhistSize[i]−1之间则不会被计入直方图. 参数 uniform 这是一个标志指示直方图是否为均匀直方图参见上述说明 参数 accumulate 累积标志。如果设置了这个标志那么在分配直方图时直方图不会在开始时被清零。这个特性使你能够在不同时刻从多组数组中计算单一的直方图或者随时间更新直方图。
函数原型3
这是一个重载的成员函数提供以方便使用。它与上述函数的不同之处仅在于它接受的参数类型。
此版本的函数仅支持均匀直方图。
ranges参数可以是一个空向量或者是一个包含histSize.size()*2个元素的扁平化向量即histSize.size()对元素。每一对元素中的第一个和第二个元素分别指定了对应维度的下界和上界。
void cv::calcHist
(InputArrayOfArrays images,const std::vector int channels,InputArray mask,OutputArray hist,const std::vector int histSize,const std::vector float ranges,bool accumulate false
) 参数3 参数 images 源图像。它们都应该具有相同的深度即CV_8UCV_16U或CV_32F并且具有相同的尺寸. 每个数组可以有任意数量的通道。 参数 channels 计算直方图的各个维度上所选择的通道列表.第一个数组的通道编号从0开始一直到images[0].channels()-1第二个数组的通道编号则从images[0].channels()开始一直到images[0].channels() images[1].channels()-1以此类推. 对于第一个图像数组images[0]其通道编号从0开始一直到该数组通道数减一。 第二个图像数组images[1]的通道编号紧接着第一个数组的通道编号之后从images[0].channels()开始直到images[0].channels() images[1].channels()-1。 同样的规则应用于后续的图像数组每个数组的通道编号都是紧接在前一个数组的通道编号之后。 这样的编号方式允许在计算直方图或其他涉及跨多个图像的通道操作时可以统一地引用所有图像的通道而不需要单独考虑每个图像的通道编号。这在处理复杂图像分析任务时特别有用比如计算多图像的联合直方图或特征提取等。 参数 mask 可选参数掩码。如果矩阵不为空它必须是一个与images[i]相同尺寸的8位数组。非零的掩码元素标记出了将在直方图中计数的数组元素。. 参数hist 输出的直方图使用SparseMat作为输出类型. 参数histSize 在每一维度上的直方图大小的数组。 参数ranges 数组ranges包含了dims个数组每个数组表示直方图在对应维度上的bin边界。当直方图是均匀的uniformtrue对于每个维度i只需要指定第0个直方图bin的下界包含 L 0 L_0 L0和最后一个binhistSize[i]-1的上界不包含 U histSize [ i ] − 1 U_{\texttt{histSize}[i]-1} UhistSize[i]−1。也就是说在均匀直方图的情况下ranges[i]是一个包含2个元素的数组分别表示该维度上bin的起始和结束边界。 然而当直方图是非均匀的uniformfalseranges[i]则包含histSize[i]1个元素 L 0 , U 0 L 1 , U 1 L 2 , . . . , U histSize[i] − 2 L histSize[i] − 1 , U histSize[i] − 1 L_0, U_0L_1, U_1L_2, ..., U_{\texttt{histSize[i]}-2}L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1} L0,U0L1,U1L2,...,UhistSize[i]−2LhistSize[i]−1,UhistSize[i]−1。这里的Lj和Uj分别表示第j个bin的下界和上界。在非均匀直方图中数组中的元素若不在 L 0 L_0 L0和 U histSize[i] − 1 U_{\texttt{histSize[i]}-1} UhistSize[i]−1之间则不会被计入直方图. 参数 accumulate 累积标志。如果设置了这个标志那么在分配直方图时直方图不会在开始时被清零。这个特性使你能够在不同时刻从多组数组中计算单一的直方图或者随时间更新直方图。
代码示例
#include opencv2/core/utility.hpp
#include opencv2/highgui.hpp
#include opencv2/imgcodecs.hpp
#include opencv2/imgproc.hpp
#include iostream
using namespace cv;
using namespace std;
int _brightness 100;
int _contrast 100;
Mat image;
/* brightness/contrast callback function */
static void updateBrightnessContrast( int /*arg*/, void* )
{int histSize 64;int brightness _brightness - 100;int contrast _contrast - 100;/** The algorithm is by Werner D. Streidt* (http://visca.com/ffactory/archives/5-99/msg00021.html)*/double a, b;if ( contrast 0 ){double delta 127. * contrast / 100;a 255. / ( 255. - delta * 2 );b a * ( brightness - delta );}else{double delta -128. * contrast / 100;a ( 256. - delta * 2 ) / 255.;b a * brightness delta;}Mat dst, hist;image.convertTo( dst, CV_8U, a, b );imshow( image, dst );calcHist( dst, 1, 0, Mat(), hist, 1, histSize, 0 );Mat histImage Mat::ones( 200, 320, CV_8U ) * 255;normalize( hist, hist, 0, histImage.rows, NORM_MINMAX, CV_32F );histImage Scalar::all( 255 );int binW cvRound( ( double )histImage.cols / histSize );for ( int i 0; i histSize; i )rectangle( histImage, Point( i * binW, histImage.rows ), Point( ( i 1 ) * binW, histImage.rows - cvRound( hist.at float ( i ) ) ), Scalar::all( 0 ), -1, 8, 0 );imshow( histogram, histImage );
}
const char* keys { {help h||}{image|baboon.jpg|input image file} };
int main( int argc, const char** argv )
{// Load the source image. HighGUI use.image imread( /media/dingxin/data/study/OpenCV/sources/images/white.jpg, cv::IMREAD_GRAYSCALE );if ( image.empty() ){std::cerr Cannot read image file std::endl;return -1;}Size sz2Sh( 300, 400 );resize( image, image, sz2Sh, 0, 0, INTER_LINEAR_EXACT );namedWindow( image, 0 );namedWindow( histogram, 0 );createTrackbar( brightness, image, _brightness, 200, updateBrightnessContrast );createTrackbar( contrast, image, _contrast, 200, updateBrightnessContrast );updateBrightnessContrast( 0, 0 );waitKey();return 0;
}运行结果
原图
直方图 你可以调整亮度的滑动块或者对比度的滑动块来观察直方图的变化从而更好地去理解直方图的概念。