1. OpenCV 에서 컬러영상 다루기

   1) R,G,B 색성분 각 256단계 표현/.

   2) CV_8UC3 타입  //그레이는 CV_8UC1 

   3) BGR 순서를 Opencv에선 기본으로 사용

2. 컬러 영상의 픽셀값 참조

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lenna.bmp");

	if (src.empty()) {
		cerr << "Image laod failed!" << endl;
		return -1;
	}

	Mat dst = 255 - src;

	imshow("src", src);
	imshow("dst", dst);
	waitKey();
}

컬러이미지 반전시 우측같이 비정상적인 결과영상이 나왔다.

** 255 는 자동으로 Scalar 형으로 변환해서 연산이 된다

Scalar 클래스는 내부에 4개의 요소가 있다. 즉     (오버로딩 연산자 - 보면 확인 가능)

Scalar(255, 0, 0 , 0 ) - src; 한것과 동일하다. 

4번째 채널은 무시하고, 2,3 채널은 G, R 이 0보다 작아짐에따라 포화연산으로 0으로 처리됨

이에 B만 형성이 되어 파란 화면이 나온다.

 

해결법 Scalar(255,255,255)

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lenna.bmp");

	if (src.empty()) {
		cerr << "Image laod failed!" << endl;
		return -1;
	}

	Mat dst = Scalar(255,255,255) - src;

	imshow("src", src);
	imshow("dst", dst);
	waitKey();
}

 

 

각 픽셀을 직접 접근해서 반전시켜보자

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lenna.bmp");

	if (src.empty()) {
		cerr << "Image laod failed!" << endl;
		return -1;
	}

	Mat dst(src.rows, src.cols, src.type());
	//Mat dst(src.rows, src.cols, CV_8UC3);
	
	for (int y = 0; y < src.rows; ++y) {
		for (int x = 0; x < src.cols; ++x) {
			//src.at<uchar>(y, x); // gray scale  다룰 시 접근 법
			 // 컬러영상 픽셀 접근법
			 Vec3b& p1 = src.at<Vec3b>(y, x);  // 참조를 사용한 이유.  p1로 사용 시 복사본으로 할당한 영상을 바꾸는 용도로 사용할 수 없다.
			 Vec3b& p2 = dst.at<Vec3b>(y, x); // 이에 참조를 사용함으로써 얕은복사와 같이 p1, p2가 변환되면 src, dst 도 변환되게 만들어준다.,
			//& 가 효율적.
			// p1을 바꾸지 않기에 const 사용하는게 좋긴하나 생략
			 p2[2] = 255 - p1[2]; // R G B 반전
			 p2[1] = 255 - p1[1];
			 p2[0] = 255 - p1[0];
		}
	}
	imshow("src", src);
	imshow("dst", dst);
	waitKey();
}

 

3줄을 한 줄로

for (int y = 0; y < src.rows; ++y) {
		for (int x = 0; x < src.cols; ++x) {
			 Vec3b& p1 = src.at<Vec3b>(y, x);  // 참조를 사용한 이유.  p1로 사용 시 복사본으로 할당한 영상을 바꾸는 용도로 사용할 수 없다.
			 Vec3b& p2 = dst.at<Vec3b>(y, x); // 이에 참조를 사용함으로써 얕은복사와 같이 p1, p2가 변환되면 src, dst 도 변환되게 만들어준다.,
			 p2 = Vec3b(255, 255, 255) - p1;

		}
	}

 

이 한줄로도 커버 가능

 

for (int y = 0; y < src.rows; ++y) {
		for (int x = 0; x < src.cols; ++x) {
		   dst.at<Vec3b>(y, x) = Vec3b(255, 255, 255) - src.at<Vec3b>(y, x);
		}
	}

 

3. 컬러영상을 그레이스케일 영상으로 변환

Y = 0.299R + 0.587G + 0.114B    // Y: GrayScale 밝기 값

          3       :        6      :     1          비율을 따름.

장점: 데이터 저장용량 감소(3Byte -> 1Byte), 연산 처리 속도향상

단점: 색상 정보 손실.

#include <iostream>
#include "opencv2/opencv.hpp"
#include<vector>
using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lenna.bmp",IMREAD_COLOR);

	if (src.empty()) {
		cerr << "Image laod failed!" << endl;
		return -1;
	}

	Mat dst(src.rows, src.cols, CV_8UC1);

	for (int y = 0; y < src.rows; y++) {
		for (int x = 0; x < src.cols; x++) {
			Vec3b& p1 = src.at<Vec3b>(y, x);
			uchar b = p1[0];
			uchar g = p1[1];
			uchar r = p1[2];

			uchar gray = (uchar)(0.299 * r + 0.587 * g + 0.114 * b + 0.5); // 0.5는 반올림 기능. 해도 안해도 그만
			
			dst.at<uchar>(y, x) = gray;
		}
	}
	imshow("src", src);
	imshow("dst", dst);
	waitKey();
}
#define RGB2GRAY(r, g, b) ((4899*(r) + 9617*(g) + 1868*(b)) >> 14 )  // >> 14 : 2의 14승으로 나눈다는 의미.



	for (int y = 0; y < src.rows; y++) {
		for (int x = 0; x < src.cols; x++) {
			Vec3b& p1 = src.at<Vec3b>(y, x);
			uchar b = p1[0];
			uchar g = p1[1];
			uchar r = p1[2];

			//uchar gray = RGB2GRAY(r, g, b); 
			dst.at<uchar>(y,x) = RGB2GRAY(r, g, b);

		}
	}

 

define 하여 이처럼 gray 변환 식 가능.

 

 

그러나, 아래 코드는 육안으로 그레이색이나,. 그레이스케일 변환 방법이 아니다. 비율을 1/3 으로 나눠주었기에.

 uchar gray = (r + g + b) / 3;  엄밀히 말하여 이 코드는 그레이스케일 변환 방법이 아니다.

 

 

opencv 함수 cvtColor 사용해서 gray색 변환

#include <iostream>
#include "opencv2/opencv.hpp"
#include<vector>
using namespace std;
using namespace cv;

int main()
{
	Mat src = imread("lenna.bmp",IMREAD_COLOR);

	if (src.empty()) {
		cerr << "Image laod failed!" << endl;
		return -1;
	}

#if 1
	Mat dst;
	cvtColor(src, dst, COLOR_BGR2GRAY);

#else
	Mat dst(src.rows, src.cols, CV_8UC1);

	for (int y = 0; y < src.rows; y++) {
		for (int x = 0; x < src.cols; x++) {
			Vec3b& p1 = src.at<Vec3b>(y, x);
			uchar b = p1[0];
			uchar g = p1[1];
			uchar r = p1[2];

			dst.at<uchar>(y,x) = RGB2GRAY(r, g, b);

		}
	}
#endif
	imshow("src", src);
	imshow("dst", dst);
	waitKey();
}

'프로그래머스 > OPENCV' 카테고리의 다른 글

모폴로지 (잡음 제거)  (0) 2022.12.08
지역이진화  (0) 2022.12.08
코너 검출 기법  (2) 2022.12.08
허프변환 알고리즘  (0) 2022.12.08
캐니 에지 검출기  (0) 2022.12.07

+ Recent posts