Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 알고리즘
- 알고리즘 스터디
- type hint
- 가상환경
- 알고리즘스터디
- MySQL
- 선그래프
- python
- 프로그래머스
- 백준
- dataframe
- Algorithm
- openCV
- 파이썬
- Matplotlib
- queue
- javascript
- 정보처리기사 c언어
- aws jupyter notebook
- String Method
- 자료구조
- Selenium
- 노마드코딩
- 코딩테스트
- Join
- NumPy
- programmers
- 데이터시각화
- pandas
- Stack
Archives
- Today
- Total
조금씩 꾸준히 완성을 향해
[OpenCV/Python] Edge 필터링 (Sobel, Laplacian) 본문
Edge 추출
# 미분과 경사도
- 함수 또는 데이터의 변화율
- 함수의 순간 변화율
# sobel filter
- 영상에서의 1차 미분 : 엣지 존재 여부 파악
▶ sobel 필터 후 나온 원본 gxo 값에 절대 값 + 루트 씌우기
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = np.zeros(shape=(512, 512), dtype=np.uint8) +255
pt1 = 200, 200
pt2 = 300, 300
src = cv2.rectangle(img, pt1, pt2, (0,0,0), -1)
# x방향 y방향으로 sobel 필터 적용 후 이미지 밝기값들 확인해 보기
gx = cv2.Sobel(src, ddepth=-1, dx=1, dy=0, ksize=3)
gy = cv2.Sobel(src, ddepth=-1, dx=0, dy=1, ksize=3)
gxo = cv2.Sobel(src, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=3)
gyo = cv2.Sobel(src, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=3)
# ddepth=cv2.CV_32F (원본 결과 보기: float32bit)
# ddepth=-1 (자동 계산: 마이너스 값은 0으로 변환)
print(' - ddepth=-1')
print(gx[195:205, 195:205])
print(gx[295:305, 295:305])
print(gy[195:205, 195:205])
print(gy[295:305, 295:305])
print(' - ddepth=cv2.CV_32F')
print(gxo[195:205, 195:205])
print(gxo[295:305, 295:305])
print(gyo[195:205, 195:205])
print(gyo[295:305, 295:305])
#절대값 쓰우기
gxo = np.abs(gxo)
gyo = np.abs(gyo)
print('- 32F after absolute')
print(gxo[195:205, 195:205])
print(gxo[295:305, 295:305])
print(gyo[195:205, 195:205])
print(gyo[295:305, 295:305])
#루트 씌우기
gxo = np.sqrt(gxo)
gyo = np.sqrt(gyo)
print('- 32F after root')
print(gxo[195:205, 195:205])
print(gxo[295:305, 295:305])
print(gyo[195:205, 195:205])
print(gyo[295:305, 295:305])
# 이미지 결과 보기
images = [src, gxo, gyo, gxo+gyo]
titles = ['original','gxo', 'gyo', 'gxo+gyo']
fig = plt.figure(figsize=(10, 10))
for i in range(4):
ax = plt.subplot(2, 2, i+1)
ax.imshow(images[i], 'gray')
ax.set_title(titles[i])
ax.axis('off')
plt.show()
- normalize : 0~255로 스트레칭 적용
gxo = cv2.normalize(gxo, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
gyo = cv2.normalize(gyo, 0, 255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
print('- 32F after stretching')
print(gxo[195:205, 195:205])
print(gxo[295:305, 295:305])
print(gyo[195:205, 195:205])
print(gyo[295:305, 295:305])
cv2.imshow('gxo', gxo)
cv2.imshow('gyo', gyo)
cv2.imshow('gxo+gyo', gxo+gyo)
cv2.waitKey()
cv2.destroyAllWindows()
- magnitude => 넘파이(절대값, 루트) 대신 사용 가능
- sobel + magnitude + nomalize
src = cv2.rectangle(img, pt1, pt2, (0,0,0), -1)
# cv2.CV_32F 원본 필수!
gxo = cv2.Sobel(src, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=3)
gyo = cv2.Sobel(src, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=3)
mag = cv2.magnitude(gxo, gyo)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(mag)
print('mag:', minVal, maxVal, minLoc, maxLoc)
# mag: 0.0 1081.8734130859375 (0, 0) (200, 200)
dstM = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(dstM)
print('mag:', minVal, maxVal, minLoc, maxLoc)
# mag: 0.0 255.0 (0, 0) (200, 200)
cv2.imshow('dstM', dstM)
cv2.waitKey()
cv2.destroyAllWindows()
# 소벨 적용해서 레나 엣지 확인
src = cv2.imread('./lena.jpg', cv2.IMREAD_GRAYSCALE)
gxo = cv2.Sobel(src, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=7)
gyo = cv2.Sobel(src, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=7)
mag = cv2.magnitude(gxo, gyo)
dstM = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
cv2.imshow('src', src)
cv2.imshow('dstM', dstM)
cv2.waitKey()
cv2.destroyAllWindows()
# Laplacian(라플라시안)
- 영상에서의 2차 미분 : 밝기 변화 파악 가능
- 잡음에 취약, 성능 개선 크지 않음 => 1차 미분을 주로 많이 사용
# 마스크가 하나여서 바로 src를 집어넣으면 됨
lap = cv2.Laplacian(src, cv2.CV_32F)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(lap)
print('lap:', minVal, maxVal, minLoc, maxLoc)
print(lap[:10, :10])
# 절대값으로 변경
dst = cv2.convertScaleAbs(lap)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(dst)
print('lap:', minVal, maxVal, minLoc, maxLoc)
print(dst[:10, :10])
# 스트레칭
dst = cv2.normalize(dst, None, 0, 255, cv2.NORM_MINMAX)
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(dst)
print('lap:', minVal, maxVal, minLoc, maxLoc)
print(dst[:10, :10])
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
# 2차 미분 => 잡음 많음
- 가우시안 필터 적용 후 라플라시안 결과 비교
lap = cv2.Laplacian(src, cv2.CV_32F)
dst = cv2.convertScaleAbs(lap)
dst = cv2.normalize(dst, None, 0, 255, cv2.NORM_MINMAX)
blur = cv2.GaussianBlur(src, ksize=(3,3), sigmaX=0.0)
lap2 = cv2.Laplacian(blur, cv2.CV_32F)
dst2 = cv2.convertScaleAbs(lap2)
dst2 = cv2.normalize(dst2, None, 0, 255, cv2.NORM_MINMAX)
cv2.imshow('dst', dst)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()