opencv(c++) RGB 값의 변경을 통해 Grayscale 표현
- 최초 작성일: 2022년 1월 10일(월)
목차
[TOC]
목표
opencv를 사용할 때, 노이즈를 없애 연산처리 속도와 정확도를 향상하기 위해 Grayscaling을 많이 사용한다.
앞에서 설명했던, IMREAD_GRAYSCALE나 cvtColor() 함수로 Grayscaling 할수도 있지만, 이 두가지 방법은 약간의 차이를 보일 가능성이 있다.
그래서, 직접 이미지의 RGB 값을 변경해 Grayscale을 표현해보자.
실습
Grayscale은 컬러이미지에서 광도만을 표현한 색 채널을 말한다.
밝으면 흰색, 어두우면 검은색이고 0~255 사이의 값으로 표현된다. (0: 검은색, 1: 흰색)
컬러 -> 흑백 이미지 변환의 방법은 여러가지가 있겠지만, 코드를 직접 작성해서 결과를 확인해보자.
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(int ac, char** av) {
Mat img_color = imread("lion.png");
Mat img_gray(img_color.rows, img_color.cols, CV_8UC1);
for (int y = 0; y < img_color.rows; y++)
{
for (int x = 0; x < img_color.cols; x++)
{
int avg = (img_color.at<Vec3b>(y, x)[0] + img_color.at<Vec3b>(y, x)[1] + img_color.at<Vec3b>(y, x)[2]) / 3;
img_gray.at<uchar>(y, x) = avg;
}
}
imshow("img_gray", img_gray);
waitKey(0);
return 0;
}
결과 (RGB 값 변경 Grayscale)
imread() 및 cvtColor() 함수와 결과 비교
imread()를 통한 Grayscale
imread() vs RBB 값 변경 (차이)
이미지가 그냥 검정 화면처럼 보이지만 밝기를 높여 보면, 아주 미세한 차이를 확인할 수 있다. 위의 이미지는 imread() 함수를 통한 Grayscale과 RGB값을 임의로 바꿔주는 Grayscale 방법의 결과에 대한 차이를 확인할 수 있다.
cvtColor()를 통한 Grayscale
cvtColor() vs RGB 값 변경 (차이)
위의 이미지는 cvtColor() 함수를 통한 Grayscale과 RGB값을 임의로 바꿔주는 Grayscale 방법의 결과에 대한 차이를 확인할 수 있다.
(위의 결과 코드)
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace cv;
using namespace std;
int main(int ac, char** av) {
Mat img_color = imread("lion.png");
Mat img_gray;
Mat img_diff(img_color.rows, img_color.cols, CV_8UC1);
cvtColor(img_color, img_gray, COLOR_BGR2GRAY);
for (int y = 0; y < img_color.rows; y++) {
for (int x = 0; x < img_color.cols; x++) {
int avg = (img_color.at<Vec3b>(y, x)[0] + img_color.at<Vec3b>(y, x)[1] + img_color.at<Vec3b>(y, x)[2]) / 3;
int diff = abs(img_gray.at<uchar>(y, x) - avg); // 음수가 나오면 안되므로 abs 함수 추가 (음수가 되면 아주 높은 숫자가 된다) (abs함수를 뺀 결과도 코드 아래 첨부)
img_diff.at<uchar>(y, x) = diff;
}
}
imshow("img_diff", img_diff);
waitKey(0);
return 0;
}
아래의 이미지는 diff를 구할 때 abs(절대값처리)를 안해주어 음수가 나왔을 때 아주 아주 밝은 색으로 흰색이 나타나는 오류
데이터로 차이 확인
육안으로 봤을 땐 그렇게 차이 안 나 보이는데라는 생각을 할 수 있으니, 수치 상으로 얼마나 차이가 있는지 확인을 해보자. 너무 많아서 인덱스 가로x세로 200~300 개의 데이터만 추려서 출력하여 일부만 가져왔다.
(위의 결과 코드)
#include <opencv2/imgcodecs.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace cv;
using namespace std;
int main(int ac, char** av) {
Mat img_color = imread("lion.png");
Mat img_gray = imread("lion.png", IMREAD_GRAYSCALE);
//Mat img_gray;
Mat img_diff(img_color.rows, img_color.cols, CV_8UC1);
//cvtColor(img_color, img_gray, COLOR_BGR2GRAY);
int col = img_color.cols;
int row = img_color.rows;
for (int y = 0; y < img_color.rows; y++) {
for (int x = 0; x < img_color.cols; x++) {
int avg = (img_color.at<Vec3b>(y, x)[0] + img_color.at<Vec3b>(y, x)[1] + img_color.at<Vec3b>(y, x)[2]) / 3;
int diff = abs(img_gray.at<uchar>(y, x) - avg);
img_diff.at<uchar>(y, x) = diff;
}
}
for (int y = 100; y < 200; y++) {
for (int x = 100; x < 200; x++) {
cout << int(img_diff.at<uchar>(y, x)) << " ";
}
cout << endl;
}
imshow("img_diff", img_diff);
waitKey(0);
return 0;
}