opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结

时间:2023-02-07 12:14:39

1)卷积

连续空间的卷积定义是 f(x)与g(x)的卷积是 f(t-x)g(x) 在t从负无穷到正无穷的积分值。t-x要在f(x)定义域内,所以看上去很大的积分实际上还是在一定范围的。实际的过程就是f(x)先做一个Y轴的反转,然后再沿X轴平移t就是f(t-x),然后再把g(x)拿来,两者乘积的值再积分.想象一下如果g(x)或者f(x)是个单位的阶越函数。那么就是f(t-x)与g(x)相交部分的面积。这就是卷积了。把积分符号换成求和就是离散空间的卷积定义了。

那么在图像中卷积卷积地是什么意思呢?就是图像就是图像f(x),模板是g(x),然后将模版g(x)在模版中移动,每到一个位置,就把f(x)与g(x)的定义域相交的元素进行乘积并且求和,得出新的图像一点,就是被卷积后的图像。模版又称为卷积核。卷积核做一个矩阵的形状。

    卷积定义上是线性系统分析经常用到的。线性系统就是一个系统的输入和输出的关系是线性关系,就是说整个系统可以分解成N多的无关独立变化,整个系统就是这些变化的累加。如 x1->y1, x2->y2; 那么A*x1 + B*x2 -> A*y1 + B*y2 这就是线性系统。 表示一个线性系统可以用积分的形式,如Y= Sf(t,x)g(x)dt  S表示积分符号,就是f(t,x)表示的是A,B之类的线性系数。
    看上去很像卷积呀。对!如果f(t,x) = F(t-x) 不就是了吗。从f(t,x)变成F(t-x)实际上是说明f(t,x)是个线性移不变,就是说,变量的差不变化的时候,那么函数的值不变化。实际上说明一个事情就是说,线性移不变系统的输出可以通过输入和表示系统线性特征的函数卷积得到。
卷积是图像处理常用的方法,给定输入图像,在输出图像中每一个像素是输入图像中一个小区域中像素的加权平均,其中权值由一个函数定义,这个函数称为卷
积核。比如说卷积公式:R(u,v)=∑∑G(u-i,v-j)f(i,j),其中f为输入,G为卷积核。


void cvFilter2D(const  CvArr*  src,
 CvArr*        dst,
                 const CvMat* kernel,
CvPoint anchor=cvPoint(-1,-1));
#define cvConvolve2D cvFilter2D
src
输入图像.
dst
输出图像.
kernel
卷积核, 单通道浮点矩阵. 如果想要应用不同的核于不同的通道,先用  cvSplit 函数分解图像到单个色彩通道上,然后单独处理。
anchor
核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。
函数  cvFilter2D 对图像进行线性滤波,支持 In-place 操作。当核运算部分超出输入图像时,函数从最近邻的图像内部象素差值得到边界外面的象素值。

代码:

#include <cv.h>
#include <highgui.h>
using namespace std;

int main()
{
float kemel[]={1.f/16,2.f/16,1.f/16,2.f/16,4.f/16,2.f/16,1.f/16,2.f/16,1.f/16};
float kemel_1[]={ 1.0, -2.0, 1.0, 4.0, -2.0, -1.0, 4.0, -2.0, 2.0 };  //核
CvMat Mkemel,Mkemel_1;
Mkemel=cvMat(3,3,CV_32FC1,kemel);
Mkemel_1=cvMat(3,3,CV_32FC1,kemel_1);

IplImage *img=cvLoadImage("f.jpg",CV_LOAD_IMAGE_COLOR);
IplImage *dst=cvCreateImage(cvGetSize(img),img->depth,img->nChannels);
IplImage *dst_1=cvCreateImage(cvGetSize(img),img->depth,img->nChannels);

cvFilter2D(img,dst,&Mkemel,cvPoint(-1,-1));////设参考点为核的中心
cvFilter2D(img,dst_1,&Mkemel_1,cvPoint(-1,-1));////设参考点为核的中心
cvNamedWindow("orignal");
cvNamedWindow("trans");
cvNamedWindow("trans_1");
cvShowImage("orignal",img);
cvSaveImage("orignal.jpg",img);
cvShowImage("trans",dst);
cvSaveImage("result.jpg",dst);
cvShowImage("trans_1",dst_1);
cvSaveImage("result_1.jpg",dst_1);
cvWaitKey(0);
cvDestroyAllWindows;
cvReleaseImage(&img);
cvReleaseImage(&dst);
cvReleaseImage(&dst_1);
return 0;
}

效果:opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结   opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结

opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结


2)卷积边界

cvCopyMakeBorder函数可以复制图像并制作边界,将特定图像轻微变大,然后以各种方式自动填充图像边界,
当 Bordertype=IPL_BORDER_REPLICATE时,原始图像边缘的行和列被复制到大图像的边缘,当 Bordertype=IPL_BORDER_CONSTANT时,有一个像素宽的黑色边界。

void cvCopyMakeBorder( const CvArr* src, CvArr* dst,
  CvPoint offset, int bordertype,
  CvScalar value=cvScalarAll(0) );
src
输入图像。
dst
输出图像。
offset:
输入图像(或者其ROI)欲拷贝到的输出图像长方形的左上角坐标(或者左下角坐标,如果以左下角为原点)。
长方形的尺寸要和原图像的尺寸的ROI分之一匹配。将源图像的副本放到目标图像中的位置。
bordertype
已拷贝的原图像长方形的边界的类型:
IPL_BORDER_CONSTANT - 填充边界为固定值,值由函数最后一个参数指定。
IPL_BORDER_REPLICATE -边界用上下行或者左右列来复制填充。
(其他两种IPL边界类型, IPL_BORDER_REFLECT 和IPL_BORDER_WRAP现已不支持)。
value
如果边界类型为IPL_BORDER_CONSTANT的话,那么此为边界像素的值。函数cvCopyMakeBorder拷贝输入2维阵列到输出阵列的内部并且在拷贝区域的周围制作一个指定类型的边界。函数可以用来模拟和嵌入在指定算法实现中的边界不同的类型。例如:和opencv中大多数其他滤波函数一样,一些形态学函数内部使用复制边界类型,但是用户可能需要零边界或者填充为1或255的边界。

代码:

#include "highgui.h"
#include "cv.h"
int main(int argc,char **argv)
{
IplImage *src,*dst;
src = cvLoadImage("f.jpg",-1);
dst = cvCreateImage(cvSize(src->width+50,src->height+50),IPL_DEPTH_8U,3);

cvNamedWindow("src");
cvShowImage("src",src);
cvNamedWindow("filtering");
cvCopyMakeBorder(src,dst,cvPoint(1,1),IPL_BORDER_CONSTANT);

//IPL_BORDER_CONSTANT-填充边界固定值,黑色
cvShowImage("dst",dst);
cvSaveImage("result.jpg",dst);
 
cvCopyMakeBorder(src,dst,cvPoint(1,1),IPL_BORDER_REPLICATE);

//IPL_BORDER_REPLICATE-复制边界
cvShowImage("filtering",dst);
cvSaveImage("result_1.jpg",dst);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&dst);
cvDestroyAllWindows();
return (0);
}


效果:

原图:opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结

结果:opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结   opencv卷积cvFileter2D与卷积边界cvCopyMakeBorder处理图像的总结


扩大图像的边界50个像素,左边显示的是IPL_BORDER_CONSTANT-填充边界固定值(黑色)的填充结果;右边显示的是IPL_BORDER_REPLICATE-复制边界的结果。