OpenCV 기본 클래스

스윗포테이토·2022년 9월 14일
1

OpenCV

목록 보기
1/3

Point

  • 2차원 좌표 상 점을 가르킴
  • 멤버변수 x, y
  • 구체적인 자료형 표기 필요
    ex ) Point2f, Point2l 등 typedef 로 정의된 것, 혹은 Point_<type>으로 사용해야 한다.
    • Point == Point2i

Size

  • 멤버변수 width, height
  • Point와 마찬가지로 자료형 표기 필요

Rect

  • 멤버변수 x, y(좌 상단 점의 좌표), width, height
  • 산술연산
    Size 객체와 더하기(크기 변화), Point 객체와 더하기(위치 이동) 연산이 가능
  • 논리연산
    & : 교차하는 영역 반환 (교집합)
    | : 두 사각형을 포함하는 최소 사각형 반환
  • RotatedRect : 회전된 Rect 클래스
    • 멤버변수 Point2f center(중심 좌표), Size2f size, float angle
    • 멤버함수
        RotatedRect::points(Point2f pts[]) // 네 꼭짓점의 좌표
        Rect RotatedRect::boundingRect() // 객체를 포함하는 최소 사각형

Range

  • 범위 또는 구간을 표현하는 클래스
  • 멤버 변수 start, end - [start, end)

String

원래 std::string과는 별개의 cv::String 클래스 존재 -> OpenCV4.0부터 완전히 같은 클래스이다
다만 과거 코드와의 호환성을 위해서 아직 cv::String으로 사용하는 경우가 많다

cv::String = format("test%02.bmp", i); //printf와 유사한 문법 사용

Mat

Mat mtx1(4, 3, CV_32F) //행, 열, 데이터타입
Mat mtx2(Size(3, 4), CV_32F) // Size(width, height) <- 행, 열과 반대
Mat ones(3, 3, CV_64F) // 1로 채워진 3*3
Mat m2 = Mat(3, 3, CV_64F, dm) // dm(2차원 배열)의 값을 참조함 -> 객체 생성이 빠르다
  • Mat_ 클래스
    Mat_<float> mat5_(2, 3); //row, col
    mat5_ << 1,2,3,4,5,6; // 간단한 인터페이스 제공
    Mat mat5 = mat5_;	// Mat 객체로 변환

기본 연산

  • 사칙연산 나머지는 동일, * 의 경우 행렬곱 수행
    matrix1.mul(matrix2) // 각각의 요소가 곱해 짐
  • 역행렬
    matrix.inv() // 정방행렬(n*n)이 아닌 경우 오류발생
  • 전치행렬
    matrix.t() // 

멤버 변수, 함수

img.elemSize(); // 한 픽셀의 사이즈 (byte)
img.channels(); // 채널 크기 (RGB - 3, RGBA - 4)
img.rows;
img.cols;
img.step; // 가로의 실제 바이트 수

자료형

CV_(Bit Depth){U|S|F}C(Channel count)
  • CV_8UC1 - 1채널 unsigned 8bit
  • CV_8UC3 - 3채널 unsigned 8bit (RGB)

Vector to Mat

vector<float> v1;
Mat m1 = Mat(r, c, CV_32FC1);

//copy vector to Mat
memcpy(m1.data(), v1.data(), v1.size()*sizeof(float));

//copy mat to vector
v1.assign((float*)m1.datastart, (float*)m1.data);

Copy image

Mat img2 = img1; // img1과 img2가 같은 값을 가리킴 (얕은 복사)
bitwise_not(img1, img1); // img1, img2가 둘 다 반전

Mat img3 = img1.clone(); // img1를 복제

Rect r(img1.cols / 4, img1.rows / 4, img.cols / 4 * 2, img.rows / 4 * 2);
Mat img4 = img1(r).clone(); // 사각형 영역만큼 복제

Mat img5;
img1.copyTo(img5); // 복제

Mat img6;
img(r).copyTo(img5) // 사각형 영역만 복제

Mat img7(Size(img.cols * 2, img.rows), img.type());
img7.setTo(255);  // 흰색으로 초기화

img.copyTo(img7(Range::all(), Range(0, img.cols)));
img2.copyTo(img7(Ragne::all(), Range(img2.cols, 2 * img2.cols)));

Mat roi(img, r); // (사각형 영역에 속한) 원본 값을 참조 -> 얕은 복사
Mat img2 = img1(Rect(220, 120, 340, 240)); // 얕은 복사
Mat img3 = img1(Range(120, 120+340), Range(220, 220+240)); // 얕은 복사

// 깊은 복사 (독립된 메모리 영역 보장)
mat1.clone();

데이터 접근

//0. data - 직접 접근 (권장 X)
    // using data
    for (int i = 0; i < img.rows; i++) {
        for (int j = 0; j < img.cols; j++) {
            int address = i * img.step + j * img.elemSize();
            for (int k = 0; k < 3; k++) {
                img.data[address + k] = 255 - img.data[address + k];
            }
        }
    }

//1. at - 가장 안정적이지만 느림
matrix.at<uchar>(0, 0);
    // using at
    for (int i = img.rows / 10 * 2; i < img.rows / 10 * 3; i++) {
        for (int j = 0; j < img.cols; j++) {
            for (int k = 0; k < 3; k++) {
                // Vec3b -> unsigned char - 3 channels
                img.at<Vec3b>(i, j)[k] = 255 - img.at<Vec3b>(i, j)[k];
            }
        }
    }

//2. ptr - 1보다는 빠른 속도, 행 단위 접근에 유리
matrix.ptr<uchar>(0); // 첫번째 행 포인터
    // using ptr
    for (int i = img.rows / 10 * 5; i < img.rows / 10 * 6; i++) {
        Vec3b* ptr = img.ptr<Vec3b>(i);  // i번째 행
        for (int j = 0; j < img.cols; j++) {
            // 방법1
            unsigned char b1 = ptr[j][0];
            unsigned char g1 = ptr[j][1];
            unsigned char r1 = ptr[j][2];

            // 방법2
            Vec3b bgr = ptr[j];  // i행 j열
            unsigned char b2 = bgr[0];
            unsigned char g2 = bgr[1];
            unsigned char r2 = bgr[2];

            ptr[j] = Vec3b(MAX - b1, MAX - g1, MAX - r1);
        }
    }
//3. MatIterator
    // using iterator
    for (MatIterator_<Vec3b> itd = img.begin<Vec3b>(); itd != img.end<Vec3b>(); itd++) {
        Vec3b bgr = (*itd);
        for (int k = 0; k < 3; k++) {
            (*itd)[k] = MAX - bgr[k];
        }
    }

Vec

행벡터 + 열벡터

Vec<uchar, 3> - RGB 한 픽셀을 많이 나타냄
Vec<num-of-data>{b|s|w|i|f|d} // b = uchar

// ex)
Vec<uchar, 3> = Vec3b;

Scalar

  • 4채널 이하의 영상에서 픽셀값을 표현하는 용도로 사용됨 (BGRA, BGR, grayscaled)
  • Scalar_ 클래스는 Vec 클래스를 상속받아 만들어짐

InputArray, OutputArray, InputOutputArray

_InputArray

  • Mat, vector 등 다양한 타입에서 생성될 수 있는 인터페이스 클래스
  • 코드 구현 편의상 사용되고, 사용자의 명시적 선언 금지
  • 비어 있는 행렬을 전달할 경우 noArray(), Mat() 등 전달
  • 내부에서는 getMat() 함수를 사용하여 Mat 타입 변환
profile
나의 삽질이 미래의 누군가를 구할 수 있다면...

0개의 댓글