본문 바로가기
코딩/OpenCV

[C++ opencv] 웹캠으로 실시간 HSV 값 추출하기

by DIYver 2020. 10. 18.

 

 

본문 목표

OpenCV를 다루다 보면 색상 인식을 많이 하게 된다.

색상 인식을 하는데 있어서 RGB를 사용해야 할 때가 있고,

HSV 색채널을 이용해야 할 때가 있다.

 

RGB는 흰색과 검은색 또는 컴퓨터상의 색을 인식할 때 좋고,

HSV 색채널은 실제 일상에서의 색을 인식할 때 좋다.

 

오늘의 목표는 내가 특정한 색을 인식하고 싶을때,

해당 색의 정보가 어떻게 되는지 OpenCV를 통해서 알아내보는 것이다.

 

 

 

키워드 :  cvtColor, HSV

 

 

 

코드 테스트 결과

- CODE

#include <iostream>
#include <stdio.h>
#include <string.h>
//#include <sys/time.h>
#include <math.h>
#include <opencv2/opencv.hpp>
#include <ctime>


using namespace std;
using namespace cv;


int main(int, char**)
{
	//VideoCapture cap(0);
	VideoCapture cap(0, CAP_DSHOW);
	cap.set(CV_CAP_PROP_FRAME_WIDTH, 1280);
	cap.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
	cap.set(CAP_PROP_FPS, 30);
	Mat img;
	while (1)
	{
		cap >> img;
		//imshow("test", img);

		Mat img_hsv;
		cvtColor(img, img_hsv, COLOR_BGR2HSV);

		Mat img_out;
		img.copyTo(img_out);

		uchar* pointer_row = img_hsv.ptr<uchar>(img_hsv.rows >> 1);

		uchar h = pointer_row[(img_hsv.cols >> 1) * 3 + 0];
		uchar s = pointer_row[(img_hsv.cols >> 1) * 3 + 1];
		uchar v = pointer_row[(img_hsv.cols >> 1) * 3 + 2];

		char str_h[30];
		char str_s[30];
		char str_v[30];
		sprintf_s(str_h, "H : %d", h);
		sprintf_s(str_s, "S : %d", s);
		sprintf_s(str_v, "V : %d", v);
		putText(img_out, str_h, Point((1280 >> 1) + 40, (720 >> 1) - 30), 2, 1, Scalar(0, 0, 255), 1);
		putText(img_out, str_s, Point((1280 >> 1) + 40, 720 >> 1), 2, 1, Scalar(0, 0, 255), 1);
		putText(img_out, str_v, Point((1280 >> 1) + 40, (720 >> 1) + 30), 2, 1, Scalar(0, 0, 255), 1);

		line(img_out, Point((img.cols >> 1) - 10, img.rows >> 1), Point((img.cols >> 1) + 10, img.rows >> 1), Scalar(0, 0, 255), 1);
		line(img_out, Point(img.cols >> 1, (img.rows >> 1) - 10), Point(img.cols >> 1, (img.rows >> 1) + 10), Scalar(0, 0, 255), 1);

		imshow("img_out", img_out);




		if (waitKey(10) == 27)
			return 0;


	}

	return 0;
}

 

- RESULT

카메라를 통해서 이미지를 받아오고

그 이미지를 HSV 색채널로 변환한다.

 

HSV 색채널로 변환한 이미지의 중앙 픽셀 데이터를 추출하여 H, S, V에 저장시키고,

sprintf_s( ) 를 이용하여 문자열에 저장시킨다.

 

putText( ) 함수를 이용하여 출력할 이미지에 데이터 정보를 출력시킨다.

 

여기서 쉬프트 연산이 사용된 것을 볼 수 있다.중심 픽셀을 구하기 위해서 원래는 img.cols / 2 처럼 코드를 작성해야 하는데,나눗셈은 연산속도를 잡아먹기 때문에 쉬프트 연산으로 바꿔준 것이다.

 

다시말해서 img.cols / 2  이 표현은 img.cols >> 1 과 완전 똑같은 표현인 것이다.이렇게 함으로써 연산 속도는 약 10배 정도 빨라졌다고 보면 된다.

 

 

결과는 위의 영상에서 확인할 수 있다.

 

색이 바뀔 때마다 HSV 색정보가 변하는 것을 확인할 수 있다.

그런데 아쉬운 점은 자연적인 색이 아니라, LCD에서 구현된 색은 색 정보가 사실과 많이 다르다는 것이다.

 

일단 카메라가 자동적으로 색보정을 하기 때문에 실제 색과 차이가 생길 수 있고,

애초에 LCD 에서 나오는 빛은 V (value : 밝기) 값이 거의 255에 가깝기 때문이다.

 

따라서 HSV 색 정보를 추출해내려면 일반적인 사물을 카메라로 찍어서 추출하는 것이 보다 정확하다.

 

이번 포스팅의 핵심은 여태 다뤘었던 내용들을 종합한 것이라 보면 되겠다.

HSV 색채널 다루기와

픽셀의 색정보 가져오기

이미지에 텍스트 삽입하기 

위의 3가지 포스팅을 다 이해했다면 충분히 이해할 수 있었을 것이라 본다.

 

 

 

이런 방식에서 색채널만 RGB를 사용한다면 중앙 픽셀의 RGB 정보를 추출하는 코드가 되겠다.

 

 

 

 

 

 

 

 

 

 

도움이 되었거나, 문제가 있는 경우 댓글로 알려주세요~!

감사의 댓글은 작성자에게 큰 힘이 됩니다 ^^

댓글