OpenCV学习指南(一)图像数据读取

前言

  OpenCV作为一个机器视觉的库,对机器视觉的应用程序开发者或者机器视觉的SDK开发者而言,了解OpenCV是十分有必要的。读者可以通过OpenCV官方使用在线文档了解OpenCV的函数。如果你需要搭建相关环境,可参照笔者的另一篇文章Win10系统下搭建OpenCV环境
  准备好后,可以在vs的工程下看到OpenCV的源码,类似于这样
在这里插入图片描述

读取图像源码介绍

  这里通过介绍imread函数和GaussianBlur函数,简单说明下OpenCV的源码
  imread函数是十分常用的,能够用于读取多种图片,其源码可以在module模块下的opencv_imgcodecs的src下
在这里插入图片描述

Mat imread( const String& filename, int flags )
{
    CV_TRACE_FUNCTION();

    /// create the basic container
    Mat img;

    /// load the data
    imread_( filename, flags, img );

    /// optionally rotate the data if EXIF' orientation flag says so
    if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
    {
        ApplyExifOrientation(filename, img);
    }

    /// return a reference to the data
    return img;
}

  imread是一个用于图片读取的函数,但OpenCV的开发者在其中倾注的心血却不容小觑。一方面OpenCV会加入大量的类似于__FILE__和__LINE__之类的宏名以帮助调试;另一方面,OpenCV为读者添加了多种图片的格式的读取方案。但如果你需要用到一些特殊的图片格式,例如医学领域常用的dcm图,那你就很可能需要自己动手来实现,不过OpenCV的Mat数据结构也是很好的图像处理工具,要知道,例如Qt的QImage以及Halcon的图像都是有做大小限制的,而Mat是支持大图的。
  通过在线文章,则能够很好的了解函数的功能
在这里插入图片描述
  值得注意的是,OpenCV的imread默认读取采图,flags = -1,表示格式不变,0表示以黑白图读取。

OpenCV的优化

  以高斯滤波函数为例,可以看到OpenCV的开发者做的许多优化

void GaussianBlur(InputArray _src, OutputArray _dst, Size ksize,
                  double sigma1, double sigma2,
                  int borderType)
{
    CV_INSTRUMENT_REGION();

    int type = _src.type();
    Size size = _src.size();
    _dst.create( size, type );

    if( (borderType & ~BORDER_ISOLATED) != BORDER_CONSTANT &&
        ((borderType & BORDER_ISOLATED) != 0 || !_src.getMat().isSubmatrix()) )
    {
        if( size.height == 1 )
            ksize.height = 1;
        if( size.width == 1 )
            ksize.width = 1;
    }

    if( ksize.width == 1 && ksize.height == 1 )
    {
        _src.copyTo(_dst);
        return;
    }

    bool useOpenCL = (ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 &&
               ((ksize.width == 3 && ksize.height == 3) ||
               (ksize.width == 5 && ksize.height == 5)) &&
               _src.rows() > ksize.height && _src.cols() > ksize.width);
    CV_UNUSED(useOpenCL);

    int sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);

    Mat kx, ky;
    createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);

    CV_OCL_RUN(useOpenCL, ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType));

    CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),
               ocl_sepFilter2D(_src, _dst, sdepth, kx, ky, Point(-1, -1), 0, borderType))

    Mat src = _src.getMat();
    Mat dst = _dst.getMat();

    Point ofs;
    Size wsz(src.cols, src.rows);
    if(!(borderType & BORDER_ISOLATED))
        src.locateROI( wsz, ofs );

    CALL_HAL(gaussianBlur, cv_hal_gaussianBlur, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn,
             ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
             sigma1, sigma2, borderType&~BORDER_ISOLATED);

    CV_OVX_RUN(true,
               openvx_gaussianBlur(src, dst, ksize, sigma1, sigma2, borderType))

    CV_IPP_RUN_FAST(ipp_GaussianBlur(src, dst, ksize, sigma1, sigma2, borderType));

    if(sdepth == CV_8U && ((borderType & BORDER_ISOLATED) || !_src.getMat().isSubmatrix()))
    {
        std::vector<ufixedpoint16> fkx, fky;
        createGaussianKernels(fkx, fky, type, ksize, sigma1, sigma2);
        if (src.data == dst.data)
            src = src.clone();
        CV_CPU_DISPATCH(GaussianBlurFixedPoint, (src, dst, (const uint16_t*)&fkx[0], (int)fkx.size(), (const uint16_t*)&fky[0], (int)fky.size(), borderType),
            CV_CPU_DISPATCH_MODES_ALL);
        return;
    }

    sepFilter2D(src, dst, sdepth, kx, ky, Point(-1, -1), 0, borderType);
}

  通过高斯滤波的源码,我们可以发现,opencv中有对代码做一些加速的操作,比如IPP等。笔者比较青睐的Cuda加速方式,在OpenCV的源码中也能找到许多实例。

关于机器视觉库

  OpenCV是使用广泛的机器视觉库,但有一些视觉库在算法优化上走得比OpenCV更靠前,比如Halcon和matlab的mVision等。OpenCV最大的好处是开源且应用广泛,很多培训机构一股脑的推销他们的高价OpenCV课程,这些课程动辄上万,这是一种不负责任的行为。

关于学习OpenCV

  对于Cpp功底不是那么好的同学(写过一定代码,完整读过三本以上的cpp书籍),建议使用Python学习OpenCV。Python伊甸园的OpenCV处理图像会是一个不错的入门课程;CPP版本的OpenCV其核心的数据结构是Mat,而python版本的OpenCV其核心是numpy,同样,也为您准备好了相应的numpy课程。如果你的Python功底也不是很好的话,那么可以考虑这份Python入门课程

作者说

  如有错误之处,欢迎批评指正。如果你认为咨询我是有必要的,我的邮箱是[email protected];如果你认为打赏我是有必要的,我的支付宝账号是[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章