Attention please

[OpenCV] OpenCV를 이용한 스캐너 만들기 본문

프로젝트

[OpenCV] OpenCV를 이용한 스캐너 만들기

Seongmin.C 2023. 1. 9. 16:45

이번에 해볼 것은 말 그대로 이미지의 원하는 부분을 스캔하는 것이다. 먼저 본 이미지가 잘 실행되는지 확인해주자.

 

import cv2
import numpy as np

img = cv2.imread('cafe.jpg')

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

 

 

 

 

 

 

 

 

좌표 구하기

직접 그림판을 열어서 원하는 지점의 좌표를 얻는 것 역시 하나의 방법이지만 너무 번거롭다. OpenCV 라이브러리에는 마우스의 움직임을 감지하는 마우스 이벤트 기능이 존재한다. 

 

다음 코드는 간단하게 왼쪽 마우스를 클릭하면 해당 지점의 좌표가 출력되도록 구성되었다.

 

img = cv2.imread('cafe.jpg')
drawing = False 

def mouse_handler(event, x, y, flags, param):
    global drawing
    dst_img = img.copy()
    
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        print(x, y)
        point_list.append((x, y))
        
    for point in point_list:
        cv2.circle(dst_img, point, 10, COLOR, cv2.FILLED)
    
    cv2.imshow('img', dst_img)
        
        
cv2.namedWindow('img')
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

클릭한 지점의 좌표를 기준으로 다음과 같이 점이 그려진다.

 

 

또한 그 지점의 좌표가 출력된다.

 

 

 

 

 

 

 

 

 

 

스캔하기

위에서 구한 좌표를 바탕으로 원하는 영역을 스캔하는 것 역시 가능하다. 우선 코드는 다음과 같다.

 

import cv2
import numpy as np

point_list = []
img = cv2.imread('cafe.jpg')

COLOR = (0, 255, 0)
COLOR_text = (0, 0, 255)
THICKNESS = 2
drawing = False 
SCALE = 0.5


def mouse_handler(event, x, y, flags, param):
    global drawing
    dst_img = 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, 10, COLOR, cv2.FILLED)
            cv2.putText(dst_img, f"({point})", point, cv2.FONT_HERSHEY_SIMPLEX, SCALE, COLOR_text, THICKNESS)
            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 = 500, 700
    
    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(img, matrix, (width, height))
    cv2.imshow('result', result)


cv2.namedWindow('img')
cv2.setMouseCallback('img', mouse_handler)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

위 코드를 실행시키고 클릭을 하게 되면 점이 찍힘과 동시에 그 점의 좌표도 그려진다. 또한 찍힌 점이 총 4개가 되면 사각형을 완성하고 해당 영역을 (500, 700) 의 크기로 스캔을 따준다.

 

 

 

Comments