컴퓨터/Python
opencv 마우스 클릭 4번 이미지 가져오기 - 마지막 코드
풍경소리^^
2022. 11. 18. 15:33
https://kyeonghyeon86.tistory.com/83
OpenCV Persperctive 2 (마우스로 좌표 찍기)
이번에는 좌표를 수기로 적는 것이 아닌, 이미지를 보고 그 위에 원하는 곳을 클릭하여 그 클릭한 곳을 좌표로 설정하여 , 이미지를 확대해보려한다. 아래는 그 예제 코드이다. 먼저 마우스 관련
kyeonghyeon86.tistory.com
b_capture.py--------------------
import cv2
import numpy as np
import mapper
image=cv2.imread("img/pexels-photo-900108.jpg") #read in the image
image=cv2.resize(image,(1300,800)) #resizing because opencv does not work well with bigger images
orig=image.copy()
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY) #RGB To Gray Scale
# cv2.imshow("Title",gray)
blurred=cv2.GaussianBlur(gray,(5,5),0) #(5,5) is the kernel size and 0 is sigma that determines the amount of blur
# cv2.imshow("Blur",blurred)
edged=cv2.Canny(blurred,30,50) #30 MinThreshold and 50 is the MaxThreshold
# cv2.imshow("Canny",edged)
contours,hierarchy=cv2.findContours(edged,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE) #retrieve the contours as a list, with simple apprximation model
contours=sorted(contours,key=cv2.contourArea,reverse=True)
#the loop extracts the boundary contours of the page
for c in contours:
p=cv2.arcLength(c,True)
approx=cv2.approxPolyDP(c,0.02*p,True)
if len(approx)==4:
target=approx
break
approx=mapper.mapp(target) #find endpoints of the sheet
pts=np.float32([[0,0],[800,0],[800,800],[0,800]]) #map to 800*800 target window
op=cv2.getPerspectiveTransform(approx,pts) #get the top or bird eye view effect
dst=cv2.warpPerspective(orig,op,(800,800))
cv2.imshow("Scanned",dst)
# press q or Esc to close
cv2.waitKey(0)
cv2.destroyAllWindows()
mapper.py--------------------
import numpy as np
def mapp(h):
h = h.reshape((4,2))
hnew = np.zeros((4,2),dtype = np.float32)
add = h.sum(1)
hnew[0] = h[np.argmin(add)]
hnew[2] = h[np.argmax(add)]
diff = np.diff(h,axis = 1)
hnew[1] = h[np.argmin(diff)]
hnew[3] = h[np.argmax(diff)]
return hnew
######################################################################
mouse_handler.py--------------------
# mouse_handler.py
import cv2
import numpy as np
img_path = './img/pexels-photo-900108.jpg'
ori_img = cv2.imread(img_path)
src = [] # 왼쪽위, 오른쪽위, 오른쪽아래, 왼쪽아래 순으로 각 점의 좌표
# mouse callback handler
def mouse_handler(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONUP: # 마우스가 좌클릭을 했을때 (4번의 클릭으로 좌표 얻기)
img = ori_img.copy()
src.append([x, y])
for xx, yy in src: # 클릭한 곳에 점 그리기
cv2.circle(img, center=(xx, yy), radius=5, color=(0, 255, 0), thickness=-1)
cv2.imshow('Original Image - Car', img)
# perspective transform
if len(src) == 4:
src_np = np.array(src, dtype=np.float32)
print("original points : \n", src_np)
cv2.namedWindow('Original Image - Car')
cv2.setMouseCallback('Original Image - Car', mouse_handler) # 마우스 이벤트 전달
cv2.imshow('Original Image - Car', ori_img)
if cv2.waitKey(0) == 32:
cv2.destroyAllWindows()
car.py--------------------
# car.py
import cv2
import numpy as np
import keyboard
img_path = './img/pexels-photo-900108.jpg'
ori_img = cv2.imread(img_path)
src = [] # 왼쪽위, 오른쪽위, 오른쪽아래, 왼쪽아래 순으로 각 점의 좌표
src.append([211, 229])
src.append([969, 68])
src.append([1079, 601])
src.append([324, 756])
# 32비트로 바꿔줌
src_np = np.array(src, dtype=np.float32)
# width ,height 길이 계산
width = max(np.linalg.norm(src_np[0] - src_np[1]), np.linalg.norm(src_np[2] - src_np[3]))
height = max(np.linalg.norm(src_np[0] - src_np[3]), np.linalg.norm(src_np[1] - src_np[2]))
# width, height 비율
width_ratio = (width / height)
height_ratio = 1
# 비율 * 300 으로 픽셀 크기 맞춤
dst_np = np.array([[0, 0],
[int(width_ratio * 300), 0],
[int(width_ratio * 300), int(height_ratio * 300)],
[0, int(height_ratio * 300)]
], dtype=np.float32)
M = cv2.getPerspectiveTransform(src=src_np, dst=dst_np)
result = cv2.warpPerspective(ori_img, M=M, dsize=(int(width_ratio * 300), height_ratio * 300))
#print("Perspective Transformation :\n", M)
cv2.imshow('img', ori_img)
print("스페이스바를 누르면 번호판의 4개 매칭점이 구해집니다.")
if cv2.waitKey(0) == ord(' '):
for xx, yy in src:
cv2.circle(ori_img, center=(xx, yy), radius=5, color=(0, 255, 0), thickness=-1, lineType=cv2.LINE_AA)
cv2.imshow('img', ori_img)
print("original points : \n", src_np)
if cv2.waitKey(0) == ord(' '):
cv2.imshow('result', result)
cv2.imwrite('result.jpg', result)
print("\ndestination points : \n", dst_np)
if cv2.waitKey(0) == ord(' '):
cv2.destroyAllWindows()
######################################################################
scanner.py--------------------
import cv2
import numpy as np
import keyboard
img_path = r'.\img\antique-art-painting-paper-162589.jpg'
ori_img = cv2.imread(img_path)
# src = [] # 왼쪽위, 오른쪽위, 오른쪽아래, 왼쪽아래 순으로 각 점의 좌표
# src.append([ 52, 23])
# src.append([600, 124])
# src.append([523, 446])
# src.append([ 13, 300])
#######################################################################
src = [] # 왼쪽위, 오른쪽위, 오른쪽아래, 왼쪽아래 순으로 각 점의 좌표
# mouse callback handler
def mouse_handler(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONUP: # 마우스가 좌클릭을 했을때 (4번의 클릭으로 좌표 얻기)
img = ori_img.copy()
src.append([x, y])
for xx, yy in src: # 클릭한 곳에 점 그리기
cv2.circle(img, center=(xx, yy), radius=5, color=(0, 255, 0), thickness=-1)
cv2.imshow('Original Image', img)
# perspective transform
if len(src) == 4:
src_np = np.array(src, dtype=np.float32)
# print("original points : \n", src_np)
cv2.namedWindow('Original Image')
cv2.setMouseCallback('Original Image', mouse_handler) # 마우스 이벤트 전달
cv2.imshow('Original Image', ori_img)
if cv2.waitKey(0) == 32:
# cv2.destroyAllWindows()
pass
#######################################################################
# 32비트로 바꿔줌
src_np = np.array(src, dtype=np.float32)
# width ,height 길이 계산
width = max(np.linalg.norm(src_np[0] - src_np[1]), np.linalg.norm(src_np[2] - src_np[3]))
height = max(np.linalg.norm(src_np[0] - src_np[3]), np.linalg.norm(src_np[1] - src_np[2]))
# width, height 비율
width_ratio = (width / height)
height_ratio = 1
# 비율 * 300 으로 픽셀 크기 맞춤
dst_np = np.array([[0, 0],
[int(width_ratio * 300), 0],
[int(width_ratio * 300), int(height_ratio * 300)],
[0, int(height_ratio * 300)]
], dtype=np.float32)
M = cv2.getPerspectiveTransform(src=src_np, dst=dst_np)
result = cv2.warpPerspective(ori_img, M=M, dsize=(int(width_ratio * 300), height_ratio * 300))
#print("Perspective Transformation :\n", M)
# cv2.imshow('img', ori_img)
# print("스페이스바를 누르면 번호판의 4개 매칭점이 구해집니다.")
# if cv2.waitKey(0) == ord(' '):
# for xx, yy in src:
# cv2.circle(ori_img, center=(xx, yy), radius=5, color=(0, 255, 0), thickness=-1, lineType=cv2.LINE_AA)
# cv2.imshow('img', ori_img)
# print("original points : \n", src_np)
cv2.imshow('result', result)
cv2.imwrite('result.jpg', result)
# if cv2.waitKey(0) == ord(' '):
# cv2.imshow('result', result)
# cv2.imwrite('result.jpg', result)
# print("\ndestination points : \n", dst_np)
if cv2.waitKey(0) == ord(' '):
cv2.destroyAllWindows()