# 실습 1: OpenCV 기반의 간략형 실험 - averaging kernel을 사용한 filtering
def prt_mtx(a, fmt): # 어레이를 출력하는 함수
print(f"\n shape of the array={a.shape}")
for r in range(a.shape[0]):
for c in range(a.shape[1]):
print(f"{a[r, c]:{fmt}}", end="")
print()
cv.imshow('img', img)
N = 31
#N = 7
kernel = np.ones((N, N), np.float32)/(N * N) # N*N으로 나누어 정규화한다.
print(np.sum(kernel)) # 커널의 모든 원소의 값을 합하면 1이 된다. (출력 0.9999..)
np.set_printoptions(precision=3) # numpy 배열의 정밀도를 소수 이하 3자리로 제한하여 출력하는 것으로 설정한다.
print(kernel)
prt_mtx(kernel, '#6.2f')
# img 영상을 kernel로 필터링(코릴레이션 연산)하여 결과 dst를 반환한다.
# 출력 영상, dst는 shape가 입력 영상과 같다. => dst.shape=src.shape.
# -1은 출력 영상의 depth가 입력 영상과 같음을 의미한다. => dst.dtype=src.dtype.
dst = cv.filter2D(img, -1, kernel)
print('type(dst)=', type(dst), ' | dst.shape=', dst.shape, ' | dst.dtype=', dst.dtype )
cv.imshow('dst', dst)
cv.waitKey()
exit(0)
# 실습 2: matplotlib, OpenCV 기반의 실험 - averaging kernel을 사용한 filtering
1단계 : matplotlib를 적용해야 하므로 b와 r의 순서를 바꿔야한다
b, g, r = cv.split(img) # img파일을 b,g,r로 분리
img = cv.merge([r, g, b]) # b, r을 바꿔서 Merge
2단계 : 평균필터를 만든다. 1로채워진 필터 -> 정규화 (방법두개)
kernel = np.ones((N, N), np.float32) / (N * N)
kernel = np.ones((N, N), np.float32) # 커널 1로 채우기
kernel /= np.sum(kernel) # 커널의 합으로 나누어 커널의 합이 1이 되도록 정규화한다.
print(np.sum(kernel)0 # 커널의 총합이 1인지 확인
3단계 : correlation 연산 시행. 여러가지 옵션값들을 적용 가능하다.
#dst = cv.filter2D(img, -1, kernel, borderType=cv.BORDER_DEFAULT) # gfedcb|abcdefgh|gfedcba. 거울 반전
#dst = cv.filter2D(img, -1, kernel, borderType=cv.BORDER_REPLICATE ) # 맨 바깥 화소의 값이 중복된 것으로 간주.
dst = cv.filter2D(img, -1, kernel, borderType=cv.BORDER_ISOLATED ) # 경계처리 안함.
# 실습 3: matplotlib 기반의 실험 - averaging kernel을 사용한 filtering. 세로필터와 가로필터 적용해보기
1단계 : matplotlib를 적용해야 하므로 b와 r의 순서를 바꿔야한다
img = img[..., ::-1]
2단계 : Average filter Kernel 만들기. 1로채워진 필터 -> 정규화
* 이때 커널의 합이 1이 되도록 정규화해야함.
N = 51 # 필터링 강도
kernel_list = [] # 다수의 커널로 list 자료로 기록한다.
# 1) 1xN 커널 정의 - 가로로 averaging 한다.
kernel = np.ones((1, N), np.float32) / (N) # 주의!!! N으로 나누어 커널의 합이 1이 되도록 정규화한다.
print('np.sum(kernel)=', np.sum(kernel)) # 커널의 총합을 확인.
kernel_list.append(kernel)
print(kernel.shape)
# 2) Nx1 커널 정의 - 세로로 averaging 한다.
kernel = np.ones((N, 1), np.float32)
kernel /= np.sum(kernel) # 커널의 합으로 나누어 커널의 합이 1이 되도록 정규화한다.
print('np.sum(kernel)=', np.sum(kernel)) # 커널의 총합을 확인.
kernel_list.append(kernel)
만들어진 필터들의 정보와 내용 출력방법
print(type(kernel_list))
np.set_printoptions(precision=2) # 소수 이하 2자리까지 출력. 이하 0이면 출력 안한다.
print('kernel=\n', kernel) # 커널의 원소 값을 출력
3단계 : correlation 연산 시행 후 plt 결과창 출력 (위에서 만든 세로 가로 필터 적용)
fig = plt.figure(num='interactive mode', figsize=(16, 5))
plt.subplots_adjust(left=0.02, right=0.98, bottom=0.02, top=0.85) # 상하좌우 여분 공백 제어하기
fig.patch.set_facecolor('purple') # 화면 바탕 색상을 정한다.
fig.patch.set_alpha(0.1) # 위에서 지정한 배경색의 투명도 -> 0이면 투명, 1이면 완전 불투명.
plt.suptitle("Averaging Filtering or Box Filtering", fontsize=14, fontweight='bold')
plt.subplot(1, 3, 1) # 1x3 창의 첫번째 창 선택
plt.imshow(img) # 원본 영상
plt.axis('off')
plt.title('Original')
#i = 0 # kernel index
for i, knl in enumerate(kernel_list):
print(type(knl), knl.shape, knl.dtype) # <class 'numpy.ndarray'> (1, 51) float32
dst = cv.filter2D(img, -1, knl, borderType=cv.BORDER_DEFAULT)
#print(f"dst.dtype={dst.dtype}") # dst.dtype=uint8
plt.subplot(132 + i) # 1x3 창의 2번째 창부터 출력
plt.imshow(dst) # filtering 결과 영상
plt.axis('off')
plt.title('Kernel=' + str(knl.shape))
i += 1
#plt.show() # interactive mode 일 때는 필요 없음
plt.waitforbuttonpress() # 키 혹은 버튼 입력을 기다린다.
# 이후 프로그램이 종료되므로 모든 창이 닫힌다.
exit(0)
'전공 과목 이수2👨💻 > 디지털영상처리' 카테고리의 다른 글
밝기를 트랙바로 조절해보기 (0) | 2021.10.27 |
---|---|
화질 개선 기법(감마, 시그모이드, 히스토그램, 샤프닝, 메디언) (0) | 2021.10.18 |
엣지검출 pyplot.imshow vs cv.imshow (0) | 2021.10.10 |
이미지 가로, 세로 평균필터링 적용 (0) | 2021.10.03 |
matplotlib 출력위한 코드 (0) | 2021.10.03 |
이미지 위에 마우스로 사각형 그리기 (0) | 2021.09.28 |