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]

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