[컴퓨터 비전] 05 Mat operator

이찬영·2024년 2월 17일
0

컴퓨터 비전

목록 보기
4/20

[컴퓨터비전 STUDY / KOCW 한동대학교 황성수 교수님 강의 Review]

Mat Operator

색 공간으로 변환하는 메소드는 다음과 같다.

void cvtColor(Mat src, Mat dst, int code, int dstCn =0)

한 색 공간을 다른 색 공간으로 이미지 frame을 변환한다.

src는 입력 mat, dst는 결과 mat, code는 변환 종류를 나타내며, dstCn은 destination channel number을 나타낸다.

  • Code : CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2YCrCb, CV_BGR2Lab...

다음은 다채널 array를 별도의 단일 채널 array로 분리하는 메소드이다.

void split(Mat src, Mat* mv)

src는 입력 mat, mv는 src.channels()와 일치해야 한다. (최소 3이상이어야 함)
mv[c][l] = src[l]*


다음은 split와 반대되는 기능을 수행하는 메소드로, 여러 개 channel의 영상이 하나로 합쳐진다.

merge(InputArrayOfArray mv, OutputArray dst)

mvs는 입력 mat로 크기와 깊이가 같아야 하며, dst는 mv[0]과 동일한 크기와 깊이의 출력 배열이다.


EX

 int main() {
	 Mat image, image_YUV, dst;
 	 // YUV 색공간으로 분리된 각 채널(Y, U, V)을 저장할 벡터
     vector<Mat> yuv_channels(3);
 	
  	// lena.png를 불러와 image 변수에 저장함  
 	image = imread("lena.png");
 	
    // 색공간을 BGR에서 YUV로 변환하고, 그 결과를 image_YUV에 저장
    cvtColor(image, image_YUV, CV_BGR2YUV);
 	
    // image_YUV을 Y, U, V 채널로 분리하여 yuv_channels 벡터에 저장함
 	split(image_YUV, yuv_channels);
 	
    // 분리된 YUV 채널을 다시 병합하여 dst에 저장
 	merge(yuv_channels, dst);
 	
 	imshow("input image", image);
 	imshow("Y", yuv_channels[0]);	// Y 채널을 "Y"라는 윈도우에 표시
 	imshow("U", yuv_channels[1]);	// U 채널을 "U"라는 윈도우에 표시
 	imshow("V", yuv_channels[2]);	// V 채널을 "V"라는 윈도우에 표시
    
    // 병합된 YUV 이미지를 "YUV image"라는 윈도우에 표시
 	imshow("YUV image", dst);
 
 	waitKey(0);
 	return 0;
 }

위의 코드를 실행하면 다음과 같은 결과가 나타난다.


ROI (Region of Interest)

ROI는 '관심 영역'이라는 말로, 그림이나 사진에서 우리가 관심있는 영역을 잘라낸 것을 의미한다.

입력 영상이 아무리 커도, ROI로 연산량을 줄일 수 있다는 장점이 있다.

마치 다음과 같다.

EX 1

 int main() {
 	// "lena.png" 이미지 파일을 불러와 Mat 타입의 변수 image에 저장
 	Mat image = imread("lena.png");
    // 좌상단 (100, 30), 너비 250, 높이 300 사각형을 정의함
 	Rect rect(100, 30, 250, 300);
    // image에서 정의된 rect 사각형에 해당하는 영역을 추출하여 rect_roi에 저장
 	Mat rect_roi = image(rect);
    // "rectROI" 윈도우에 이미지 표시
 	imshow("rectROI", rect_roi);
 
 	waitKey(0);
 }

EX 2

 int main() {
 	// "lena.png" 이미지를 불러와 Mat 타입의 image 변수에 저장
 	Mat image = imread("lena.png");
 	Mat poly_roi;
    // 원본 이미지와 동일한 크기와 타입의 행렬을 생성, 
    // 모든 값을 0으로 초기화하여 다각형 마스크를 준비
 	Mat poly_mask= Mat::zeros(image.size(), image.type());
 	
    // 4개의 점으로 구성된 하나의 다각형을 구성하는 점들의 배열을 선언
 	Point poly[1][4];
    // 좌표 저장
 	poly[0][0] = Point(226, 100);
 	poly[0][1] = Point(286, 100);
 	poly[0][2] = Point(316, 300);
 	poly[0][3] = Point(196, 300);
 	// poly 배열에서 다각형의 꼭짓점을 가리키는 포인터 배열을 초기화
    const Point* ppt[1] = { poly[0] };
    // 다각형을 구성하는 점의 개수를 나타내는 배열을 초기화
 	int npt[] = { 4 };
 	
    // 관심 영역 추출
 	// function that draws polygon with given points, 다각형 형태와 크기를 지정
 	fillPoly(poly_mask, ppt, npt, 1, Scalar(255, 255, 255), 8);
 	image.copyTo(poly_roi, poly_mask);
 	
    // "polyROI" 윈도우에 이미지 표시
    imshow("polyROI", poly_roi);
 	waitKey(0);
 }

fillPoly(poly_mask, ppt, npt, 1, Scalar(255, 255, 255), 8); 메소드에서 poly_mask는 다각형이 그려질 대상 이미지, ppt는 다각형의 꼭짓점 배열을 가리키는 포인터 배열, 1은 그려질 다각형의 개수, Scalar(255, 255, 255)은 다각형 색상, 8은 선의 유형을 나타낸다.


Addition/Substraction operation

void add (Mat src1, Mat src2, Mat dst, Mat mask=noArray(), int dtype = -1)

src1과 src2의 합의 결과를 dst에 저장한다.

  • mask : 연산이 적용될 영역을 지정하는 8비트 단일 채널 마스크이다. 마스크의 픽셀 값이 0이 아닌 위치에서만 덧셈 연산이 수행된다. 기본값은 noArray()로 지정되어 있다.

  • dtype : 출력 행렬의 깊이를 명시적으로 지정한다. -1일 경우, src1의 데이터 타입이 사용된다.

  • dst(I) = saturate(src1(I)+src2(I) if mask(I) != 0
    참고로, saturate는 src1(l)+src2(l)의 결과를 0~255로 만들어주는 역할을 함 (8 bit)

EX

int main() {
 	Mat img1 = imread("lena.jpg");
 	Mat img2 = imread("lena.png");
 	Mat dst;
    // img1과 img2를 더한 결과를 dst에 저장함
 	add(img1, img2, dst);
	
    // "dst" 윈도우에 dst 표시
 	imshow("dst", dst);
 	waitKey(0);
 }

void scaleAdd(Mat src1, double scale, Mat src2, Mat dst)

dst(I) = scale * src1(I) + src2(I) 의미이다.

void absdiff(Mat src1, Mat src2, Mat dst)

dst(I) = saturate( | src1(I)-src2(I) | ) 의미이다.
0~255 사이의 값이 나오도록 만듬

void subtract(Mat src1, Mat src2, Mat dst, Mat mask=noArray(), int dtype = -1)

dst(I) = saturate( src1(I) – src2(I) ) if mask(I) != 0 의미이다.


Threshold operation

double threshold (Mat src, Mat dst, double thresh, double maxval, int type)

이 메소드는 일반적으로 grayscale 입력 영상에서 이진 영상을 가져오는데 사용된다.
각 배열 요소에 fixed level thresh를 적용한다.

maxval : dst(I) = maxval if src(I) > thresh, 0
otherwise, when type is THRESH_BINARY 을 의미한다.

Type에는 다음과 같은 종류들이 있다.

  • Type : THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV

Threshold를 넘어가면 다른 값으로 대체되거나, 아니면 그 반대로 된다.

EX

int main() {
	// "lena.jpg" 이미지 파일을 불러와 Mat 타입의 image 변수에 저장
 	Mat image = imread("lena.jpg");
    // image에서 BGR 색상을 그레이스케일로 변환
 	cvtColor(image, image, CV_BGR2GRAY);
 	Mat dst;
    // 그레이스케일로 변환된 이미지 image에 이진 임계값을 적용
    // 임계값은 100이며, 픽셀 값이 100보다 크면 255(흰색)로 설정되고, 그렇지 않으면 0으로 설정됨, 결과값은 dst에 저장됨
 	threshold(image, dst, 100, 255, THRESH_BINARY);
 
 	// grayscale로 변환된 image가 "dst" 윈도우에 저장됨
 	imshow("dst", dst);
 	imshow("image", image);
    
 	waitKey(0);
 	return 0;
 }

결과는 다음과 같다.

다음은 이미지의 각 지역에 따라 임계값을 적응적으로 조정하여 이진화를 수행하는 메소드이다.

Void adaptiveThreshold(Mat src, Mat dst, double maxval, int adaptiveMethod, int thresholdType, int blockSize, double C)

src는 입력, dst는 결과이며 maxval은 임계값을 넘었을 때 적용될 최대값이다. 일반적으로 255를 사용한다.

adaptiveMethod는 ADAPTIVE_THRESH_MEAN_C (가우시안 분포), ADAPTIVE_THRESH_GAUSSIAN_C (가중치 평균) 등이 있으며, threshold를 결정하는 방식을 지정해준다.

thresholdType은 임계값 타입으로, THRESH_BINARY 또는 THRESH_BINARY_INV 중 하나를 사용한다.

blocksize는 픽셀에 적용될 이웃의 크기를 나타내며, 홀수로 지정해야 한다.

C는 계산된 평균이나 가중 평균에서 뺄 상수로, 이 값에 따라 임계값이 조절된다.

dst(x, y) is computed as MEAN(blockSize x blockSize)-C
or
GAUSSIAN(blockSize x blockSize) –C around (x,y)
를 의미한다.

EX

 int main() {
 	Mat image = imread("lena.jpg");
    // image의 색상을 BGR에서 GRAY 스케일로 변환
 	cvtColor(image, image, CV_BGR2GRAY);
 	Mat dst;
    // 이진화 적용
 	adaptiveThreshold(image, dst, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 7, 10);
 	
    imshow("dst", dst);
 	imshow("image", image);
 
 	waitKey(0);
 	return 0;
 }

결과는 다음과 같다.

다음은 주어진 범위 내의 값에 해당하는 픽셀을 찾아서 이진 이미지 형태로 결과를 반환하는 메서드이다.
각 픽셀의 값이 지정된 상한값과 하한값 사이에 있는지를 검사하고, 그 결과를 이진 이미지로 출력한다.

Void inRange(cv::InputArray src, cv::InputArray lowerb, cv::InputArray upperb, cv::OutputArray dst)

  • src : 입력 array
  • Lowerb : threshold 하한값
  • Upperb : threshold 상한값
  • Dst : 결과 이진 이미지가 저장될 출력 배열이다. 이 배열은 입력 배열과 동일한 크기를 가지며, 타입은 CV_8U 이다.

EX

 int main() {
	 Mat image = imread("hand.jpg");
 	
    // 색상 공간을 BGR(Blue, Green, Red)에서 YCrCb로 변환함
 	cvtColor(image, image, CV_BGR2YCrCb);
    // 변환된 YCrCb 이미지에서, Scalar(0, 133, 77)과 Scalar(255, 173, 127) 사이의 색상 범위에 속하는 픽셀을 찾음
    // 첫번째 image는 입력 영상, 두 번째 image는 출력 영상이다.
 	inRange(image, Scalar(0, 133, 77), Scalar(255, 173, 127), image);
 	
    // 결과 표시함
 	imshow("inRange", image);
 	waitKey(0);
 	return 0;
 }

결과는 다음과 같다.


Others

다음은 이미지나 행렬의 데이터 타입을 변환하고, 선택적으로 픽셀 값에 대한 스케일링 및 이동 변환을 수행하는 메소드이다.

Mat convertTo(OutputArray m, int rtype, double alpha=1, double beta=0)

  • m : size 또는 type이 적절하지 않으면 재할당됨
  • rtype : 원하는 출력 행렬
  • m(x, y) = saturate_cast< rType > (alpha (this)(x, y) + beta) 를 의미함
    alpha와 beta는 정규화를 위함이다.

다음은 Mat 객체의 모든 요소 또는 특정 마스크에 해당하는 요소들을 지정된 값으로 설정하는 메소드이다.

Mat setTo(InputArray value, InputArray mask=noArray()

  • mask : 동일한 크기의 mask

다음은 입력 배열의 각 요소에 스케일링 인자(alpha)를 곱하고, 오프셋(beta)을 더한 후, 결과를 절대값으로 변환하고 8비트 unsigned integer 타입으로 변환하는 메소드이다.

Void convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)

  • Src : input array
  • Dst : output array
  • Alpha : optional scale factor
  • Beta : optional delta added to the scaled vector

Dst(I) = saturate_cast< uchar >(|src(I)| * alpha + beta|) 를 의미함

EX

 int main() {
 	Mat image = imread("lena.png");
	Mat after_convertTo, after_convertScaleAbs;
 	imshow("original", image);
    
    // image의 데이터 타입을 CV_16SC1로 변환하여 after_convertTo에 저장
 	image.convertTo(after_convertTo, CV_16SC1);
 	imshow("after convertTo", after_convertTo);
 	
    // 원본 image에 스케일링 인자 2와 오프셋 3을 적용 후, 결과를 절대값으로 변환하고 8비트 unsigned integer 타입으로 변환하여 after_convertScaleAbs에 저장
    // 이미지의 대비를 증가시키고 밝기를 조절함
 	convertScaleAbs(image, after_convertScaleAbs, 2, 3);
 	
    imshow("after convertScaleAbs", after_convertScaleAbs);
 	image.setTo(Scalar(0));
 	
    imshow("after setTo", image);
 	waitKey(0)

결과는 다음과 같다.

profile
자율주행, AI, 클라우드

0개의 댓글