简短介绍一个OpenCV基本操作--图像的卷积2

初步了解OpenCV

安装的内容如下
Windows下安装
源码下载地址:https://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.13/opencv-2.4.13.exe/download
安装程序:http://jingyan.baidu.com/article/4dc408484c0ec0c8d946f180.html~

OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

OpenCV采用BSD协议,这是一个非常宽松的协议。简而言之,用户可以修改OpenCV的源代码,可以将OpenCV嵌入到自己的软件中,可以将包含OpenCV的软件销售,可以用于商业产品,也可以用于科研领域。BSD协议并不具有“传染性”,如果你的软件中使用了OpenCV,你不需要公开代码。你可以对OpenCV做任何操作,协议对用户的唯一约束是要在软件的文档或者说明中注明使用了OpenCV,并附上OpenCV的协议。

C/C++语言中的main函数,经常带有参数argc,argv,如下:

int main(int argc,char** argv)
或者
int main(int argc, char* argv[])

在上面代码中,argc表示命令行输入参数的个数(以空白符分隔),argv中存储了所有的命令行参数。

进入实战

图像的卷积我们介绍俩种方法:普通求导与卷积求导。

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

#define PI 3.1415926
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
/*//普通求导
  Mat src = imread("G:/project.jpg", 1);//读入G盘下的图片,自己根据自己图片的存储位置来引入
  cvtColor(src, src, COLOR_BGR2GRAY);//将彩色图转换为黑白图
  nameWindow("src", WINDOW_AUTOSIZE);//使图像自动适应屏幕
  imshow("src", src);//展示转换后的图片
  
  Mat dImg = Mat(src.rows, src.cols -2 , CV_8UC1);//创建一个和原始图像行数一致列数少2行的8位无符号的  单通道的灰度图片容器(CV_8UC1:创建无符号的8位单通道图片	)
  for(int i = 0 ; i<src.rows; i++)
  {
     for(int j=1; j<src.cols; j++)
       {
           dImg.at<uchar>(i , j-1) = src.at<uchar>(i , j +1)-src.at<uchar>(i , j - 1)//求导公式,目的在于得出转换后的图片
        }
 }
 cvNameWindow("dst", CV_WINDOW_AUTOSIZE);//创建窗口显示目录
 imshow("dst", dImg);//显示求导后的图片
 waitKey(0);//让窗口暂停直到按下任意键*/

//卷积求导
Mat src = imread("G:/protect.jpg", 1);
cvtColor(src, src, COLOR_BGR2GRAY);
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);//上面已解释

      //5*5卷积模板
 Mat model = Mat(5 , 5 ,CV_64FCI);//创建高斯模板
double sigma = 80;
for(int  i =-2; i<=2 ;i++)
{
   for(int j = -2; j<=2 ; j++)
    {
        model.at<double>(i + 2 , j + 2) = exp(-(i * i +j * j) / (2 *sigma *sigma)) / (2 * PI * sigma);//根据公式给高斯模板中的各个元素赋值
    }
}

//矩阵求和
double  gaussSum = 0;
gaussSum = sum(model).val[0];//所有元素求和
for(int i = 0; i<model.rows; i++)
{
    for(int j = 0; j<5 ; j++)
    {
      model.at<double>(i , j) = model.at<double>(i ,j) / gaussSum;//将高斯模板归一化
      }
}
Mat  dst =   Mat(src.rows - 4 ,src.cols - , CV_8UC1);
for(int i = 2; i < src.rows - 2; i++)//对src行进行循环
{
  for(int j = 2; j<src.cols - 2 ; j++)//对src列进行循环
  { 
      double sum = 0;
     for(int m = 0; m < mopdel.rows; m++)
     {
         for(int n =0; n <model.cols ; n++)
         {
            sum += (double)src.at<uchar>(i + m - 2 , J +n - 2)<double>(m,n);//对应位置的数相乘放到sum中
            }
      }
      dst.at<uchar>(i - 2 , j - 2) = (uchar)sum;//sum的值再赋给dst的每个元素
   }
}
nameWindow("gaussBlur", WINDOw_AUTOSIZE);
imshow("gaussBlur" , dst);

waitKey(0);

补充的数学知识

高斯模糊

高斯模糊将正态分布用于图像处理,接下来介绍“高斯模糊“算法。本质上它是一种数据平滑技术,适用于多个场合。
所谓模糊 可以理解成每一个像素都取周边像素的平均值。
在图形上,正态分布是一种钟形曲线,越接近中心,取值越大,越远离中心,取值越小。计算平均值的时候,我们只需要将”中心点”作为原点,其他点按照其在正态曲线上的位置,分配权重,就可以得到一个加权平均值。
正态分布的密度函数叫做“高斯函数”(Gaussian function)。它的一维形式是:

f ( x ) = 1 σ 2 π e − ( x 2 − μ 2 ) 2 σ 2 f(x)=\frac{1}{\sigma\sqrt{2{\pi}}}e^\frac{-(x^2-\mu^2)}{2\sigma^2} f(x)=σ2π 1e2σ2(x2μ2)

其中,μ是x的均值,σ是x的方差。因为计算平均值的时候,中心点就是原点,所以μ等于0。

f ( x ) = 1 σ 2 π e − x 2 2 σ 2 f(x)=\frac{1}{\sigma\sqrt{2{\pi}}}e^\frac{-x^2}{2\sigma^2} f(x)=σ2π 1e2σ2x2

根据一维高斯函数,可以推导得到二维高斯函数:

G ( x , y ) = 1 2 π σ 2 e ( x 2 + y 2 ) 2 σ 2 G(x,y)=\frac{1}{2{\pi}{\sigma^2}}e^\frac{(x^2+y^2)}{2\sigma^2} G(x,y)=2πσ21e2σ2(x2+y2)

有了这个函数 ,就可以计算每个点的权重了。

在上面的公式中σ就是我们的模糊半径,而x和y就是我们周边像素对于中心像素的相对坐标。

图例演示请访问
http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

补充为何要用高斯模糊

说道图像模糊算法,实现原理也并不是很难懂,要设计一个程序来模糊处理一个图像的话,对于正在处理的每一个像素,取周围若干个像素的RGB值并且平均,然后这个平均值就是模糊处理过的像素,如果对图片中的所有像素都这么处理的话,处理完成的图片就会变得模糊。但是这样做的效果并不是,如果图片颜色变化频繁而且单位面积里面颜色反差很大,并且模糊半径很大的话,那么结果就是:模糊范围的最外层的像素和中心像素周围的像素的权重是一样的,这样处理的图片可能过渡并不是很平滑。

所以,需要有一个算法,来为这些在模糊范围中的像素来分别计算权重,这样的话越在模糊半径外围的像素权重越低,造成的影响就越小,越在内侧的像素得到的权重最高,因为内侧像素更加重要,他们的颜色应该与我们要处理的中心像素更接近,更密切。这个时候就需要用到高斯模糊算法了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值