(35)Air Band OpenCV2.4.13

    xiaoxiao2021-03-25  43

    本文是对OpenCV2.4.13文档的部分翻译,作个人学习之用,并不完整。

    直方图就是将一组数据组织成一系列已定义的bins。

    当我们谈到数据,我们不只会限于灰度值,收集到的数据都会对描述特性非常有用。

    我们以下图为例:

    我们可以将里面出现的256个值按区间组织起来

    然后计数每个区间中的像素的个数,我们可以得到下图:

    直方图不仅能计数图像强度,还可以度量任意图像特性。

    定义直方图中的元素:

    dims:你想要收集的数据的参数个数,上例中dims=1,因为只计算了每个像素的强度

    bins:每个dim中子分割的数量,上例中bins=16

    range:要度量的值的范围,上例中range=[0,255]

    如果我们想要计算两种特性,可以将直方图画成3D图像,x、y就是binx和biny描述特性,z是每个(binx,biny)的计数值。

    OpenCV实现了clacHist函数用于计算一组数组的直方图,它可以操作最多32个维度。

    #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; /** * @function main */ int main() { Mat src, dst; /// 载入图像 src = imread("lena.jpg", 1 ); if( !src.data ) { return -1; } /// 将图像分成3个通道,B、G、R各自保存到一个矩阵中 vector<Mat> bgr_planes; // 输入要分割的图像,输出Mat的向量 split( src, bgr_planes ); // 为每个通道计算直方图,值的范围都在[0,255] /// 形成bins的计数 int histSize = 256; /// 为B,G,R设置范围 float range[] = { 0, 256 } ;//上界不包含 const float* histRange = { range }; // 让bins有相同的大小,清除一开始的直方图 bool uniform = true; bool accumulate = false; // 为每个通道创建Mat对象保存直方图 Mat b_hist, g_hist, r_hist; /// 计算直方图(源数组,源数组个数,要度量的通道数(我们只看强度所以每个数组都是单通道的为0),用于原数组的掩码矩阵(0表示像素都被忽略,不定义则不使用),直方图存储的Mat对象,直方图的维度,每个维度的bins的个数,每个维度的值的范围,bin大小是否一样,直方图原始值是否清除) calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate ); calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); // 为B、G、R画出直方图 int hist_w = 512; int hist_h = 400; int bin_w = cvRound( (double) hist_w/histSize ); Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) ); /// 将结果标准化,直方图的值就会落在输入的参数值的范围内[ 0, histImage.rows ] // (输入数组,输出的标准化组(可以是一样的),0(标准化一个数组的下界),histImage.rows(标准化一个数组的上界),表示标准化类型的参数,表示输出的标准化数组和输入的一样,掩码矩阵(可选)) normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); /// 为每个通道画出图像,每一点用b.hist.at<float>(i)作为纵坐标,i表示了维度,如果是二维的,就使用b.hist.at<float>(i,j) for( int i = 1; i < histSize; i++ ) { line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ), Scalar( 255, 0, 0), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ), Scalar( 0, 255, 0), 2, 8, 0 ); line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) , Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ), Scalar( 0, 0, 255), 2, 8, 0 ); } /// 显示图像 namedWindow("calcHist Demo", WINDOW_AUTOSIZE ); imshow("calcHist Demo", histImage ); waitKey(0); return 0; } 我们使用lena的图像,结果为:

    转载请注明原文地址: https://ju.6miu.com/read-26123.html

    最新回复(0)