网站和微信,wordpress 内置浏览量,可以玩的网页游戏,php成品网站源码3.直方图 直方图是用来表现图像中亮度分布的#xff0c;给出的是图像中某个亮度或者某个范围亮度下共有几个像素#xff0c;即统计一幅图某个亮度像素的数量。 直方图不能反映某一灰度值像素在图像中的位置#xff0c;失去了图像的空间信息。图像直方图由于其计算代价较小给出的是图像中某个亮度或者某个范围亮度下共有几个像素即统计一幅图某个亮度像素的数量。 直方图不能反映某一灰度值像素在图像中的位置失去了图像的空间信息。图像直方图由于其计算代价较小且具有图像平移、旋转、缩放不变性等众多优点被广泛地应用于图像处理的各个领域特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类。
3.1 标准直方图 OpenCV中的直方图函数calcHist()定义如下。 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)
具体参数解析如下
const Mat *images要求Mat指针。可以传递一个数组可以同时求很多幅图像的直方图前提是深度相同如CV_8U和CV_32F尺寸相同通道数可以不同。int nimages源图像数。const int* channels传递要加入直方图计算的通道。该函数可以求多个通道的直方图通道编号从0开始依次递增。假如第一幅图像有3个通道第二幅图像有两个通道则images[0]的通道编号为0、1、2images[1]的通道编号则为3、4如果想通过5个通道计算直方图则传递的通道channels为int channels[5] {0,1,2,3,4,5}。InputArray mask掩码矩阵。没有掩码则传递空矩阵就行了如果非空则掩码矩阵大小必须和图像大小相同在掩码矩阵中非空元素将被计算到直方图内。OutputArray hist输出直方图。int dims直方图维度。必须大于0并小于CV_MAX_DIMS(32)。const int*histSize直方图中每个维度的级别数量。例如灰度值0—255如果级别数量为4则灰度值直方图会按照[0, 63]、[64,127]、[128,191]、[192,255]划分也称为bin数目级别数量为4就是4个bin。如果是多维的就需要传递多个histSize每个维度的大小用一个int型数据来表示所以histSize是一个数组。const float**ranges一个维度中的每一个bin的取值范围。bool uniform如果为 true则range可以用一个具有两个元素一个最小值和一个最大值的数组表示如果为false则需要用一个具有histSize1个元素每相邻两个元素组成的取值空间代表对应的bin的取值范围的数组表示。如果统计多个维度则需要传递多个数组所以ranges是一个二维数组。bool accumulate决定在计算直方图时是否清空传入的hist。其值为true表示不清空为false则表示清空。该参数一般设置为false只有在想要统计多个图像序列中的累加直方图时才会设置为true。 OpenCV中在进行直方图绘图之前需要用函数normalize ()对数据进行归一化处理。简单来说就是将数据限制在一定范围内方便处理。normalize()函数声明如下。 void cv::normalize(InputArray src,
InputOutputArray dst,
double alpha1,
double beta0,
int norm_typeNORM_L2,
int dtype-1,
InputArray marknoArray())
具体参数解析如下
InputArray src输入数组。OutputArray dst输出数组。大小和原数组一致。double alpha用来规范值或者规范范围并且是下限。double beta用来规范范围并且是上限。因此该参数只在NORM_MINMAX中起作用。int norm_type归一化选择的数学公式类型。int dtype其值为负输出的大小、深度、通道数都等于输入其值为正输出只有深度与输入不同不同的地方由dtype决定。InputArray mark掩码。选择感兴趣区域选定后只能对该区域进行操作。 示例代码
void function2()
{//读取一张图片Mat src imread(C:/Users/27844/Desktop/icon.jpg);if(src.empty()){coutimage is emptyendl;return;}//分离图片通道vectorMat channels;split(src,channels);//计算直方图int histSize 256; //直方图的bin数float range[] {0,9}; //设置值的范围const float* histRange { range };Mat b_hist, g_hist, r_hist;//创建Mat对象分别保存直方图每个通道均为1calcHist(channels[0],1,0,Mat(),b_hist,1,histSize,histRange,true,false);calcHist(channels[1],1,0,Mat(),g_hist,1,histSize,histRange,true,false);calcHist(channels[2],1,0,Mat(),r_hist,1,histSize,histRange,true,false);//数据归一化normalize(b_hist,b_hist,0,255,NORM_MINMAX,-1,Mat());normalize(g_hist,g_hist,0,255,NORM_MINMAX,-1,Mat());normalize(r_hist,r_hist,0,255,NORM_MINMAX,-1,Mat());//绘制直方图int hist_height400,hist_width512;int bin_width cvRound((double)hist_width/hist_height); //bin的宽度Mat histImage(hist_width,hist_width,CV_8UC3,Scalar(255,255,255)); // 白色背景for(int i1;ihistSize;i){line(histImage,Point(bin_width * (i - 1), hist_height - cvRound(b_hist.atfloat(i - 1))),Point(bin_width * (i), hist_height - cvRound(b_hist.atfloat(i))),Scalar(255, 0, 0), 2, 8, 0);line(histImage,Point(bin_width * (i - 1), hist_height - cvRound(g_hist.atfloat(i - 1))),Point(bin_width * (i), hist_height - cvRound(g_hist.atfloat(i))),Scalar(0,255,0), 2, 8, 0);line(histImage,Point(bin_width * (i - 1), hist_height - cvRound(r_hist.atfloat(i - 1))),Point(bin_width * (i), hist_height - cvRound(r_hist.atfloat(i))),Scalar(0, 0,255), 2, 8, 0);}namedWindow(histImage,WINDOW_AUTOSIZE);imshow(histImage,histImage);waitKey(0);}
3.2 直方图均衡化 直方图均衡化是一种增强图像对比度的方法也叫直方图线性变换。其主要思想是将一幅图像的直方图分布变成近似均匀分布从而增强图像的对比度其基本原理是对在图像中像素个数多的灰度值即对画面起主要作用的灰度值进行展宽而对像素个数少的灰度值即对画面不起主要作用的灰度值进行归并从而加强对比度使图像清晰达到图像增强的目的。 OpenCV提供了一个直方图均衡化的函数可以通过使用这个函数来实现直方图均衡化函数定义如下。 cv::equalizeHist(image,result) 参数解析如下
image输入图像即源图像必须是8位的单通道图像。result函数调用后的运算结果需和源图像有一样的尺寸和类型。 示例代码
void function3()
{//直方图均衡化Mat src,dst;src imread(C:/Users/27844/Desktop/icon.jpg);if(src.empty()){coutimage is emptyendl;return;}//将图片转换为灰度图并显示cvtColor(src,src,COLOR_BGR2GRAY);imshow(src,src);//进行直方图均衡化equalizeHist(src,dst);imshow(dst,dst);waitKey(0);destroyAllWindows();
}
3.3 直方图匹配
直方图的均衡化自动确定了变换函数可以很方便地得到变换后的图像。但是在有些应用中这种自动的增强并不是最好的方法。有时候需要图像具有某一特定的直方图形状也就是灰度分布而不是均匀分布的直方图这时可以使用直方图匹配。 直方图匹配也叫作直方图规定化用于将图像变换为某一特定的灰度分布适用于目标灰度直方图已知的情况。 直方图匹配的步骤如下
1将源图像的灰度直方图进行均衡化得到一个变换函数 s T ( r )其中 s 是均衡化后的像素 r 是原始像素。
2对规定的直方图进行均衡化得到一个变换函数 v G ( z )其中 v 是均衡化后的像素 z 是规定的像素。
3上面都是对同一图像的均衡化其结果应该是相等的即 s v 且 z G -1 ( v ) G -1 T ( r )。
3.4 局部直方图处理 全局直方图适用于整张图像的增强但有时存在这样的情况只需要增强图像中小区域的细节。在这些区域中一些像素的影响在全局变换的计算中可能被忽略了因为全局直方图没有必要保证期望的局部增强解决方法是以图像中每个像素的邻域中的灰度分布为基础设计变换函数。处理过程是定义一个邻域并把该区域的中心从一个像素移至另一个像素。在每个位置计算邻域中点的直方图并且得到的不是直方图的均衡化就是规定化的变换函数这个函数最终用于映射邻域中心像素的灰度。然后邻域的中心被移至一个相邻像素位置重复该过程。当邻域进行逐像素平移时由于只有邻域中的一行或一列改变所以可以在移动一步的过程中以新数据更新前一个位置得到的直方图。
局部直方图操作的具体步骤如下
1求第一个邻域内的直方图。
2根据直方图均衡化将该邻域中心点的像素更新。
3将中心点移向下一个邻域例如此时中心点为(3,3)第一个数为行第二个值为列先向下移动一个像素中心点变为(4,3)假设局部直方图大小为7×7则此时得到的邻域与前一个邻域相比只有一行像素不同即(0,0)、(0,1)……(0,6)与(7,0)、(7,1)……(7,6)可能不同此时比较第0行和第7行相对应的元素是否相同来更新直方图如果直方图有变化则更新当前中心点的像素值。
4对所有的像素执行第三歩。 4. 图像去噪 图像去噪是指减少数字图像中噪声的过程。现实中的数字图像在数字化和传输过程中常受到成像设备与外部环境噪声等的影响在这种条件下得到的图像称为含噪图像或噪声图像。噪声是干扰图像的重要因素。一幅图像在实际应用中可能存在各种各样的噪声这些噪声可能在传输过程中产生也可能在量化处理等过程中产生。
下面举例几种常用的
4.1 均值滤波 均值滤波是由当前像素邻近的若干像素组成的模板的均值来替代原像素的值的方法。在opencv中用blur()函数进行均值滤波。 均值滤波卷积核 注意在处理噪声的同时也存在一个问题就是源图像的一些细节变得模糊了。
4.2 高斯滤波 高斯滤波是线性滤波中的一种。在OpenCV图像滤波处理中高斯滤波用于平滑图像或者说是进行图像模糊处理。 其原理是将正态分布又名高斯分布用于图像处理相当于在图像上产生“模糊”效果“中间点”会失去细节所以高斯滤波属于低通滤波低通滤波就是去掉高频信号留下低频信号。相反高通滤波就是去掉低频信号留下高频信号。 在opencv中用GaussianBlur()函数进行高斯滤波。函数定义如下。 void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY0, int borderTypeBORDER_DEFAULT)
参数解析如下。
InputArray src输入图像。图像可以具有任何数量的通道。OutputArray dst输出图像。与输入图像大小、类型相同。Size ksize高斯核大小。ksize.width 和 ksize.height 可以有所不同但它们都必须是正数和奇数。double sigmaX x 方向上的高斯核标准偏差。 double sigmaY y 方向上的高斯核标准偏差。如果sigmaY为0则将其设置为与sigmaX相同的值如果sigmaX和sigmaY都是0则分别根据ksize.width和ksize.height计算而来。 int borderType用于推断图像外部像素的某种边界模式。
高斯滤波对被高斯噪声污染的图像具有很好的处理效果。均值滤波是基于平均权重无法克服边缘像素信息丢失的缺陷。高斯滤波部分克服了该缺陷但是无法完全克服因为没有考虑像素值的不同对边缘信息权值较低。
4.3 中值滤波 中值滤波在某些情况下可以做到既能去除噪声又能保护图像的边缘是一种非线性的去除噪声的方法。在opencv中用medianBlur()函数进行高斯滤波。 中值滤波相较于均值滤波在去除噪声的同时更多地保留了图像的细节。中值滤波处理对滤除脉冲噪声比较有效。脉冲噪声也称椒盐噪声是图像中经常见到的一种噪声它是一种随机出现的白点或者黑点可能是在亮的区域有黑色像素或是在暗的区域有白色像素或是两者皆有。
4.4 双边滤波 双边滤波是一种非线性的滤波方法是结合图像的空间邻近度和像素值相似度的一种折中处理同时考虑空域信息和灰度相似性达到保边去噪的目的。在opencv中使用bilateralFilter()函数来进行双边滤波。 示例代码
void function4()
{// 图像去噪// 1.均值滤波Mat src imread(C:/Users/27844/Desktop/icon.jpg);if(src.empty()){coutimage is emptyendl;return;}imshow(src,src);Mat dst;dst.create(src.size(),src.type());blur(src,dst,Size(7,7));imshow(blur,dst);// 2.高斯滤波Mat dst2;dst2.create(src.size(),src.type());GaussianBlur(src,dst2,Size(7,7),0,0);imshow(GaussianBlur,dst2);// 3.中值滤波Mat dst3;dst3.create(src.size(),src.type());medianBlur(src,dst3,7);imshow(medianBlur,dst3);// 4.双边滤波Mat dst4;dst4.create(src.size(),src.type());bilateralFilter(src,dst4,9,60,15);imshow(bilateralFilter,dst4);waitKey(0);}