OpenCV Convert Image
(주) 글을 읽기 전에
이 글은 저와 같은 OpenCV초보자를 위해서 정리하는 것입니다.
전문가시라면 굳이 읽을 필요가 없습니다.
공부하면서 정리하는 글이라서 서툰 부분이 많이많이 보입니다.
영상 처리를 하기 위해서는 때때로 컬러 공간을 바꾸어 줘야 할 때가 많습니다.
영상에서 필요한 정보를 찾아서 추출하기 위해서는 RGB공간에서 얻을 수 없는 정보를
다른 컬러 공간에서 얻어낼 수 있기 때문입니다.
예를들어서 사진에서 휘도를 바꾸고 싶을 경우
YCbCr로 바꾼후에 Y를 변경하고 다시 이것을 RGB로 바꾸는 과정을 거치게 됩니다.
이럴 경우 컬러 공간을 변환하는 함수가 있어야 하는데
OpenCV에서는 아래 함수가 그 동작을 도와줍니다.
cvCvtColor( 입력 이미지 , 출력 이미지 , 옵션 );
옵션은 아주 많이 있지만 아래에 몇가지 중요한 옵션을 설명하였습니다.
CV_RGB2GRAY : 흑백으로 바꾸기
수식은 다음과 같다.
RGB[A]->Gray: Y<-0.299*R + 0.587*G + 0.114*B
CV_RGB2YCrCb : YCrCb로 바꾸기
Y <- 0.299*R + 0.587*G + 0.114*B
Cr <- (R-Y)*0.713 + delta
Cb <- (B-Y)*0.564 + delta
CV_RGB2HLS : ( Hue Lightness Saturation ) 으로 변환한다.
// In case of 8-bit and 16-bit images
// R, G and B are converted to floating-point format and scaled to fit 0..1 range
V,,max,, <- max(R,G,B)
V,,min,, <- min(R,G,B)
L <- (V,,max,, + V,,min,,)/2
S <- (V,,max,, - V,,min,,)/(V,,max,, + V,,min,,) if L < 0.5
(V,,max,, - V,,min,,)/(2 - (V,,max,, + V,,min,,)) if L = 0.5
(G - B)*60/S, if V,,max,,=R
H <- 180+(B - R)*60/S, if V,,max,,=G
240+(R - G)*60/S, if V,,max,,=B
if H<0 then H<-H+360
On output 0=L=1, 0=S=1, 0=H=360.
The values are then converted to the destination data type:
8-bit images:
L <- L*255, S <- S*255, H <- H/2
16-bit images (currently not supported):
L <- L*65535, S <- S*65535, H <- H
32-bit images:
H, L, S are left as is
CV_RGB2HSV : RGB 값을 HSV로 바꾼다. HSV란 Hue Saturation Value를 의미한다.
// In case of 8-bit and 16-bit images
// R, G and B are converted to floating-point format and scaled to fit 0..1 range
V <- max(R,G,B)
S <- (V-min(R,G,B))/V if V?0, 0 otherwise
(G - B)*60/S, if V=R
H <- 120+(B - R)*60/S, if V=G
240+(R - G)*60/S, if V=B
if H<0 then H<-H+360
On output 0=V=1, 0=S=1, 0=H=360.
The values are then converted to the destination data type:
8-bit images:
V <- V*255, S <- S*255, H <- H/2 (to fit to 0..255)
16-bit images (currently not supported):
V <- V*65535, S <- S*65535, H <- H
32-bit images:
H, S, V are left as is
CV_RGB2Lab : CIE Lab Color로 변환한다.
// In case of 8-bit and 16-bit images
// R, G and B are converted to floating-point format and scaled to fit 0..1 range
// convert R,G,B to CIE XYZ
|X| |0.412453 0.357580 0.180423| |R|
|Y| <- |0.212671 0.715160 0.072169|*|G|
|Z| |0.019334 0.119193 0.950227| |B|
X <- X/Xn, where Xn = 0.950456
Z <- Z/Zn, where Zn = 1.088754
L <- 116*Y^1/3-16 for Y>0.008856
L <- 903.3*Y for Y<=0.008856
a <- 500*(f(X)-f(Y)) + delta
b <- 200*(f(Y)-f(Z)) + delta
where f(t)=t^1/3^ for t>0.008856
f(t)=7.787*t+16/116 for t<=0.008856
where delta = 128 for 8-bit images,
0 for floating-point images
On output 0=L=100, -127=a=127, -127=b=127
The values are then converted to the destination data type:
8-bit images:
L <- L*255/100, a <- a + 128, b <- b + 128
16-bit images are currently not supported
32-bit images:
L, a, b are left as is
- CV_RGB2Luv CIE Luv Color로 변환한다.
// In case of 8-bit and 16-bit images
// R, G and B are converted to floating-point format and scaled to fit 0..1 range
// convert R,G,B to CIE XYZ
|X| |0.412453 0.357580 0.180423| |R|
|Y| <- |0.212671 0.715160 0.072169|*|G|
|Z| |0.019334 0.119193 0.950227| |B|
L <- 116*Y^1/3^ for Y>0.008856
L <- 903.3*Y for Y<=0.008856
u' <- 4*X/(X + 15*Y + 3*Z)
v' <- 9*Y/(X + 15*Y + 3*Z)
u <- 13*L*(u' - u,,n,,), where u,,n,,=0.19793943
v <- 13*L*(v' - v,,n,,), where v,,n,,=0.46831096
On output 0=L=100, -134=u=220, -140=v=122
The values are then converted to the destination data type:
8-bit images:
L <- L*255/100, u <- (u + 134)*255/354, v <- (v + 140)*255/256
16-bit images are currently not supported
32-bit images:
L, u, v are left as is
코드는 아래와 같습니다.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
int main(int argc , char *argv[]){
IplImage *imgB ;
if (argc < 3 )
{
printf("usage : colorcvt.elf srcimage dstimage option \n");
printf(" srcimage : source image file name\n");
printf(" dstimage : destination image file name\n");
printf(" option : 0 : CV_RGB2GRAY \n");
printf(" 1 : CV_RGB2YCrCb \n");
printf(" 2 : CV_RGB2HLS \n");
printf(" 3 : CV_RGB2HSV \n");
printf(" 4 : CV_RGB2Lab \n");
printf(" 5 : CV_RGB2Luv \n");
exit(0);
}
// 이미지 읽기
IplImage *imgA = cvLoadImage( argv[1] , 1);
// 대상 이미지 확정
switch( *argv[3] )
{
case '0' :
imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 1);
cvCvtColor(imgA , imgB , CV_RGB2GRAY );
break;
case '1' :
imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);
cvCvtColor(imgA , imgB , CV_RGB2YCrCb );
break;
case '2' :
imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);
cvCvtColor(imgA , imgB , CV_RGB2HLS );
break;
case '3' :
imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);
cvCvtColor(imgA , imgB , CV_RGB2HSV );
break;
case '4' :
imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);
cvCvtColor(imgA , imgB , CV_RGB2Lab );
break;
case '5' :
imgB = cvCreateImage( cvGetSize( imgA), IPL_DEPTH_8U, 3);
cvCvtColor(imgA , imgB , CV_RGB2Luv );
break;
}
cvNamedWindow("Converted Image",0);
cvShowImage("Converted Image",(CvArr*)imgB);
cvWaitKey(0);
cvDestroyWindow("Converted Image");
cvSaveImage( argv[2] , imgB);
cvReleaseImage( &imgA );
cvReleaseImage( &imgB );
return 0;
}
아래는 각각의 옵션으로 했을때의 그림입니다.
컬러 스페이스가 틀린것을 강제로 출력한 형태이므로 다른 컬러 공간의 그림은 정확하게 표현되지는 않습니다. 그냥 이렇게 되었다는 것만 보면 될 듯 합니다.
원본 이미지
흑백으로 변환 이미지