픽셀 기반 영상처리와 영역 기반 영상처리가 무엇인가?
by 효기’s
python을 사용하여 openCV 영상처리 실습
배경 내에 검정 좌표를 이동시키는 방법 (픽셀 값을 읽고 바꾸기)
import cv2 import numpy as np img = cv2.imread('images/scene2.jpg', cv2.IMREAD_GRAYSCALE) #이미지를 Grayscale로 읽는다 cv2.imshow('Image Processing', img) print(img.shape) px = img[200,200] print(px) img[100:210,100:210] = 0 #[배경상단 100 : 세로, 배경좌측 100 : 가로] cv2.imshow('Results', img) cv2.waitKey(0) cv2.destroyAllWindows()

픽셀 값과 컬러 영상을 읽는다.
import cv2 import numpy as np img = cv2.imread('images/scene2.jpg', cv2.IMREAD_COLOR) #이미지파일을 컬러로 읽어들인다. cv2.imshow('Image Processing', img) print(img.shape) px = img[100,100] print(px) img[100:110,100:110] = 0 # black img[110:120,110:120] = [255,255,255] # white (컬러를 바꾸고 싶으면 이부분을 수정해본다) cv2.imshow('Results', img) cv2.waitKey(0) cv2.destroyAllWindows()

컬러 영상을 읽고 red, green, blue 채널을 분리한다.
import cv2 import numpy as np img = cv2.imread('images/fruits.png', cv2.IMREAD_COLOR) #이미지 파일을 읽어들인다. cv2.imshow('Image Processing', img) # b,g,r = cv2.split(img) # img = cv2.merge((b,g,r)) # split()함수보다 numpy indexing이 빠르다. b = img[:,:,0] #파란색(blue) 채널분리 g = img[:,:,1] #녹색 (green) 채널분리 r = img[:,:,2] #빨간색 (red) 채널분리 cv2.imshow('Blue', b) cv2.imshow('Green', g) cv2.imshow('Red', r) cv2.waitKey(0) cv2.destroyAllWindows()

산술연산 ( 각 픽셀에 +, -, *, / )
import cv2 import numpy as np img = cv2.imread('images/scene2.jpg', cv2.IMREAD_GRAYSCALE) cv2.imshow('Image Processing', img) img_plus = cv2.add(img, 50,) # cv2연산은 saturated 연산이어서 255보다 크면 255로 고정됨 img_minus = cv2.subtract(img, 50) # cv2연산은 saturated 연산이어서 0보다 작으면 0으로 고정됨 img_mul = cv2.multiply(img,2) img_div = cv2.divide(img,2) # img_plus = img + 50 #이것도 가능하나, 0~255로 변환이 필요하다. img_pp = np.clip(img+50., 0, 255).astype(np.uint8) # opencv에는 이외에도 max(), min(), minMaxLoc(), # bitwise_and(), bitwise_or() 등 다양한 함수를 제공한다. cv2.imshow('ResultsP', img_plus) #+ cv2.imshow('ResultsM', img_minus) #- cv2.imshow('ResultsMu', img_mul) #* cv2.imshow('ResultsD', img_div) #/ cv2.imshow('ResultsPP', img_pp) cv2.waitKey(0) cv2.destroyAllWindows()

색이 있는 산술연산 ( 각 픽셀에 +, -, *, / )
import cv2 import numpy as np img = cv2.imread('images/scene2.jpg', cv2.IMREAD_COLOR) cv2.imshow('Image Processing', img) img_plus = cv2.add(img, (50,50,50,0)) # cv2연산은 saturated 연산이어서 255보다 크면 255로 고정됨 img_minus = cv2.subtract(img, (50,50,50,0)) # cv2연산은 saturated 연산이어서 0보다 작으면 0으로 고정됨 img_mul = cv2.multiply(img,(2,2,2,0)) img_div = cv2.divide(img,(2,2,2,0)) # opencv에는 이외에도 max(), min(), minMaxLoc(), # bitwise_and(), bitwise_or() 등 다양한 함수를 제공한다. cv2.imshow('ResultsP', img_plus) #+ cv2.imshow('ResultsM', img_minus) #- cv2.imshow('ResultsMu', img_mul) #* cv2.imshow('ResultsD', img_div) #/ cv2.waitKey(0) cv2.destroyAllWindows()

이진화 (Thresholding)
import cv2 import numpy as np img = cv2.imread('images/apples.jpg', cv2.IMREAD_GRAYSCALE) cv2.imshow('Image Processing', img) #cv2.THRESH_BINARY : 픽셀 값이 임계값을 넘으면 value로 지정하고, 넘지 못하면 0으로 지정 ret, img_binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 127임계값, 255 픽셀값 # 최적의 임계값을 찾아주는 otsu의 알고리즘 적용 ret, img_otsu = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) cv2.imshow('ResultsB', img_binary) cv2.imshow('ResultsO', img_otsu) cv2.waitKey(0) cv2.destroyAllWindows()

적응적 이진화 (adaptiveThreshold)
import cv2 import numpy as np img = cv2.imread('images/sudoku.jpg', cv2.IMREAD_GRAYSCALE) cv2.imshow('Image Processing', img) blk_size = 9 # 블럭 사이즈 C = 5 # 차감 상수 ret, img_otsu = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) img_a1 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY, blk_size, C) img_a2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, blk_size, C) cv2.imshow('Results Otsu', img_otsu) #OTSU 알고리즘을 적용 cv2.imshow('Results Adaptive1', img_a1) #적응적 이진화 : 이웃 픽셀의 평균으로 결정 cv2.imshow('Results Adaptive2', img_a2) #적응적 이진화 : 가우시안 분포에 따른 가중치의 합으로 결정 cv2.waitKey(0) cv2.destroyAllWindows()

히스토그램
import cv2 import numpy as np import matplotlib.pylab as plt # 이미지 그레이 스케일로 읽기 및 출력 img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE) cv2.imshow('Image Processing', img) # 히스토그램 계산 및 그리기 # 이미지 리스트에 감싸서 전달, 분석 처리 할 채널 리스트에 감싸서 전달, # 마스크에 지정한 픽셀만 히스토그램 계산 None이면 전체영역, 계급(Bin)의 개수 채널 개수에 맞게 리스트로 표현, 픽셀이 가질 수 있는 값의 범위 RGB인경우 [0, 256] hist = cv2.calcHist([img], [0], None, [256], [0,256]) plt.plot(hist) #히스토그램 출력 print("hist.shape:", hist.shape) # 히스토그램의 shape (256,1) print("hist.sum():", hist.sum(), "img.shape:",img.shape) # 히스토그램 총 합계와 이미지의 크기 plt.show()

컬러 영상의 히스토그램
import cv2 import numpy as np import matplotlib.pylab as plt # 컬러영상 img = cv2.imread('images/Lenna.png', cv2.IMREAD_COLOR) cv2.imshow('Image Processing', img) # 히스토그램 계산 및 그리기 channels = cv2.split(img) colors = ('b', 'g', 'r') for (ch, color) in zip (channels, colors): hist = cv2.calcHist([ch], [0], None, [256], [0, 256]) plt.plot(hist, color = color) plt.show()

히스토그램 평활화
import cv2 import numpy as np import matplotlib.pylab as plt # 그레이 스케일로 읽기 img = cv2.imread('images/low_contrast.jpg', cv2.IMREAD_GRAYSCALE) rows, cols = img.shape[:2] # 히스토그램 평활화 계산 hist = cv2.calcHist([img], [0], None, [256], [0, 256]) # 히스토그램 계산 cdf = hist.cumsum() # 누적 히스토그램 cdf_m = np.ma.masked_equal(cdf, 0) # 0(zero)인 값을 NaN으로 제거 cdf_m = (cdf_m - cdf_m.min()) /(rows * cols) * 255 # 이퀄라이즈 히스토그램 계산 cdf = np.ma.filled(cdf_m,0).astype('uint8') # NaN을 다시 0으로 환원 print(cdf.shape) img2 = cdf[img] # 히스토그램을 픽셀로 맵핑 # OpenCV API로 이퀄라이즈 히스토그램 적용 img3 = cv2.equalizeHist(img) # 이퀄라이즈 결과 히스토그램 계산 hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256]) hist3 = cv2.calcHist([img3], [0], None, [256], [0, 256]) # 결과 출력 cv2.imshow('Before', img) cv2.imshow('Manual', img2) cv2.imshow('cv2.equalizeHist()', img3) hists = {'Before':hist, 'Manual':hist2, 'cv2.equalizeHist()':hist3} for i, (k, v) in enumerate(hists.items()): plt.subplot(1,3,i+1) plt.title(k) plt.plot(v) plt.show()

컬러영상 히스토그램 평활화
import cv2 import numpy as np import matplotlib.pylab as plt # 컬러영상 읽기 img = cv2.imread('images/cute.jpg', cv2.IMREAD_COLOR) # 컬러공간을 HSV로 변경 img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # V(밝기값) 공간에 히스토그램 평활화 적용 img_hsv[:,:,2] = cv2.equalizeHist(img_hsv[:,:,2]) # 컬러공간을 RGB로 원위치 img2 = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR) b, g, r = cv2.split(img) b = cv2.equalizeHist(b) g = cv2.equalizeHist(g) r = cv2.equalizeHist(r) img3 = cv2.merge((b,g,r)) # 결과 출력 cv2.imshow('Before', img) cv2.imshow('After', img2) cv2.imshow('RGB', img3) cv2.waitKey() cv2.destroyAllWindows()

영역기반 영상처리
입력 픽셀과 그 주변 픽셀을 이용하여 출력 픽셀 값을 결정
합성곱 기법을 널리 이용
ex) 흐리게하기, 선명하게하기, 경계산 검출, 노이즈 제거
합성곱 (Convolution) 필터 적용으로 영상 흐림
합성곱 : 하나의 함수와 다른 함수를 반전 이동한 값을 곱하고 구간에 대해 적분하여 새로운 함수를 구하는 수학 연산자(회선)
콘볼루션 : 함수 f가 주어졌을 떄 우리가 원하는 목적에 따라 함수 g를 선정하여 분해, 변환, 필터링 할 수 있다.
합성곱 영상처리 : 입력 픽셀과 주위 픽셀 값에 합성곱 마스크의 값을 곱하여 더한 값을 출력 픽셀 값으로 정한다.
합성곱하는 함수 : 마스크(mask), 필터(filter), 템플릿(template), 커널(kernel)
마스크가 데칭이므로 실제 연산은 correlation(상관) 과 같다.
import cv2 import sys import numpy as np img = cv2.imread('images/Lenna.png', cv2.IMREAD_COLOR) if img is None: print('영상 읽기 실패') sys.exit() size = 7 #사이즈를 조절하면 흐림 정도 조절가능 높을수록 흐림 kernel = np.ones((size, size), dtype=np.float64) / (size*size) result = cv2.filter2D(img, -1, kernel) cv2.imshow('Original', img) cv2.imshow('Result', result) cv2.waitKey() cv2.destroyAllWindows()

합성곱 (Convolution) 마스터
# blur()함수로 영상 흐림 import cv2 import sys import numpy as np img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE) if img is None: print('영상 읽기 실패') sys.exit() result3 = cv2.blur(img, (3,3)) result5 = cv2.blur(img, (5,5)) cv2.imshow('Original', img) cv2.imshow('Result3', result3) cv2.imshow('Result5', result5) cv2.waitKey() cv2.destroyAllWindows()
합성 곱 마스터 특징 : 픽셀 주변을 대칭적으로 계산하므로 홀수 값을 사용(3 * 3, 5 * 5)
마스크 계수의 합은 1또는 0이 되도록 함
0 -1 0
-1 5 -1
0 -1 0

경계 계산 : 0으로 계산, 이웃 픽셀 값 복사, wrap-around 등, 경계선 안쪽에서만 합성곱 계산, 계산 안된 부분은 그대로
영상 흐리게 하기 (Blurring) : 영상의 노이즈를 없애거나, 부드럽게 한다(smoothing), 평균값, 가우시안, 중간값 등의 필터 사용
평균값 필터로 흐리게 하기 : 영상의 노이즈는 없애지만 명암비는 낮아짐 (일반적인 잡티를 없앨 수 있음)
가우시안 필터로 흐리게하기
중앙 픽셀의 가중치가 높음 (영상의 중요 부분 보전 하면서 흐려짐)
# GaussianBlur()함수로 영상 흐림 import cv2 import sys import numpy as np img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE) if img is None: print('영상 읽기 실패') sys.exit() # sigma 지정 result1 = cv2.GaussianBlur(img, (0,0), 1) result3 = cv2.GaussianBlur(img, (0,0), 3) # ksize 지정, mean smoothing과 비교 resultB = cv2.blur(img, (5,5)) #평균값필터 resultG = cv2.GaussianBlur(img, (5,5), 0) cv2.imshow('Original', img) cv2.imshow('Result_S_1', result1) cv2.imshow('Result_S_3', result3) cv2.imshow('Result_mean', resultB) #평균값필터 cv2.imshow('Result_Gaussian', resultG) cv2.waitKey() cv2.destroyAllWindows()

중간값 필터 (Median) 필터
비전형 필터, 이웃 픽셀들 값을 오름차순으로 정렬한 수 중앙에 있는 값을 출력 값으로 선택
노이즈 제거에 효과적
# Median Filtering 중간값 필터 import cv2 import sys import numpy as np # img = cv2.imread('images/Lenna.png', cv2.IMREAD_GRAYSCALE) # img = cv2.imread('images/pns.jpg', cv2.IMREAD_GRAYSCALE) img = cv2.imread('images/gnoise.jpg', cv2.IMREAD_GRAYSCALE) if img is None: print('영상 읽기 실패') sys.exit() # sigma 지정 result3 = cv2.medianBlur(img, 3) result5 = cv2.medianBlur(img, 5) # ksize 지정, mean smoothing과 비교 resultB = cv2.blur(img, (5,5)) resultG = cv2.GaussianBlur(img, (5,5), 0) cv2.imshow('Original', img) cv2.imshow('Result_3', result3) #중간값 필터3 cv2.imshow('Result_5', result5) #중간값 필터5 cv2.imshow('Result_mean', resultB) #평균값필터 cv2.imshow('Result_Gaussian', resultG) #가우시안필터 cv2.waitKey() cv2.destroyAllWindows()


블로그의 정보
감성 개발자 효기
효기’s