Imgproc_1_图像滤波模块

一边界拓展

有时滤波处理需要考虑边界,为图像增加一定的边缘,以适应卷积核在原图上的边界操作。
拓展边界的方法:
1>重复:
aaaaaa|abcdefgh|hhhhhhh
2>反射:
fedcba|abcdefgh|hgfedcb
3>反射101:
gfedcb|abcdefgh|gfedcba
4>外包装:
cdefgh|abcdefgh|abcdefg
5>常量:
iiiiii|abcdefgh|iiiiiii

void copyMakeBorder(InputArray src, OutputArray dst, 
                    int top, int bottom, int left, int right,          
                    int borderType, 
                    const Scalar&value=Scalar())
/*top,bottom,left,right,上下左右边界拓展的长度
 *dst的size为Size(src.rows+top+down,src.cols+left+right);
 *borderType:
 *BORDER_REPLICATE      重复     
 *BORDER_REFLECT        反射 
 *BORDER_REFLECT_101    反射101
 *BORDER_WRAP           外包装
 *BORDER_CONSTANT       常量
 *value 当borderType=BORDER_CONSTANT时,边界的拓展像素值
 */

二常见滤波

1,线性滤波
每个像素的输出值,是输入像素的加权和

1>方框滤波
所用核:
这里写图片描述
where
这里写图片描述

void boxFilter(InputArray src, OutputArray dst, 
               int ddepth,     Size ksize, 
               Point anchor=Point(-1,-1), bool normalize=true, 
               int borderType=BORDER_DEFAULT )
/*ddepth输出图像的深度(-1,就用src.depth())
 *ksize滤波的核大小
 *anchor锚点,Point(-1,-1)代表在核的中心
 *normalize是否归一化
 *(归一化把要处理的量缩放到一个范围内,以便统一的处理和直观量化)
 *borderType边界拓展类型
 */

2>均值滤波
这里写图片描述
调用boxFilter的归一化
缺点:
不能很好的保护图像的细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好的去除噪声点

void blur(InputArray src, OutputArray dst, 
          Size ksize, Point anchor=Point(-1,-1), 
          int borderType=BORDER_DEFAULT )
//src的depth应该为CV_8U,CV_16U,CV_16S,CV_32F,CV_64F之一

3>高斯滤波
高斯滤波是一种线性平滑滤波,可以消除高斯噪声。高斯模糊对于图像来说就是一个低通滤波操作。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。

void GaussianBlur(InputArray src, OutputArray dst, 
                  Size ksize, double sigmaX, double sigmaY=0,                  
                  int borderType=BORDER_DEFAULT )
/*src图像深度为CV_8U,CV_16U,CV_16S,CV_32F,CV_64F之一
 *ksize核大小,ksize.width和ksize.height可以不同,但都得为正奇数
 *ksize可以为0,可以通过sigmaX,sigmaY计算出来
 *sigmaX,sigmaY表示在X,Y方向的标准偏差
 *使用时可以只指定ksize或者只指定sigmaX和sigmaY,或者两者都指定
 */

4>filter2D
用自定义核与图像卷积

void filter2D(InputArray src, OutputArray dst, 
              int ddepth, InputArray kernel, 
              Point anchor=Point(-1,-1), double delta=0, 
              int borderType=BORDER_DEFAULT )
/*ddepth dst的深度:(以下为src相应深度,dst可以选择深度,-1为不变)
 *src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
 *src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
 *src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
 *src.depth() = CV_64F, ddepth = -1/CV_64F
 *delta为像素点在存储之前,额外增加的值
 */
 用法见Core的图像Sharp

5>滤波引擎
FilterEngine类
几乎可以把所有的滤波操作施加到图像上

//很多跟滤波相关的create函数,就是返回Ptr<FilterEngine>
  cv::createSeparableLinearFilter()
  cv::createLinearFilter(),cv::createGaussianFilter()
  cv::createGaussianFilter(), cv::createDerivFilter()
  cv::createBoxFilter(),cv::createMorphologhyFilter()

2,非线性滤波
1>中值滤波
基本思想用像素点邻域的灰度值的中值来代替该像素点的灰度值,该方法在去除脉冲噪声,椒盐噪声的同时又能保留图像的边缘细节

优点:
同样的3×3的区域进行处理,中值滤波的消除的能力更强,无论在去除噪声,还是保留边缘都不错
缺点:
时间是均值滤波的五倍以上

中值滤波的步骤:
1)将n×n范围内的像素点按强度排列
2) 选择中间值作为新值

void medianBlur(InputArray src, OutputArray dst, int ksize)
//src,channels应该为1,3,4  
//当ksize为3,5的时候depth为CV_8U,CV_16U,CV_32F,当ksize更大时,就CV_8U

2>双边滤波
结合图像的空间邻近度和像素值近似度的一种折中处理,同时考虑空域信息和灰度相似度,达到保边去噪的目的,具有简单,非迭代,局部的特点
优点:
边缘保存

void bilateralFilter(InputArray src, OutputArray dst, 
                     int d, double sigmaColor, 
                     double sigmaSpace, 
                     int borderType=BORDER_DEFAULT )
//src为8-bit或浮点型,1或3通道
//d每个像素的邻域直径,如果为负,则通过sigmaSpace,成正比关系
//sigmaColor颜色空间的sigma值,值越大,表明该像素邻域内有越宽广的颜色混合到一起
//sigmaSpace坐标空间的sigma值,值越大,表明越远的像素会相互影响,
//使更大区域中足够相似的颜色获取相同的颜色

3,滤波综合
操作图像:
这里写图片描述

//方框滤波      time:0.000488141s
cv::boxFilter(image,result1,-1,cv::Size(3,3));
//均值滤波      time:0.000788124s
cv::blur(image,result2,cv::Size(3,3));
//高斯滤波      time:0.000333969s
cv::GaussianBlur(image,result3,cv::Size(3,3),0);
//中值滤波      time:0.000296508s
cv::medianBlur(image,result4,3);
//双边滤波      time:0.00323766s
cv::bilateralFilter(image,result5,3,3,3);

二形态学滤波

1,腐蚀和膨胀
腐蚀和膨胀的功能:
1)消除噪声
2)分割出独立的图像元素,在图像连接相邻的元素
3)寻找图像中的明显的极大值或极小值区域
4)求出图像的梯度

1>膨胀
核与图像卷积,以核区域的最大值代替当前像素值。

void dilate(InputArray src, OutputArray dst, 
            InputArray kernel, Point anchor=Point(-1,-1), 
            int iterations=1, int borderType=BORDER_CONSTANT,   
            const Scalar&borderValue=morphologyDefaultBorderValue() )
//src的depth应该为CV_8U,CV_16U,CV_16S,CV_32F,CV_64F.
//kernel,膨胀操作的核,当为NULL时,表示使用3*3的核
//iterations,使用dilate的迭代次数
//borderValue,BORDER_CONSTANT情况下的边界拓展填充
//morphologyDefaultBorderValue会默认,dilate填充-Inf

//kernel可以使用getStructuringElement得到
Mat getStructuringElement(int shape, Size ksize, 
                          Point anchor=Point(-1,-1))
//shape:
//MORPH_RECT    举行
//MORPH_ELLIPSE 交叉性
//MORPH_CROSS   椭圆形

2>腐蚀
核与图像卷积,以核区域的最小值代替当前像素值

void erode(InputArray src, OutputArray dst, 
           InputArray kernel, Point anchor=Point(-1,-1), 
           int iterations=1, int borderType=BORDER_CONSTANT, 
           const Scalar& borderValue=morphologyDefaultBorderValue() )
//用法见膨胀
//morphologyDefaultBorderValue,会默认填充+Inf

2,开运算,闭运算,形态学梯度,顶帽,黑帽

//提前定义核
//核的半径自己调整
int kel_size=3;
cv::Mat kel=cv::getStructuringElement(cv::MORPH_RECT,
            cv::Size(2*kel_size+1,2*kel_size+1),
            //锚点,为中心点
            cv::Point(kel_size,kel_size));

1>开运算
先腐蚀,后膨胀的过程
dst=dilate(erode(src,element));
用来消除小物体,在纤细出分离物体,并且在平滑较大物体的边界同事不明显改变其面积

void Opening(const cv::Mat &image,cv::Mat &result)
{
    cv::Mat Image=image.clone();
    cv::Mat Image2;
    //腐蚀
    cv::erode(Image,Image2,kel);
    //膨胀
    cv::dilate(Image2,result,kel);
}

效果图:
Opening
2>闭运算
先膨胀,后腐蚀的过程
dst=erode(dilate(src,element));
闭运算能够排除小型黑色区域

void Closing(const cv::Mat &image,cv::Mat &result)
{
    cv::Mat Image=image.clone();
    cv::Mat Image2;
    //膨胀
    cv::dilate(Image,Image2,kel);
    //腐蚀
    cv::erode(Image2,result,kel);
}

效果图:
这里写图片描述
3>形态学梯度
膨胀图与腐蚀图之差
dst=dilate(src,element)-erode(src,element);
对于二值图像进行这一操作可以将团块的边缘突出,可以用形态学梯度保留物体的边缘轮廓

void Morphological(const cv::Mat &image,cv::Mat &result)
{
    cv::Mat Image=image.clone();
    cv::Mat Image2,Image3;

    cv::dilate(Image,Image2,kel);
    cv::erode (Image,Image3,kel);

    result=Image2-Image3;
}

效果图:
这里写图片描述
4>顶帽
是原图像与与开运算的结果图之差
dst=src-open(src,element);
突出了比原图轮廓周围的区域更加明亮的区域,且这一操作与选择的核的大小相关,在一幅图像具有大幅背景,而微笑物体比较有规律的情况下,可以使用顶帽操作进行背景提取。

void TopHat(const cv::Mat &image,cv::Mat &result)
{
    cv::Mat Image=image.clone();
    cv::Mat Image2;
    Opening(Image,Image2);
    result=Image-Image2;
}

5>黑帽
闭运算的结果图与原图像之差
dst=close(src,element)-src;
突出比原图轮廓周围更暗的区域,用来分离比邻近暗的斑块

void BlackHat(const cv::Mat &image,cv::Mat &result)
{
    cv::Mat Image=image.clone();
    cv::Mat Image2;
    Closing(Image,Image2);
    result=Image2-Image;
}

5>多功能API
morphologyEx
进行形态学滤波

void morphologyEx(InputArray src, OutputArray dst, 
                  int op,         InputArray kernel, 
                  Point anchor=Point(-1,-1), int iterations=1, 
                  int borderType=BORDER_CONSTANT, 
const Scalar& borderValue=morphologyDefaultBorderValue() )
//src的depth应该为CV_8U,CV_16U,CV_16S,CV_32F,CV_64F.
//op:
//MORPH_OPEN     开运算
//MORPH_CLOSE    闭运算
//MORPH_GRADIENT 形态学梯度
//MORPH_TOPHAT   顶帽
//MORPH_BLACKHAT 黑帽
//kernel,通过getStructuringElement()得到

三图像金字塔与图像尺寸缩放

1>尺寸调整

void resize(InputArray src, OutputArray dst, Size dsize, 
            double fx=0, double fy=0, 
            int interpolation=INTER_LINEAR )
/*dst,有着dsize的尺寸,或者由src.size()计算出来
 *dsize,输出图像的大小,如果为0,通过
 *dsize=Size(round(fx*src.cols),round(fy*src.rows))计算
 *fxx轴的缩放系数,如果为0,则为size.width/src.cols
 *fyy轴的缩放系数,如果为0,则为size.height/src.cols
 *interpolation:
 *INTER_NEAREST  最邻近插值
 *INTER_LINEAR   线性插值
 *INTER_AREA     区域差值_利用像素区域关系的重采样插值
 *INTER_CUBIC    三次样条插值_超过4*4像素邻域内的双三次插值
 *INTER_LANCZOS4 Lanczos插值_超过8*8像素邻域内的Lancaos插值
 *
 *缩小图像用:INTER_AREA
 *放大图像用:INTER_CUBIC 效率不高 或者 INTER_LINEAR 效率高_速度快
 */

 //两种使用方法
 //[1]:显示指定dsize
 resize(src,dst,dst.size());
 //[2]:显示指定fx和fy
 resize(src,dst,Size(),0.5,0.5);

2>高斯金字塔
第K层高斯金字塔通过平滑,亚采样就可以获得K+1层高斯图像。包含一系列低通滤波器。
为了获得第i+1层金字塔图像:
1)对图像i进行高斯内核卷积
2)将所有偶数行和列去除
结果图只有原图四分之一

void pyrDown(InputArray src,OutputArray dst,
             const Size& dstsize=Size(),
             int borderType=BORDER_DEFAULT)
//dstsize输出图像的大小,在默认值Size()情况下为
//Size((src.cols+1)/2,(src.rows+1)/2)          

任何情况都要满足
这里写图片描述
首先进行卷积运算
这里写图片描述
对偶数行和列做插值

3>拉普拉斯金字塔
Li=Gi-UP(Gi+1)×g5×5
UP()操作将源图像中位置为(x,y)的像素映射到目标图像的(2x+1,2y+1)位置

void pyrUp(InputArray src, OutputArray dst, 
           const Size& dstsize=Size(), 
           int borderType=BORDER_DEFAULT )
 //dstsize输出图像大小,如果默认值Size(),则
 //Size(src.cols*2,src.rows*2)

都要满足:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值