딥러닝
[딥러닝] 평활화, 정규화, YCrCb, HSV, CLAHE, inRange(), copyTo()
Uno_says
2024. 8. 20. 15:00
728x90
1. 균등화, 평탄화(Equalization)
- 히스토그램을 활용하여 이미지의 품질을 개선하기 위한 방법
- 이미지의 대비를 증가시키는 데 유용하다. 특히 명암비가 낮아 어두운 부분이 많은 이미지에서 효과적이다.
- 화소값을 0~255 사이에 고르게 분포하도록 개선
- cv2.equalizeHist()
✔️ 히스토그램 평탄화를 적용하여 명암비 개선하기
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('./Hawkes.jpg', cv2.IMREAD_GRAYSCALE)
dst = cv2.equalizeHist(img) # 평탄화: 이미지의 명암을 균일하게 분포시켜 대비를 높임
hist1 = cv2.calcHist([img], [0], None, [256], [0, 255]) # 원본 이미지
hist2 = cv2.calcHist([dst], [0], None, [256], [0, 255]) # 평탄화 적용된 이미지
cv2.imshow('img', img)
cv2.imshow('dst', dst)
hists = {'hist1': hist1, 'hist2': hist2}
plt.figure(figsize=(12, 8))
for i, (k, v) in enumerate(hists.items()):
plt.subplot(1, 2, i+1)
plt.title(k)
plt.plot(v)
plt.show()
cv2.waitKey()
2. 색공간
- YCbCr
- 색공간을 밝기 정보로 표현하는 방식
- Y: 밝기 정보
- HSV
- 색을 표현하는 방법이자 색을 배치하는 방식
- H(색상, 빨강녹색파랑), S(채도, 선명도), V(명도, 빛의 밝기)의 좌표를 색으로 지정
✔️ YCrCb 색 공간을 이용하여 평탄화하기
import cv2
img = cv2.imread('./field.bmp')
ycrcb = []
dst = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb) # BGR -> YCrCb로 변환, Y: 밝기, CrCb: 색차
ycrcb = cv2.split(dst) # Y, Cr, Cb로 분리
ycrcb = list(ycrcb) # 리스트로 변환
ycrcb[0] = cv2.equalizeHist(ycrcb[0]) # Y채널에 평탄화 적용
dst = cv2.merge(ycrcb) # 다시 하나의 YCrCb 이미지로 병합
dst = cv2.cvtColor(dst, cv2.COLOR_YCrCb2BGR) # YCrCb -> BGR로 변환
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
# split()와 merge()를 사용하지 않고 위 예제와 동일한 결과 영상 만들기
dst = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
dst[:, :, 0] = cv2.equalizeHist(dst[:, :, 0])
dst = cv2.cvtColor(dst, cv2.COLOR_YCrCb2BGR)
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
3. CLAHE(Contrast Limited Adaptive Histogram Equalization)
- 평탄화를 하면 이미지의 밝은 부분이 날라가는 현상이 생길 수 있음
- 이미지의 일정한 영역을 나누어 평탄화를 적용
- CLAHE는 일반적인 히스토그램 평탄화와 달리, 이미지의 작은 영역에서 명암비를 조정하여 더 자연스러운 보정을 제공
- 객체 = cv2.createCLAHE() -> 객체.apply(영상)
✔️ 평탄화와 CLAHE 비교하기
import cv2
img = cv2.imread('./field.bmp')
img = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb) # BGR -> YCrCb
img_eq = img.copy()
img_clahe = img.copy()
img = cv2.cvtColor(img, cv2.COLOR_YCrCb2BGR) # 원래 이미지는 다시 BGR로 변환하여 저장
# 히스토그램 평탄화 적용
img_eq[:, :, 0] = cv2.equalizeHist(img_eq[:, :, 0])
img_eq = cv2.cvtColor(img_eq, cv2.COLOR_YCrCb2BGR)
# CLAHE 적용
# clipLimit: 명암비 제한 설정, tileGridSize: 이미지를 타일로 나누는 그리드 크기 설정
clahe = cv2.createCLAHE(clipLimit=2, tileGridSize=(4, 4))
img_clahe[:, :, 0] = clahe.apply(img_clahe[:, :, o]) # CLAHE를 img_clahe의 Y채널에 적용
img_clahe = cv2.cvtColor(img_clahe, cv2.COLOR_YCrCb2BGR)
cv2.imshow('img', img)
cv2.imshow('img_eq', img_eq)
cv2.imshow('img_clahe', img_clahe)
cv2.waitKey()
4. 정규화(Normalization)
- 특정 영역에 값이 몰려 있는 경우 화질을 개선하고, 이미지 간의 연산 시 서로 조건이 다른 경우 같은 조건으로 변경
- cv2.normalize()
- cv2.NORM_MINMAX: 최솟값과 최댓값 계산
- cv2.NORM_L1: 전체 합으로 나눔
- cv2.NORM_L2: 단위 벡터로 정규화
- cv2.NORM_INF: 최댓값으로 나눔
✔️ 이미지를 정규화하고 히스토그램 비교하기
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./Hawkes.jpg', cv2.IMREAD_GRAYSCALE)
# 밝기 값을 0에서 255사이의 범위로 정규화
# 이미지의 최소값을 0으로, 최대값을 255로 스케일링
img_norm = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)
# 히스토그램 계산
hist = cv2.calHist([img], [0], None, [256], [0, 255])
hist_norm = cv2.calcHist([img_norm], [0], None, [256], [0 255])
cv2.imshow('img', img)
cv2.imshow('img_norm', img_norm)
hists = {'hist': hist, 'hist_norm': hist_norm}
for i, (k, v) in enumerate(hists.items()):
plt.subplot(1, 2, i+1)
plt.title(k)
plt.plot(v)
plt.show()
cv2.waitKey()
5. 색상 추출
- 영상에서 지정된 범위 안에 픽셀을 선택
- cv2.inRange()
- BGR에서 녹색계열
- 0 <= B <= 100
- 128 <= G <= 255
- 0 <= R <= 100
- HSV에서 녹색계열
- 50 <= H <= 80
- 150 <= S <= 255
- 0 <= V <= 255
✔️ 녹색계열을 필터링하고, 그 결과를 바이너리 이미지로 표시하기
import cv2
img = cv2.imread('./candies.png')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # BGR -> HSV(색조, 채도, 명도)
# 특정 색상 범위 필터링
# (50, 150, 0)은 하한 값, (80, 255, 255)은 상한 값으로, 이 범위 내의 색상만 선택됨
# 결과로 dst는 바이너리 이미지로, 지정된 색상 범위에 해당하는 픽셀은 흰색(255), 그렇지 않은 픽셀은 검은색(0)으로 표시됨
dst = cv2.inRange(hsv, (50, 150, 0), (80, 255, 255))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
6. 마스크 연산
- 마스크 연산을 지원하는 픽셀 값 복사 함수
- cv2.copyTo()
✔️ 마스크 이미지를 활용하여 복사, 합성하기
import cv2
img = cv2.imread('./airplane.bmp') # 복사할 소스 이미지
mask = cv2.imread('./mask_plane.bmp') # img의 복사될 영역을 지정
dst = cv2.imread('./field.bmp') # img가 복사될 대상 이미지
temp = cv2.copyTo(img, mask) # img 이미지를 mask의 흰색 부분에 해당하는 영역에만 복사함
cv2.copyTo(img, mask, dst) # img 이미지를 dst 이미지에 mask에 해당하는 부분만 복사하여 덮어씀
cv2.imshow('img', img)
cv2.imshow('mask', mask)
cv2.imshow('temp', temp)
cv2.imshow('dst', dst)
cv2.waitKey()
✔️ 크로마키 영상 다루기
import cv2
cap1 = cv2.VideoCapture('./woman.mp4')
cap2 = cv2.VideoCapture('./sea.mp4')
w = round(cap1.get(cv2.CAP_PROP_FRAME_WIDTH)) # 'woman.mp4'의 너비
h = round(cap1.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 'woman.mp4'의 높이
frame_cnt1 = round(cap1.get(cv2.CAP_PROP_FRAME_COUNT) # 'woman.mp4'의 총 프레임 수
frame_cnt2 = round(cap2.get(cv2.CAP_PROP_FRAME_COUNT) # 'sea.mp4'의 총 프레임 수
fps = round(cap1.get(cv2.CAP_PROP_FPS)) # 'woman.mp4'의 초당 프레임 수
print(w)
print(h)
print(frame_cnt1)
print(frame_cnt2)
print(fps)
while True:
ret1, frame1 = cap1.read() # 'woman.mp4' 프레임 읽어오기
if not ret1: # 프레임 읽지 못하면 종료
break
ret2, frame2 = cap2.read() # 'sea.mp4' 프레임 읽어오기
if not ret2:
break
hsv = cv2.cvtColor(frame1, cv2.COLOR_BGR2HSV) # BGR -> HSV 색공간 변환
mask = cv2.inRange(hsv, (50, 150, 0), (70, 255, 255)) # 특정 색상 범위 선택을 위한 마스크 생성
cv2.copyTo(frame2, mask, frame1) # frame2에서 마스크가 적용된 영역만큼 frame1에 복사함
cv2.imshow('frame1', frame1)
key = cv2.waitKey(10) # 10ms 동안 키 입력 대기
if key == ord(' '): # 스페이스바가 눌리면, 프로그램이 멈추가 추가 키 입력 대기
cv2.waitKey()
elif key == 27:
break
cap1.release()
cap2.release()
728x90