opencv2学习笔记(2)

滤波是信号处理的及图像处理中的一个基本操作,旨在特定的应用程序中,选择性地提取图像中被认为的传达重要信息的部分。滤波去除图像中的噪声,提取感兴趣的视觉特征,允许图像重样,等等。
观察图像中变化的频率构成了描述图像的一种方式,这种观点被称为频域,而通过灰度分布来描述一副图像被称为空间域。
#低通滤波器
低通滤波器的目的是降低图像变化的速率幅度。
cv::blur函数的作用是将每个像素替换为相邻矩形内像素的平均值。用法如下。

cv::blur(image,result,cv::Size(5,5));

在一些情况下,对于靠近的像素需要给予更多的重要性。这可以通过计算加权平均数,即离的近的像素比离的远的像素拥有更多权重。常用的加权方案基于高斯函数。cv::GaussianBlur函数起到这个作用,它的用法如下:

cv::GaussianBlur(image,result,cv::Size(5,5),1.5);

不难看出低通滤波器的的效果是对图像进行模糊或平滑,它减弱了物体边缘处可见的快速变化。
当滤波器的作用相当于将一个像素替换为相邻像素的加权总和时,我们称它是线性的。箱式滤波器便属于这一类,它将一个像素替换为相邻矩形内的像素和,并除以相邻像素的个数(以得到平均值)。这就像是将每个相邻像素乘以1后进行求和。滤波器的不同权重可以通过矩阵表示,矩阵的每一项都是对应位置像素的相乘因子。位于中心的元素对应的是滤波器当前正处理的像素。这样一个矩阵有时被称为核(Kernel )或掩码( Mask )。
想要在一幅图像上应用二维高斯滤波器,可以先对图像的行应用一维高斯滤波器(这将影响垂直频率),接着对图像的列应用相同的一维滤波器(影响的是垂直频率)。
当图像大小改变时也将使用低通滤波器,会由空间扭曲引起一些不受欢迎的瑕疵,这发生于将高频成分放入过小的图像时。事实上,小些的图像(即拥有更少像素点的图像)无法如同高分辨率图像一般表现出精美的纹理及尖锐的边缘。由于图像中的精致细节对应于高频分量,在将尺寸缩小前我们需要移除这些分量。在本秘诀中我们了解到低通滤波器可以达成该目的。也就是说,若想缩减一半的尺寸而不添加瑕疵,必须先对原图应用低通滤波,然后隔行、隔列去除像素。这也正是cv::pyrDown 函数的作用度:

cv::Mat reducedImage;//包含缩小后的图像
cv::pyrDown(image,reducedTmage);//将图像尺寸减半

存在一个更通用的cv::resize函数允许指定目标 图像的尺寸。尺寸既可以小于原图,也可以大于原图。

cv::Mat resizedImage;//包含改变尺寸后的图像
cv::resize(image,resizedImage,cv::Size(image.cols/3,image.row/3));//改为1/3大小

在其他选项也可以通过设置放缩因子来确定尺寸,或是挑选重采样过程中的特定插值方式。
#中值滤波
由于中值滤波器是非线性的,它无法表示为一个核矩阵。然而,它也对一个像素的相邻区域进行操作以确定输出像素的值。该像素及它的相邻区域组成一组数组,同时中值滤波仅仅计算这组数的中值,并用中值替换当前的像素值。
这解释了为何该滤波器在去除椒盐噪点方面是如此的高效。事实上,当一个例外的黑色或白色像素出现在一个给定的相邻区域时,它从不会被选为中值(它或为极大值,或为极小值),因此它总替换为某个相邻像素的值。与之相反,一个简单的均值滤波器将会极大地受到这类噪点的影响。
噪点像素使得相邻像素的平均值发生变化。即便已经被中值滤波器进行模糊。结界中的噪点还是依然可见的。
中值滤波器的同时还有保留边缘锐利度的优点。然而,它也会除去相同区域中的纹理。

#方向滤波器检测边缘
Sobel滤波器具有方向性,根据使用的核的不同,他只改变图像的水平或竖直频率。水平滤波器的使用方法如下

cv::Sobel(image,sobelX,CV_8U,1,0,3,0.4,128);

垂直滤波器的使用方法类似

cv::Sobel(image,sobelY,CV_8U,1,0,3,0.4,128);

它们能生成8位图像来表示结果。
在这种表示方法中,零值对应的灰度值位128,负数被表示为较暗的像素,而整数被表示为较亮的像素。
Sobel滤波器 的结果通过保存在16位的有符号整数图像中。两个结果(垂直和水平的)结合得到Sobel滤波器的范式(norm)。

//计算Sobel范式
cv::Sobel(image,SobelX,CV_16S,1,0);
cv::Sobel(image,SobelY,CV_16S,0,1);
cv::Mat sobel;
//计算L1范式
sobel = abs(SobelX)+abs(SobelY);

通过converTo函数可选的缩放参数,Sobel距离可以很方便地显示在一副图像中,零值对应于白色,而较高的值被赋予暗灰色:

//搜寻Sobel极大值
double sobmin,sobbmin;
cv::minMaxLoc(sobel,&sobmin,&sobmax);
//变换位8位图像
sobelTmage = -alpha*sobel+255;
cv::Mat sobelImage;
sobel.convertTo(sobelImage,CV_8U,-255./sobmax,255);

Sobel算子通过在水平和垂直方向下进行像素差分给图像梯度的近似。它在感兴趣像素的小窗口内运算,以减少噪声的影响。cv::Sobel函数使用Sobel核计算图像卷积的结果。它的完整使用说明如下:

cv::Sobel(image,      //输入
          sobel,          //输出
          image_depth,    //图像类型
          xorder,yorder,  //核的阶数
          kernel_size,    //方形核的大小
          alpha,beta);    //缩放值及偏移量

可以选择图像的类型为无符号字符、有符号字符或是浮点数。如果及如果位于像素值域之外,将进行饱和截断,这就是最后两个参数起作用的地方。在结果被保存之前,可以乘以alpah变量,再加上beta偏移量。
然而,在图像处理,我们通常计算的绝对值之和,也就是L1距离。它的结果于L2距离相近但是复杂度低很多。

//计算L1范式
sobel = abs(sobelX)+abs(sobelY);

梯度向量总是指向变化最剧烈的方向。在图像中,这意味着梯度向量总是与边缘增加哦,从暗处指向亮出。
在边缘检测中,如果既需要距离有需要方向,可以使用下述方法。

//Sobel必须以浮点数格式进行计算
cv::Sobel(image,sobelX,CV_32F,1,0);
cv::Sobel(image,sobelY,CV_32F,0,1);
//L2范式及梯度方向
cv::Mat norm,dir;
cv::cartToPolar(sobelX,sobelY,norm.dir);

默认情况下,方向的单位是弧度。设置一个额外的参数为true即可得到角度值。

#计算图像的拉普拉斯变换

Laplacian(拉普拉斯)是另一种基于图像倒数的高通线性滤波器,它计算二阶导数以衡量图像的弯曲度。
OpenCV函数cv::Laplacian使用基础函数cv::getDerivKernels来获取核矩阵。

class LaplacianZC{
  private:
      //原图
      cv::Mat img;
      //包含Laplacian的32位浮点图像
      cv::Mat laplacian;
      //Laplacian卷积核的大小
      int aperture;
  public:
      LaplacianZC():aperture(3){}
      //设置卷积核的大小
      void setAperture(int a){
           aperture = a;
      }
      //计算浮点数laplacian
       cv::Mat computeLaplacian(contest  cv::Mat& Image){
      //计算Laplacian
       cv::Laplacian(image,laplace,CV_32F,aperture);
       //保留图像的局部备份
       img = image.clone();
       return laplace;
       }
       

Laplacian的计算结果保存在浮点数图像中。为了得到结果,我们进行与之前秘诀相同的重缩放。这个重缩放基于拉普拉斯最大绝对值,其中0对应灰度128。用类似德方法允许得到该图像:

//返回8位图像存储德Laplacian结果
//零点交叉于灰度值128
//如果没有指定scale参数,那么最大值将缩放至强度255
//你必须在调用它之前用computeLaplacian
cv::Mat getLaplacianImage(double scale=-1.0){
    if(scale<0){
       double lapmin,lapmax;
       cv::minMaxLoc(laplace,&lapmin,&lapmax)
       scale = 127/std::max(-lapmin,lapmax);
    }
    cv::Mat LaplaceImage;
    laplace.convertTo(LaplaceImage,CV_8U,scale,128);
    return laplace;
 

使用该类,可以这么计算图像的7x7拉普拉斯变换;

//使用LaplacianZC类进行计算
LaplacianZC laplacian;
laplacian.setAperture(7);
cv::Mat flap = laplacian.computeLaplacian(image);
laplance = laplacian.getLaplacianImage();

跟随Laplacian 图像中零交叉曲线是一件容易出错的事情。然而,一个简化的算法被用于检测近似的零交叉位置,过程如下。扫描Laplacian图像,比较当前像素与左侧像素。如果两者的符号不同,那么说明当前像素存在零交叉。如果没有,在正上方位置重复相同测试。这个算法使用下述方法实现,能够生产零交叉的二值图像:

//得到零点交叉的二值图像
//如国相邻像素的乘积小于threshold
//那么零点交叉将被忽略
cv::Mat getZeroCrossings(float threshold=1.0){
//创建迭代器
cv::Mat_<float>::const_itertor it=
laplace.begin<float>()+laplace.step1();
cv::Mat_<float>::const_itertor itend=
laplace.end<float>();
cv::Mat_<float>::const_itertor itup=
laplace.begin<float>();
//初始化白色的二值图像
cv::Mat binary(laplace.size(),CV_8U,cv::Scalar(255));
cv::Mat_<uchar>::iterator itout=binary.begin<uchar>()+binary.step1();
//对输入阈值取反
threshold*=-1.0;
for(;it!= itend;++it,++itup,++itout)
//如果相邻像素的乘积为负数,那么符号发生改变
if(*it**(it-1)<threshold)
   *itout = 0;
else if(*it**itup<threshold)
   *itout = 0:
   }
   return binary;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,OpenCV是一个开源计算机视觉和机器学习软件库,用于开发图像和视频处理应用程序。通过使用OpenCV,您可以读取摄像头并显示实时图像,打开视频文件或摄像头文件,并获取视频的相关信息,例如帧宽度、帧高度、帧率和总帧数。 对于学习OpenCV,你可以按照以下步骤进行: 1. 安装OpenCV库:在开始学习OpenCV之前,您需要从OpenCV官方网站下载和安装OpenCV库。根据您的操作系统和编程语言选择合适的版本。 2. 学习基本概念:熟悉OpenCV的基本概念和术语,例如图像和视频的加载、显示、保存以及常用的图像处理操作,如滤波、边缘检测和特征提取等。 3. 掌握OpenCV函数和类:深入了解OpenCV提供的函数和类,例如cv::Mat用于图像和矩阵操作,cv::VideoCapture用于读取和处理视频,以及cv::imshow和cv::waitKey等用于显示图像的函数。 4. 实践项目:通过完成一些实践项目来应用您所学到的知识。例如,利用OpenCV实现人脸检测、目标追踪、图像识别等。 5. 学习资料和资源:查找和阅读OpenCV的官方文档、教程和示例代码,参与开源社区讨论和交流,加入相关的论坛和邮件列表等。 总结起来,学习OpenCV包括安装OpenCV库、学习基本概念、掌握OpenCV函数和类、实践项目以及查找和阅读相关资料和资源。通过不断实践和学习,您将能够更好地理解和应用OpenCV库来开发图像和视频处理应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值