【说明】 看的教程书上是用的opencv基于C的函数,但是在代码实现过程用的是C++的函数。因此,下文中的函数介绍和示例代码会有一些出入,理解效果就好,都是通用的。

一、卷积(convolution)

一个特殊卷积所实现的功能是由其卷积核的形式决定的。这个核本质是一个大小固定、由数值参数构成的数组,数组的参考点(anchor point)通常位于数组的中心。数组的大小成为核支撑(support of the kernel)。

1. opencv函数—cvFilter2D

  • 方法名
void cvFilter2D(
        const CvArr *   src,     
        CvArr *         dst,
        const CvMat *   kernel,
        CvPoint         anchor = cvPoint(-1,-1)
                );
  • 参数说明
  • anchor 参考点的位置,默认值(cvPoint(-1,-1))指参考点为核的中心。
  • src 和dst 大小应该相同。因为opencv在处理时,在原图像上通过复制边缘像素的方法创建了虚拟边界。因此,dst大小与src保持相同即可。

2. 示例

  • 代码
// 加载原始图像
    Mat src_door = imread("../source/door.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    imshow("源图像", src_door);

    // 生成一个新的核
    Mat mask = (Mat_<char>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    Mat dst;
    // 卷积处理图像
    filter2D(src_door, dst, src_door.depth(), mask);
    imshow("卷积图像", dst);
  • 效果

opencv解析dcm转jpg opencv dct变换_opencv解析dcm转jpg

opencv解析dcm转jpg opencv dct变换_opencv_02

  • 二、卷积边界

如上文所述,在使用filter2D时,需要对边界进行预处理,此函数就是用不同方式处理的边界。它可以使特定的图像轻微变大,然后以各种方式自动填充图像边界。

1. opencv函数—cvCopyMakeBorder

  • 方法名
void cvCopyMakeBorder(
        const CvArr *   src,     
        CvArr *         dst,
        CvPoint         offset,
        int             bordertype,
        CvScalar        value = cvScalarAll(0)
                );
  • 参数说明
  • offset 将源图像的副本放到目标图像中的位置
  • 如果核为N X N,N为奇数,那么边界在每一侧的宽度都应该是 (N-1)/2,即这幅图像比源图像宽或高 N-1。此时可以把offset设置为 CvPoint((N-1)/2, (N-1)/2 ),使得边界在每一侧都是偶数。
  • bordertype
  • IPL_BORDER_CONSTANT 固定值填充
  • IPL_BORDER_REPLICATE 行列复制
  • BORDER_REFLECT
  • BORDER_REFLECT_101
  • BORDER_WRAP
  • -

2. 示例

  • 代码
// 加载原始图像
    Mat src_door = imread("../source/door.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    imshow("源图像", src_door);

    Mat mask = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    Mat dst_replicate, dst_reflect, dst_reflect101, dst_wrap, dst_constant;
    int winsize = 40;
    copyMakeBorder(src_door, dst_replicate, winsize, winsize, winsize, winsize,
        BORDER_REPLICATE);
    copyMakeBorder(src_door, dst_reflect, winsize, winsize, winsize, winsize,
        BORDER_REFLECT);
    copyMakeBorder(src_door, dst_reflect101, winsize, winsize, winsize, winsize,
        BORDER_REFLECT_101);
    copyMakeBorder(src_door, dst_wrap, winsize, winsize, winsize, winsize,
        BORDER_WRAP);
    copyMakeBorder(src_door, dst_constant, winsize, winsize, winsize, winsize,
        BORDER_CONSTANT);

    imshow("BORDER_REPLICATE", dst_replicate);
    imshow("BORDER_REFLECT", dst_reflect);
    imshow("BORDER_REFLECT_101", dst_reflect101);
    imshow("BORDER_WRAP", dst_wrap);
    imshow("BORDER_CONSTANT", dst_constant);
  • 效果

opencv解析dcm转jpg opencv dct变换_数组_03

opencv解析dcm转jpg opencv dct变换_opencv_04

opencv解析dcm转jpg opencv dct变换_参数说明_05

opencv解析dcm转jpg opencv dct变换_卷积_06

opencv解析dcm转jpg opencv dct变换_参数说明_07

opencv解析dcm转jpg opencv dct变换_opencv_08

三、梯度和Sobel导数

  • 一般用作边缘检测
  • 一个最重要最基本的卷积就是导数的计算,通常用Sobel微分算子来表达微分;
  • Sobel并不是真正意义的导数,只是通过多项式拟合得到的结果;
  • 通常人们都用较大的核,因为较大的核有更好的逼近,同时也会使更多像素参与拟合计算。

1. opencv函数—cvSobel

  • 方法名
void Sobel (
             InputArray      src,  //输入图
             OutputArray     dst,  //输出图
             int             ddepth,//输出图像的深度
             int             dx,
             int             dy,
             int             ksize=3,
             double          scale=1,
             double          delta=0,
             int             borderType=BORDER_DEFAULT );
  • 参数说明
  • src 和 dst 是输入图像和输出图像
  • ddepth 输出图像的深度,支持如下src.depth()和ddepth的组合:
    若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
  • dx 和 dy是求导的阶数,只能为0, 1, 2
  • ksize 是方形滤波器的宽(或高)并且只能是奇数,目前支持1, 3, 5, 7
  • scale 是计算导数值时的缩放因子,默认1
  • borderType 是边界形式

2. 示例

  • 代码
// 加载原始图像
    Mat src_door = imread("../source/door.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    imshow("源图像", src_door);

    Mat dst_gradx, dst_grady;// x和y方向的求导 
    Mat abs_gradx, abs_grady;
    Mat dst_addweight;

    // x 导数
    Sobel(src_door, dst_gradx, src_door.depth(), 1, 0, 3); // Sobel检测
    convertScaleAbs(dst_gradx, abs_gradx); // 线性转换成8位无符号整形

    // y 导数
    Sobel(src_door, dst_grady, src_door.depth(), 0, 1, 3);
    convertScaleAbs(dst_grady, abs_grady);

    // 方向加权
    addWeighted(abs_gradx, 0.5, abs_grady, 0.5, 0, dst_addweight);

    imshow("x方向导数", dst_gradx);
    imshow("y方向导数", dst_grady);
    imshow("加权结果", dst_addweight);
  • 效果

opencv解析dcm转jpg opencv dct变换_opencv解析dcm转jpg_09

opencv解析dcm转jpg opencv dct变换_参数说明_10

opencv解析dcm转jpg opencv dct变换_卷积_11

opencv解析dcm转jpg opencv dct变换_opencv_12

  • (未完待续。。。)