【OpenCV】笔记(7)——图像滤波和形态学变换

图像滤波:包括图像平滑,锐化,以及图像金字塔
形态学运算的应用:膨胀、腐蚀、开运算、闭运算
几何变换:仿射和透视变换
修复:用于重构图像的受损部分
去噪:用于降低图像拍摄设备所产生的图像噪声




图像滤波

图像滤波是增强或者修改图像的过程
滤波是增强或者修改图像的过程。增强图像中的某些特征,或者消除其他特征

滤波是一种领域运算,领域是选定区域周围像素几何,通过利用在该像素周围一定领域内像素集合的值执行的某些运算


平滑:又称为模糊。将位于(xi,yj)位置及周围的输入像素值进行加权的值作为该处的输出像素值
线性运算中,像素的权值通常存储在一个称为kernel的矩阵中
因此一个滤波可以表示为为一个滑动窗口


最常用的平滑滤波方法
中值滤波     适合去除椒盐噪声  & 斑点噪声
高斯滤波     适合边缘检测的预处理阶段
双边滤波     适合处理平滑强边缘的图像

常用滤波函数
void boxFilter( 输入,输出,输出图像深度,核大小,核中心(默认(-1,-1)及定位像素是核中心),=true时 输出像素值是核领域的均值,边界类型)

void GaussianBlur
@param src input image; the image can have any number of channels, which are processed
independently, but the depth should be CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param ksize Gaussian kernel size. ksize.width and ksize.height can differ but they both must be
positive and odd. Or, they can be zero's and then they are computed from sigma.
@param sigmaX Gaussian kernel standard deviation in X direction.
@param sigmaY Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be
equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height,
respectively (see cv::getGaussianKernel for details); to fully control the result regardless of
possible future modifications of all this semantics, it is recommended to specify all of ksize,
sigmaX, and sigmaY.
@param borderType pixel extrapolation method, see cv::BorderTypes

@sa  sepFilter2D, filter2D, blur, boxFilter, bilateralFilter, medianBlur
 */
CV_EXPORTS_Wvoid GaussianBlur( InputArraysrc,OutputArray dst, Size ksize,
                               double sigmaX , double sigmaY= 0,
                               int borderType = BORDER_DEFAULT );

void medianBlur          顾名思义:输出图像的像素值是领域的中值


void bilateralBlur          
This filter does not work inplace.
@param src Source 8-bit or floating-point, 1-channel or 3-channel image.
@param dst Destination image of the same size and type as src .
@param d Diameter of each pixel neighborhood that is used during filtering. If it is non-positive,
it is computed from sigmaSpace.
@param sigmaColor Filter sigma in the color space. A larger value of the parameter means that
farther colors within the pixel neighborhood (see sigmaSpace) will be mixed together, resulting
in larger areas of semi-equal color.
@param sigmaSpace Filter sigma in the coordinate space. A larger value of the parameter means that
farther pixels will influence each other as long as their colors are close enough (see sigmaColor
). When d\>0, it specifies the neighborhood size regardless of sigmaSpace. Otherwise, d is
proportional to sigmaSpace.
@param borderType border mode used to extrapolate pixels outside of the image, see cv::BorderTypes
 */
CV_EXPORTS_Wvoid bilateralFilter( InputArray src,OutputArray dst, int d,
                                  double sigmaColor , double sigmaSpace,
                                  int borderType = BORDER_DEFAULT );

void blur                    使用归一化的盒式滤波来平滑图像


#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>

usingnamespacestd;
usingnamespacecv;

intmain(intargc,char**argv)
{
                //read the src image
                Matsrc;
                src=imread("math.png");

                //open the fliter
                Matdst, dst2;
                GaussianBlur(src, dst,Size(9, 9), 0, 0);
                medianBlur(src, dst2, 9);

                //show
                namedWindow("Original image",WINDOW_AUTOSIZE);
                imshow("Original image", src);

                namedWindow("Gussian blur",WINDOW_AUTOSIZE);
                imshow("Gussian blur", dst);

                namedWindow("Median blur",WINDOW_AUTOSIZE);
                imshow("Median blur", dst2);

                //wait
                waitKey();

                return0;
}






锐化

锐化用于突出显示图像的边界和其他精细部分
锐化是基于一阶导数和二阶导数的,一幅数字图像的离散量即梯度,其的一阶导数计算图像强度梯度的逼近,而二阶导数定义为该梯度的散度

一阶导数可以产生粗的图像边缘,广泛用于边缘提取
二阶导数对于细节的响应更好,常被用于图像增强

用于获取导数的两种常用算子是Sobel和Laplacian

Sobel算子计算一幅图像I的一阶导数,公式如下




通过整合两个方向上的梯度逼近值,可以获得如下的Soble梯度幅值



一幅图像的Laplacian值,可以使用下述核的卷积给出



常用的锐化函数
void Sobel( InputArray src , OutputArray dst , int ddepth ,
                         int dx , int dy , int ksize = 3,
                         double scale = 1, double delta = 0,
                         int borderType = BORDER_DEFAULT );

使用Soble算子计算src的一幅图像的一阶导数、二阶导数、三阶导数或混合导数
参数解释:
@param src input image.
@param dst output image of the same size and the same number of channels as src .
@param ddepth output image depth, see @ref filter_depths "combinations"; in the case of
    8-bit input images it will result in truncated derivatives.
     当值为-1时,输出与输入图像的深度相同
@param dx order of the derivative x.
@param dy order of the derivative y.     表示希望求导的阶
@param ksize size of the extended Sobel kernel; it must be 1, 3, 5, or 7.
@param scale optional scale factor for the computed derivative values; by default, no scaling is
applied (see cv::getDerivKernels for details).     建立计算导数值得尺度因子
@param delta optional delta value that is added to the results prior to storing them in dst.
@param borderType pixel extrapolation method, see cv::BorderTypes
@sa  Scharr, Laplacian, sepFilter2D, filter2D, GaussianBlur, cartToPolar

void Scharr     用于计算一个3*3大小的核更精确的导数
@param src input image.
@param dst output image of the same size and the same number of channels as src.
@param ddepth output image depth, see @ref filter_depths "combinations"
@param dx order of the derivative x.
@param dy order of the derivative y.
@param scale optional scale factor for the computed derivative values; by default, no scaling is
applied (see getDerivKernels for details).
@param delta optional delta value that is added to the results prior to storing them in dst.
@param borderType pixel extrapolation method, see cv::BorderTypes
@sa  cartToPolar
 */
CV_EXPORTS_Wvoid Scharr( InputArraysrc,OutputArray dst, int ddepth,
                         int dx , int dy,double scale = 1, double delta= 0,
                         int borderType = BORDER_DEFAULT );


void Laplacian     用于计算一幅图像的Laplacian值
除了ksize之外所有的参数和sobel &scharr 中的相同
ksize==1     使用3*3的核(中心值为-4,四个角的值为0,其余值为1)对图像进行滤波
ksize>1        使用Sobel算子通过累加x的二阶导数和y的二阶导数来计算源图像的Laplacian
@param src Source image.
@param dst Destination image of the same size and the same number of channels as src .
@param ddepth Desired depth of the destination image.
@param ksize Aperture size used to compute the second-derivative filters. See getDerivKernels for
details. The size must be positive and odd.
@param scale Optional scale factor for the computed Laplacian values. By default, no scaling is
applied. See getDerivKernels for details.
@param delta Optional delta value that is added to the results prior to storing them in dst .
@param borderType Pixel extrapolation method, see cv::BorderTypes
@sa  Sobel, Scharr
 */
CV_EXPORTS_Wvoid Laplacian( InputArraysrc,OutputArray dst, int ddepth,
                            int ksize = 1, double scale= 1, double delta= 0,
                            int borderType = BORDER_DEFAULT );


#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>

usingnamespacestd;
usingnamespacecv;

intmain(intargc,char**argv)
{
                //read the src image
                Matsrc;
                src=imread("go.png");

                //sharpen
                Matdst, dst2;
                Sobel(src, dst, -1, 0, 0);
                Laplacian(src, dst2, -1);

                //show
                namedWindow("Original image",WINDOW_AUTOSIZE);
                imshow("Original image", src);

                namedWindow("Sobel",WINDOW_AUTOSIZE);
                imshow("Soble", dst);

                namedWindow("Laplacian",WINDOW_AUTOSIZE);
                imshow("Laplacian", dst2);

                //wait
                waitKey();

                return0;
}









图像金字塔
在某些情况下使用固定的图像工作是不可能的,可能需要不同分辨率的原始图像
例如,检测图像,从较小分辨率的图像进行搜索更为有效

这种类型的图像集合按照从下到上,从大到小堆起来,被形象地称为金字塔或者多级纹理(mipmap)
越到上面层数越高,图像的面积越小

有两类图像金字塔:高斯金字塔,拉普拉斯金字塔

1     高斯金字塔
在低一层通过交替隔行和隔列删除像素,然后对底层领域进行高斯滤波来获得更高一层的像素值
这样每执行一次,图像的宽和高变为原来的一半,面积减少为原来的1/4

2     拉普拉斯金字塔
可以看作是其大部分元素为0的一些边界图像,其第i层是高斯金字塔的第i层和第i+1层的膨胀般的差
OpenCV中没有专门提供拉普拉斯金字塔的函数

计算高斯金字塔的函数
void pyrDown     采样并模糊源图像,将结果传递给目标图像,当没有设置输出图像的大小时,使用Size((src.cols+1)/2,(src.rows+1)/2)来计算

void pyrUp          计算与函数pyrDown相反的过程

#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>

usingnamespacestd;
usingnamespacecv;

intmain(intargc,char**argv)
{
                //read the src image
                Matsrc;
                src=imread("cat2.png");

                //pyrDown*2
                Matdst, dst2;
                pyrDown(src, dst);
                pyrDown(dst, dst2);

                //show
                namedWindow("Original image",WINDOW_AUTOSIZE);
                imshow("Original image", src);

                namedWindow("1st pyrDown",WINDOW_AUTOSIZE);
                imshow("1st pyrDown", dst);

                namedWindow("2st pyrDown",WINDOW_AUTOSIZE);
                imshow("2st pyrDown", dst2);

                //pyrUp
                pyrUp(dst2, dst);
                pyrUp(dst, src);

                //show
                namedWindow("New",WINDOW_AUTOSIZE);
                imshow("New", dst2);

                namedWindow("1st pyrUp",WINDOW_AUTOSIZE);
                imshow("1st pyrUp", dst);

                namedWindow("2st pyrUp",WINDOW_AUTOSIZE);
                imshow("2st pyrUp", src);

                //wait
                waitKey();

                return0;
}




void buildPyramid 该函数为源图像建立一个有参数maxlevel张图像的高斯金字塔,并将金字塔储存在目标图像的数组中,原始图像是该数组的第一个元素dst[0]


基于均值漂移分割算法第一步的均值漂移金字塔建立函数
void pyrMeanShiftFiltering     实现均值漂移分割的第一步,滤波。获取一幅具有颜色梯度和细粒度纹理平滑的目标图像dst。有参数sp代表空间窗口半径,sr代表颜色窗口半径




形态学计算(morphological operation)
即根据图像的形态处理图像
从而使得对某些特定的形状更加敏感或者相反

两个基本的形态学运算:膨胀(dilation)&腐蚀(erosion)
膨胀是指从对象的背景到边界添加像素
腐蚀则是清除像素

定义形态结构,来表示要添加或者删除的元素,通过比较(xi,yj)处的输入像素值和领域的像素值来计算(xi,yj)处的像素得到一幅新的图像
膨胀运算中,输出像素的值是其领域所有像素的最大值
腐蚀运算中,输出像素的值是其领域所有像素的最小值

开运算:先腐蚀,后膨胀     清除小对象,保留大对象
闭运算:先膨胀,后腐蚀     清除小洞,保留更大的对象

形态学梯度:一幅图像膨胀运算和腐蚀运算的差值

top-hat:原图像与其开运算的差值
black-hat:闭运算与原图像的差值

可以推出:[闭运算图]>[原图]>[开运算图]


void dilate          对源图像进行膨胀运算,结果储存在目标图像中
The function supports the in-place mode. Dilation can be applied several ( iterations ) times. In
case of multi-channel images, each channel is processed independently.

@param src input image; the number of channels can be arbitrary, but the depth should be one of
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src\`.
@param kernel structuring element used for dilation; if elemenat=Mat(), a 3 x 3 rectangular
structuring element is used. Kernel can be created using getStructuringElement
@param anchor position of the anchor within the element; default value (-1, -1) means that the
anchor is at the element center.
@param iterations number of times dilation is applied.          迭代的次数,可以多次执行该运算  
@param borderType pixel extrapolation method, see cv::BorderTypes
@param borderValue border value in case of a constant border
@sa  erode, morphologyEx, getStructuringElement
 */
CV_EXPORTS_Wvoid dilate( InputArraysrc,OutputArray dst, InputArray kernel,
                         Point anchor = Point(-1,-1), int iterations= 1,
                         int borderType = BORDER_CONSTANT,
                         const Scalar & borderValue = morphologyDefaultBorderValue() );

void erode           对源图像进行腐蚀运算,结果储存在目标图像中
The function supports the in-place mode. Erosion can be applied several ( iterations ) times. In
case of multi-channel images, each channel is processed independently.

@param src input image; the number of channels can be arbitrary, but the depth should be one of
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst output image of the same size and type as src.
@param kernel structuring element used for erosion; if `element=Mat()`, a `3 x 3` rectangular
structuring element is used. Kernel can be created using getStructuringElement.
@param anchor position of the anchor within the element; default value (-1, -1) means that the
anchor is at the element center.
@param iterations number of times erosion is applied.
@param borderType pixel extrapolation method, see cv::BorderTypes
@param borderValue border value in case of a constant border
@sa  dilate, morphologyEx, getStructuringElement
 */
CV_EXPORTS_Wvoid erode( InputArraysrc,OutputArray dst, InputArray kernel,
                        Point anchor = Point(-1,-1), int iterations= 1,
                        int borderType = BORDER_CONSTANT,
                        const Scalar & borderValue = morphologyDefaultBorderValue() );


void morphologyEx               执行使用参数op定义的形态学运算

The function can perform advanced morphological transformations using an erosion and dilation as
basic operations.

Any of the operations can be done in-place. In case of multi-channel images, each channel is
processed independently.

@param src Source image. The number of channels can be arbitrary. The depth should be one of
CV_8U, CV_16U, CV_16S, CV_32F or CV_64F.
@param dst Destination image of the same size and type as  src\` .
@param kernel Structuring element. It can be created using getStructuringElement.
@param anchor Anchor position with the kernel. Negative values mean that the anchor is at the
kernel center.
@param op Type of a morphological operation, see cv::MorphTypes
@param iterations Number of times erosion and dilation are applied.
@param borderType Pixel extrapolation method, see cv::BorderTypes
@param borderValue Border value in case of a constant border. The default value has a special
meaning.
@sa  dilate, erode, getStructuringElement
 */
CV_EXPORTS_Wvoid morphologyEx( InputArraysrc,OutputArray dst,
                               int op , InputArray kernel,
                               Point anchor = Point(-1,-1), int iterations= 1,
                               int borderType = BORDER_CONSTANT,
                               const Scalar & borderValue = morphologyDefaultBorderValue() );


Mat getStructuringElement          返回一个指定大小和形状的结构元素
The function constructs and returns the structuring element that can be further passed to cv::erode,
cv::dilate or cv::morphologyEx. But you can also construct an arbitrary binary mask yourself and use it as
the structuring element.

@param shape Element shape that could be one of cv::MorphShapes
@param ksize Size of the structuring element.
@param anchor Anchor position within the element. The default value \f$(-1, -1)\f$ means that the
anchor is at the center. Note that only the shape of a cross-shaped element depends on the anchor
position. In other cases the anchor just regulates how much the result of the morphological
operation is shifted.
 */
CV_EXPORTS_WMat getStructuringElement(intshape,Size ksize , Point anchor= Point(-1,-1));


#include"opencv2/opencv.hpp"
#include"opencv.hpp"
#include<iostream>

usingnamespacestd;
usingnamespacecv;

intmain(intargc,char**argv)
{
                //read the src image
                Matsrc;
                src=imread("go.png");

                //blur
                Matdst, dst2,dst3,dst4,dst5;
                inRange(src,Scalar(210, 210, 210),Scalar(255,255, 255), dst);//二值化阀值

                Matelement = getStructuringElement(MORPH_ELLIPSE,Size(15, 15));

                //closed operation
                dilate(dst, dst2, element);
                erode(dst2, dst3, element);

                //open operation
                erode(dst, dst4, element);
                dilate(dst4, dst5, element);

                //show
                namedWindow("Original image",WINDOW_AUTOSIZE);
                imshow("Original image", src);

                namedWindow("Segmented",WINDOW_AUTOSIZE);
                imshow("Segmented", dst);

/*            namedWindow("Dilation", WINDOW_AUTOSIZE);
                imshow("Dilation", dst2);

                namedWindow("Dilation->Erision", WINDOW_AUTOSIZE);
                imshow("Dilation->Erision", dst3);*/

                //open operation
                namedWindow("Dilation",WINDOW_AUTOSIZE);
                imshow("Dilation", dst4);

                namedWindow("Erision->Dilation",WINDOW_AUTOSIZE);
                imshow("Erision->Dilation", dst5);
                

                //wait
                waitKey();

                return0;
}


//闭运算



//开运算





查找表LUT(Look up table)
一个LUT变换,根据表中的值为输入图像的每个像素分配一个新的像素值
在该表中,其索引代表输入的亮度值,而相应索引单元的内容代表对应的输出值

该转化实际上是对每个可能的亮度值计算


#include "opencv2/opencv.hpp"
#include "opencv.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main( int argc , char ** argv )
{
                 //read the src image
                 Mat src;
                src = imread( "color.png" );

                 //creat the table and init
                 uchar *M = ( uchar *)malloc(256 * sizeof ( uchar ));
                 for ( int i = 0; i < 256; i++)
                {
                                M[i] = i*0.5;
                }
                 Mat lut(1, 256, CV_8UC1 , M);



                 //LUT
                 Mat dst;
                LUT(src, lut, dst);

                 //show
                namedWindow( "Orginal" , WINDOW_AUTOSIZE );
                imshow( "Orginal" , src);

                namedWindow( "LUT" , WINDOW_AUTOSIZE );
                imshow( "LUT" , dst);

                 //wait
                waitKey();

                 return 0;
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值