Color Processing
컬러 영상을 preprocessing 하는 것
Usage of HSI (or YCbCr 색공간으로 변환)
- 특정한 축이 intensity 값이 아니라 rgb 각 채널들이 합쳐져서 intensity 값을 표현하는 것이다.
- HSI or YCbCr 경우는 특정한 채널 값이 intensity 값을 의미한다.
- 따라서 HSI or YCbCr로 변환시킨 후 I값이나 Y값을 건드리는 방식으로 color processing을 수행한다.
- (HSI로 변환한 후에는 밝기값 변환이나 히스토그램 평활화, 평균값 필터 등을 수행할 수 있다.)
- Color Slicing : 특정한 hue 값을 제외하고 나머지 값들을 0으로 변환
- Color Conversion : hue 값을 조정
Pseudo Coloring
- 우리 눈이 그레이스케일 영상에서 색상을 구별할 수 있는 범위가 30~50개 사이이다. 즉, 픽셀의 개수가 256개라 할지라도 사람의 눈은 30~50개의 경우의 수만 인지 가능하다는 것이다.
- 하지만 컬러의 경우 100k ~ 10m 가지의 색을 구별 가능하다. 따라서 Pseudo Coloring을 사용하는 것이다.
- 각각의 컬러가 어떠한 의미를 가지는지 표시해야 한다.
- Intensity Slicing : 각각의 Intensity 값에 대해 특정한 값을 할당시키는 것이다.
Color Balancing
- 특정한 색채의 영향을 빼주는 것
color balancing 방법
1. color checker 이용
2. 두 가지 가정 이용
- gray world assuption : 사진을 찍으면 사진의 픽셀 값의 평균은 회색에 가깝다 [128,128,128]
- 원래 흰색 값이 영상 내에서 가장 밝다. -> 영상 내 가장 밝은 값을 흰색이었다고 가정
Color Processing - Usage of HSI
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;
cvtColor(image, HSV, CV_BGR2HSV);
split(HSV, ic);
split(HSV, mo);
split(HSV, cc);
//eqaulizing the histogram of I mat
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
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);
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;
}
Pseudo coloring
int main() {
Mat gray = imread("xray.jpg", 0);
Mat color;
// Applies a colormap on a given image
// gray: src, color: dst, COLORMAP_JET: the color map to apply
applyColorMap(gray, color, COLORMAP_JET); /(입력, 결과, colormap)
imshow("gray", gray);
imshow("image", color);
waitKey(0);
return 0;
}
Color Balancing
int main() {
Mat image = imread("lena.png");
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
split(image, ch);
uchar* b;
uchar* g;
uchar* r;
// 각 컬러 채널에 대해 평균 계산
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
// 원래 평균값이 [128,128,128]이어야 하는데 그렇지 않은 값들에 대해 128로 만들기 위한 처리
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
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;
}
출처 - 컴퓨터 비전 한동대학교 황성수
'openCV' 카테고리의 다른 글
[openCV] 동영상 분할 (0) | 2020.01.18 |
---|---|
[openCV] 영상 분할 (0) | 2020.01.18 |
[openCV] 공간 도메인 필터링 (0) | 2020.01.18 |
[openCV] 히스토그램 평활화 (0) | 2020.01.18 |
[openCV] 밝기 값 변환 (1) | 2020.01.18 |
댓글