InputArray와 OutputArray

OpenCV에서 입력과 출력에 사용되는 프록시 클래스이다. 다음과 같이 OutputArray는 InputArray를 상속 받아서 만들어진 객체이고, IunputOutputArray는 OutputArray를 상속 받아서 만들어진 객체이다. 때문이 이들 간에는 상속 관계에 의한 호환이 가능하다.

class CV_EXPORTS _InputArray {...}
class CV_EXPORTS _OutputArray : public _InputArray {...}
class CV_EXPORTS _InputOutputArray : public _OutputArray {...}

Mat 클래스

행렬을 표현하기 위한 용도로 단일 채널 또는 n차원의 채널을 나타낼 수 있다. Mat 클래스는 정수, 실수 또는 복소수 벡터 및 행렬, 회색조 또는 컬러 이미지, 복셀 볼륨, 벡터 필드, 포인트 클라우드, 텐서, 히스토그램을 저장하는데 사용된다.

Mat class의 데이터 타입

재정의 이름의미Depth_mask범위
CV_8Uunsigned char 8-bit unsigned integers00 ~ 255
CV_8Ssigned char 8-bit signed integers1-128 ~ 127
CV_16Uunsigned short 16-bit unsigned integers20 ~ 65535
CV_16Ssigned short 16-bit signed integers3-32768 ~ 32767
CV_32Sint 32-bit signed integers4-2147483648
CV_32Ffloat 32-bit floating-point numbers5-FLT_MAX ~ FLT_MAX, INF, NAN
CV_64Fdouble 64-bit floating-point numbers6-DBL_MAX ~ DBL_MAX, INF, NAN
CV_16Ffloat16 16-bit floating-point numbers7-OpenCV 4부터 지원 / 정보 없음

Mat 객체 생성 방법

Mat class는 다양한 생성자와 초기화 방법이 구현되어 있다. 가장 먼저 빈 객체를 생성하는 방법이다. 카메라로 부터 받을 데이터를 저장하는 용도로 사용될 수 있다.

Mat img1;
// empty matrix

다음 방법은 행렬의 크기와 저장할 데이터의 타입을 지정하여 객체를 생성하는 방법이다. 정수 타입의 인자로 Mat 객체를 생성하는 경우 height, width 순서대로 넣어주어야 한다.

Mat img2(480, 640, CV_8UC1);
// unsigned char, 1-channel
Mat img3(480, 640, CV_8UC3);		
// unsigned char, 3-channels

정수 형태의 인자 대신 Size() 객체를 이용해서 초기화가 가능하다. Size()는 영상 또는 사각형의 크기를 정의위해 사용되는 템플릿 클래스이다. 이때 위 방법과 달리 width, height 순으로 입력할 수 있다.

Mat img4(Size(640, 480), CV_8UC3);	
// Size(width, height)

Mat 객체 초기화 방법

먼저 생성과 동시에 데이터를 초기화 하는 방법이다. Scalar()는 크기 4의 double 타입의 배열을 가지고 있는 클래스이다. 각각 영상의 색을 나타내는 B G R A을 저장하며, 배열과 마찬가지로 []연산자를 통해 데이터에 접근이 가능하다.

Mat img5(480, 640, CV_8UC1, Scalar(128));		
// initial values, 128
Mat img6(480, 640, CV_8UC3, Scalar(0, 0, 255));	
// initial values, red
Mat mat5 = (Mat_<float>(2, 3) << 1, 2, 3, 4, 5, 6);
Mat mat6 = Mat_<uchar>({2, 3}, {1, 2, 3, 4, 5, 6});

Mat의 멤버 함수를 이용한 초기화 방법이다. zeros, ones, eye는 각각 행렬 전체를 0이나 1로 혹은 단위 행렬 형태로 초기화 하는 기능을 수행한다.

Mat mat1 = Mat::zeros(3, 3, CV_32SC1);	
// 0's matrix
Mat mat2 = Mat::ones(3, 3, CV_32FC1);	
// 1's matrix
Mat mat3 = Mat::eye(3, 3, CV_32FC1);	
// identity matrix

이미 생성된 객체에 데이터를 추가하거나, 다른 크기, 데이터 타입의 형태로 변수를 초기화하는 방법이다.

mat4.create(256, 256, CV_8UC3);	// uchar, 3-channels
mat5.create(4, 4, CV_32FC1);	// float, 1-channel
mat4 = Scalar(255, 0, 0);
mat5.setTo(1.f);

마지막으로 1차원 배열을 통해 데이터를 초기화 할 수 있다. 다만 행렬 전체 크기와 배열의 크기가 일치해야 한다.

float data[] = {1, 2, 3, 4, 5, 6};
Mat mat4(2, 3, CV_32FC1, data);

Mat 객체의 유용한 멤버 함수들

Mat::zeros()

//! Matlab-style matrix initialization
Mat::zeros(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::zeros(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::zeros(int ndims, const int* sz, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::zeros(int rows, int cols, int type) { return zeros(rows, cols, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload
Mat::zeros(Size size, int type) { return zeros(size, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload
Mat::zeros(int ndims, const int* sz, int type) { return zeros(ndims, sz, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload

Mat::ones()

Mat::ones(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::ones(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::ones(int ndims, const int* sz, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::ones(int rows, int cols, int type) { return ones(rows, cols, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload
Mat::ones(Size size, int type) { return ones(size, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload
Mat::ones(int ndims, const int* sz, int type) { return ones(ndims, sz, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload

Mat::eye()

Mat::eye(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::eye(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
Mat::eye(int rows, int cols, int type) { return eye(rows, cols, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload
Mat::eye(Size size, int type) { return eye(size, type, USAGE_DEFAULT); }  // OpenCV 5.0: remove abi compatibility overload

mat.depth()

cout << mat.depth() << endl;
// 행렬의 원소의 자료형을 반환하는 매크로 상수이다.
// 8:1byte, U: unsigned, S: signed
// #define CV_8U   0
// #define CV_8S   1
// #define CV_16U  2
// #define CV_16S  3
// #define CV_32S  4
// #define CV_32F  5
// #define CV_64F  6
// #define CV_16F  7

mat.channels()

cout << mat.channels() << endl;
// 이미지의 채널 수를 출력하는 매크로 상수이다.
// 흑백의 경우 1채널, 컬러 영상의 경우 3채널이다.

mat.type()

cout << mat.type() << endl;
// 행렬의 깊이와 채널을 한 번에 출력하는 매크로 상수이다.

Vec 클래스

벡터(vector)는 같은 동일한 타입의 데이터를 여러개 묶어놓은 형태로 저장하는 클래스이다. []에 대한 연산자 오버로딩을 지원하기 때문에 행렬과 동일하게 데이터 원소 접근이 가능하다. 또한 << 연사자를 오버로딩 하고 있기 때문에 std::cout을 통해 출력이 가능하다.

template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>
{
public:
    ...
    //! default constructor
    Vec();
    Vec(_Tp v0); //!< 1-element vector constructor
    Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13); //!< 14-element vector constructor
    explicit Vec(const _Tp* values);

    //! per-element multiplication
    Vec mul(const Vec<_Tp, cn>& v) const;

    //! conjugation (makes sense for complex numbers and quaternions)
    Vec conj() const;

    /*!
      cross product of the two 3D vectors.

      For other dimensionalities the exception is raised
    */
    Vec cross(const Vec& v) const;
    //! conversion to another data type
    template<typename T2> operator Vec<T2, cn>() const;

    /*! element access */
    const _Tp& operator [](int i) const;
    _Tp& operator[](int i);
    const _Tp& operator ()(int i) const;
    _Tp& operator ()(int i);
    ...
};

자주 사용되는 Vec 클래스의 경우 Vec2(데이터의 수)b(데이터 타입) 으로 사용할 수 있도록 정의되어 있다.

typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;

typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;

typedef Vec<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;

typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;

typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;

typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

Scalar 클래스

크기가 4인 double 타입의 배열을 멤버 변수로 가지고 있는 클래스이다. 4채널 이하의 영상 데이터의 한 픽셀을 표현하는데 사용된다. [] 연사자를 오버로딩 하고있어 행렬과 동일한 방법으로 데이터 원소 접근이 가능하다.

template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>
{
public:
    //! default constructor
    Scalar_();
    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
    Scalar_(_Tp v0);

    Scalar_(const Scalar_& s);
    Scalar_(Scalar_&& s) CV_NOEXCEPT;

    Scalar_& operator=(const Scalar_& s);
    Scalar_& operator=(Scalar_&& s) CV_NOEXCEPT;

    template<typename _Tp2, int cn>
    Scalar_(const Vec<_Tp2, cn>& v);

    //! returns a scalar with all elements set to v0
    static Scalar_<_Tp> all(_Tp v0);

    //! conversion to another data type
    template<typename T2> operator Scalar_<T2>() const;

    //! per-element product
    Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;

    //! returns (v0, -v1, -v2, -v3)
    Scalar_<_Tp> conj() const;

    //! returns true iff v1 == v2 == v3 == 0
    bool isReal() const;
};

기본적으로 double 데이터 타입으로 정의되어 있다.

typedef Scalar_<double> Scalar;

행렬 연산 관련된 함수

{: .note } mask 인자의 경우 0 이 아닌 위치의 데이터 원소들만 연산에 사용한다.

sum()

행렬의 합을 구하는 함수이다. Scalar 데이터 타입의 각 채널에 대한 행렬의 합을 반환한다.

Scalar sum(InputArray src);

mean()

평균을 구하는 함수이다. sum 함수와 마찬가지로 각 채널에 대한 평균을 Scalar 형태의 데이터 타입을 반환한다.

Scalar mean(InputArray src, InputArray mask = noArray());

minMaxLoc()

void minMaxLoc(InputArray src, CV_OUT double* minVal,
                CV_OUT double* maxVal = 0, CV_OUT Point* minLoc = 0,
                CV_OUT Point* maxLoc = 0, InputArray mask = noArray());

converTo()

void GpuMat::convertTo(OutputArray dst, int rtype, double alpha, double beta) const
{
    convertTo(dst, rtype, alpha, beta, Stream::Null());
}

normalize()

void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0,
                int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());
enum NormTypes {
                NORM_INF       = 1,
                NORM_L1        = 2,
                NORM_L2        = 4,
                NORM_L2SQR     = 5,
                NORM_HAMMING   = 6,
                NORM_HAMMING2  = 7,
                NORM_TYPE_MASK = 7, //!< bit-mask which can be used to separate norm type from norm flags
                NORM_RELATIVE  = 8, //!< flag
                NORM_MINMAX    = 32 //!< flag
               };

Exampl code

void ex_ops(){
    uchar data[] = {1,2,3,4,5,6};
    Mat mat(2,3, CV_8UC1, data);
    cout << mat << endl;

    int ret_sum = (int)sum(mat)[0];
    cout << ret_sum << endl;

    double ret_mean = (double)mean(mat)[0];
    cout << ret_mean << endl;

    double minval, maxval;
    Point minloc, maxloc;
    minMaxLoc(mat, &minval, &maxval, &minloc, &maxloc);
    cout << format("%f %f (%d, %d) (%d, %d)", 
    minval, maxval, 
    minloc.x, minloc.y, 
    maxloc.x, maxloc.y) << endl;
    
    Mat cvt_mat;
    mat.convertTo(cvt_mat, CV_32FC1, 0.1, -5);
    cout << cvt_mat << endl;
    
    uchar maks_data[] = {1,1,1,1,1,0};
    Mat mask(2,3, CV_8UC1, maks_data);
    cout << mask << endl;

    Mat norm_mat;
    normalize(mat, norm_mat, 0, 1, NORM_MINMAX, CV_32FC1, mask);
    cout << norm_mat << endl;

}
[  1,   2,   3;
   4,   5,   6]
21
3.5
1.000000 6.000000 (0, 0) (2, 1)
[-4.9000001, -4.8000002, -4.6999998;
 -4.5999999, -4.5, -4.4000001]
[  1,   1,   1;
   1,   1,   0]
[0, 0.25, 0.5;
 0.75, 1, 0]

Point_ 클래스

2차원 점의 좌표를 표현하기 위한 템플릿 클래스이다. 좌표를 나타내는 x와 y 두 멤버 변수를 가지고 있다. 또한 내적을 구하는 dot() 함수, double 타입의 내적을 구하는 ddot() 함수, 외적을 구하는 cross(), 사격형의 겹치는 부분이 있는지를 확인하는 inside()로 4개의 멤버 함수로 구성된다.

template<typename _Tp> class Point_
{
public:
    Point_();
    Point_(_Tp _x, _Tp _y);
    ...
    _Tp dot(const Point_& pt) const;
    //! dot product computed in double-precision arithmetics
    double ddot(const Point_& pt) const;
    //! cross-product
    double cross(const Point_& pt) const;
    //! checks whether the point is inside the specified rectangle
    bool inside(const Rect_<_Tp>& r) const;
    _Tp x; //!< x coordinate of the point
    _Tp y; //!< y coordinate of the point
};

자주 사용되는 데이터 타입에 대해서 아래와 같이 정의되어 있어 이를 사용해도 된다.

typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;

다양한 사칙 연산에 대한 연산자 오버로딩과 std::cout 출력을 위한 << 연산자 오버로딩을 지원한다.

pt1 = pt2 + pt3;
pt1 = pt2 - pt3;
pt1 = pt2 * a;
pt1 = a * pt2;
pt1 = pt2 / a;
pt1 += pt2;
pt1 -= pt2;
pt1 *= a;
pt1 /= a;
double value = norm(pt); // L2 norm
pt1 == pt2;
pt1 != pt2;

Size_ 클래스

영상 또는 사각형의 크기를 표현하기 위한 템플릿 클래스이다. width, height 두 멤버 변수를 가지고 있으며, 면적을 구하는 area() 함수가 구현되어 있다.

template<typename _Tp> class Size_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Size_();
    Size_(_Tp _width, _Tp _height);
    ...
    _Tp area() const;
    //! aspect ratio (width/height)
    double aspectRatio() const;
    //! true if empty
    bool empty() const;

    //! conversion of another data type.
    template<typename _Tp2> operator Size_<_Tp2>() const;

    _Tp width; //!< the width
    _Tp height; //!< the height
};

point_ 클래스와 마찬가지로 사칙 연사에 대한 오버로딩과 << 연산자에 대한 오버로딩을 지원한다.

또한 자주 사용되는 데이터 타입에 대해서 다음과 같이 정의되어 있다.

typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;

Rect_ 클래스

2차원의 사각형 표현을 위함 템플릿 클래스이다. 좌상단과 넓이와 높이를 가지고 정의되며, x, y, width, height 멤버 변수를 가지고 있다. 또한 사각형의 좌상단, 우하단을 반환하는 tl(), br(), 점이 사각형 안에 존재하는지를 확인해 주는 contains() 멤버 함수가 정의되어 있다.

template<typename _Tp> class Rect_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Rect_();
    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
    ...
    //! the top-left corner
    Point_<_Tp> tl() const;
    //! the bottom-right corner
    Point_<_Tp> br() const;

    //! size (width, height) of the rectangle
    Size_<_Tp> size() const;
    //! area (width*height) of the rectangle
    _Tp area() const;
    //! true if empty
    bool empty() const;

    //! conversion to another data type
    template<typename _Tp2> operator Rect_<_Tp2>() const;

    //! checks whether the rectangle contains the point
    bool contains(const Point_<_Tp>& pt) const;

    _Tp x; //!< x coordinate of the top-left corner
    _Tp y; //!< y coordinate of the top-left corner
    _Tp width; //!< width of the rectangle
    _Tp height; //!< height of the rectangle
};

자주 사용되는 데이터 타입에 대해서 다음과 같이 정의되어 있다.

typedef Rect_<int> Rect2i;
typedef Rect_<float> Rect2f;
typedef Rect_<double> Rect2d;
typedef Rect2i Rect;

Rect 객체와 Size, Point 객체의 덧셈과 뺼셈, Rect 객체 간의 논리 연산을 지원한다.

Rect rc1; // [0 x 0 from (0, 0)]
Rect rc2(10, 10 60, 40); // [60 x 40 from (10, 10)]
Rect rc3 = rc1 + Size(50, 40); // [50 x 40 from (0, 0)]
Rect rc4 = rc2 + Point(10, 10); // [60 x 40 from (20, 20)]
Rect rc5 = rc3 & rc4; // [30 x 20 from (20, 20)]
Rect rc6 = rc3 | rc4; // [80 x 60 from (0, 0)]

Range 클래스

정수 데이터 타입의 범위를 나타내는 클래스이다. 시작과 끝을 나타내는 두 멤버 변수를 가지고 있으며, 이때 시작은 범위에 포함되고 끝은 포함되지 않는다(e.g.(시작:끝]).

class CV_EXPORTS Range
{
public:
    Range();
    Range(int _start, int _end);
    int size() const;
    bool empty() const;
    static Range all();

    int start, end;
};

0개의 댓글

Powered by GraphCDN, the GraphQL CDN