Python과 Tello Drone 자율주행
Part1. OpenCV와 영상처리
영상처리(Image Processing)란?
입출력이 영상인 모든 형태의 정보 처리
OpenCV란?
영상처리와 컴퓨터 비전을 위한 오픈소스 라이브러리로 C, C++, Python 등에서 사용 가능하다.
💡 영상처리의 기본 과정
1. 영상 입력받는다.
2. 영상 데이터를 전처리한다.
3. 전처리된 영상 데이터에서 특징을 추출한다.
4. 추출된 특징으로 정보를 해석하거나 인식한다.
우리가 앞선 메뉴얼에서 실행해보았던 video_effect.py를 실행하면 카메라로 추출되는 영상과 Canny Edge 영상이 잘 나올 것이다. 해당 예제 파일에서 tellopy의 get_video_stream, av의 open, cv2의 imshow 등의 라이브러리와 함수를 사용하여 스트림을 추출하도록 명령해주었기 때문이다. 이 부분이 영상처리의 과정 중 “영상을 입력받는다.” 부분에 해당한다.
Tello의 자율주행을 위해서는 2, 3, 4번 단계를 효율적이고 정확하게 수행하는 것이 중요할 것이다. 이러한 테스크들을 수행하기 위해서는 영상 데이터가 어떻게 표현되는지 알아보도록 하자.
Part2. 영상 처리의 이해 및 필터링
영상 처리의 이해
영상은 수학적으로는 2차원 함수 f(x,y)로 정의될 수 있으며, f의 값이 해당 좌표에서의 영상의 밝기 즉, 픽셀을 뜻한다. 이러한 픽셀은 이미지의 가장 작은 단위이며, 특정 위치에서의 색상 정보를 나타낸다. 각 색상 채널의 강도를 조합하여 픽셀의 색상이 결정된다.
흑백 영상의 경우 각 픽셀은 0부터 255까지의 값을 갖는 그레이스케일로 표현된다. 검정에 가까울수록 0에 가까워지며 어둡고, 흰색에 가까울수록 255에 가까워지며 밝다. 따라서 각 픽셀의 밝기를 그레이스케일 값으로 나타낼 수 있다. 흑백 영상의 크기는 (이미지 너비*이미지 높이*1)이다.
컬러 영상의 경우, 각 픽셀은 빨강(R), 초록(G), 파랑(B) 채널의 각각의 강도값을 가지게 된다. 컬러 영상의 크기는 (이미지 너비*이미지 높이*3)이다. 컬러 영상의 밝기를 나타내는 방법은 보통 픽셀의 R, G, B 값 또는 평균 값을 사용하여 표현한다.
영상처리의 잡음
영상 처리의 관점에서 잡음(noise)이란 원본 신호에 추가된 원치 않은 신호를 뜻한다. 영상에서 잡음은 주로 영상을 획득하는 과정 즉, 입력 과정에서 많이 발생한다. 우리가 앞으로 미션을 잘 수행하기 위해서는 이러한 영상 처리 잡음을 제거하는 것이 중요하다. 입력된 영상/이미지 등에서 원하는 특징을 잘 추출하기 위해 전처리 과정이 필요한데, 이러한 전처리 과정을 필터링(filtering)이라고 한다.
필터링(filtering)이란?
입력 받은 영상에서 원하는 정보만 통과시키고 원하는 정보는 걸러내는 작업을 말한다.
필터링의 방법에는 아래 2 가지 방법이 있다.
1. 영상의 잡음을 제거하여 영상을 깔끔하게 만든다.
2. 부드러운 느낌의 성분을 제거하여 날카로운 느낌이 들도록 한다.
영상의 필터링은 마스크(mask)라고 불리는 작은 크기의 행렬을 이용한다. 마스크는 필터링의 성격을 정의하는 행렬로 커널(kernel), 윈도우(window)라고도 부른다.
여러가지 전처리 방법
1. 명암 변환
명암 변환은 영상의 픽셀값에 연산을 하는 방식이다. 단순히 이미지에 +, - 등의 연산을 통해 수행할 수 있다. 아래 예시는 픽셀값 조정을 통해 이미지를 밝게한 것이다.
2. 이미지 필터링을 위한 가우시안 필터(Gaussian filter)
가우시안 필터는 이미지 처리에서 주로 사용되는 필터 중 하나로, 이미지의 잡음을 줄이거나 이미지를 부드럽게 만들기 위해 사용된다. 이 필터의 이름에서 나타나는 것처럼 가우시안 분포(Gaussian distribution) 함수를 근사하여 생성한 필터 마스크를 사용하는 필터링 기법이다. 가우시안 분포는 우리가 흔히 알고있는 정규분포(normal distribution)이다.
따라서 가우시안 분포는 평균과 표준 편차에 따라 분포 모양이 결정된다. 영상의 가우시안 필터에서는 주로 평균이 0인 가우시안 분포 함수를 사용한다. OpenCV에서 가우시안 필터링을 수행하기 위해 GaussianBlur() 함수를 제공한다.
Python 언어를 통한 사용법은 다음과 같다.
cv2.GaussianBlur(src, ksize, sigmaX, sigmaY)
# src: 입력 영상
# ksize: 가우시안 커널 크기
# sigmaX: x 방향으로의 가우시안 커널 표준 편차
# sigmaY: y 방향으로의 가우시안 커널 표준 편차
3. 영상의 이진화(binarization)
공학을 배운 사람이라면 이진화에 대한 개념은 익숙할 것이다. 영상에서의 이진화란 영상의 각 픽셀을 2 개의 부류로 나누는 작업을 말한다. 예를 들어 영상에서 중요도가 높은 관심 영역(ROI)과 비관심 영역으로 구분하는 등의 용도로 이러한 이진화 작업을 수행한다.
다만, 영상에서의 이진화는 0과 1로 설정하는 것이 아닌 픽셀값을 0 또는 255로 설정하는 것이다. 이를 통해 이진화가 적용된 이진 영상은 흰색과 검정 픽셀로 구분되는 것을 알 수 있다.
OpenCV에서 이진화를 위한 threshold() 함수를 제공한다.
threshold는 임계값을 뜻하는데 픽셀 크기 비교 대상이 되는 값을 뜻한다. 임계값은 그레이스케일 범위인 0부터 255까지 사이의 임의의 정수이다. 이러한 비교 대상을 통해 이진화를 수행할 수 있다.
cv2.threshold(src, thresh, maxval, type)
# src: 입력 영상
# threshold_value: 임계값
# maxval: 결과 영상의 최댓값
# type: 임계값 함수 동작 지정 및 자동 임계값 결정 방법 지정
영상의 이진화 예제 코드 (https://sunkyoo.github.io/opencv4cvml/)
src = cv2.imread('cells.png', cv2.IMREAD_GRAYSCALE)
if src is None:
print('Image load failed!')
sys.exit
# 트랙바 함수 정의
def on_threshold(pos):
_, dst = cv2.threshold(src, pos, 255, cv2.THRESH_BINARY)
cv2.imshow('dst', dst)
cv2.imshow('src', src)
cv2.namedWindow('dst')
cv2.createTrackbar('Threshold', 'dst', 0, 255, on_threshold) # 임계값 범위 0~255
cv2.setTrackbarpos('Threshold', 'dst', 128) # 임계값 초기값 128
cv2.waitKey()
cv2.destroyAllWindows()
4. Edge 검출
에지 검출은 우리가 앞서 보았던 video_effect.py에서도 확인 가능하며, 선발 시험에도 출제되었다. 에지는 픽셀 값이 급격하게 변화하는 부분을 말한다. 따라서 에지 검출 결과를 통해 영상 특징을 많이 뽑아낸다. 대표적으로 쓰이는 Canny 에지 검출은 OpenCV의 Canny 함수로 쉽게 구현이 가능하며, 이외에도 다양한 함수와 알고리즘 등이 존재한다.
Canny Edge 검출 예제 코드 (https://sunkyoo.github.io/opencv4cvml/)
src = cv2.imread('building.jpg', cv2.IMREAD_GRAYSCALE) # 그레이 스케일 영상
if src is None:
print('Image load failed!')
sys.exit()
dst = cv2.Canny(src, 50, 150) # 하단 임계값과 상단 임계값은 실험적으로 결정하기
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
'ML > OpenCV' 카테고리의 다른 글
[자율주행] djitellopy & opencv Object Detection - (2) (1) | 2023.08.06 |
---|---|
[자율주행] djitellopy & opencv Object Detection - (1) (0) | 2023.08.06 |
[자율주행] Tello SDK 환경 세팅 | 간단한 이착륙 코드 | OpenCV 비디오 스트림 (0) | 2023.07.31 |