브이로그
2024년 7월 22일 Python-Translate 본문
더보기
영상의 변환
- 영상을 구성하는 픽셀의 배치 구조를 변경함으로 전체 영상의 모양을 바꾸는 작업
이미지 이동(translate)
원래 있던 좌표에 이동시키려는 거리만큼 연산
변환행렬
M = [1 0 a ]
[0 1 b ]
x방향으로 a만큼, y방향으로 b만큼 이동하는 행렬
cv2.warpaffine()
* (0, 0)을 매개변수로 전달하면 입력 영상과 크기가 같은 행렬을 반환
* 보간법 알고리즘
cv2.INTER_LINEAR: 인접한 4개의 픽셀 값에 거리 가중치를 사용(속도는 빠르지만 퀄이 떨어짐)
cv2.INTER_NEAREST: 가장 가까운 픽셀 값을 사용
cv2.INTER_AREA: 픽셀 영역 관계를 이용한 재샘플링(영역적인 정보를 추출해서 영상을 세팅하기 때문에 다운 샘플링 시 효과적
cv2.INTER_CUBIC: 인접한 16개의 픽셀 값에 가중치를 사용(퀄이 가장 높지만 속도가 떨어짐)
크기 변환(resize)
영상의 크기를 원본 영상보다 크게 또는 작게 만드는 변환
cv2.resize()
회전(rotation)
영상을 특정 각도만큼 회전시키는 변환(반시계 방향, 음수는 시계방향)
cv2.getRotationMatrix2D(중심좌표, 회전각도, 확대비율)
확대비율: 0~1사이의 실수
투시 변환(perspective)
- 직사각형 형태의 영상을 임의의 입체감 있는 사각형 형태로 변환
- 원본 영상에 있는 직선은 결과 영상에서 그대로 유지 되지 않고 평행 관계가 깨질 수 있음
- 투시 변환은 보통 3*3 크기의 실수 행렬로 표현
cv2.getPerspectiveTransform(영상, 4개의 결과 좌표점) -> 투시 변환 행렬
cv2.warpPerspective(영상, 투시변환행렬, 결과영상크기)
필터링 연산
커널 또는 필터라고 하는 행렬을 정의하고 이미지 위에서 이동해가며 커널과 겹쳐진 이미지 영역과 연산을 한 후 그 결과값을 픽셀을 대신하여 새로운 이미지로 만드는 연산
cv.filter2D(영상, -1, 커널, 중심점 좌표, 추가될 값, 가장자리 화소처리)
-1: 입력과 동일한 크기의 영상
커널: 정방 행렬(3*3, 5*5 ...)
가장자리 화소처리
BORDER_CONSTANT: 800픽셀픽셀800
BORDER_REPLICATE: aaaabcdddd
...
블러링(Blurring)
초점이 맞지 않은 듯 영상을 흐릿하게 하는 작업
- 평균 블러링: 가장 일반적인 블러링 방법 균일한 값을 정규화 된 커널을 이용한 이미지 필터링 방법
- 커널 영역 내에서 평균 값으로 해당 픽셀을 대체함
- 주변 픽셀들의 평균값을 적용하면 픽셀 간 차이가 적어져 선명도가 떨어지므로 전체적으로 흐려짐
- 필터의 크기가 클수록 평균 블러링을 적용했을 때 선명도가 더 떨어짐
- 가우시안 블러링: 가우시안 분포를 갖는 커널로 블러링 하는 것
- 대상 픽셀에 가까울수록 많은 영향을 주고, 멀어질수록 적은 영향을 주기 때문에 원래의 영상과 비슷하면서도 노이즈를 제거하는 효과가 있음
cv2.GaussianBlur()
- 미디언 블러링: 커널의 픽셀값 중 중앙값을 선택
- 소금-후추 잡음을 제거하는 효과
- 바이레터럴 필터: 기존 블러링의 문제점을 해결하기 위한 방법
- 잡음을 제거하는 효과는 뛰어났지만, 해당 잡음의 경계도 흐릿하게 만드는 문제를 해결
- 경계도 뚜렷하고 노이즈도 제거되는 효과가 있지만 속도가 느림
cv2.bilateralFilter(영상, 픽셀의 거리, 시그마 컬러 범위, 시그마 스페이스 범위)
에지(edge) 검출
- 영상에서 화소의 밝기가 급격하게 변하는 부분
- 물체의 윤곽선(경계선)이 해당
- 에지를 검출할 수 있으면 물체의 윤곽선을 알 수 있음
- '케니 에지 검출'은 상당한 수준으로 에지를 신뢰서 있게 검출하는 방법
cv2.Canny(영상, 최소임계값, 최대임계값, 커널)
최소임계값, 최대임계값: 두 개의 경계 값을 지정해서 경계에 있는 영역을 표시
문제
웹캡 영상에서 필터링을 적용(스페이스바를 누를 때마다)하는 프로그램을 작성
- 일반영상 -> 가우시안 필터링 -> 케니 필터링 -> 일반영상
1. translate
import cv2
import numpy as np
img = cv2.imread('./dog.bmp')
aff = np.array([[1, 0, 150], [0, 1, 100]], dtype=np.float32)
dst = cv2.warpAffine(img, aff, (0, 0))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
중심을 다르게 잡으면 dst처럼 나오는듯?
2. resize
import cv2
img = cv2.imread('./dog.bmp')
dst1 = cv2.resize(img, (1280, 1024), interpolation=cv2.INTER_NEAREST)
dst2 = cv2.resize(img, (1280, 1024), interpolation=cv2.INTER_CUBIC)
cv2.imshow('img', img)
cv2.imshow('dst1', dst1[400:800, 200:600])
cv2.imshow('dst2', dst2[400:800, 200:600])
cv2.waitKey()
이제부터는 dog사진은 원본사진은 제외하고 올릴께 이건 어는 좌표를 확대해놓은 것
3. rotation
import cv2
img = cv2.imread('./dog.bmp')
cp = (img.shape[1] / 2, img.shape[0] / 2)
rot = cv2.getRotationMatrix2D(cp, 30, 0.7)
dst = cv2.warpAffine(img, rot, (0, 0))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
기울이기~~~
4. perspective
import cv2
import numpy as np
img = cv2.imread('./pic.jpg')
w, h = 600, 400
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('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
원본은 그냥 책인데 이걸 책 모서리 좌표만으로 뽑아온 것 노트북이라 책 사진이 너무 커서...
5. Answer
import cv2
import numpy as np
import sys
img = cv2.imread('./namecard.jpg')
h, w = img.shape[:2]
dh = 500
# A4용지 크기: 210*297mm
dw = round(dh * 297 / 210)
srcQuad = np.array([[30, 30], [30, h-30], [w-30, h-30], [w-30, 30]], np.float32)
dstQuad = np.array([[0, 0], [0, dh], [dw, dh], [dw, 0]], np.float32)
dragSrc = [False, False, False, False]
def drawROI(img, corners):
cpy = img.copy()
c1 = (192, 192, 255)
c2 = (128, 128, 255)
for pt in corners:
cv2.circle(cpy, tuple(pt.astype(int)), 25, c1, -1)
cv2.line(cpy, tuple(corners[0].astype(int)), tuple(corners[1].astype(int)), c2, 2)
cv2.line(cpy, tuple(corners[1].astype(int)), tuple(corners[2].astype(int)), c2, 2)
cv2.line(cpy, tuple(corners[2].astype(int)), tuple(corners[3].astype(int)), c2, 2)
cv2.line(cpy, tuple(corners[3].astype(int)), tuple(corners[0].astype(int)), c2, 2)
return cpy
def onMouse(event, x, y, flags, param):
global srcQuad, dragSrc, ptOld, img
if event == cv2.EVENT_LBUTTONDOWN:
for i in range(4):
if cv2.norm(srcQuad[i] - (x, y)) < 25:
dragSrc[i] = True
ptOld = (x, y)
break
if event == cv2.EVENT_LBUTTONUP:
for i in range(4):
dragSrc[i] = False
if event == cv2.EVENT_MOUSEMOVE:
for i in range(4):
if dragSrc[i]:
srcQuad[i] = (x, y)
cpy = drawROI(img, srcQuad)
cv2.imshow('img', cpy)
ptOld = (x, y)
break
disp = drawROI(img, srcQuad)
cv2.namedWindow('img')
cv2.setMouseCallback('img', onMouse)
cv2.imshow('img', disp)
while True:
key = cv2.waitKey()
if key == 13:
break
elif key == 27:
sys.exit()
pers = cv2.getPerspectiveTransform(srcQuad, dstQuad)
dst = cv2.warpPerspective(img, pers, (dw, dh), flags=cv2.INTER_CUBIC)
cv2.imshow('dst', dst)
cv2.waitKey()
이것도 노트북이라 아래부분이 안나오네.. 그래서 원을 드래그해서 각 모서리에 놓고 엔터키를 누르면 그 모양대로 뽑히는거지~~
6. blurring
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('./dog.bmp')
dst1 = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
dst2 = cv2.blur(img, (7, 7))
cv2.imshow('img', img)
cv2.imshow('dst2', dst2)
cv2.waitKey()
plt.figure(figsize=(10, 5))
for i, k in enumerate([5, 7, 9]):
kernel = np.ones((k, k)) / k ** 2
filtering = cv2.filter2D(dst1, -1, kernel)
plt.subplot(1, 3, i+1)
plt.imshow(filtering)
plt.title('kernel size : {}'.format(k))
plt.axis('off')
plt.show()
살짝 뿌옇게 된 dog사진~
7. gaussian
import cv2
img = cv2.imread('./dog.bmp', cv2.IMREAD_GRAYSCALE)
dst1 = cv2.GaussianBlur(img, (0, 0), 2)
dst2 = cv2.blur(img, (5,5))
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
원본 dog사진에 흑백으로 넣어주고 뿌옇게 해주기~~
8. median
import cv2
img = cv2.imread('./noise.bmp', cv2.IMREAD_GRAYSCALE)
dst = cv2.medianBlur(img, 3)
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
잡티 없애기~~
9. bilateral
import cv2
img = cv2.imread('./gaussian_noise.jpg', cv2.IMREAD_GRAYSCALE)
dst1 = cv2.GaussianBlur(img, (5, 5), 1)
dst2 = cv2.bilateralFilter(img, 5, 80, 80)
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
대체 뭔 차이가? dst1은 뿌옇게 한거 같고 dst2는 잡티까지 없애버리기~~
10. canny
import cv2
import numpy as np
img = cv2.imread('./dog.bmp')
med_val = np.median(img)
lower = int(max(0, 0.7*med_val))
upper = int(max(255, 1.3*med_val))
print(lower)
print(upper)
dst = cv2.GaussianBlur(img, (3, 3), 0)
dst = cv2.Canny(dst, lower, upper, 3)
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
인간극장을 모티브로 한 동물극장?
11. filtering
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
def blur_filter(img):
img = cv2.GaussianBlur(img, (0, 0), 3)
return img
def canny_filter(img):
med_val = np.median(img)
lower = int(max(0, 0.7*med_val))
upper = int(min(255, 1.3*med_val))
dst = cv2.GaussianBlur(img, (3, 3), 0, 0)
dst = cv2.Canny(dst, lower, upper, 3)
return dst
cam_mode = 0
while True:
ret, frame = cap.read()
if cam_mode == 1:
frame = blur_filter(frame)
cv2.imshow('frame', frame)
key = cv2.waitKey(10)
if key == 27:
break
elif key == ord(' '):
cam_mode += 1
if cam_mode == 3:
cam_mode = 0
cap.release()
이건 카메라가 되는 pc나 노트북이면 한 번씩 해보면 좋을거같아
'Python' 카테고리의 다른 글
2024년 7월 24일 Python-Classification (0) | 2024.07.25 |
---|---|
2024년 7월 23일 Python-Morphology (5) | 2024.07.25 |
2024년 7월 19일 Python-DL Task (0) | 2024.07.22 |
2024년 7월 17일 Python-ROI (4) | 2024.07.22 |
2024년 7월 16일 Python-Event (3) | 2024.07.22 |