11-14 07:42
Notice
Recent Posts
Recent Comments
관리 메뉴

Scientific Computing & Data Science

[OpenCV] RGB Color를 Grayscale로 변환하기 본문

Programming/OpenCV

[OpenCV] RGB Color를 Grayscale로 변환하기

cinema4dr12 2015. 7. 21. 20:39

이번 포스팅에서는 OpenCV에서 RGB 컬러를 Grayscale로 변환하는 방법에 대하여 알아보도록 하겠습니다.


우선 이론적으로 살펴보면, 가장 널리 사용되는 방법 중 하나가
Luma Coding(
https://en.wikipedia.org/wiki/Grayscale)을 이용한 방법인데, 수식은 다음과 같습니다:


\( Y' = 0.2126 \times R' + 0.7152 \times G' + 0.0722 \times B' \)


여기서, R', G', B'은 Red, Green, Blue 채널에 대한 비디오 시스템의 Gamma-compressed 값입니다. 이들로부터 계산된 Y'은 비선형 Luma 컴포넌트(Nonlinear Luma Component)이며, Grayscale된 값입니다. 이 수식을 기반으로 RGB 컬러를 Grayscale로 변환하는 OpenCV Source Code는 다음과 같습니다.

Example 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
#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;
 
  forint j = 0 ; j < nRows ; j++ ) {
 
    forint 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;
}
cs


결과를 살펴보면 다음과 같습니다.


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로 변환하는 코드를 작성하면 다음과 같습니다.

Example 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
#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;
}
cs


당연한 얘기겠지만 소스가 매우 간결해졌습니다. 결과는 다음과 같습니다.


Result

Comments