-
[CHAPTER 13] OpenCVDeep Learning/인공지능 입문 코딩 2021. 6. 6. 16:28728x90
이미지를 다루는 모듈, OpenCV에 대해 살펴보자
이미지 읽기
cv2.imread() 함수를 사용해 이미지를 읽고
cv2.imshow() 함수를 사용해 이미지를 그릴 수 있다.
import cv2 img_gray = cv2.imread('../data/mandrill.png', cv2.IMREAD_GRAYSCALE) img_color = cv2.imread('../data/mandrill.png', cv2.IMREAD_COLOR) cv2.imshow('grayscale', img_gray) cv2.imshow('color', img_color) cv2.waitKey(0) # 사용자 입력을 기다림 cv2.destroyAllWindows() # 모든 창을 없애고 프로그램 종료
합성사진
img1, im2를 합성해보자.
addWeighted() 함수를 이용해서 각 이미지의 weigth를 조절한다.
createTrackbar() 함수는 트랙바(trackbar)를 만들 수 있는데 이 트랙바를 조절하면서 이미지의 weight 를 조절하도록 만들었다.
주의할 점은 합성할 이미지의 사이즈가 같아야한다는 것이다.
import cv2 global img1, img2 def on_change_weight(x): weight = x / 100 img_merged = cv2.addWeighted(img1, 1 - weight, img2, weight, 0) cv2.imshow('Display', img_merged) cv2.namedWindow('Display') cv2.createTrackbar('weight', 'Display', 0, 100, on_change_weight) img1 = cv2.imread('../data/green_back.png') img2 = cv2.imread('../data/iceberg.png') img1 = cv2.resize(img1, (300, 400)) img2 = cv2.resize(img2, (300, 400)) cv2.imshow('Display', img1) cv2.waitKey(0) cv2.destroyAllWindows()
이미지 마스크
이미지에 and, or, xor 연산을 해보자.
mask 이미지의 검정부분은 1, 흰색 배경부분은 0이다.
import cv2 mask_image = cv2.imread('../data/mask_circle.png') back_image = cv2.imread('../data/iceberg.png') mask_image = cv2.resize(mask_image, (300, 400)) back_image = cv2.resize(back_image, (300, 400)) mask_ANDed = cv2.bitwise_and(mask_image, back_image) mask_ORed = cv2.bitwise_or(mask_image, back_image) mask_XORed = cv2.bitwise_xor(mask_image, back_image) mask_Inverted = cv2.bitwise_and(cv2.bitwise_not(mask_image), back_image) cv2.imshow('mask', mask_image) cv2.imshow('back', back_image) cv2.imshow('mask and', mask_ANDed) cv2.imshow('mask or', mask_ORed) cv2.imshow('maskxor', mask_XORed) cv2.waitKey(0) cv2.destroyAllWindows()
bitwise_and() 비트단위로 AND연산을 하는 함수이다.
마스크의 검은 부분은 0이니까 0 AND x = 0 이므로
따라서 왼쪽의 그림과 같은 결과가 나온다.
bitwise_or() 비트단위로 OR연산을 하는 함수이다.
마스크의 배경 흰색 부분은 1이다. 1 OR x = 1 이고
마스크의 검은 부분은 0이다. 0 OR x = x 이므로 오른쪽의 그림과 같은 결과가 나온다.
1 XOR 1 = 0, 1 XOR 0 = 1
1과 XOR 연산을 하면 반전이 되는 결과가 나온다.
따라서 배경은 색이 반전이 되었고
0 XOR 1 = 1, 0 XOR 0 = 0
0과 XOR 연산을 하면 그대로 나온다. 따라서 왼쪽의 그림과 같은 결과가 나온다.
원하는 색 추출
mandrill.png madrill.png 에서 푸른색만 추출해 보려고한다.
푸른색 픽셀만 추출할 때에는 RGB나 BGR 방식의 색상 모드 보다는 HSV 방식이 더 적합하다.
HSV는 색상의 범위를 0도에서 360도로 표현한다.
0에서 360사이의 정수로 표현한다면 한 바이트 이상이 필요하다.
그래서 이미지 파일에서는 이 값을 반으로 줄여 0도에서 180도로 표현한다.
구글에서 color picker를 검색하면 HSV의 색상을 얻을 수 있다.
cvtColor() 함수는 OpenCV의 기본 이미지모드는 BGR 모드에서 원하는 모드로 바꿔주는 함수이다.
HSV로 변경할 것이다.
푸른색의 범위는 160 ~ 260이다. 반으로 나눈 값 80 ~ 130 을 범위로 쓸 것이다.
명도 채도는 0~255로 모든 범위를 지정해 최소값을 blue_low 최대값을 blue_high에 저장했다.
inRange() 함수를 이용해 특정이미지 image_hsv에서 blue_low와 blue_high 사이의 픽셀들을 찾아낸다.
import numpy as np import cv2 image = cv2.imread('../data/mandrill.png') image_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) blue_low = np.array([80, 0, 0]) blue_high = np.array([130, 255, 255]) my_mask = cv2.inRange(image_hsv, blue_low, blue_high) extracted = cv2.bitwise_and(image, image, mask=my_mask) cv2.imshow('extracted', extracted) cv2.imshow('mask', my_mask) cv2.waitKey(0) cv2.destroyAllWindows()
my_mask(image, my_mask)라고 하지 않은 이유는 채널 수가 다르기 때문이다.
이러한 경우 같은 이미지로 and연산을한 뒤 mask인자로 my_mask를 전달하면 된다.
이미지 필터
커널(kernel)을 이용한 필터링을 알아보자.
커널이 아래와 같은 행렬 이라면
자신을 포함한 주위 8개의 픽셀의 합을 구해 평균을 취한다.
커널 필터링은 한 픽셀의 주위의 값을 고려하여 평균을 취하는 것이다. 그러면 전체적으로 부드러운 이미지가 된다.
이러한 처리를 이미지 흐림(blur) 이라고한다.
코드로는 3 x 3 행렬의 커널, 9 x 9 행렬의 커널을 만들어서 적용 시켜보자.
filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) 함수를 사용하면 된다.
ddepth에 -1을 주면 주어진 입력 이미지와 동일한 값이 돤다.
import numpy as np import cv2 org = cv2.imread('../data/mandrill.png', 1) kernel1 = np.ones((3, 3), np.float32) / 9 kernel2 = np.ones((9, 9), np.float32) / 81 averaged33 = cv2.filter2D(org, -1, kernel1) averaged99 = cv2.filter2D(org, -1, kernel2) cv2.imshow('original', org) cv2.imshow('filtered1', averaged33) cv2.imshow('filtered2', averaged99) cv2.waitKey(0) cv2.destroyAllWindows()
커널이 클 수록 더 많이 흐려지는 것을 볼 수 있다. 적당한 값을 적용 시키는게 중요한 것 같다.
가우스 필터
가우스 필터는 평균치를 적용하는게 아닌 중앙값에 더 높은 가중치를 주는 필터이다.
cv2.GaussianBlur(src, ksize, sigmaX[, dst[, simgmaY[, borderType]]]) 함수를 사용하면 된다.
ksize는 커널의 크기, sigmaX는 x축 방향으로의 정규분포 표준편차이다. 네 번째 인자부터는 선택사항이다.
dst는 결과가 출력될 이미지, sigmaY는 y축 표준편차이다.
import cv2 org = cv2.imread('../data/mandrill.png', 1) averaged33 = cv2.GaussianBlur(org, (3,3), 1) averaged99 = cv2.GaussianBlur(org, (9,9), 1) cv2.imshow('original', org) cv2.imshow('Gaussian 33', averaged33) cv2.imshow('Gaussian 99', averaged99) cv2.waitKey(0) cv2.destroyAllWindows()
중앙값 흐림(median blur)
medan blur는 이미지에서 주위에 비해 튀는 작은 점들을 지우는 데에 효과적이다.
첫 번째 인자는 원본 이미지, 두번 번째 인자는 필터의 크기이다.
import cv2 original_image = cv2.imread('../data/salt_pepper.png', 0) result_image = cv2.medianBlur(original_image, 5) cv2.imshow('original_image', original_image) cv2.imshow('result', result_image) cv2.waitKey(0) cv2.destroyAllWindows()
양방향 필터(bilateral filter)
커널의 중심에서 얼마나 떨어져 있는가, 픽셀의 색상값이 얼마나 차이가 나는가 두가지를 고려한 것이 양방향 필터(bilateral filter)이다.
원본 이미지, 필터의 크기 가 첫 번째, 두 번째 인자로 전달되고
커널 함수의 퍼진 정도가 세 번째, 네 번째 인자로 전달된다.
3개의 필터를 비교해 보자.
import numpy as np import cv2 original_image = cv2.imread('../data/mandrill.png', 1) result_image1 = cv2.GaussianBlur(original_image, (9,9), 1) result_image2 = cv2.medianBlur(original_image, 9) result_image3 = cv2.bilateralFilter(original_image, 9, 50, 50) cv2.imshow('original_image', original_image) cv2.imshow('GaussianBlur', result_image1) cv2.imshow('medianBlur', result_image2) cv2.imshow('bilateralFilter', result_image3) cv2.waitKey(0) cv2.destroyAllWindows()
관심 있는 곳만 남겨보자.
candles.jpg 특정한 임계값 이상인 값은 유효한 값, 그렇지 않은 값은 유ㅜ효하지 않은 값으로 구분하여 작업이 필요할 때가 있다. 이러한 작업을 이진화(binarization)라고한다.
threshold() 함수를 이용하여 이진화를 할 수있다.
ret, result_image = threshold(src_image, thresh_value, maxValue, thresh_option)
ret , result : (사용된 임계값, 임계값을 적용하여 얻은 새로운 이미지)
src_image : 원본 이미지
thresh_value : 임계값,
maxValue : 이진화를 하여 픽셀을 최댓값으로 바꿀 때 이 값이 사용됨
thresh_option : 아래 6가지 옵션을 선택
- THRESH_BINARY : 조건 만족하는 픽셀 값은 최대, 만족하지 않는 픽셀값은 0
- THRESH_BINARY_INV : 조건 만족하는 픽셀 값은 0, 만족하지 않는 픽셀값은 최대
- THRESH_TRUNC : 조건 만족하는 픽셀 값은 최대, 만족하지 않는 픽셀값은 원본
- THRESH_TOZERO : 조건 만족하는 픽셀 값은 원본, 만족하지 않는 픽셀값은 0
- THRESH_TOZERO_INV : 조건 만족하는 픽셀 값은 0, 만족하지 않는 픽셀값은 원본
THRESH_OPTION import cv2 global color_image # 트랙바가 변경되면 그 값을 임계치로 이진화 def on_change_threshold(x): _, th_image = cv2.threshold(color_image, x, 255, cv2.THRESH_BINARY) cv2.imshow('Thresholding', th_image) # 윈도를 생성함 cv2.namedWindow('Thresholding') cv2.createTrackbar('threshold', 'Thresholding', 0, 255, on_change_threshold) # 촛불 이미지를 읽음 color_image = cv2.imread('../data/candles.jpg', cv2.IMREAD_COLOR) # 처음에는 원본 이미지를 그림 (트랙바를 변경하면 임계치에 따라 이진화 결과 출력) cv2.imshow('Thresholding', color_image) cv2.waitKey(0) cv2.destroyAllWindows()
윤곽선 뽑아내기
green_back.jpg 윤곽선은 주위에 비해 튀는 값을 가진 픽셀이다.
adaptiveThreshold() 함수를 사용하면 된다.
cv2.adaptiveThreshold(img, value, method, thresholdType, blocksize, C)
img : 원본 이미지
value : 조건을 만족하는 픽셀에 적용할 최대 값
method : 임계치를 결정하는 방법
ADAPTIVE_THRESH_MEAN_C : blockSize 영역의 모든 픽셀에 평균 가중치를 적용
ADAPTIVE_THRESH_GAUSSOAN_C : blockSize 영역의 모든 픽셀에 중심점으로부터의 거리에 대한 가우시안 가중치 적용
green_back.jpg에서 윤곽선을 뽑아내보자.
import cv2 global color_image img_gray = cv2.imread('../data/green_back.png', cv2.IMREAD_GRAYSCALE) # 5가 임계치가 되고, 이보다 크면 255 아니면 0 img_edge = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, blockSize=9, C=0) cv2.imshow('result', img_edge) cv2.waitKey(0) cv2.destroyAllWindows()
지금까지 배운 것들로
책에서 글자 추출하기
아래 book.png에 있는 글자만들 추출해보자.
book.png 먼저 book.png에 잡음을 제거하기 위해 bilateralFilter를 적용한 후,
adaptiveThreshold() 를 사용해 윤곽선 추출 즉, 글자를 추출한다.
import cv2 img = cv2.imread('../data/book.png') img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 잡음은 제거하면서 특징은 유지할 수 있는 양방향 필터 적용 blur_bilateral = cv2.bilateralFilter(img, 11, 75, 75) # 회색조로 변환 gray = cv2.cvtColor(blur_bilateral, cv2.COLOR_BGR2GRAY) # 인근 픽셀과 비교한 이진화 thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, 7) gray = cv2.cvtColor(gray, cv2.COLOR_BGR2RGB) thresh = cv2.cvtColor(thresh, cv2.COLOR_BGR2RGB) cv2.imshow('result',thresh) cv2.waitKey(0) cv2.destroyAllWindows()
728x90'Deep Learning > 인공지능 입문 코딩' 카테고리의 다른 글
[CHAPTER 15] 딥러닝 | TensorFlow (0) 2021.06.16 [CHAPTER 14] Machine Learning (0) 2021.06.10 [CHAPTER 12] 데이터 분석 | pandas (1) 2021.06.03 [CHAPTER 11] 데이터 시각화 | matplotlib (0) 2021.06.02 [CHAPTER 10]넘파이(numpy) (0) 2021.05.30