내맘대로 공부기록.

[ C++ ]

[ openCV | C++ ] 머신비전 이해를 위한 openCV 기초 리뷰

fwanggus 2021. 1. 30. 19:18


 

🙋🏻‍♂️ openCV를 시작하면서, 무(無) 일 때 openCV의 느낌?

📋 튜토리얼 시작

📏 이미지 리사이징 

🖼 이미지 변환 

     1. 그레이 스케일링

     2. HSV 스케일링

 ⭕️ 엣지검출

     1. 블러(Blur) 처리

     2. 엣지 검출, Canny Edge Detector 

🙇🏻‍♂️ 기초 이미지 처리를 학습 후 openCV의 느낌?

 



 

🙋🏻‍♂️ openCV를 시작하면서, 무(無) 일 때 openCV의 느낌?

많은 조사를 하지 않고 막 공부하자! 느낌으로 달려들다가, openCV를 openGL과 헷갈려 openGL을 공부해부렸다.

.

openGL ?

 

openCV 😎

 

처음부터 하고자 했던 방향은 머신 비전을 이용한 자율주행, 또는 머신 비전을 이용한 결품 검사 소프트웨어 작성 등을 목표로 했었지만 완전히 다른 방향으로 가고 있었다.

 

어쨌든 openCV로 방향을 다시 잡았고, openCV을 시작해보기로 했다.

openCV는 computer vision 관련 머신러닝 라이브러리이며, 이름에서 알 수 있듯이 비전을 소재로 머신러닝을 할 수 있다. 자세한 설명은 공홈을 참고하자.

 


📋 튜토리얼 시작

openCV 튜토리얼, 소개자료 등을 시중에 찾아보면 정말 많다. 크게 두 가지 언어로 나뉘는데 C++ vs Python의 구도가 형성된다.

일하면서 C, Fortran을 접할 수 있는 환경에 있기 때문에, 자연스럽게 생태가 비슷한 C++로 선택했다.

그리고 실제 머신러닝 앱? 또는 프로그램을 개발할 때는 C++로 많이 한다는 글을 보고, 나중을 생각해서?(어떻게 될지 아무도 모르는 거니깐) 그냥 어렵게 시작하기로 했다.

 

튜토리얼은 유튜브의 LEARN OPENCV C++ in 4 HOURS | Including 3x Example Projects Win/Mac (2021)를 참고했다.

맥을 사용 중이기 때문에, Xcode환경에서 진행했다. 초기 다이나믹 라이브러리 임포트와, Include Path 설정 등 어려운 부분이 있었지만, 동영상 보면서 따라 하니깐 문제없이 넘어갔다.

 

통상 VISUAL STUDIO CODE를 에디터로 사용하면서 단축키를 많이 썼었는데, Xcode에서는 비슷한 단축키가 없다? 그래서 불편하다.

(커서 단어 바로 선택 이라던가, auto indent 라던가... 설정 방법 또는 단축키 아시면 알려주세요🙏)

 

튜토리얼에 사용할 이미지를 골랐다. 너무 큰 것 같다. 리사이즈해서 써보도록 하자.

 

미국 고속도로 이미지

 

먼저 공통적으로 필요한 코드를 상단에 적어보자. 

  • 입출력 스탠다드 라이브러리

  • openCV라이브러리

#include <iostream>
// openCV heeader
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

int main(){

	// 코드 ...
    .
    .
    .
    return 0;
}

 

 

📏 이미지 리사이징 

cv::resize(orgImage, dstImage, size(width_px, height_px), scale_x, scale_y)

resize함수 후미에 있는 size()와 scale은 둘 중 하나만 선택해서 사용한다. 여기서는 특정 픽셀 정의가 아닌 scale로 조정했다.

 

	...
    
	string path = "Resources/road.jpeg";
	Mat img = imread(path);
	Mat imgResize;

	// resizing
	resize(img, imgResize, Size(), 0.5,0.5);
    
	imshow("Image", img);
	imshow("Image Resize", imgResize);
    
	// 이미지가 바로 사라지기 때문에 시간을 부여, 0은 무한대를 의미한다.
	waitKey(0);
	
	...

 

0.5 스케일(축소)로 이미지 리사이즈 성공! 리사이즈된 이미지를 소스로 이용한다.

 

이미지 리사이징(0.5 scale)

 

🖼 이미지 변환 

1. 그레이 스케일링

cv::cvtColor(orgImage, dstImage, int code)

 

원본 이미지를 그레이 색상 이미지로 변환한다. code는 원본의 color space를 어떤 color space로 변환할지 지정한다.

그레이 색상 space로 변환하기 위해, COLOR_BGR2GRAY를 사용했다.

openCV 에서는 색상이 들어간 이미지 또는 영상을 소스로 다루기 때문에, 색에 관한 지식이 조금 필요하다.

 

색의 3원소 RGB

 

이 세상에 존재하는 색의 구성은 일반적으로 RGB(Red, Green, Bule)의 용어로 많이 알려져 있다.

openCV에서 마찬가지다. 하지만 그 순서가 조금 다른다. BGR(Blue, Green, Red)의 순서로 (내장 매크로 변수(?)가 선언되어있다.

그래서 "BGR2GRAY" 이런 식으로 변수 명이 지어져 있다.

 

	...
    
	string path = "Resources/road.jpeg";
	Mat img = imread(path);
	Mat imgResize, imgGray;

	// resizing
	resize(img, imgResize, Size(), 0.5,0.5);
    
	// Change to Gray Scale
	cvtColor(imgResize, imgGRAY, COLOR_BGR2GRAY);
    
	imshow("Image Resize", imgResize);
	imshow("Image Gray", imgGRAY);
    
	// 이미지가 바로 사라지기 때문에 시간을 부여, 0은 무한대를 의미한다.
	waitKey(0);
	
	...

 

 

GRAY SCALE 결과

 

2. HSV 스케일링

그레이 스케일링과 같은 방법을 사용한다. 하지만, cvtColor의 마지막 인수(int code)만 다른다.

 

COLOR_BGR2GRAY  → COLOR_BGR2HSV

 

여기서 HSV는 Hue, Saturation, Value를 나타낸다. 순서대로 색조, 채도, 명도를 나타내는 변수가 된다. BGR color space와는 다르게, 디테일 있게 채도 명도를 고려해서 색을 표현할 수 있게 된다.

 

 

RGB vs HSV Color Space

 

HSV 상판 가장 외곽에 있는 원주방향 띠 한 칸이, RGB 대표색 요소를 나타내는 부분이 되고, 나머지는 색조, 채도, 명도 차이에 따라 그 성분이 달라지는 게 아닌가? 하는 느낌이다.

 

그래서 어디에 사용하나?

당연히 색상 검출(detection)에 사용된다. 이미지 또는 영상에서 접하게 되는 여러 소스들은 그 색상을 한 가지 요소로 딱 표현하기란 쉬운 일이 아니다. 그래서 검출하고자 하는 대상의 색상을 HSV 범위를 지정, 필터링함으로써 추상화해 나갈 수 있다. 해당 내용은 추후 다룰 수 있을 것 같다. 

 

 ⭕️ 엣지검출

카메라를 이용한 자율주행에서는 차선을 감지 후, 해당 정보를 차량의 조향, 주행 시스템과 보정함으로써 조타를 결정하거나 차선을 안정적으로 유지할 수 있게 해 준다. 그럼 먼저 차선을 검출해야 할 텐데, 그 과정에서 수행될 수 있는 엣지검출 방법을 공부해보자.

 

Edge Detection algorithm의 키워드로 검색해 보면, 알고리즘으로 꽤나 많이 검색된다. 그중에서도 다음 내용을 추가로 읽어봤다.

 

 Comparing Edge Detection Methods(Medium)
  • Sobel edge detector

  • Prewitt edge detector

  • Laplacian edge detector

  • Canny edge detector

 

기본적인 원리는, 픽셀에 대해서 횡방향 종방향의 픽셀 Gradient를 계산 후, 특정 kernel(행렬을 나타내는 듯?)을 통과시킨다. 그러고 나서, 각 알고리즘 수법에 맞게 마스킹 또는 엣지 化(이미지에 남겨두기)를 해서 이미지의 엣지를 검출하는 것 같다. 자세한 내용을 원본 글을 참고하자! 

 

여기서는 그중에 가장 일반적이고, 많이 사용되는 Canny edge detector를 사용해 엣지를 검출한다.

엣지 검출을 위해서 원본 이미지의 전처리 작업(Pre-Processing)이 필요하게 되는데, 픽셀 그래디언트(미분하여 계산함)를 구할 때 노이즈를 최소화하기 위해, 이미지를 Blur처리(희미하게, 번짐 효과를 주는 것)를 해 준다.

 

1. 블러(Blur) 처리

GaussiasnBlur(orgImage, dstImage, kernelSize, 0)

 

이미지의 인접한 픽셀끼리 그 경계가 부드러워지는 효과를 준다. kernelSize는 홀수 개수의 행, 열 을 가져야 한다.

예를 들어, 3 X 3 또는 5 X 5처럼 구성한다. 구성된 행과 열의 표준편차가 계산되며 블러 효과를 주는 데 사용된다.

 

	...

	Mat imgResize, imgGray, imgBlur;

	... 
	
	// Change to Gray Scale
	cvtColor(imgResize, imgGRAY, COLOR_BGR2GRAY);
    
	// Blur the Image
	GaussianBlur(imgGRAY, imgBlur, Size(3,3),0);
    
	imshow("Image Gray", imgGRAY);
	imshow("Image Blur", imgBlur);
    
	...

 

이론적으론 정확하게 설명하긴 어렵지만, Gaussian kenel 사이즈를 증가시킬수록, 블러 효과의 정도가 점점 강해진다.

다른 말로 예를 들면, 촘촘하게 몰려있던 엣지들 중에 점점 부드러운 효과가 생겨, 뭉개져 보이게 될 것이다. 그렇게 되면, 엣지 검출 시 가장 외곽에 있는 라인들만 검출되지 않을까?라는 생각을 할 수 있다.

 

아래 사진의 나무를 주목해보자. 미미하지만 차이가 느껴지는가?

 

(좌):원본, (중앙): 3X3 kernel, (우): 5X5 kernel

 

2. 엣지 검출, Canny Edge Detector 

Canny(orgImage, dstImage, low_threshold, high_threshold)

 

블러 된 이미지를 소스로 엣지를 검출한다. 엣지로 판단하기 위해, 하한&상한 값을 입력해준다. 여기서 입력해준 경곗값이라는 것이 픽셀 그래디언트의 경곗값을 설정해주는 것인지.. 조사해봤지만 아직 정확하진 않다. 어떤 느낌인지는 알겠는데, 정확한 내용이 머리에 들어오지 않습니다. 🤮 

아무튼 정해준 경계값을 벗어나면 검정, 경계 안이면 엣지로 검출하여 흰색으로 표시된다.

 

	...

	Mat imgResize, imgGray, imgBlur, imgCanny;

	... 
    
	// Blur the Image
	GaussianBlur(imgGRAY, imgBlur, Size(3,3),0);
    
	// Go Canny detector
	Canny(imgBlur, imgCanny, 25, 75);
    
	imshow("Image Blur", imgBlur);
   	imshow("Image Canny", imgCanny);
    
	...



 

캐니 검출기로 엣지 검출

 

앞서 진행한 블러 처리에서 kernel 사이즈를 달리하여 출력했었다. 각 이미지 소스를 이용해서 노이즈를 어떻게 처리하는지 확인해보자.

 

(좌): 3X3 kernel 사이즈, (우): 5X5 kernel 사이즈

 

결과에서 알 수 있듯이, 5X5 kernel 사이즈를 적용한 이미지에서 노이즈가 적은 상태로 엣지를 검출하고 있다.

 

🙇🏻‍♂️ 기초 이미지 처리를 학습 후 openCV의 느낌?

라이브러리 조금 공부하면 머신러닝 돌아갈 줄 알았다. 그런데 아니다. 이미지 처리는 사용자에 의해서 별도로 수행되는 것이고, 머신 비전에서의 머신러닝은 이미지 처리 작업을 학습시키는 알고리즘에 적용하는 형태라고 생각된다. openCV안에 비전 소스를 기반으로 하는 머신러닝 기능이 있을 거라 생각되지만, 아직 그런 걸 공부할 단계가 아닌 것 같다. 먼저, 기본적인 이미지 처리, 검출(detection)에 대한 개념을 익힌 후, 머신러닝 기능/개념으로 진입하면 이질감이 없지 않을까 하는 개인적인 생각이다.

반응형