출처 : http://cinema4dr12.tistory.com/entry/OpenCV-RGB-Color%EB%A5%BC-Grayscale%EB%A1%9C-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0
이번 글에서는 OpenCV에서 RGB 컬러를 Grayscale로 변환하는 방법에 대하여 알아보도록 하겠다.
우선 이론적으로 살펴보면, 가장 널리 사용되는 방법 중 하나가
Luma Coding(https://en.wikipedia.org/wiki/Grayscale)을 이용한 방법인데, 수식은 다음과 같다:
여기서, R', G', B'은 Red, Green, Blue 채널에 대한 비디오 시스템의 Gamma-compressed 값이다.
이들로부터 계산된 Y'은 비선형 Luma 컴포넌트(Nonlinear Luma Component)이며, Grayscale된 값이다.
이 수식을 기반으로 RGB 컬러를 Grayscale로 변환하는 OpenCV Source Code는 다음과 같다.
[Source Code 1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include <iostream> #include <opencv2/opencv.hpp> #include <stdlib.h> #include <stdio.h> using namespace std; using namespace cv; /* @ function main */ int main( int argc, char ** argv ) { /// Load an image cv::Mat image = cv::imread( {YOUR_IMAGE_PATH}, 1 ); cv::Mat image_gray; /// Copy image image.copyTo( image_gray ); int nRows = image.rows; int nCols = image.cols; /// Convert to gray float fGray = 0.0f; float chBlue, chGreen, chRed; for ( int j = 0 ; j < nRows ; j++ ) { for ( int i = 0 ; i < nCols ; i++ ) { chBlue = ( float )( image.at<cv::Vec3b>(j,i)[0] ); chGreen = ( float )( image.at<cv::Vec3b>(j,i)[1] ); chRed = ( float )( image.at<cv::Vec3b>(j,i)[2] ); fGray = 0.2126f * chRed + 0.7152f * chGreen + 0.0722f * chBlue; if ( fGray < 0.0 ) fGray = 0.0f; if ( fGray > 255.0 ) fGray = 255.0f; image_gray.at<cv::Vec3b>(j,i)[0] = ( int )fGray; image_gray.at<cv::Vec3b>(j,i)[1] = ( int )fGray; image_gray.at<cv::Vec3b>(j,i)[2] = ( int )fGray; } } /// Creates window cv::namedWindow( "Image Original" , CV_WINDOW_AUTOSIZE ); cv::namedWindow( "Image Grayed" , CV_WINDOW_AUTOSIZE ); /// Show stuff cv::imshow( "Image Original" , image ); cv::imshow( "Image Grayed" , image_gray ); /// Wait until user press some key cv::waitKey(); return 0; } |
결과를 살펴보면 다음과 같다.
[Result]
위의 코드는 순전히 이론을 바탕으로 정말 충실하게 픽셀 하나하나 끄집어내어 계산한 것이다. 하지만 매우 효율면에서 떨어질뿐더러 OpenCV가 위의 연산을 수행하는 함수를 제공하지 않을리 없다.
OpenCV의 cvtColor() 함수는 상당히 다양한 Color Space 간 변환을 해주는 함수이며, 계산 속도도 매우 빠르다. 이 함수의 프로토타입은 다음과 같다:
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn=0 )
src: input image
dst: output image (destination image)
code: color space conversion code
dstCn: number of channels in the destination image
이 함수를 이용하여 RGB를 Grayscale로 변환하는 코드를 작성하면 다음과 같다.
[Source Code 2]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <iostream> #include <opencv2/opencv.hpp> #include <stdlib.h> #include <stdio.h> using namespace std; using namespace cv; /* @ function main */ int main( int argc, char ** argv ) { cv::Mat image, image_gray; /// Load an image image = cv::imread( {YOUR_IMAGE_PATH}, 1 ); if ( !image.data ) { return -1; } /// Convert it to gray cv::cvtColor( image, image_gray, CV_RGB2GRAY ); /// Create window cv::namedWindow( "Image Original" , CV_WINDOW_AUTOSIZE ); cv::namedWindow( "Image Grayed" , CV_WINDOW_AUTOSIZE ); /// Show stuff cv::imshow( "Image Original" , image ); cv::imshow( "Image Grayed" , image_gray ); /// Wait until user press some key cv::waitKey(); return 0; } |
당연한 얘기겠지만 소스가 매우 간결해졌다. 결과는 다음과 같다.
[Result]
'Programming' 카테고리의 다른 글
RealTime Mesh ★ Phaser 3 ★ Alea GPU ★ Fast 2D GPU ★ Parallel-For ★ GPU Voxel (0) | 2017.04.03 |
---|---|
PCL 라이브러리과 VTK라이브러리의 Namespace detail이 겹칠 경우 (0) | 2017.04.03 |
[PCL] error C2661: 'pcl::PointCloud<PointT>::operator new' : no overloaded function takes 3 arguments (1) | 2017.03.30 |
폴더명 추출 및 파일명 리스트 텍스트 파일로 만들기 (0) | 2017.03.28 |
Social Tagging 데이터 셋 (Datasets) (0) | 2014.08.08 |