一个最重要并且最基本的卷积是导数的计算(或者是其近似值)。
用来表达微分的最常用的操作是Sobel微分算子。Sobel算子包含任意阶的微分及融合偏导。Sobel导数可以定义任意大小的核,而且这些核可以用快速且迭代的方式构造,大核对导数有更好的逼近,因为小核对噪声更敏感。
必须认识到,Sobel导数并不是真正的导数,因为Sobel算子定义在一个离散的空间上。Sobel算子真正表示的是多项式拟合。
以3×3的模板为例:
函数形式:
void cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size=3 );
-
src
- 输入图像. dst
- 输出图像. xorder
- x 方向上的差分阶数 yorder
- y 方向上的差分阶数 aperture_size
- 参数是方形滤波器的宽(或高)并且应该是奇数。目前支持1,3,5,7. xorder和yorder通常只可能用到0,1,最多2。
实例代码:
#include
#include
int main(int argc, char** argv)
{
IplImage *src, *gray, *sobel;
src = cvLoadImage("f:\\opencvEx\\lena.jpg");
gray = cvCreateImage(cvGetSize(src), src->depth, 1);//灰度图
//sobel = cvCreateImage(cvGetSize(src), src->depth, 1);
sobel = cvCreateImage(cvGetSize(src), IPL_DEPTH_16S, 1);
cvNamedWindow("src");
cvNamedWindow("gray");
cvNamedWindow("sobel");
cvCvtColor(src, gray, CV_BGR2GRAY);//源图像转为灰度
cvSobel(gray, sobel, 1, 1, 3);
IplImage *sobel8u = cvCreateImage(cvGetSize(sobel), IPL_DEPTH_8U, 1);
cvConvertScaleAbs(sobel, sobel8u, 1, 0);
cvShowImage("src", src);//显示图像
cvShowImage("gray", gray);
cvShowImage("sobel", sobel8u);
cvWaitKey(0);
cvReleaseImage(&src);//释放空间
cvReleaseImage(&gray);
cvReleaseImage(&sobel);
cvDestroyAllWindows();
return 0;
}
-
注意:如果源图像是8位的,为避免溢出,目标图像的深度必须是IPL_DEPTH_16S。但是,图像显示是以8位无符号显示的,现在是16位有符号的,所以我们需要将16位的再转换为8位的来显示,可以使用函数cvConvertScaleAbs()进行转换,然后再显示即可。