길어서 두번째 부분 예제 시작하겠습니다.
3. 영상의 이진화
* 이진화(Binary Thresholding) 는 영상을 흑백(0 또는 255)으로 변환하여 특정 임계값(threshold) 이상인 픽셀을 흰색(255)으로, 이하인 픽셀을 검은색(0)으로 변환하는 과정입니다.
* 이는 객체 검출, OCR(광학 문자 인식), 엣지 검출 등의 전처리 과정에서 중요한 역할을 합니다.
* OpenCV에서는 cv2.threshold() 함수를 사용하여 고정 임계값 이진화, 적응형 이진화, Otsu의 이진화 등을 적용할 수 있습니다.
* 특히, cv2.THRESH_BINARY는 기본적인 이진화 방법이며, cv2.ADAPTIVE_THRESH_GAUSSIAN_C는 조명이 균일하지 않은 경우에도 효과적으로 이진화를 수행할 수 있습니다.
3-1. 오츠 이진화
* 오츠 이진화(Otsu's Binarization) 는 OpenCV에서 제공하는 자동 임계값 결정 기법으로, 영상의 히스토그램을 분석하여 객체와 배경을 가장 잘 구분할 수 있는 최적의 임계값을 자동으로 찾는 방법입니다.
* 이는 cv2.THRESH_OTSU 옵션을 사용하여 cv2.threshold() 함수에서 적용할 수 있으며, 특히 배경과 객체 간의 명암 대비가 뚜렷한 경우 효과적으로 동작합니다.
* 오츠 이진화는 모든 픽셀 값의 분포를 기반으로 클래스 내 분산(intra-class variance)을 최소화하는 임계값을 자동으로 선택하여 수동으로 임계값을 설정하는 불편함을 줄여줍니다.
* 일반적으로 cv2.THRESH_BINARY + cv2.THRESH_OTSU를 함께 사용하여 이진화를 수행하며, 그레이스케일 변환이 선행되어야 합니다.
3-2. 적응형 이진화
* 적응형 이진화(Adaptive Thresholding) 는 OpenCV에서 제공하는 이진화 기법 중 하나로, 조명 변화가 심한 영상에서도 적절한 임계값을 적용하여 이진화를 수행하는 방법입니다.
* 일반적인 cv2.threshold()는 하나의 고정된 임계값을 사용하지만, cv2.adaptiveThreshold()는 영상의 작은 영역마다 서로 다른 임계값을 계산하여 적용합니다.
* 이를 통해 명암 차이가 고르지 않은 이미지에서도 효과적으로 객체와 배경을 분리할 수 있습니다.
* OpenCV에서는 평균값을 이용하는 cv2.ADAPTIVE_THRESH_MEAN_C와 가우시안 가중치를 적용하는 cv2.ADAPTIVE_THRESH_GAUSSIAN_C 두 가지 방식을 제공하며, 블록 크기(blockSize)와 상수 값(C)을 조절하여 최적의 결과를 얻을 수 있습니다.
4. 영상의 변환
* 영상의 변환(Image Transformation) 이란 영상의 형태, 크기, 밝기, 색상 등을 변경하여 새로운 영상으로 변환하는 과정으로, 컴퓨터 비전에서 다양한 전처리 및 후처리에 활용됩니다.
* OpenCV에서는 대표적으로 기하학적 변환(Geometric Transformation) 과 강도 변환(Intensity Transformation) 을 제공합니다.
* 기하학적 변환에는 확대/축소(Scaling), 회전(Rotation), 이동(Translation), 투시 변환(Perspective Transform) 등이 있으며, cv2.warpAffine()과 cv2.getPerspectiveTransform()을 통해 수행할 수 있습니다.
* 강도 변환은 픽셀 값의 변화를 조정하는 방법으로 명암 조절, 히스토그램 평활화, 이진화(Thresholding) 등이 있으며, cv2.equalizeHist(), cv2.threshold(), cv2.adaptiveThreshold() 등이 이에 해당합니다.
5. 영상의 필터링 연산
* 영상의 필터링 연산(Image Filtering Operation) 은 영상의 특성을 강조하거나 잡음을 제거하기 위해 커널(필터)을 활용하여 픽셀 값을 변환하는 과정입니다.
* OpenCV에서는 필터링을 통해 노이즈 제거, 엣지 검출, 블러 효과, 샤프닝 등의 처리를 수행할 수 있습니다. 대표적인 필터링 기법으로는 평균 블러링(Averaging), 가우시안 블러링(Gaussian Blur), 미디언 블러링(Median Blur) 등이 있으며, cv2.blur(), cv2.GaussianBlur(), cv2.medianBlur() 함수를 통해 적용할 수 있습니다.
* 또한, 고급 필터링 기법으로 소벨 필터(Sobel Filter), 라플라시안 필터(Laplacian Filter) 와 같은 엣지 검출 필터도 제공되며, cv2.Sobel() 및 cv2.Laplacian()을 사용하여 적용할 수 있습니다.
* 필터링 연산은 영상 내 중요한 특징을 강조하거나 불필요한 정보를 제거하는 데 활용되며, 영상 분석 및 전처리에 필수적인 기법입니다.
https://pixabay.com/ko/videos/
동영상 2개를 다운받아 movie1.mp4, movie2.mp4로 저장하고 아래 예제를 실행합니다.
예시 1)
import cv2
import sys
# 동영상 파일 또는 웹캠에서 영상을 가져오기
cap = cv2.VideoCapture('./london.mp4') # 'london.mp4'라는 동영상 파일을 불러옴
# 동영상을 정상적으로 불러왔는지 확인
if not cap.isOpened(): # 동영상을 불러올 수 없는 경우
print('동영상을 불러올 수 없음') # 오류 메시지 출력
sys.exit() # 프로그램 종료
print('동영상을 불러올 수 있음') # 정상적으로 동영상이 열렸다면 출력
# 동영상의 기본 속성 출력
print('가로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))) # 동영상 프레임의 가로 크기 출력
print('세로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 동영상 프레임의 세로 크기 출력
print('프레임 수: ', int(cap.get(cv2.CAP_PROP_FRAME_COUNT))) # 동영상의 총 프레임 수 출력
print('FPS: ', cap.get(cv2.CAP_PROP_FPS)) # 초당 프레임 수(FPS) 출력
# 동영상 프레임을 반복적으로 읽어와서 화면에 표시
while True:
ret, frame = cap.read() # 한 프레임 읽기
if not ret: # 프레임을 더 이상 읽을 수 없는 경우 (영상이 끝난 경우)
break # 반복문 종료
cv2.imshow('frame', frame) # 읽어온 프레임을 화면에 표시
if cv2.waitKey(10) == 27: # 키 입력을 기다림 (ESC(27) 키를 누르면 종료)
break
cap.release() # 메모리 해제
예시 2)
import cv2
import sys
# 웹캠을 열어서 비디오 캡처 객체 생성 (0은 기본 웹캠을 의미)
cap = cv2.VideoCapture(0)
# 카메라가 정상적으로 열렸는지 확인
if not cap.isOpened(): # 카메라를 열 수 없는 경우
print('카메라를 열 수 없음') # 오류 메시지 출력
sys.exit() # 프로그램 종료
print('카메라 연결 성공') # 정상적으로 카메라가 연결되었음을 출력
# 카메라의 기본 속성 출력
print('가로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))) # 웹캠 프레임의 가로 크기 출력
print('세로 사이즈: ', int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 웹캠 프레임의 세로 크기 출력
print('FPS: ', cap.get(cv2.CAP_PROP_FPS)) # 초당 프레임 수(FPS) 출력
# 카메라에서 영상을 지속적으로 받아와서 화면에 출력
while True:
ret, frame = cap.read() # 한 프레임 읽기
if not ret: # 프레임을 정상적으로 읽지 못한 경우
break # 반복문 종료
cv2.imshow('frame', frame) # 읽어온 프레임을 화면에 표시
if cv2.waitKey(10) == 27: # ESC(27) 키를 누르면 종료
break
cap.release() # 카메라 자원 해제
예시 3)
import cv2
# 두 개의 동영상 파일 불러오기
cap1 = cv2.VideoCapture('./london.mp4') # 첫 번째 동영상
cap2 = cv2.VideoCapture('./forest.mp4') # 두 번째 동영상
# 첫 번째 동영상의 프레임 너비와 높이 가져오기
w = int(cap1.get(cv2.CAP_PROP_FRAME_WIDTH)) # 가로 크기
h = int(cap1.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 세로 크기
# 두 동영상의 총 프레임 수 가져오기
frame_cnt1 = int(cap1.get(cv2.CAP_PROP_FRAME_COUNT)) # 첫 번째 동영상의 프레임 개수
frame_cnt2 = int(cap2.get(cv2.CAP_PROP_FRAME_COUNT)) # 두 번째 동영상의 프레임 개수
# 두 동영상의 초당 프레임 수(FPS) 가져오기
fps1 = cap1.get(cv2.CAP_PROP_FPS) # 첫 번째 동영상의 FPS
fps2 = cap2.get(cv2.CAP_PROP_FPS) # 여기서 cap1이 아니라 cap2에서 FPS를 가져와야 함 (오타 수정 필요)
# 동영상 정보 출력
print(w, h) # 동영상 해상도 출력 (예: 640 360)
print(frame_cnt1, frame_cnt2) # 두 동영상의 총 프레임 수 출력 (예: 242 315)
print(fps1, fps2) # 두 동영상의 FPS 출력 (예: 24.0 24.0)
# 비디오 코덱 설정 및 출력 파일 생성 (DIVX 코덱 사용)
fourcc = cv2.VideoWriter.fourcc(*'DIVX')
out = cv2.VideoWriter('mix.avi', fourcc, fps1, (w, h)) # 새로운 동영상 파일 생성
# 첫 번째 동영상을 프레임 단위로 읽어서 저장
for i in range(frame_cnt1):
ret, frame = cap1.read() # 프레임 한 장 읽기
if not ret: # 프레임을 읽을 수 없으면 중단
break
cv2.imshow('output', frame) # 프레임을 화면에 표시
out.write(frame) # 프레임을 새 동영상 파일에 저장
if cv2.waitKey(10) == 27: # ESC(27) 키를 누르면 종료
break
# 메모리 해제
cap1.release()
cap2.release()
out.release()
예제 4)
import cv2
# 웹캠 열기 (0: 기본 웹캠)
cap = cv2.VideoCapture(0)
# 웹캠의 해상도 및 FPS 값 가져오기
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 가로 크기
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 세로 크기
fps = cap.get(cv2.CAP_PROP_FPS) # 초당 프레임 수
# 현재 웹캠 정보 출력
print(w, h) # 해상도 출력
print(fps) # FPS 출력
# 동영상 저장을 위한 설정
fourcc = cv2.VideoWriter.fourcc(*'DIVX') # 코덱 설정 (DIVX)
out = cv2.VideoWriter('mix.avi', fourcc, fps, (w, h)) # 'mix.avi' 파일 생성
# 웹캠으로 영상 촬영 및 저장
while True:
ret, frame = cap.read() # 한 프레임 읽기
if not ret: # 프레임을 정상적으로 읽지 못한 경우 종료
break
cv2.imshow('frame', frame) # 프레임을 화면에 표시
out.write(frame) # 프레임을 동영상 파일에 저장
if cv2.waitKey(10) == 27: # ESC(27) 키를 누르면 종료
break
# 메모리 해제
cap.release()
out.release()
예시 5)
import cv2
import matplotlib.pyplot as plt
# 그레이스케일 이미지 불러오기
img = cv2.imread('./images/apple.png', cv2.IMREAD_GRAYSCALE)
# 이미지가 정상적으로 로드되었는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 히스토그램 계산(이미지의 픽셀 값 분포를 나타냄)
# calcHist(히스토그램을 계산할 이미지 목록, 그레이스케일 이미지의 채널, 마스크를 사용하지 않음,
# 빈(bin)을 사용하여 0부터 255까지의 픽셀 값 분포를 계산, 0 ~ 255의 픽셀 값의 범위)
hist = cv2.calcHist([img], [0], None, [256], [0, 255])
# 임계값을 기준으로 이미지를 이진화
# threshold(이진화를 적용할 이미지, 임계값, 임계값을 넘는 픽셀에 부여할 최대값, 임계값 적용방식)
# THRESH_BINARY: 픽셀 값이 임계값보다 크면 최대값으로 설정, 작거나 같으면 0으로 설정
# a, dst1: a(임계값), dst1(이진화가 적용된 이미지)
a, dst1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY) # 임계값 100 적용
b, dst2 = cv2.threshold(img, 150, 255, cv2.THRESH_BINARY) # 임계값 150 적용
# 원본 이미지 및 이진화된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Thresholded Image (100)', dst1) # 임계값 100 적용된 이미지
cv2.imshow('Thresholded Image (150)', dst2) # 임계값 150 적용된 이미지
# 히스토그램 그래프 출력
plt.plot(hist) # 히스토그램 그래프 그리기
plt.title('Grayscale Histogram') # 그래프 제목
plt.xlabel('Pixel Value') # X축 라벨 (픽셀 값)
plt.ylabel('Frequency') # Y축 라벨 (픽셀 빈도수)
plt.show() # 그래프 표시
cv2.waitKey()
--->

예시 6)
import cv2
# 그레이스케일 이미지 불러오기
img = cv2.imread('./images/apple.png', cv2.IMREAD_GRAYSCALE)
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# Otsu의 이진화 적용 (자동 임계값 결정)
# cv2.threshold(입력 이미지, 초기 임계값(0), 최댓값(255), 이진화 방식)
# THRESH_OTSU: Otsu 알고리즘을 사용하여 최적의 임계값을 자동으로 결정
th, dst = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 결정된 임계값 출력
print('Otsu Threshold Value: ', th) # Otsu 알고리즘이 결정한 임계값 출력 (예: 128.0)
# 원본 이미지 및 이진화된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지 표시
cv2.imshow('Otsu Thresholding', dst) # Otsu 이진화 적용된 이미지 표시
cv2.waitKey()
--->

예시 7)
import cv2
import matplotlib.pyplot as plt
# 그레이스케일 이미지 불러오기
img = cv2.imread('./images/apple.png', cv2.IMREAD_GRAYSCALE)
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# Otsu의 이진화 적용 (자동 임계값 결정)
th, dst1 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print('Otsu Threshold Value: ', th) # otsu: 128.0
# 적응형 이진화 적용 (Adaptive Thresholding)
# cv2.adaptiveThreshold(입력 이미지, 최댓값, 적응형 방식, 임계 방식, 블록 크기, 상수)
# ADAPTIVE_THRESH_MEAN_C : 지정한 영역 내 픽셀들의 평균값을 임계값으로 사용
dst2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 5)
# ADAPTIVE_THRESH_GAUSSIAN_C : 가우시안 가중치를 적용한 평균값을 임계값으로 사용
dst3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 9, 5)
# 이미지 및 이진화 결과를 딕셔너리에 저장
dic = {'Original Image': img,
'Otsu Thresholding': dst1,
'Adaptive Mean Thresholding': dst2,
'Adaptive Gaussian Thresholding': dst3}
# 결과 이미지 출력
plt.figure(figsize=(10, 10)) # 그래프 크기 설정
for i, (title, image) in enumerate(dic.items()):
plt.subplot(2, 2, i + 1) # 2x2 배열의 서브플롯 생성
plt.title(title) # 제목 설정
plt.imshow(image, cmap='gray') # 이미지를 흑백(Grayscale)으로 출력
plt.axis('off') # 축 제거
plt.show() # 그래프 표시
--->

예시 8)
import cv2 # OpenCV 라이브러리 불러오기
import numpy as np # Numpy 라이브러리 불러오기 (행렬 연산)
# 이미지 불러오기
img = cv2.imread('./images/dog.bmp')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 이동 변환 행렬 (Affine Transformation)
# [[1, 0, 150], [0, 1, 100]] : x 방향으로 150, y 방향으로 100 이동
aff = np.array([[1, 0, 150],
[0, 1, 100]], dtype=np.float32)
# 이미지 이동 적용
# cv2.warpAffine(입력 이미지, 변환 행렬, 출력 이미지 크기)
dst = cv2.warpAffine(img, aff, (img.shape[1], img.shape[0]))
# 원본 및 이동된 이미지 출력
cv2.imshow('Original Image', img)
cv2.imshow('Translated Image', dst)
cv2.waitKey()
--->

예시 9)
import cv2
# 이미지 불러오기
img = cv2.imread('./images/dog.bmp')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# INTER_NEAREST(보간법): 가장 가까운 이웃의 픽셀 값을 사용하여 리사이즈,계산이 빠르지만 계단현상이 발생할수 있음
dst1 = cv2.resize(img, (1280, 1024), interpolation=cv2.INTER_NEAREST)
# INTER_CUBIC : 주변 16개 픽셀 값을 이용하여 리사이즈, 상대적으로 부드럽고 자연스러운 결과를 얻을 수 있지만 계산량이 많음
dst2 = cv2.resize(img, (1280, 1024), interpolation=cv2.INTER_CUBIC)
# 원본 및 리사이즈된 이미지 출력 (일부 영역만 표시)
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Resized (INTER_NEAREST)', dst1[400:800, 200:600]) # INTER_NEAREST 방식 리사이즈 후 일부 영역 크롭
cv2.imshow('Resized (INTER_CUBIC)', dst2[400:800, 200:600]) # INTER_CUBIC 방식 리사이즈 후 일부 영역 크롭
cv2.waitKey()
--->

예시 10)
import cv2
# 이미지 불러오기
img = cv2.imread('./images/dog.bmp')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 회전 중심 좌표 (이미지의 중심)
cp = (img.shape[1] / 2, img.shape[0] / 2)
# 회전 변환 행렬 생성 (cv2.getRotationMatrix2D)
# - 회전 중심(cp): 이미지의 중심
# - 회전 각도(30): 시계 반대 방향으로 30도 회전
# - 크기 조절 비율(0.7): 이미지 크기를 70%로 축소
rot = cv2.getRotationMatrix2D(cp, 30, 0.7)
# 이미지 회전 적용 (cv2.warpAffine)
# warpAffine(입력 이미지, 변환 행렬, 출력 이미지 크기)
dst = cv2.warpAffine(img, rot, (img.shape[1], img.shape[0]))
# 원본 및 회전된 이미지 출력
cv2.imshow('Original Image', img)
cv2.imshow('Rotated Image', dst)
cv2.waitKey()
--->

예시 11)
import cv2
import numpy as np
# 이미지 불러오기
img = cv2.imread('./images/gram.jpg')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 출력 이미지 크기 설정
w, h = 600, 400 # 변환 후 이미지의 너비(W)와 높이(H)
# 원본 이미지에서 투영 변환할 4개의 좌표 (시계 방향으로 선택)
# 예제에서 문서 코너를 기준으로 좌표 설정
srcQuad = np.array([[369, 172], # 좌상단
[1228, 156], # 우상단
[1424, 846], # 우하단
[207, 801]], np.float32) # 좌하단
# 변환 후의 좌표 (출력 이미지에서 사각형 형태로 정렬)
dstQuad = np.array([[0, 0], # 좌상단
[w, 0], # 우상단
[w, h], # 우하단
[0, h]], np.float32) # 좌하단
# 투시 변환 행렬 계산
pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
# 투시 변환 적용
dst = cv2.warpPerspective(img, pers, (w, h))
# 원본 및 변환된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Perspective Transformed Image', dst) # 투시 변환된 이미지
cv2.waitKey()
--->

예시 12)
import cv2
import matplotlib.pyplot as plt
import numpy as np
# 이미지 불러오기
img = cv2.imread('./images/dog.bmp')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# BGR -> RGB 변환 (Matplotlib에서 올바른 색상 표시를 위해)
dst1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 평균 블러 적용 (커널 크기: 7x7)
dst2 = cv2.blur(img, (7, 7))
# 원본 및 블러링된 이미지 출력 (OpenCV 사용)
cv2.imshow('Original Image', img)
cv2.imshow('Blurred Image (7x7)', dst2)
# 다양한 커널 크기로 필터링 적용 (Matplotlib 사용)
plt.figure(figsize=(10, 5))
for i, k in enumerate([5, 7, 9]): # 5x5, 7x7, 9x9 크기의 커널 적용
kernel = np.ones((k, k), np.float32) / (k ** 2) # 평균 필터 커널 생성
filtering = cv2.filter2D(dst1, -1, kernel) # 필터 적용
plt.subplot(1, 3, i + 1) # 1x3 배열로 그래프 표시
plt.imshow(filtering) # 필터링된 이미지 출력
plt.title(f'Kernel size: {k}') # 제목 설정
plt.axis('off') # 축 제거
plt.show() # 그래프 표시
cv2.waitKey(0) # 키 입력 대기
--->

예시 13)
import cv2 # OpenCV 라이브러리 불러오기
# 그레이스케일 이미지 불러오기
img = cv2.imread('./images/dog.bmp', cv2.IMREAD_GRAYSCALE)
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 가우시안 블러 적용 (GaussianBlur)
# GaussianBlur(입력 이미지, 커널 크기(0,0): 자동 설정, 표준 편차(1))
# 노이즈 제거에 효과적이며 엣지를 더 잘 보존
dst1 = cv2.GaussianBlur(img, (0, 0), 1)
# 평균 블러 적용 (Blur)
# blur(입력 이미지, 커널 크기(5,5)): 단순히 주변 픽셀 평균을 사용하여 블러 효과 적용
dst2 = cv2.blur(img, (5, 5))
# 원본 및 블러링된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Gaussian Blur (σ=1)', dst1) # 가우시안 블러 적용된 이미지
cv2.imshow('Mean Blur (5x5)', dst2) # 평균 블러 적용된 이미지
cv2.waitKey(0) # 키 입력 대기
--->

예시 14)
import cv2
# 그레이스케일 이미지 불러오기
img = cv2.imread('./images/space.webp', cv2.IMREAD_GRAYSCALE)
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 미디언 블러 적용 (Median Blur)
# medianBlur(입력 이미지, 커널 크기)
# 커널 크기 3을 사용하여 노이즈 제거 (특히 Salt & Pepper 노이즈 제거에 효과적)
dst1 = cv2.medianBlur(img, 3)
# 가우시안 블러 적용 (Gaussian Blur)
# GaussianBlur(입력 이미지, 커널 크기(0,0): 자동 설정, 표준 편차(σ=2))
# 노이즈 제거 및 부드러운 블러 효과 적용
dst2 = cv2.GaussianBlur(img, (0, 0), 2)
# 원본 및 블러링된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Median Blur (3x3)', dst1) # 미디언 블러 적용된 이미지
cv2.imshow('Gaussian Blur (σ=2)', dst2) # 가우시안 블러 적용된 이미지
cv2.waitKey() # 키 입력 대기
--->

예시 15)
import cv2
import numpy as np # Numpy 라이브러리 불러오기 (행렬 연산)
# 이미지 불러오기
img = cv2.imread('./images/dog.bmp')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 이미지의 중간(중앙) 픽셀 값 계산 (Canny 엣지 검출을 위한 임계값 설정)
med_val = np.median(img)
print(f"Median Pixel Value: {med_val}") # 예: 129.0
# Canny 엣지 검출을 위한 낮은 임계값과 높은 임계값 설정
lower = int(max(0, 0.7 * med_val)) # 0보다 작은 값 방지
print(f"Lower Threshold: {lower}") # 예: 90
upper = int(min(255, 1.3 * med_val)) # 255보다 큰 값 방지
print(f"Upper Threshold: {upper}") # 예: 167
# 가우시안 블러 적용 (노이즈 제거)
dst = cv2.GaussianBlur(img, (3, 3), 0)
# Canny 엣지 검출 적용
# Canny(입력 이미지, 낮은 임계값, 높은 임계값, Sobel 커널 크기)
# 낮은 임계값보다 작은 값은 무시하고, 높은 임계값보다 큰 값만 엣지로 인식
dst = cv2.Canny(dst, lower, upper, 3)
# 원본 및 엣지 검출된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Canny Edge Detection', dst) # Canny 엣지 검출 이미지
cv2.waitKey(0) # 키 입력 대기
cv2.destroyAllWindows() # 모든 창 닫기
예시 16)
import cv2
import numpy as np # Numpy 라이브러리 불러오기 (행렬 연산)
# 이미지 불러오기
img = cv2.imread('./images/dog.bmp')
# 이미지가 정상적으로 불러와졌는지 확인
if img is None:
print("이미지를 불러올 수 없습니다.")
exit()
# 이미지의 중간(중앙) 픽셀 값 계산 (Canny 엣지 검출을 위한 임계값 설정)
med_val = np.median(img)
print(f"Median Pixel Value: {med_val}") # 예: 129.0
# Canny 엣지 검출을 위한 낮은 임계값과 높은 임계값 설정
lower = int(max(0, 0.7 * med_val)) # 0보다 작은 값 방지
print(f"Lower Threshold: {lower}") # 예: 90
upper = int(min(255, 1.3 * med_val)) # 255보다 큰 값 방지
print(f"Upper Threshold: {upper}") # 예: 167
# 가우시안 블러 적용 (노이즈 제거)
dst = cv2.GaussianBlur(img, (3, 3), 0)
# Canny 엣지 검출 적용
# Canny(입력 이미지, 낮은 임계값, 높은 임계값, Sobel 커널 크기)
# 낮은 임계값보다 작은 값은 무시하고, 높은 임계값보다 큰 값만 엣지로 인식
dst = cv2.Canny(dst, lower, upper, 3)
# 원본 및 엣지 검출된 이미지 출력
cv2.imshow('Original Image', img) # 원본 이미지
cv2.imshow('Canny Edge Detection', dst) # Canny 엣지 검출 이미지
cv2.waitKey(0) # 키 입력 대기
-->
129.0
90
167
--->

'컴퓨터 비전' 카테고리의 다른 글
Object Detection (2) | 2025.03.07 |
---|---|
OCR (6) | 2025.03.06 |
4. OpenCV (0) | 2025.03.05 |
3. 포켓몬 분류 데이터셋 (8) | 2025.03.04 |
2. Classification (0) | 2025.02.28 |