[컴퓨터 비전] 11 Color Processing

이찬영·2024년 2월 24일
0

컴퓨터 비전

목록 보기
10/20

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

Usage of HSI

Color Processing을 하기 위해 RGB 영상을 HSI나 YCbCr 색 공간으로 변화시킨다.

HSI와 YCbCr로부터 Intensity 값을 얻을 수 있다.

HSI
HSI는 Hue(색조), Saturation(순도), Intensity(세기)로 이루어져 있다.
HSI는 HSV로도 불린다.

Hue (색조) : 순수한 색깔을 나타내며, 붉은 색으로부터 얼마나 떨어져 있는지를 의미하기도 한다.
Saturation (순도) : 색상의 순도를 나타내며, 흰색이 섞인 정도를 의미한다.
Intensity (세기) : 밝기를 의미하며, 값이 높을수록 밝다.

S가 크면 -> clear color
I가 크면 -> bright color


원본 영상은 다음과 같다.

Color Slicing

Hue 채널에서 원하는 색상 범위의 픽셀을 찾는다.

Saturation(포화) 채널에서 다른 모든 픽셀을 0으로 설정한다.


Color Conversion

Hue 채널에 액세스하면 색상의 영역을 변경할 수 있다.


Pseudo Coloring

Pseudo Coloring은 grayscale 이미지에서 많이 적용된다.

Grayscale 이미지 내에서 우리 눈은 약 30~50가지의 다른 회색들밖에 구분하지 못한다.

반면에, Color 이미지 내에서 우리 눈은 약 100만가지에 달하는 다른 색깔들을 구분할 수 있다.

따라서, Pseudo Coloring의 목적은 정보를 더 잘 시각화하기 위해 색상을 사용하여 그레이 스케일 영상을 표현하고자 하는 것이다.


또한, 색상이 나타내는 바를 잘 이해하기 위해 이미지에 색상 척도를 포함하는 것이 중요하다. (Coloring)

예를 들어, grayscale 이미지를 다음과 같이 pseudo-coloring을 수행할 수 있다. (Intensity Slicing)

다음은 Pseudo Coloring을 수행하는 코드이다.

 int main() {
 	Mat gray = imread("xray.jpg", 0);	// 이미지를 grayscale로 로드함
 	Mat color;
 
 	// Applies a colormap on a given image
 	// gray: src, color: dst, COLORMAP_JET: the color map to apply
    // grayscale 이미지에 COLORMAP_JET 컬러맵을 적용
 	applyColorMap(gray, color, COLORMAP_JET);
 	imshow("gray", gray);	// 원본 이미지 출력
 	imshow("image", color);		// 컬러맵이 적용된 이미지 출력
 	
    waitKey(0);
 	return 0;

Color balancing

색상의 강도에 대한 글로벌 조정을 Color balancing 이라고 한다.

Color balancing을 하는 간단한 방법

  • 중립인 것으로 추정되는 물체가 다음과 같이 나타나도록 R,G,B 구성 요소를 축적한다.

다음은 Color balancing을 수행하는 코드이다.

 int main() {
 	Mat image = imread("lena.png");		// 이미지를 읽어 Mat 객체에 저장함	
 	Mat result;
 	vector<Mat> ch(3);
 	int b_sum = 0, g_sum = 0, r_sum = 0;
 	int b_avg, g_avg, r_avg, b_tmp, g_tmp, r_tmp;
 	if (image.empty()) {
 		cerr<< "read fail" << endl;
 		exit(-1);
 	}
 	int rows = image.rows;
 	int cols = image.cols;
 	int pixno= rows * cols;
 	
 	// split by B, G, R channel
    // 이미지를 BGR(파랑, 초록, 빨강) 채널로 분리
 	split(image, ch);
 	uchar* b;
 	uchar* g;
 	uchar* r;
 
 	// calculate each channel's average
    // 각 채널별로 픽셀 값의 합을 구함
 	for (int i = 0; i < rows; i++) {
 		b = ch[0].ptr<uchar>(i);
 		g = ch[1].ptr<uchar>(i);
 		r = ch[2].ptr<uchar>(i);
 		for (int j = 0; j < cols; j++) {
 			b_sum+= b[j];
 			g_sum+= g[j];
 			r_sum+= r[j];
 		}
 	}
    
    // 전체 픽셀 수로 나누어 평균 값을 계산함
    b_avg= b_sum/ pixno;
 	g_avg= g_sum/ pixno;
 	r_avg = r_sum / pixno;
 
 	// color balancing using gray world assumsption
 	for (int i = 0; i < rows; i++) {
 		b = ch[0].ptr<uchar>(i);
 		g = ch[1].ptr<uchar>(i);
 		r = ch[2].ptr<uchar>(i);
 		for (int j = 0; j < cols; j++) {
 			// to prevent overflow
            // 조정된 값이 255를 초과하지 않도록 하여 오버플로우를 방지
 			b_tmp= (128 * b[j]) / b_avg;
 			if (b_tmp> 255) {
 				b[j] = 255;
 			}
 			else {
 				b[j] = b_tmp;
 			}
 
 			g_tmp = (128 * g[j]) / g_avg;
 			if (g_tmp> 255) {
 				g[j] = 255;
 			}
 			else {
 				g[j] = g_tmp;
 			}
            
            r_tmp = (128 * r[j]) / r_avg;
 			if (r_tmp > 255) {
 				r[j] = 255;
 			}
 			else {
 				r[j] = r_tmp;
 			}
 		}
    }

    // merge 3 channel's image, 조정된 채널들을 다시 병합함
 	merge(ch, result);
 
 	imshow("image", image);
 	imshow("result", result);
 	waitKey(0);
 	return 0;
 }


Color checker로부터 Color balancing을 수행할 수 있다.

두 가지 가정을 통해서 Color balancing을 수행할 수 있다.

  • 모든 픽셀의 값들의 평균을 내보면 그 값은 회색에 가깝다.

  • 흰색 픽셀이 가장 밝은 값을 가진다.

다음은 Color processing을 수행하는 코드이다.

 int main() {
 	Mat image = imread("colorful.jpg");		// 이미지 로드함
 	Mat HSV, intensity_change, mask_out, change_color;
 	// 채널 별로 이미지를 분리할 벡터들을 선언함
    vector<Mat> ic(3);	
 	vector<Mat> mo(3);
 	vector<Mat> cc(3);
 	
    int rows = image.rows;
 	int cols = image.cols;
 	uchar* h;
 	uchar* s;
 	uchar* v;
 	
    // BGR 색상 공간에서 HSV 색상 공간으로 이미지를 변환함
 	cvtColor(image, HSV, CV_BGR2HSV);
    //  HSV 이미지를 각각 H(색상), S(채도), V(밝기) 채널로 분리함
 	split(HSV, ic);
 	split(HSV, mo);
 	split(HSV, cc);
 
 	//eqaulizingthe histogram of I mat
    // 밝기(V) 채널의 히스토그램을 평활화하여 이미지의 대비를 개선함
 	equalizeHist(ic[2], ic[2]);
 
 	//masking out except orange
    // 오랜지 색을 제외한 모든 색상을 마스킹함
 	for (int i = 0; i < rows; i++) {
 		h = mo[0].ptr<uchar>(i);
 		s = mo[1].ptr<uchar>(i);
 		for (int j = 0; j < cols; j++) {
 			if (h[j] > 9 && h[j] < 23) s[j] = s[j];
 			else s[j] = 0;
 		}
 	}
    
     //changing all colors
     // 모든 픽셀 색상 값을 50만큼 증가시킴
     // 색상 값이 255를 초과하는 경우, 255를 넘어간 만큼을 0부터 다시 시작하는 방식으로 조정
 	for (int i = 0; i < rows; i++) {
 		h = cc[0].ptr<uchar>(i);
 		s = cc[1].ptr<uchar>(i);
 		for (int j = 0; j < cols; j++) {
 		if (h[j] + 50 > 255) h[j] = h[j] + 50 -255;
 		else h[j] += 50;
 		}
 	}
    
    // 수정된 채널들을 다시 병합함
    merge(ic, intensity_change);
 	merge(mo, mask_out);
 	merge(cc, change_color);
    // HSV 공간에서 BGR 색상 공간으로 이미지를 다시 변환함
 	cvtColor(intensity_change, intensity_change, CV_HSV2BGR);
 	cvtColor(mask_out, mask_out, CV_HSV2BGR);
 	cvtColor(change_color, change_color, CV_HSV2BGR);
 	
    // 원본 이미지와 각각의 처리 결과를 표시함
 	imshow("image", image);
 	imshow("intensity change", intensity_change);
 	imshow("mask out", mask_out);
 	imshow("change color", change_color);
 
 	waitKey(0);
 	return 0;
 }

위 코드를 수행한 결과는 다음과 같다.


참고로, Color processing은 컴퓨터 비전에서 널리 쓰이지는 않는다.

결과는 다음과 같다.

원본 영상

Histogram eqalization을 수행한 결과이다.

Color slicing을 수행한 결과이다.

Color changing을 수행한 결과이다.


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

0개의 댓글