OpenCV 이미지 처리 1
해당 포스트는 나도코딩님의 파이썬 무료 강의 (활용편6) - 이미지 처리(OpenCV)를 들으며 정리한 내용과 코드 입니다.
환경설정
import cv2
cv2.__version__
'4.7.0'
OpenCV(Computer Vision)
이미지/동영상 처리에 사용되는 오픈소스 라이브러리
1.이미지 출력
pixabay - 무료 이미지
import cv2
img = cv2.imread('img.jpg') # 해당경로 파일 읽어오기
cv2.imshow('img', img) # img이름 창에 img표시
key = cv2.waitKey(5000) # 지정된 시간(ms) 동안 사용자 키 입력 대기 # 0: 무한
# key = cv2.waitKey(5000)
# print(key) # 아스키 코드로 입력확인(a:87, q:113)
cv2.destroyAllWindows() # 모든 창 닫기
읽기 옵션
- cv2.IMREAD_COLOR: 컬러 이미지, 투명 영역은 무시(디폴트)
- cv2.IMREAD_GRAYSCALE: 흑백 이미지
- cv2.IMREAD_UNCHANGED: 투명 영역까지 포함
import cv2
img_color = cv2.imread('img.jpg', cv2.IMREAD_COLOR)
img_gray = cv2.imread('img.jpg', cv2.IMREAD_GRAYSCALE)
img_unchanged = cv2.imread('img.jpg', cv2.IMREAD_UNCHANGED)
cv2.imshow('img_color', img_color)
cv2.imshow('img_gray', img_gray)
cv2.imshow('img_unchanged', img_unchanged)
key = cv2.waitKey(0)
cv2.destroyAllWindows()
Shape
이미지의 height, width, channel 정보 출력
import cv2
im = cv2.imread('img.jpg')
img.shape # 높이, 넓이, channel # r,g,b, a(알파값)
(640, 613, 3)
2.동영상 출력
pexels - 무료 영상, 이미지
동영상 파일 출력
import cv2
cap = cv2.VideoCapture('video.mp4')
while cap.isOpened(): # 영상파일이 올바르게 열렸는 확인
ret, frame = cap.read() # ret: 성공여부, frame: 받아온 이미지(프레임)
if not ret:
print('더 이상 가져올 프레임이 없어요')
break
cv2.imshow('video', frame)
if cv2.waitKey(25) == ord('q'): # ord: 아스키 코드로 변환 # key대기 숫자에 따라 재생속도 조절가능
print('사용자 입력에 의해 종료합니다')
break
cap.release() # 자원 해제(반환)
cv2.destroyAllWindows()
더 이상 가져올 프레임이 없어요
카메라 출력
import cv2
cap = cv2.VideoCapture(0) # 0번째 카메라 장치(Device ID)
if not cap.isOpened(): # 카메라가 잘 열리지 않은 경우
exit() # 프로그램 종료
while True:
ret, frame = cap.read()
if not ret:
break
cv2.imshow('camera', frame)
if cv2.waitKey(1) == ord('q'): # 사용자가 q 입력 시
break
cap.release()
cv2.destroyAllWindows()
3.도형 그리기
빈 스케치북 만들기
import cv2
import numpy as np
# 세로 480, 가로 640, 3 channel(BGR)에 해당하는 스케치북 만들기
img = np.zeros((480, 640 ,3), dtype=np.uint8) # 0(검은색) 으로 채운
# img[:] = (255, 255, 255) # 전체 공간을 흰색으로 채우기
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
일부 영역 색칠
import cv2
import numpy as np
img = np.zeros((480, 640 ,3), dtype=np.uint8)
img[100:200, 200:300] = (255, 255, 255) # 세로영역, 가로영역을 흰색으로 채우기
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
직선
직선의 종류(line type)
- cv2.LINE_4: 상하좌우 4방향으로 연결된 선
- cv2.LINE_8: 대각선을 포함한 8방향으로 연결된 선(디폴트)
- cv2.LINE_AA: 부드러운 선(anti-aliasing)
import cv2
import numpy as np
img = np.zeros((480, 640 ,3), dtype=np.uint8)
COLOR = (0, 255, 255) # 색깔: BGR순서, Yellow
THICKNESS = 3 # 두께
cv2.line(img, (50, 100), (400, 50), COLOR, THICKNESS, cv2.LINE_8)
# 그릴 위치, 시작점, 끝점, 색깔, 두께, 선종류
cv2.line(img, (50, 200), (400, 150), COLOR, THICKNESS, cv2.LINE_4)
cv2.line(img, (50, 300), (400, 250), COLOR, THICKNESS, cv2.LINE_AA)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
원
import cv2
import numpy as np
img = np.zeros((480, 640 ,3), dtype=np.uint8)
COLOR = (255, 255, 0) # 색깔: BGR순서, Skyblue
RADIUS = 50 # 반지름
THICKNESS = 10 # 두께
cv2.circle(img, (200, 100), RADIUS, COLOR, THICKNESS, cv2.LINE_AA) # 속이 빈 원
# 그릴 위치, 원의 중심점, 반지름, 색깔, 두께, 선종류
cv2.circle(img, (400, 100), RADIUS, COLOR, cv2.FILLED, cv2.LINE_AA) # 꽉 찬 원
# cv2.circle(img, (400, 100), RADIUS, COLOR, -1, cv2.LINE_AA) # 속이 꽉찬 원
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
사각형
import cv2
import numpy as np
img = np.zeros((480, 640 ,3), dtype=np.uint8)
COLOR = (0, 255, 0) # 색깔: BGR순서, Green
THICKNESS = 3 # 두께
cv2.rectangle(img, (100, 100), (200, 200), COLOR, THICKNESS) # 속이 빈 사각형
# 그릴 위치, 왼쪽 위 좌표, 오른쪽 아래 좌표, 색깔, 두께
cv2.rectangle(img, (300, 100), (400, 300), COLOR, cv2.FILLED) # 꽉 찬 사각형
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
다각형
import cv2
import numpy as np
img = np.zeros((480, 640 ,3), dtype=np.uint8)
COLOR = (0, 0, 255) # 색깔: BGR순서, Red
THICKNESS = 3 # 두께
pts1 = np.array([[100, 100], [200, 100], [100, 200]]) # 3개 좌표를 잇는 다각형: 삼각형
pts2 = np.array([[200, 100], [300, 100], [300, 200]])
# cv2.polylines(img, [pts1], True, COLOR, THICKNESS, cv2.LINE_AA)
# cv2.polylines(img, [pts2], True, COLOR, THICKNESS, cv2.LINE_AA)
# 그릴 위치, [그릴 좌표들], 닫힘 여부, 색깔, 두께, 선종류
cv2.polylines(img, [pts1, pts2], True, COLOR, THICKNESS, cv2.LINE_AA)
pts3 = np.array([[[100, 300], [200, 300], [100, 400]], [[200, 300], [300, 300], [300, 400]]])
cv2.fillPoly(img, pts3, COLOR, cv2.LINE_AA) # 꽉 찬 다각형
# 그릴 윛, 그릴 좌표들, 색깔, 선종류
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
4.텍스트
OpenCV에서 사용하는 글꼴 종류
- cv2.FONT_HERSHEY_SIMPLEX : 보통 크기의 산 세리프(sans-serif) 글꼴
- cv2.FONT_HERSHEY_PLAIN : 작은 크기의 산 세리프 글꼴
- cv2.FONT_HERSHEY_SCRIPT_SIMPLEX : 필기체 스타일 글꼴
- cv2.FONT_HERSHEY_TRIPLEX : 보통 크기의 세리프 글꼴
- cv2.FONT_ITALIC : 기울임 (이텔릭)
import numpy as np
import cv2
img = np.zeros((480, 640, 3), dtype=np.uint8)
SCALE = 1 # 크기
COLOR = (255, 255, 255) # 흰색
THICKNESS = 1 # 두께
cv2.putText(img, "Text Simplex", (20, 50), cv2.FONT_HERSHEY_SIMPLEX, SCALE, COLOR, THICKNESS)
# 그릴 위치, 텍스트 내용, 시작위치, 폰트종류, 크기, 색깔, 두께
cv2.putText(img, "Text Plain", (20, 150), cv2.FONT_HERSHEY_PLAIN, SCALE, COLOR, THICKNESS)
cv2.putText(img, "Text Script Simplex", (20, 250), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, SCALE, COLOR, THICKNESS)
cv2.putText(img, "Text Triplex", (20, 350), cv2.FONT_HERSHEY_TRIPLEX, SCALE, COLOR, THICKNESS)
cv2.putText(img, "Text Italic", (20, 450), cv2.FONT_HERSHEY_TRIPLEX | cv2.FONT_ITALIC, SCALE, COLOR, THICKNESS)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
한글 우회
import numpy as np
import cv2
img = np.zeros((480, 640, 3), dtype=np.uint8)
SCALE = 1 # 크기
COLOR = (255, 255, 255) # 흰색
THICKNESS = 1 # 두께
cv2.putText(img, "텍스트 출력", (20, 50), cv2.FONT_HERSHEY_SIMPLEX, SCALE, COLOR, THICKNESS)
# 그릴 위치, 텍스트 내용, 시작위치, 폰트종류, 크기, 색깔, 두께
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
한글 우회 방법
import numpy as np
import cv2
# PIL (Python Image Library)
from PIL import ImageFont, ImageDraw, Image
def myPutText(src, text, pos, font_size, font_color):
img_pil = Image.fromarray(src)
draw = ImageDraw.Draw(img_pil)
font = ImageFont.truetype('fonts/gulim.ttc', font_size)
draw.text(pos, text, font=font, fill=font_color)
return np.array(img_pil)
img = np.zeros((480, 640, 3), dtype=np.uint8)
FONT_SIZE = 30
COLOR = (255, 255, 255) # 흰색
# cv2.putText(img, "텍스트 출력", (20, 50), cv2.FONT_HERSHEY_SIMPLEX, SCALE, COLOR, THICKNESS)
# 그릴 위치, 텍스트 내용, 시작위치, 폰트종류, 크기, 색깔, 두께
img = myPutText(img, "텍스트 출력", (20, 50), FONT_SIZE, COLOR)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
5.파일 저장
이미지 저장
import cv2
img = cv2.imread('img.jpg', cv2.IMREAD_GRAYSCALE) # 흑백으로 이미지 불러오기
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
result = cv2.imwrite('img_save.jpg', img)
print(result)
True
저장 포맷(jpg, png)
import cv2
img = cv2.imread('img.jpg', cv2.IMREAD_GRAYSCALE) # 흑백으로 이미지 불러오기
# 이미지 처리 과정 삽입 가능
cv2.imwrite('img_save.png', img) # png 형태로 저장
True
동영상 저장
import cv2
cap = cv2.VideoCapture('video.mp4')
# 코덱 정의(four character code)
fourcc = cv2.VideoWriter_fourcc(*'DIVX') # *'DIVX' == 'D','I','V','X'
# 프레임 크기, FPS 정의
width = round(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
# fps = cap.get(cv2.CAP_PROP_FPS)*2 # 영상 재생 속도 2배
out = cv2.VideoWriter('output_fast.avi', fourcc, fps, (width, height))
# 저장 파일명, 코덱, FPS, 크기(width, height)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
out.write(frame) # 영상 데이터만 저장(소리x)
cv2.imshow('viedo', frame)
if cv2.waitKey(1) == ord('q'):
break
out.release() # 자원 해제
cap.release()
cv2.destroyAllWindows()
# *'DIVX' == 'D','I','V','X'
codec = 'DIVX'
print(codec)
print(*codec)
print([codec])
print([*codec])
DIVX
D I V X
['DIVX']
['D', 'I', 'V', 'X']
6. 크기조정
이미지
고정 크기로 설정
import cv2
img = cv2.imread('img.jpg')
dst = cv2.resize(img, (400, 500)) # width, height 고정크기
cv2.imshow('img', img)
cv2.imshow('resize', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
비율로 설정
import cv2
img = cv2.imread('img.jpg')
dst = cv2.resize(img, None, fx=0.5, fy=0.5) # x, y 비율 정의(0.5배로 축소)
cv2.imshow('img', img)
cv2.imshow('resize', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
보간법
이미지를 줄이거나 키울 때 자연스럽게 처리하는 방법
- cv2.INTER_AREA: 크기를 줄일 때 사용
- cv2.INTER_CUBIC: 크기를 늘릴 때 사용(속도 느림, 퀄리티 좋음)
- cv2.INTER_LINEAR: 크기를 늘릴 때 사용(default)
보간법 적용 축소
import cv2
img = cv2.imread('img.jpg')
dst = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_AREA) # x, y 비율 정의(0.5배로 축소)
cv2.imshow('img', img)
cv2.imshow('resize', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
보간법 적용 확대
import cv2
img = cv2.imread('img.jpg')
dst = cv2.resize(img, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC) # x, y 비율 정의(1.5배로 확대)
cv2.imshow('img', img)
cv2.imshow('resize', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
동영상
고정 크기로 설정
import cv2
cap = cv2.VideoCapture('video.mp4')
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
frame_resized = cv2.resize(frame, (400, 500)) # 프레임을 고정 크기로
cv2.imshow('video', frame_resized)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
비율로 설정
import cv2
cap = cv2.VideoCapture('video.mp4')
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
frame_resized = cv2.resize(frame, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC) # 프레임을 비율로
cv2.imshow('video', frame_resized)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
7.이미지 자르기
영역을 잘라서 새로운 윈도우에 표시
import cv2
img = cv2.imread('img.jpg')
# img.shape # (640, 613, 3)
crop = img[100:200, 200:400] # [세로범위, 가로범위]
cv2.imshow('img', img)
cv2.imshow('crop', crop)
cv2.waitKey(0)
cv2.destroyAllWindows()
영역을 잘라서 기존 윈도우에 표시
import cv2
img = cv2.imread('img.jpg')
crop = img[100:200, 200:400] # [세로범위, 가로범위]
img[100:200, 400:600] = crop
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
8.이미지 대칭
좌우 대칭
import cv2
img = cv2.imread('img.jpg')
flip_horizontal = cv2.flip(img, 1) # flipCode > 0: 좌우 대칭 Horizontal
cv2.imshow('img', img)
cv2.imshow('flip_horizontal', flip_horizontal)
cv2.waitKey(0)
cv2.destroyAllWindows()
상하 대칭
import cv2
img = cv2.imread('img.jpg')
flip_vertical = cv2.flip(img, 0) # flipCode == 0: 상하 대칭 Vertical
cv2.imshow('img', img)
cv2.imshow('flip_vertical', flip_vertical)
cv2.waitKey(0)
cv2.destroyAllWindows()
상하좌우 대칭
import cv2
img = cv2.imread('img.jpg')
flip_both = cv2.flip(img, -1) # flipCode < 0: 상하좌우 대칭 Vertical
cv2.imshow('img', img)
cv2.imshow('flip_both', flip_both)
cv2.waitKey(0)
cv2.destroyAllWindows()
9.이미지 회전
시계 방향 90도 회전
import cv2
img = cv2.imread('img.jpg')
rotate_90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE) # 시계 방향으로 90도 회전
cv2.imshow('img', img)
cv2.imshow('rotate_90', rotate_90)
cv2.waitKey(0)
cv2.destroyAllWindows()
180도 회전
import cv2
img = cv2.imread('img.jpg')
rotate_180 = cv2.rotate(img, cv2.ROTATE_180) # 180도 회전
cv2.imshow('img', img)
cv2.imshow('rotate_180', rotate_180)
cv2.waitKey(0)
cv2.destroyAllWindows()
반시계 방향으로 90도 회전(시계 방향으로 270도 회전)
import cv2
img = cv2.imread('img.jpg')
rotate_270 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE) # 반시계 방향으로 90도 회전
cv2.imshow('img', img)
cv2.imshow('rotate_270', rotate_270)
cv2.waitKey(0)
cv2.destroyAllWindows()
10.이미지 변형(흑백)
이미지에서 필요없는 부분을 없애는 전처리
이미지를 흑백으로 읽음
import cv2
img = cv2.imread('img.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
불러온 이미지를 흑백으로 변형
import cv2
img = cv2.imread('img.jpg')
dst = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('img', img)
cv2.imshow('gray', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
11.이미지 변형(흐림)
외곽선 검출을 더 쉽게, 노이즈 제거
가우시안 블러
커널 사이즈 변화에 따른 흐림
import cv2
img = cv2.imread('img.jpg')
# 커널 사이즈는 일반적으로 양의 홀수가 우수한 성능
# (3, 3), (5, 5), (7, 7)
kernel_3 = cv2.GaussianBlur(img, (3, 3), 0) # 0:자동으로 시그마x(표준편차)
kernel_5 = cv2.GaussianBlur(img, (5, 5), 0)
kernel_7 = cv2.GaussianBlur(img, (7, 7), 0)
cv2.imshow('img', img)
cv2.imshow('kernel_3', kernel_3)
cv2.imshow('kernel_5', kernel_5)
cv2.imshow('kernel_7', kernel_7)
cv2.waitKey(0)
cv2.destroyAllWindows()
표준 편차 변화에 따른 흐림
import cv2
img = cv2.imread('img.jpg')
sigma_1 = cv2.GaussianBlur(img, (0, 0), 1) # sigmaX: 가우시안 커널의 x 방향의 표준편차
sigma_2 = cv2.GaussianBlur(img, (0, 0), 2)
sigma_3 = cv2.GaussianBlur(img, (0, 0), 3)
cv2.imshow('img', img)
cv2.imshow('sigma_1', sigma_1)
cv2.imshow('sigma_2', sigma_2)
cv2.imshow('sigma_3', sigma_3) # 가우시안보다 블러가 많이 적용
cv2.waitKey(0)
cv2.destroyAllWindows()
12.이미지 변형(원근)
사다리꼴 이미지 펼치기
import cv2
import numpy as np
img = cv2.imread('newspaper.jpg')
width, height = 640, 240 # 출력 결과물
src = np.array([[511, 352], [1008, 345], [1122, 584], [455, 594]], dtype=np.float32) # 변형할 영역 4개의 지점(input)
dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=np.float32) # output
# 좌상, 우상, 우하, 좌하 (시계 방향으로 4지점 정의)
matrix = cv2.getPerspectiveTransform(src, dst) # matrix 얻어옴
result = cv2.warpPerspective(img, matrix, (width, height)) # matrix 대로 변환함
cv2.imshow('img', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
회전된 이미지 세우기
import cv2
import numpy as np
img = cv2.imread('poker.jpg')
width, height = 530, 710
src = np.array([[702, 143], [1133, 414], [726, 1007], [276, 700]], dtype=np.float32) # 변형할 영역 4개의 지점(input)
dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=np.float32) # output
# 좌상, 우상, 우하, 좌하 (시계 방향으로 4지점 정의)
matrix = cv2.getPerspectiveTransform(src, dst) # matrix 얻어옴
result = cv2.warpPerspective(img, matrix, (width, height)) # matrix 대로 변환함
cv2.imshow('img', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
미니 프로젝트: 반자동 문서 스캐너
마우스 이벤트 등록
import cv2
def mouse_handler(event, x, y, flags, params):
if event == cv2.EVENT_LBUTTONDOWN: # 좌측 버튼 DOWN 이벤트
print('좌버튼 Down')
print(x, y)
elif event == cv2.EVENT_LBUTTONUP: # 좌측 버튼 UP 이벤트
print('좌버튼 Up')
print(x, y)
elif event == cv2.EVENT_LBUTTONDBLCLK: # 좌측 버튼 더블 클릭
print('더블클릭')
# elif event == cv2.EVENT_MOUSEMOVE: # 마우스 이동
# print('마우스 이동')
elif event == cv2.EVENT_RBUTTONDOWN: # 마우스 우측 버튼 DOWN
print('우클릭')
img = cv2.imread('poker.jpg')
cv2.namedWindow('img') # img란 이름의 윈도우를 먼저 만들어둠, 여기에 마우스 이벤트를 처리하기 위한 핸들러 적용
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
좌버튼 Down
368 329
좌버튼 Up
368 329
더블클릭
좌버튼 Up
368 329
미니 프로젝트
import cv2
import numpy as np
point_list = []
src_img = cv2.imread('poker.jpg')
COLOR = (255, 0, 255) # pink
def mouse_handler(event, x, y, flags, params):
if event == cv2.EVENT_LBUTTONDOWN:
point_list.append((x, y))
for point in point_list:
cv2.circle(src_img, point, 15, COLOR, cv2.FILLED)
if len(point_list) == 4:
show_result() # 결과 출력
cv2.imshow('img', src_img)
def show_result():
width, height = 530, 710
src = np.float32(point_list)
dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=np.float32)
matrix = cv2.getPerspectiveTransform(src, dst)
result = cv2.warpPerspective(src_img, matrix, (width, height))
cv2.imshow('result', result)
cv2.namedWindow('img')
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', src_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
선 긋기 추가
import cv2
import numpy as np
point_list = []
src_img = cv2.imread('poker.jpg')
COLOR = (255, 0, 255) # pink
THICKNESS = 3
drawing = False # 선을 그릴지 여부
def mouse_handler(event, x, y, flags, params):
global drawing
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True # 선을 그리기 시작
point_list.append((x, y))
if drawing:
prev_point = None # 직선의 시작점
for point in point_list:
cv2.circle(src_img, point, 15, COLOR, cv2.FILLED)
if prev_point:
cv2.line(src_img, prev_point, point, COLOR, THICKNESS, cv2.LINE_AA)
prev_point = point
if len(point_list) == 4:
show_result() # 결과 출력
cv2.imshow('img', src_img)
def show_result():
width, height = 530, 710
src = np.float32(point_list)
dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=np.float32)
matrix = cv2.getPerspectiveTransform(src, dst)
result = cv2.warpPerspective(src_img, matrix, (width, height))
cv2.imshow('result', result)
cv2.namedWindow('img')
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', src_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
실시간 선 긋기
import cv2
import numpy as np
point_list = []
src_img = cv2.imread('poker.jpg')
COLOR = (255, 0, 255) # pink
THICKNESS = 3
drawing = False # 선을 그릴지 여부
def mouse_handler(event, x, y, flags, params):
global drawing
dst_img = src_img.copy()
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True # 선을 그리기 시작
point_list.append((x, y))
if drawing:
prev_point = None # 직선의 시작점
for point in point_list:
cv2.circle(dst_img, point, 15, COLOR, cv2.FILLED)
if prev_point:
cv2.line(dst_img, prev_point, point, COLOR, THICKNESS, cv2.LINE_AA)
prev_point = point
next_point = (x, y)
if len(point_list) == 4:
show_result() # 결과 출력
next_point = point_list[0] # 첫 번째 클릭한 점
cv2.line(dst_img, prev_point, next_point, COLOR, THICKNESS, cv2.LINE_AA)
cv2.imshow('img', dst_img)
def show_result():
width, height = 530, 710
src = np.float32(point_list)
dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=np.float32)
matrix = cv2.getPerspectiveTransform(src, dst)
result = cv2.warpPerspective(src_img, matrix, (width, height))
cv2.imshow('result', result)
cv2.namedWindow('img')
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', src_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Reference
- 나도코딩: 파이썬 코딩 무료 강의 (활용편6) - OpenCV 이미지 처리
- Pixabay, Ty_Swartz: 고양이 이미지
- Pexels, Magda Ehlers: 고양이 영상
- Pixabay, ChristopherPluta: 신문 이미지
- Pixabay, IvicaM90: 카드 이미지
댓글남기기