2023.04.20 - [Code/C++] - [OpenCV C++] 이미지 불러오고 저장하기 (Ubuntu CMakeLists, Command args 연결, Clion)
2023.04.20 - [Code/C++] - [OpenCV C++] 이미지 저장하고 불러오기 , 창닫기 (CV 함수 설명 - 1)
🤗 cvtColor를 이용한 방법
- cvtColor 는 어떤 함수인가?
- document를 눌러보면 알다시피 영상을 다른 색공간으로 변환해 주는 함수이다.
void cv::cvtColor(InputArray src,OutputArray dst,int code,int dstCn = 0 )
// src : 입력영상
// dst : 출력영상
// code : 색변환코드
// dstCn : 결과 영상의 채널수 -> 정하지 않으면 자동설정
🤗 연산을 이용한 방법
어떤 연산을 통해서 컬러영상을 그레이로 만들 수 있을까? 단순하게 B, G, R을 1/3 씩 썩을 수 있겠지만 그렇게 하면 정확한 그레이 스케일 영상을 얻었다고 하긴 어렵다.
RGB 영상을 → Gray채널로 바꾸기 위해서는 ( Y = 0.299R + 0.587G + 0.114B (3:6:1 분포로 구성되어 있음))연산과정이 필요하다.
아래 주석 1 ~ 3 중 원하는 방법을 골라서 사용하면 됨
#define RGB2GRAY(r, g, b)((4899*(r) + 9617*(g) + 1868*(b))>>14)
// 14번 shift 연산 (기존의 0.299~~ 비율에 2^14 승을 곱한 것이 4899) -> 이걸 다시 역으로 2^14으로 나누는 것
// 1000으로 나누는 것보다 시프트연산자를 이용하여 빠르게 연산이 가능
// 2^16보다 작고 충분히 큰 수를 얻기 위해 사용
cv::Mat dst(src.rows, src.cols, CV_8UC1);
// 아래 과정은 사실 cv::cvtColor(src, dst, COLOR_BGR2GRAY); 로 표현 가능
for (int y = 0; y < src.rows; y++){
for (int x = 0; x<src.cols ; x++){
cv::Vec3b& p1 = src.at<cv::Vec3b>(y, x);
uchar b = p1[0];
uchar g = p1[1];
uchar r = p1[2];
// 1. 실수연산을 많이 하면 느려짐
// uchar gray = (uchar)(0.2999 * r + 0.587 * g + 0.114 * b + 0.5);
// 2. 1000으로 나누는 과정을 가질 수도 있지만 역시 연산이 추가됨
//uchar gray = (uchar)((299*r+587*g+114*b)/1000);
// 3. shift 연산자를 이용한 방법
uchar gray= RGB2GRAY(r, g, b);
dst.at<uchar>(y, x) = gray;
}
}
🔐 연산을 이용한 방법 중 발생할 수 있는 문제와 이유
- 직접적인 계산을 이용해 컬러이미지를 그레이스케일로 변환하면서 아래 사진과 같은 문제를 마주했다.
- 원본 영상의 크기에 1/3로 출력이미지가 생성되었다.
- 왜 그러럴ㄹ가.. 고민을 좀 해보자 하다가!
- 출력 영상을 선언하는 부분인데 그레이스케일 이미지 타입이 아닌 Color 이미지 타입 CV_8UC3로 선언했기 때문
cv::Mat dst(src.rows, src.cols, CV_8UC3);
- 위와 같이 지정한 후에 for 함수 안에 픽셀별로 계산한 값을 아래와 같은 과정으로 입력하게 되면
dst.at<uchar>(y,x) = gray;
CV_8UC1으로 지정해서 [512x512]만 있어도 될 값들이 [512x512(x3)]으로 늘어나면서 그림이 1/3으로 압축되는 현상이 발생할 수도 있다.
** 내용에 이상이 있다면 댓글로 지적부탁드립니다.
'Code > C++' 카테고리의 다른 글
[OpenCV C++] 이미지 저장하고 불러오기 , 창닫기 (CV 함수 설명 - 1) (0) | 2023.04.20 |
---|---|
[OpenCV C++] 이미지 불러오고 저장하기 (Ubuntu CMakeLists, Command args 연결, Clion) (0) | 2023.04.20 |