OpenCV 편하게 사용하기 (팁)

프로그래밍/opencv 2013. 2. 13. 12:18

1. OpenCV 링크 편하게 하기

2. OpenCV 행렬 원소접근 편하게 하기

3. TypedMat 사용법




1. OpenCV 링크 편하게 하기


OpenCV를 이용한 프로그램을 작성하려면 필요한 헤더화일 및 라이브러리 파일들을 링크시키기 위해 이런 저런 세팅을 해 주어야 합니다.


저는 OpenCV 헤더파일 및 라이브러리 파일들을 다음과 같이 하나의 파일에 모두 넣어놓고 사용합니다 (물론 프로젝트 설정에서 opencv include directory, opencv library directory 는 별도로 설정해 주어야 합니다).


이제 opencv를 사용하고 싶으면 아래 파일만 include하면 ok입니다.


<use_opencv.h>

#ifndef __USE_OPENCV_H__

#define __USE_OPENCV_H__


#include "opencv2/highgui/highgui.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/core/core.hpp"

#include "opencv2/core/core_c.h"

#include "opencv2/highgui/highgui_c.h"

#include "opencv2/imgproc/imgproc_c.h"

#include "opencv2/video/video.hpp"

#include "opencv2/nonfree/nonfree.hpp"

#include "opencv2/videostab/videostab.hpp"

#include "opencv2/features2d/features2d.hpp"

#include "opencv2/objdetect/objdetect.hpp"

#include "opencv2/flann/miniflann.hpp"

#include "opencv2/photo/photo.hpp"

#include "opencv2/calib3d/calib3d.hpp"

#include "opencv2/ml/ml.hpp"

#include "opencv2/contrib/contrib.hpp"

#include "opencv2/ts/ts.hpp"

#include "opencv2/stitching/stitcher.hpp"

#include "opencv2/legacy/legacy.hpp"


#ifdef _DEBUG

      #pragma comment(lib,"opencv_core241d.lib")

      #pragma comment(lib,"opencv_highgui241d.lib")

      #pragma comment(lib,"opencv_imgproc241d.lib")

      #pragma comment(lib,"opencv_video241d.lib")

      #pragma comment(lib,"opencv_nonfree241d.lib")

      #pragma comment(lib,"opencv_videostab241d.lib")

      #pragma comment(lib,"opencv_features2d241d.lib")

      #pragma comment(lib,"opencv_objdetect241d.lib")

      #pragma comment(lib,"opencv_flann241d.lib")

      #pragma comment(lib,"opencv_photo241d.lib")

      #pragma comment(lib,"opencv_calib3d241d.lib")

      #pragma comment(lib,"opencv_ml241d.lib")

      #pragma comment(lib,"opencv_contrib241d.lib")

      #pragma comment(lib,"opencv_ts241d.lib")

      #pragma comment(lib,"opencv_stitching241d.lib")

      #pragma comment(lib,"opencv_legacy241d.lib")

#else

      #pragma comment(lib,"opencv_core241.lib")

      #pragma comment(lib,"opencv_highgui241.lib")

      #pragma comment(lib,"opencv_imgproc241.lib")

      #pragma comment(lib,"opencv_video241.lib")

      #pragma comment(lib,"opencv_nonfree241.lib")

      #pragma comment(lib,"opencv_videostab241.lib")

      #pragma comment(lib,"opencv_features2d241.lib")

      #pragma comment(lib,"opencv_objdetect241.lib")

      #pragma comment(lib,"opencv_flann241.lib")

      #pragma comment(lib,"opencv_photo241.lib")

      #pragma comment(lib,"opencv_calib3d241.lib")

      #pragma comment(lib,"opencv_ml241.lib")

      #pragma comment(lib,"opencv_contrib241.lib")

      #pragma comment(lib,"opencv_ts241.lib")

      #pragma comment(lib,"opencv_stitching241.lib")

      #pragma comment(lib,"opencv_legacy241.lib")

#endif  // _DEBUG


#endif  // __USE_OPENCV_H__



2. OpenCV 행렬 원소접근 편하게 하기


저는 opencv를 사용하면서 가장 불편한 점 중의 하나가 행렬(Mat)의 원소를 접근하는 것입니다. 특히나 영상처리를 하다보면 이미지 픽셀 단위로 처리를 할 필요가 있는데 OpenCV가 제공하는 원소 접근 방법(at)은 상당히 불편합니다.


그래서 아래와 같이 Wrapper class를 하나 작성해 보았습니다.


template<class T>

class TypedMat

{

        T** m_pData;

        int m_nChannels;

        int m_nRows, m_nCols;


public:

        TypedMat():m_pData(NULL),m_nChannels(1),m_nRows(0),m_nCols(0){}

        ~TypedMat(){if(m_pData) delete [] m_pData;}


        // OpenCV Mat 연동 (메모리 공유)

        void Attach(const cv::Mat& m);

        void Attach(const IplImage& m);

        TypedMat(const cv::Mat& m):m_pData(NULL),m_nChannels(1),m_nRows(0),m_nCols(0) { Attach(m);}

        TypedMat(const IplImage& m):m_pData(NULL),m_nChannels(1),m_nRows(0),m_nCols(0) { Attach(m);}

        const TypedMat & operator =(const cv::Mat& m){ Attach(m); return *this;}

        const TypedMat & operator =(const IplImage& m){ Attach(m); return *this;}


        // 행(row) 반환

        T* GetPtr(int r)

        { assert(r>=0 && r<m_nRows); return m_pData[r];}


        // 연산자 중첩 (원소접근) -- 2D

        T * operator [](int r)

        { assert(r>=0 && r<m_nRows); return m_pData[r];}


        const T * operator [](int r) const

        { assert(r>=0 && r<m_nRows); return m_pData[r];}


        // 연산자 중첩 (원소접근) -- 3D

        T & operator ()(int r, int c, int k)

        { assert(r>=0 && r<m_nRows && c>=0 && c<m_nCols && k>=0 && k<m_nChannels); return m_pData[r][c*m_nChannels+k];}


        const T operator ()(int r, int c, int k) const

        { assert(r>=0 && r<m_nRows && c>=0 && c<m_nCols && k>=0 && k<m_nChannels); return m_pData[r][c*m_nChannels+k];}

};


template<class T>

void TypedMat<T>::Attach(const cv::Mat& m)

{

        assert(sizeof(T)==m.elemSize1());


        m_nChannels = m.channels();

        m_nRows = m.rows;

        m_nCols = m.cols;

        

        if(m_pData) delete [] m_pData;

        m_pData = new T * [m_nRows];

        for(int r=0; r<m_nRows; r++)

        {

                m_pData[r] = (T *)(m.data + r*m.step);

        }

}


template<class T>

void TypedMat<T>::Attach(const IplImage& m)

{

        assert(sizeof(T) == m.widthStep/(m.width*m.nChannels));


        m_nChannels = m.nChannels;

        m_nRows = m.height;

        m_nCols = m.width;

        

        if(m_pData) delete [] m_pData;

        m_pData = new T * [m_nRows];

        for(int r=0; r<m_nRows; r++)

        {

                m_pData[r] = (T *)(m.imageData + r*m.widthStep);

        }

}



use_opencv.h



3. TypedMat 사용법


메모리를 공유하기 때문에 추가적인 연산 로드는 거의 없습니다. IplImage, cv::Mat을 지원합니다. 사용법은 다음과 같습니다.


* 이미지의 경우

#include "use_opencv.h"


Mat image;


TypedMat<unsigned char> tm = image;    // 연결방법 1

TypedMat<unsigned char> tm; tm = image;    // 연결방법 2

TypedMat<unsigned char> tm; tm.Attach(image);    // 연결방법 3


// image가 1채널 grayscale 이미지일 경우

tm[y][x] = 100;    // (x,y)의 픽셀값을 100으로 설정


// image가 3채널 color 이미지일 경우

tm(y,x,0) = 100;    // (x,y)의 픽셀의 blue값을 100으로 설정

tm(y,x,1) = 200;    // (x,y)의 픽셀의 green값을 200으로 설정

tm(y,x,2) = 50;    // (x,y)의 픽셀의 red값을 50으로 설정


* 2D float 타입 행렬의 경우

#include "use_opencv.h"

Mat f_image;

TypedMat<float> fm = f_image;

fm[y][x] = 3.12f;


by 다크 프로그래머