Skip to content
Snippets Groups Projects
Commit cd443282 authored by parkminwoo's avatar parkminwoo
Browse files

final

parent 36c53a92
Branches master
No related tags found
No related merge requests found
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import numpy as np import numpy as np
import cv2 import cv2
import glob import glob
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import tkinter as tk import tkinter as tk
from PIL import Image from PIL import Image
from PIL import ImageTk from PIL import ImageTk
import os import os
from fpdf import FPDF from fpdf import FPDF
from PIL import Image from PIL import Image
import os
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 두 점 사이의 거리를 구한다. # 두 점 사이의 거리를 구한다.
# param : point1, point2 - 거리를 구할 두 점이다. # param : point1, point2 - 거리를 구할 두 점이다.
# return : point1, point2 사이의 거리이다. # return : point1, point2 사이의 거리이다.
def distance(point1, point2): def distance(point1, point2):
x1,y1 = point1 x1,y1 = point1
x2,y2 = point2 x2,y2 = point2
return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))) return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다. # 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.
# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다, # param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다,
# flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다, # flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,
# param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다. # param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.
# return : none # return : none
def mouse_callback(event,x,y,flags,param): def mouse_callback(event,x,y,flags,param):
global mouse_is_pressing, points global mouse_is_pressing, points
# step == 1 이면,마우스 콜백 함수가 등록된 것이다. # step == 1 이면,마우스 콜백 함수가 등록된 것이다.
# step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다. # step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.
if step != 1: if step != 1:
return return
# CASE 1 - 마우스가 움직이고 # CASE 1 - 마우스가 움직이고
if event == cv2.EVENT_MOUSEMOVE: if event == cv2.EVENT_MOUSEMOVE:
# 눌린상태일때 # 눌린상태일때
if mouse_is_pressing == True: if mouse_is_pressing == True:
#마우스의 좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다 #마우스의 좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다
for i,point in enumerate(points): for i,point in enumerate(points):
if distance((x,y), point) < 15: if distance((x,y), point) < 15:
points[i][0] = x points[i][0] = x
points[i][1] = y points[i][1] = y
break break
# CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때, # CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때,
elif event == cv2.EVENT_LBUTTONDOWN: elif event == cv2.EVENT_LBUTTONDOWN:
# 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다. # 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.
for point in points: for point in points:
if distance((x,y), point) < 10: if distance((x,y), point) < 10:
mouse_is_pressing = True mouse_is_pressing = True
break break
# CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈 # CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈
elif event == cv2.EVENT_LBUTTONUP: elif event == cv2.EVENT_LBUTTONUP:
mouse_is_pressing = False mouse_is_pressing = False
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 두 벡터 사이의 각도를 구한다. # 두 벡터 사이의 각도를 구한다.
# param : A, B - 벡터를 표현한 ndarray이다. # param : A, B - 벡터를 표현한 ndarray이다.
# return : angle - 벡터 A와 B 사이의 각도이다. # return : angle - 벡터 A와 B 사이의 각도이다.
def angle_between(A, B): def angle_between(A, B):
x1 = A[0] x1 = A[0]
y1 = A[1] y1 = A[1]
x2 = B[0] x2 = B[0]
y2 = B[1] y2 = B[1]
dot = x1*x2 + y1*y2 dot = x1*x2 + y1*y2
det = x1*y2 - y1*x2 det = x1*y2 - y1*x2
angle = np.arctan2(det, dot) * 180/np.pi angle = np.arctan2(det, dot) * 180/np.pi
return angle return angle
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 다음 순서를 갖도록 꼭짓점을 정렬한다. # 다음 순서를 갖도록 꼭짓점을 정렬한다.
# top left, top right, bottom right, bottom left # top left, top right, bottom right, bottom left
# param : points - 정렬되기 전의 꼭짓점의 ndarray이다. # param : points - 정렬되기 전의 꼭짓점의 ndarray이다.
# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다. # return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.
def sort_points(points): def sort_points(points):
points = points.astype(np.float32) points = points.astype(np.float32)
new_points = np.zeros((4, 2), dtype = "float32") new_points = np.zeros((4, 2), dtype = "float32")
# top left를 구한다. # top left를 구한다.
s = points.sum(axis = 1) s = points.sum(axis = 1)
min_index = np.argmin(s) min_index = np.argmin(s)
new_points[0] = points[min_index] new_points[0] = points[min_index]
points = np.delete(points, min_index, axis = 0) points = np.delete(points, min_index, axis = 0)
# bottom right를 구한다. # bottom right를 구한다.
s = points.sum(axis = 1) s = points.sum(axis = 1)
max_index = np.argmax(s) max_index = np.argmax(s)
new_points[2] = points[max_index] new_points[2] = points[max_index]
points = np.delete(points, max_index, axis = 0) points = np.delete(points, max_index, axis = 0)
# top right, bottom left를 구한다. # top right, bottom left를 구한다.
v0 = points[0] - new_points[0] v0 = points[0] - new_points[0]
v1 = points[1] - new_points[0] v1 = points[1] - new_points[0]
angle = angle_between(v0, v1) angle = angle_between(v0, v1)
# angle_between() : 벡터 사이의 각도를 구한다. # angle_between() : 벡터 사이의 각도를 구한다.
if angle < 0: if angle < 0:
new_points[1] = points[1] new_points[1] = points[1]
new_points[3] = points[0] new_points[3] = points[0]
else: else:
new_points[1] = points[0] new_points[1] = points[0]
new_points[3] = points[1] new_points[3] = points[1]
return new_points return new_points
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 이미지(문서 영역)를 정면 방향으로 변환한다. # 이미지(문서 영역)를 정면 방향으로 변환한다.
# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다. # param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.
# return : img_warped - 정면 방향으로 변환된 이미지이다. # return : img_warped - 정면 방향으로 변환된 이미지이다.
def transform(img_input, points): def transform(img_input, points):
# 다음 순서롤 갖도록 꼭지점을 정렬한다. # 다음 순서롤 갖도록 꼭지점을 정렬한다.
# top left, top right, bottom right, bottom left # top left, top right, bottom right, bottom left
points = sort_points(points) points = sort_points(points)
topLeft, topRight, bottomRight, bottomLeft = points topLeft, topRight, bottomRight, bottomLeft = points
#print(topLeft, topRight, bottomRight, bottomLeft) #print(topLeft, topRight, bottomRight, bottomLeft)
#print(topLeft[0] + topLeft[1], topRight[0]+topRight[1], #print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],
#bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1]) #bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])
# 변환 후 책의 너비와 높이를 결정한다. # 변환 후 책의 너비와 높이를 결정한다.
topWidth = distance(bottomLeft, bottomRight) topWidth = distance(bottomLeft, bottomRight)
bottomWidth = distance(topLeft, topRight) bottomWidth = distance(topLeft, topRight)
maxWidth = max(int(topWidth), int(bottomWidth)) maxWidth = max(int(topWidth), int(bottomWidth))
leftHeight = distance(topLeft, bottomLeft) leftHeight = distance(topLeft, bottomLeft)
rightHeight = distance(topRight, bottomRight) rightHeight = distance(topRight, bottomRight)
maxHeight = max(int(leftHeight), int(rightHeight)) maxHeight = max(int(leftHeight), int(rightHeight))
# 정면에서 바라본 책의 좌표를 결정한다. # 정면에서 바라본 책의 좌표를 결정한다.
dst = np.array([[0, 0],[maxWidth - 1, 0], dst = np.array([[0, 0],[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32") [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32")
H = cv2.getPerspectiveTransform(points, dst) H = cv2.getPerspectiveTransform(points, dst)
img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight)) img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))
return img_warped return img_warped
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 가장 큰 영역을 갖는 컨투어를 찾는다. # 가장 큰 영역을 갖는 컨투어를 찾는다.
# param : contours - 컨투어들의 리스트이다. # param : contours - 컨투어들의 리스트이다.
# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다. # return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.
def findMaxArea(contours): def findMaxArea(contours):
max_area = -1 max_area = -1
max_index = -1 max_index = -1
# 가장 큰 영역을 갖는 컨투어를 찾는다. # 가장 큰 영역을 갖는 컨투어를 찾는다.
for i,contour in enumerate(contours): for i,contour in enumerate(contours):
# cv2.contourArea : 컨투어의 넓이를 얻는다. # cv2.contourArea : 컨투어의 넓이를 얻는다.
area = cv2.contourArea(contour) area = cv2.contourArea(contour)
# cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다. # cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.
x,y,w,h = cv2.boundingRect(contour) x,y,w,h = cv2.boundingRect(contour)
if (w*h)*0.4 > area: if (w*h)*0.4 > area:
continue continue
if w > h: if w > h:
continue continue
if area > max_area: if area > max_area:
max_area = area max_area = area
max_index = i max_index = i
if max_area < 10000: if max_area < 10000:
max_index = -1 max_index = -1
return max_index return max_index
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def convert_to_tkimage(): def convert_to_tkimage():
global src global src
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY) _, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
img = Image.fromarray(binary) img = Image.fromarray(binary)
imgtk = ImageTk.PhotoImage(image=img) imgtk = ImageTk.PhotoImage(image=img)
label.config(image=imgtk) label.config(image=imgtk)
label.image = imgtk label.image = imgtk
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def scanning(image): def scanning(image):
global contours global contours
global max_index global max_index
global max_contour global max_contour
#grabcut , 배경 제거 #grabcut , 배경 제거
points = [] points = []
height,width =image.shape[:2] height,width =image.shape[:2]
image_mask = np.zeros(image.shape[:2], np.uint8) image_mask = np.zeros(image.shape[:2], np.uint8)
bgdModel = np.zeros((1,65),np.float64) bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64) fgdModel = np.zeros((1,65),np.float64)
rect = (10,10,width-30,height-30) rect = (10,10,width-30,height-30)
cv2.grabCut(image, image_mask, rect, bgdModel,fgdModel, 3, cv2.GC_INIT_WITH_RECT) cv2.grabCut(image, image_mask, rect, bgdModel,fgdModel, 3, cv2.GC_INIT_WITH_RECT)
image_mask = np.where((image_mask==2)|(image_mask==0), 0, 1).astype('uint8') image_mask = np.where((image_mask==2)|(image_mask==0), 0, 1).astype('uint8')
image_grabcut = image*image_mask[:,:,np.newaxis] image_grabcut = image*image_mask[:,:,np.newaxis]
#케니에지 디텍션을 이용하여 에지 검출 #케니에지 디텍션을 이용하여 에지 검출
image_gray = cv2.cvtColor(image_grabcut, cv2.COLOR_BGR2GRAY); image_gray = cv2.cvtColor(image_grabcut, cv2.COLOR_BGR2GRAY);
image_canny = cv2.Canny(image_gray, 30, 90); image_canny = cv2.Canny(image_gray, 30, 90);
#모폴로지 클로즈 연산 #모폴로지 클로즈 연산
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1) image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1)
# 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다. # 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다.
contours, hierarchy = cv2.findContours(image_canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours, hierarchy = cv2.findContours(image_canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
max_index = findMaxArea(contours) max_index = findMaxArea(contours)
image_fixed = image.copy() image_fixed = image.copy()
if max_index < 0: if max_index < 0:
## 꼭짓점을 찾지 못한경우, 마우스 입력을 받기위해 임의로 네개의 꼭짓점을 이미지 가장자리로 배정한다. ## 꼭짓점을 찾지 못한경우, 마우스 입력을 받기위해 임의로 네개의 꼭짓점을 이미지 가장자리로 배정한다.
points = np.array([[10,10], [width-10, 10], [width-10, height-10], [10, height-10]]) points = np.array([[10,10], [width-10, 10], [width-10, height-10], [10, height-10]])
return points return points
max_contour = contours[max_index] max_contour = contours[max_index]
## approxPolyDP 함수를 사용하여 convex hull을 구한다. ## approxPolyDP 함수를 사용하여 convex hull을 구한다.
max_contour = cv2.approxPolyDP(max_contour,0.02*cv2.arcLength(max_contour,True),True) max_contour = cv2.approxPolyDP(max_contour,0.02*cv2.arcLength(max_contour,True),True)
hull = cv2.convexHull(max_contour) hull = cv2.convexHull(max_contour)
size = len(max_contour) size = len(max_contour)
if size == 4: if size == 4:
## 책의 꼭지점을 구한다. ## 책의 꼭지점을 구한다.
for c in hull: for c in hull:
points.append(c[0]) points.append(c[0])
points = np.array(points) points = np.array(points)
else: else:
## 꼭지점이 5개 이상인 경우 경계 박스를 이용한다. ## 꼭지점이 5개 이상인 경우 경계 박스를 이용한다.
rect = cv2.minAreaRect(hull) rect = cv2.minAreaRect(hull)
box = cv2.boxPoints(rect) box = cv2.boxPoints(rect)
points = np.int0(box.tolist()) points = np.int0(box.tolist())
## 검출된 꼭지점이 이미지 범위를 벗어난 경우 책 꼭지점 처리 ## 검출된 꼭지점이 이미지 범위를 벗어난 경우 책 꼭지점 처리
found = False found = False
for p in points: for p in points:
if p[0] < 0 or p[0] > width-1 or p[1] < 0 or p[1] > height -1: if p[0] < 0 or p[0] > width-1 or p[1] < 0 or p[1] > height -1:
found = True found = True
break break
if found: if found:
points = np.array([[10,10], [width-11, 10], [width-11, height-11], [10, height-11]]) points = np.array([[10,10], [width-11, 10], [width-11, height-11], [10, height-11]])
return points return points
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#pdf로 이미지 저장 #pdf로 이미지 저장
def save_pdf(): def save_pdf():
pdf = FPDF() pdf = FPDF()
imagelist = [] imagelist = []
# ------------- ADD ALL THE IMAGES IN A LIST ------------- # # ------------- ADD ALL THE IMAGES IN A LIST ------------- #
folder = './modified/' folder = './modified/'
for dirpath, dirnames, filenames in os.walk(folder): for dirpath, dirnames, filenames in os.walk(folder):
for filename in [f for f in filenames if f.endswith(".jpg")]: for filename in [f for f in filenames if f.endswith(".jpg")]:
full_path = os.path.join(dirpath, filename) full_path = os.path.join(dirpath, filename)
imagelist.append(full_path) imagelist.append(full_path)
imagelist.sort() # Sort the images by name. imagelist.sort() # Sort the images by name.
for i in range(0, len(imagelist)): for i in range(0, len(imagelist)):
print(imagelist[i]) print(imagelist[i])
# -------------- CONVERT TO PDF ------------ # # -------------- CONVERT TO PDF ------------ #
for image in imagelist: for image in imagelist:
pdf.add_page() pdf.add_page()
pdf.image(image, 0, 0, 210, 297) # 210 and 297 are the dimensions of an A4 size sheet. pdf.image(image, 0, 0, 210, 297) # 210 and 297 are the dimensions of an A4 size sheet.
pdf.output(folder + "image_list" + '.pdf', "F") pdf.output(folder + "image_list" + '.pdf', "F")
print("PDF generated successfully!") print("PDF generated successfully!")
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# o 버튼(마우스 사용)을 눌렀을 때, # o 버튼(마우스 사용)을 눌렀을 때,
def b1event(): def b1event():
global step global step
if sizes == 4: if sizes == 4:
cv2.namedWindow('input') cv2.namedWindow('input')
cv2.setMouseCallback("input", mouse_callback, 0); cv2.setMouseCallback("input", mouse_callback, 0);
step = 1 step = 1
while True: while True:
image_result = image.copy() image_result = image.copy()
for point in points: for point in points:
cv2.circle(image_result, tuple(point), 10, (255,0,0), 3) cv2.circle(image_result, tuple(point), 10, (255,0,0), 3)
cv2.imshow('input', image_result) cv2.imshow('input', image_result)
key = cv2.waitKey(1) key = cv2.waitKey(1)
if key == 32: if key == 32:
break break
image_final = transform(image, points) image_final = transform(image, points)
cv2.imshow('input', image_result) cv2.imshow('input', image_result)
cv2.imshow('result', image_final) cv2.imshow('result', image_final)
cv2.imwrite(modified_path + filename, image_final) cv2.imwrite(modified_path + filename, image_final)
#print(filename + " i got 4 edges!!") #print(filename + " i got 4 edges!!")
else: else:
cv2.imshow('input', image) cv2.imshow('input', image)
cv2.imwrite(modified_path + filename, image) cv2.imwrite(modified_path + filename, image)
#print(filename + " i don't got 4 edges!") #print(filename + " i don't got 4 edges!")
cv2.waitKey(0) cv2.waitKey(0)
cv2.destroyAllWindows() cv2.destroyAllWindows()
win.destroy() win.destroy()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#x 버튼(마우스입력을 안함)을 눌렀을 때 #x 버튼(마우스입력을 안함)을 눌렀을 때
def b2event(): def b2event():
## 꼭지점 4개를 찾은경우 ## 꼭지점 4개를 찾은경우
if sizes == 4: if sizes == 4:
image_final = transform(image, points) image_final = transform(image, points)
cv2.imshow('result', image_final) cv2.imshow('result', image_final)
cv2.imwrite(modified_path +filename, image_final) cv2.imwrite(modified_path +filename, image_final)
#print(i + " i got 4 edges!!/no button") #print(i + " i got 4 edges!!/no button")
else: else:
cv2.imshow('input', image) cv2.imshow('input', image)
cv2.imwrite(modified_path +filename, image) cv2.imwrite(modified_path +filename, image)
#print(i + " i don't got 4 edges!/no button") #print(i + " i don't got 4 edges!/no button")
cv2.waitKey(0) cv2.waitKey(0)
cv2.destroyAllWindows() cv2.destroyAllWindows()
win.destroy() win.destroy()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
mouse_is_pressing = False mouse_is_pressing = False
image_path = './images/' __file__ = 'openCV_scanner.ipynb'
root = os.path.dirname(os.path.abspath(__file__))
image_path = root +'/images/'
if not os.path.isdir(image_path): if not os.path.isdir(image_path):
os.mkdir(image_path) os.mkdir(image_path)
## image 폴더안에 있는 이미지파일들을 하나씩 탐색. ## image 폴더안에 있는 이미지파일들을 하나씩 탐색.
for filename in os.listdir(image_path): for filename in os.listdir(image_path):
path = image_path + filename path = image_path + filename
count = len(os.listdir(image_path)) count = len(os.listdir(image_path))
##이미지 파일이 하나도 없는경우 ##이미지 파일이 하나도 없는경우
if count == 0: if count == 0:
print("there are no images") print("there are no images")
image = cv2.imread(path, cv2.IMREAD_COLOR) image = cv2.imread(path, cv2.IMREAD_COLOR)
##이미지가 너무 큰경우, 적당한 크기로 줄임 ##이미지가 너무 큰경우, 적당한 크기로 줄임
height, width, channel = image.shape height, width, channel = image.shape
if height > 720 or width > 540: if height > 720 or width > 540:
height,width = 720,540 height,width = 720,540
image=cv2.resize(image,(width,height)) image=cv2.resize(image,(width,height))
#print(height, width , channel) #print(height, width , channel)
points = scanning(image) points = scanning(image)
#scanning 결과 나온 contour 이미지를 만듬. #scanning 결과 나온 contour 이미지를 만듬.
image_contour = image.copy() image_contour = image.copy()
cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3) cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)
sizes = len(points) sizes = len(points)
#UI 창 띄우기 #UI 창 띄우기
win = tk.Tk() win = tk.Tk()
win.title("Ask") win.title("Ask")
win.geometry("600x800+50+100") win.geometry("600x800+50+100")
win.resizable(False, False) win.resizable(False, False)
lbl = tk.Label(win, text="마우스 입력 O/X?") lbl = tk.Label(win, text="마우스 입력 O/X?")
lbl.pack() lbl.pack()
## contour 이미지 파일을 저장하기. 폴더가 없을경우 폴더를 만듬 ## contour 이미지 파일을 저장하기. 폴더가 없을경우 폴더를 만듬
contour_path = './contour/' contour_path = root +'/contour/'
if not os.path.isdir(contour_path): if not os.path.isdir(contour_path):
os.mkdir(contour_path) os.mkdir(contour_path)
cv2.imwrite(contour_path + filename, image_contour) cv2.imwrite(contour_path + filename, image_contour)
imgtk = ImageTk.PhotoImage(file = contour_path + filename, master=win) imgtk = ImageTk.PhotoImage(file = contour_path + filename, master=win)
label = tk.Label(win, image=imgtk) label = tk.Label(win, image=imgtk)
label.pack() label.pack()
## 최종 수정된 이미지를 저장하기. 폴더가 없을경우 폴더 생성 ## 최종 수정된 이미지를 저장하기. 폴더가 없을경우 폴더 생성
modified_path = './modified/' modified_path = root+'/modified/'
if not os.path.isdir(modified_path): if not os.path.isdir(modified_path):
os.mkdir(modified_path) os.mkdir(modified_path)
b1 = tk.Button(win, text='마우스 입력O', command = b1event) b1 = tk.Button(win, text='마우스 입력O', command = b1event)
b2 = tk.Button(win, text='마우스 입력X', command = b2event) b2 = tk.Button(win, text='마우스 입력X', command = b2event)
b1.pack() b1.pack()
b2.pack() b2.pack()
win.mainloop() win.mainloop()
save_pdf() save_pdf()
``` ```
%% Output %% Output
./modified/bookcover.jpg
./modified/example.jpg ./modified/example.jpg
./modified/example2.jpg
./modified/example3.jpg
./modified/example4.jpg ./modified/example4.jpg
./modified/framework1821.jpg
./modified/receipt.jpg
./modified/tilted_document.jpg
PDF generated successfully! PDF generated successfully!
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
File added
No preview for this file type
File added
contour/bookcover.jpg

56.7 KiB

contour/example.jpg

143 KiB

contour/example2.jpg

96.8 KiB

contour/example3.jpg

167 KiB

contour/example4.jpg

147 KiB

contour/framework1821.jpg

134 KiB

contour/receipt.jpg

137 KiB

contour/tilted_document.jpg

91.6 KiB

images/example3.jpg

1.16 MiB

modified/example3.jpg

80.8 KiB

modified/framework1821.jpg

93.4 KiB | W: | H:

modified/framework1821.jpg

79.8 KiB | W: | H:

modified/framework1821.jpg
modified/framework1821.jpg
modified/framework1821.jpg
modified/framework1821.jpg
  • 2-up
  • Swipe
  • Onion skin
No preview for this file type
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
import numpy as np import numpy as np
import cv2 import cv2
import glob import glob
from matplotlib import pyplot as plt from matplotlib import pyplot as plt
import tkinter as tk import tkinter as tk
from PIL import Image from PIL import Image
from PIL import ImageTk from PIL import ImageTk
import os import os
from fpdf import FPDF from fpdf import FPDF
from PIL import Image from PIL import Image
import os
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 두 점 사이의 거리를 구한다. # 두 점 사이의 거리를 구한다.
# param : point1, point2 - 거리를 구할 두 점이다. # param : point1, point2 - 거리를 구할 두 점이다.
# return : point1, point2 사이의 거리이다. # return : point1, point2 사이의 거리이다.
def distance(point1, point2): def distance(point1, point2):
x1,y1 = point1 x1,y1 = point1
x2,y2 = point2 x2,y2 = point2
return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))) return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다. # 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.
# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다, # param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다,
# flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다, # flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,
# param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다. # param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.
# return : none # return : none
def mouse_callback(event,x,y,flags,param): def mouse_callback(event,x,y,flags,param):
global mouse_is_pressing, points global mouse_is_pressing, points
# step == 1 이면,마우스 콜백 함수가 등록된 것이다. # step == 1 이면,마우스 콜백 함수가 등록된 것이다.
# step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다. # step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.
if step != 1: if step != 1:
return return
# CASE 1 - 마우스가 움직이고 # CASE 1 - 마우스가 움직이고
if event == cv2.EVENT_MOUSEMOVE: if event == cv2.EVENT_MOUSEMOVE:
# 눌린상태일때 # 눌린상태일때
if mouse_is_pressing == True: if mouse_is_pressing == True:
#마우스의 좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다 #마우스의 좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다
for i,point in enumerate(points): for i,point in enumerate(points):
if distance((x,y), point) < 15: if distance((x,y), point) < 15:
points[i][0] = x points[i][0] = x
points[i][1] = y points[i][1] = y
break break
# CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때, # CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때,
elif event == cv2.EVENT_LBUTTONDOWN: elif event == cv2.EVENT_LBUTTONDOWN:
# 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다. # 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.
for point in points: for point in points:
if distance((x,y), point) < 10: if distance((x,y), point) < 10:
mouse_is_pressing = True mouse_is_pressing = True
break break
# CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈 # CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈
elif event == cv2.EVENT_LBUTTONUP: elif event == cv2.EVENT_LBUTTONUP:
mouse_is_pressing = False mouse_is_pressing = False
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 두 벡터 사이의 각도를 구한다. # 두 벡터 사이의 각도를 구한다.
# param : A, B - 벡터를 표현한 ndarray이다. # param : A, B - 벡터를 표현한 ndarray이다.
# return : angle - 벡터 A와 B 사이의 각도이다. # return : angle - 벡터 A와 B 사이의 각도이다.
def angle_between(A, B): def angle_between(A, B):
x1 = A[0] x1 = A[0]
y1 = A[1] y1 = A[1]
x2 = B[0] x2 = B[0]
y2 = B[1] y2 = B[1]
dot = x1*x2 + y1*y2 dot = x1*x2 + y1*y2
det = x1*y2 - y1*x2 det = x1*y2 - y1*x2
angle = np.arctan2(det, dot) * 180/np.pi angle = np.arctan2(det, dot) * 180/np.pi
return angle return angle
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 다음 순서를 갖도록 꼭짓점을 정렬한다. # 다음 순서를 갖도록 꼭짓점을 정렬한다.
# top left, top right, bottom right, bottom left # top left, top right, bottom right, bottom left
# param : points - 정렬되기 전의 꼭짓점의 ndarray이다. # param : points - 정렬되기 전의 꼭짓점의 ndarray이다.
# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다. # return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.
def sort_points(points): def sort_points(points):
points = points.astype(np.float32) points = points.astype(np.float32)
new_points = np.zeros((4, 2), dtype = "float32") new_points = np.zeros((4, 2), dtype = "float32")
# top left를 구한다. # top left를 구한다.
s = points.sum(axis = 1) s = points.sum(axis = 1)
min_index = np.argmin(s) min_index = np.argmin(s)
new_points[0] = points[min_index] new_points[0] = points[min_index]
points = np.delete(points, min_index, axis = 0) points = np.delete(points, min_index, axis = 0)
# bottom right를 구한다. # bottom right를 구한다.
s = points.sum(axis = 1) s = points.sum(axis = 1)
max_index = np.argmax(s) max_index = np.argmax(s)
new_points[2] = points[max_index] new_points[2] = points[max_index]
points = np.delete(points, max_index, axis = 0) points = np.delete(points, max_index, axis = 0)
# top right, bottom left를 구한다. # top right, bottom left를 구한다.
v0 = points[0] - new_points[0] v0 = points[0] - new_points[0]
v1 = points[1] - new_points[0] v1 = points[1] - new_points[0]
angle = angle_between(v0, v1) angle = angle_between(v0, v1)
# angle_between() : 벡터 사이의 각도를 구한다. # angle_between() : 벡터 사이의 각도를 구한다.
if angle < 0: if angle < 0:
new_points[1] = points[1] new_points[1] = points[1]
new_points[3] = points[0] new_points[3] = points[0]
else: else:
new_points[1] = points[0] new_points[1] = points[0]
new_points[3] = points[1] new_points[3] = points[1]
return new_points return new_points
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 이미지(문서 영역)를 정면 방향으로 변환한다. # 이미지(문서 영역)를 정면 방향으로 변환한다.
# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다. # param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.
# return : img_warped - 정면 방향으로 변환된 이미지이다. # return : img_warped - 정면 방향으로 변환된 이미지이다.
def transform(img_input, points): def transform(img_input, points):
# 다음 순서롤 갖도록 꼭지점을 정렬한다. # 다음 순서롤 갖도록 꼭지점을 정렬한다.
# top left, top right, bottom right, bottom left # top left, top right, bottom right, bottom left
points = sort_points(points) points = sort_points(points)
topLeft, topRight, bottomRight, bottomLeft = points topLeft, topRight, bottomRight, bottomLeft = points
#print(topLeft, topRight, bottomRight, bottomLeft) #print(topLeft, topRight, bottomRight, bottomLeft)
#print(topLeft[0] + topLeft[1], topRight[0]+topRight[1], #print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],
#bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1]) #bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])
# 변환 후 책의 너비와 높이를 결정한다. # 변환 후 책의 너비와 높이를 결정한다.
topWidth = distance(bottomLeft, bottomRight) topWidth = distance(bottomLeft, bottomRight)
bottomWidth = distance(topLeft, topRight) bottomWidth = distance(topLeft, topRight)
maxWidth = max(int(topWidth), int(bottomWidth)) maxWidth = max(int(topWidth), int(bottomWidth))
leftHeight = distance(topLeft, bottomLeft) leftHeight = distance(topLeft, bottomLeft)
rightHeight = distance(topRight, bottomRight) rightHeight = distance(topRight, bottomRight)
maxHeight = max(int(leftHeight), int(rightHeight)) maxHeight = max(int(leftHeight), int(rightHeight))
# 정면에서 바라본 책의 좌표를 결정한다. # 정면에서 바라본 책의 좌표를 결정한다.
dst = np.array([[0, 0],[maxWidth - 1, 0], dst = np.array([[0, 0],[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32") [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32")
H = cv2.getPerspectiveTransform(points, dst) H = cv2.getPerspectiveTransform(points, dst)
img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight)) img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))
return img_warped return img_warped
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# 가장 큰 영역을 갖는 컨투어를 찾는다. # 가장 큰 영역을 갖는 컨투어를 찾는다.
# param : contours - 컨투어들의 리스트이다. # param : contours - 컨투어들의 리스트이다.
# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다. # return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.
def findMaxArea(contours): def findMaxArea(contours):
max_area = -1 max_area = -1
max_index = -1 max_index = -1
# 가장 큰 영역을 갖는 컨투어를 찾는다. # 가장 큰 영역을 갖는 컨투어를 찾는다.
for i,contour in enumerate(contours): for i,contour in enumerate(contours):
# cv2.contourArea : 컨투어의 넓이를 얻는다. # cv2.contourArea : 컨투어의 넓이를 얻는다.
area = cv2.contourArea(contour) area = cv2.contourArea(contour)
# cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다. # cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.
x,y,w,h = cv2.boundingRect(contour) x,y,w,h = cv2.boundingRect(contour)
if (w*h)*0.4 > area: if (w*h)*0.4 > area:
continue continue
if w > h: if w > h:
continue continue
if area > max_area: if area > max_area:
max_area = area max_area = area
max_index = i max_index = i
if max_area < 10000: if max_area < 10000:
max_index = -1 max_index = -1
return max_index return max_index
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def convert_to_tkimage(): def convert_to_tkimage():
global src global src
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY) _, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
img = Image.fromarray(binary) img = Image.fromarray(binary)
imgtk = ImageTk.PhotoImage(image=img) imgtk = ImageTk.PhotoImage(image=img)
label.config(image=imgtk) label.config(image=imgtk)
label.image = imgtk label.image = imgtk
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
def scanning(image): def scanning(image):
global contours global contours
global max_index global max_index
global max_contour global max_contour
#grabcut , 배경 제거 #grabcut , 배경 제거
points = [] points = []
height,width =image.shape[:2] height,width =image.shape[:2]
image_mask = np.zeros(image.shape[:2], np.uint8) image_mask = np.zeros(image.shape[:2], np.uint8)
bgdModel = np.zeros((1,65),np.float64) bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64) fgdModel = np.zeros((1,65),np.float64)
rect = (10,10,width-30,height-30) rect = (10,10,width-30,height-30)
cv2.grabCut(image, image_mask, rect, bgdModel,fgdModel, 3, cv2.GC_INIT_WITH_RECT) cv2.grabCut(image, image_mask, rect, bgdModel,fgdModel, 3, cv2.GC_INIT_WITH_RECT)
image_mask = np.where((image_mask==2)|(image_mask==0), 0, 1).astype('uint8') image_mask = np.where((image_mask==2)|(image_mask==0), 0, 1).astype('uint8')
image_grabcut = image*image_mask[:,:,np.newaxis] image_grabcut = image*image_mask[:,:,np.newaxis]
#케니에지 디텍션을 이용하여 에지 검출 #케니에지 디텍션을 이용하여 에지 검출
image_gray = cv2.cvtColor(image_grabcut, cv2.COLOR_BGR2GRAY); image_gray = cv2.cvtColor(image_grabcut, cv2.COLOR_BGR2GRAY);
image_canny = cv2.Canny(image_gray, 30, 90); image_canny = cv2.Canny(image_gray, 30, 90);
#모폴로지 클로즈 연산 #모폴로지 클로즈 연산
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1) image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1)
# 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다. # 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다.
contours, hierarchy = cv2.findContours(image_canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours, hierarchy = cv2.findContours(image_canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
max_index = findMaxArea(contours) max_index = findMaxArea(contours)
image_fixed = image.copy() image_fixed = image.copy()
if max_index < 0: if max_index < 0:
## 꼭짓점을 찾지 못한경우, 마우스 입력을 받기위해 임의로 네개의 꼭짓점을 이미지 가장자리로 배정한다. ## 꼭짓점을 찾지 못한경우, 마우스 입력을 받기위해 임의로 네개의 꼭짓점을 이미지 가장자리로 배정한다.
points = np.array([[10,10], [width-10, 10], [width-10, height-10], [10, height-10]]) points = np.array([[10,10], [width-10, 10], [width-10, height-10], [10, height-10]])
return points return points
max_contour = contours[max_index] max_contour = contours[max_index]
## approxPolyDP 함수를 사용하여 convex hull을 구한다. ## approxPolyDP 함수를 사용하여 convex hull을 구한다.
max_contour = cv2.approxPolyDP(max_contour,0.02*cv2.arcLength(max_contour,True),True) max_contour = cv2.approxPolyDP(max_contour,0.02*cv2.arcLength(max_contour,True),True)
hull = cv2.convexHull(max_contour) hull = cv2.convexHull(max_contour)
size = len(max_contour) size = len(max_contour)
if size == 4: if size == 4:
## 책의 꼭지점을 구한다. ## 책의 꼭지점을 구한다.
for c in hull: for c in hull:
points.append(c[0]) points.append(c[0])
points = np.array(points) points = np.array(points)
else: else:
## 꼭지점이 5개 이상인 경우 경계 박스를 이용한다. ## 꼭지점이 5개 이상인 경우 경계 박스를 이용한다.
rect = cv2.minAreaRect(hull) rect = cv2.minAreaRect(hull)
box = cv2.boxPoints(rect) box = cv2.boxPoints(rect)
points = np.int0(box.tolist()) points = np.int0(box.tolist())
## 검출된 꼭지점이 이미지 범위를 벗어난 경우 책 꼭지점 처리 ## 검출된 꼭지점이 이미지 범위를 벗어난 경우 책 꼭지점 처리
found = False found = False
for p in points: for p in points:
if p[0] < 0 or p[0] > width-1 or p[1] < 0 or p[1] > height -1: if p[0] < 0 or p[0] > width-1 or p[1] < 0 or p[1] > height -1:
found = True found = True
break break
if found: if found:
points = np.array([[10,10], [width-11, 10], [width-11, height-11], [10, height-11]]) points = np.array([[10,10], [width-11, 10], [width-11, height-11], [10, height-11]])
return points return points
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#pdf로 이미지 저장 #pdf로 이미지 저장
def save_pdf(): def save_pdf():
pdf = FPDF() pdf = FPDF()
imagelist = [] imagelist = []
# ------------- ADD ALL THE IMAGES IN A LIST ------------- # # ------------- ADD ALL THE IMAGES IN A LIST ------------- #
folder = './modified/' folder = './modified/'
for dirpath, dirnames, filenames in os.walk(folder): for dirpath, dirnames, filenames in os.walk(folder):
for filename in [f for f in filenames if f.endswith(".jpg")]: for filename in [f for f in filenames if f.endswith(".jpg")]:
full_path = os.path.join(dirpath, filename) full_path = os.path.join(dirpath, filename)
imagelist.append(full_path) imagelist.append(full_path)
imagelist.sort() # Sort the images by name. imagelist.sort() # Sort the images by name.
for i in range(0, len(imagelist)): for i in range(0, len(imagelist)):
print(imagelist[i]) print(imagelist[i])
# -------------- CONVERT TO PDF ------------ # # -------------- CONVERT TO PDF ------------ #
for image in imagelist: for image in imagelist:
pdf.add_page() pdf.add_page()
pdf.image(image, 0, 0, 210, 297) # 210 and 297 are the dimensions of an A4 size sheet. pdf.image(image, 0, 0, 210, 297) # 210 and 297 are the dimensions of an A4 size sheet.
pdf.output(folder + "image_list" + '.pdf', "F") pdf.output(folder + "image_list" + '.pdf', "F")
print("PDF generated successfully!") print("PDF generated successfully!")
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# o 버튼(마우스 사용)을 눌렀을 때, # o 버튼(마우스 사용)을 눌렀을 때,
def b1event(): def b1event():
global step global step
if sizes == 4: if sizes == 4:
cv2.namedWindow('input') cv2.namedWindow('input')
cv2.setMouseCallback("input", mouse_callback, 0); cv2.setMouseCallback("input", mouse_callback, 0);
step = 1 step = 1
while True: while True:
image_result = image.copy() image_result = image.copy()
for point in points: for point in points:
cv2.circle(image_result, tuple(point), 10, (255,0,0), 3) cv2.circle(image_result, tuple(point), 10, (255,0,0), 3)
cv2.imshow('input', image_result) cv2.imshow('input', image_result)
key = cv2.waitKey(1) key = cv2.waitKey(1)
if key == 32: if key == 32:
break break
image_final = transform(image, points) image_final = transform(image, points)
cv2.imshow('input', image_result) cv2.imshow('input', image_result)
cv2.imshow('result', image_final) cv2.imshow('result', image_final)
cv2.imwrite(modified_path + filename, image_final) cv2.imwrite(modified_path + filename, image_final)
#print(filename + " i got 4 edges!!") #print(filename + " i got 4 edges!!")
else: else:
cv2.imshow('input', image) cv2.imshow('input', image)
cv2.imwrite(modified_path + filename, image) cv2.imwrite(modified_path + filename, image)
#print(filename + " i don't got 4 edges!") #print(filename + " i don't got 4 edges!")
cv2.waitKey(0) cv2.waitKey(0)
cv2.destroyAllWindows() cv2.destroyAllWindows()
win.destroy() win.destroy()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#x 버튼(마우스입력을 안함)을 눌렀을 때 #x 버튼(마우스입력을 안함)을 눌렀을 때
def b2event(): def b2event():
## 꼭지점 4개를 찾은경우 ## 꼭지점 4개를 찾은경우
if sizes == 4: if sizes == 4:
image_final = transform(image, points) image_final = transform(image, points)
cv2.imshow('result', image_final) cv2.imshow('result', image_final)
cv2.imwrite(modified_path +filename, image_final) cv2.imwrite(modified_path +filename, image_final)
#print(i + " i got 4 edges!!/no button") #print(i + " i got 4 edges!!/no button")
else: else:
cv2.imshow('input', image) cv2.imshow('input', image)
cv2.imwrite(modified_path +filename, image) cv2.imwrite(modified_path +filename, image)
#print(i + " i don't got 4 edges!/no button") #print(i + " i don't got 4 edges!/no button")
cv2.waitKey(0) cv2.waitKey(0)
cv2.destroyAllWindows() cv2.destroyAllWindows()
win.destroy() win.destroy()
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
mouse_is_pressing = False mouse_is_pressing = False
image_path = './images/'
__file__ = 'openCV_scanner.ipynb'
root = os.path.dirname(os.path.abspath(__file__))
image_path = root +'/images/'
modified_path = root+'/modified/'
contour_path = root +'/contour/'
if not os.path.isdir(image_path): if not os.path.isdir(image_path):
os.mkdir(image_path) os.mkdir(image_path)
## image 폴더안에 있는 이미지파일들을 하나씩 탐색. ## image 폴더안에 있는 이미지파일들을 하나씩 탐색.
for filename in os.listdir(image_path): for filename in os.listdir(image_path):
path = image_path + filename path = image_path + filename
count = len(os.listdir(image_path)) count = len(os.listdir(image_path))
##이미지 파일이 하나도 없는경우 ##이미지 파일이 하나도 없는경우
if count == 0: if count == 0:
print("there are no images") print("there are no images")
image = cv2.imread(path, cv2.IMREAD_COLOR) image = cv2.imread(path, cv2.IMREAD_COLOR)
##이미지가 너무 큰경우, 적당한 크기로 줄임 ##이미지가 너무 큰경우, 적당한 크기로 줄임
height, width, channel = image.shape height, width, channel = image.shape
if height > 720 or width > 540: if height > 720 or width > 540:
height,width = 720,540 height,width = 720,540
image=cv2.resize(image,(width,height)) image=cv2.resize(image,(width,height))
#print(height, width , channel) #print(height, width , channel)
points = scanning(image) points = scanning(image)
#scanning 결과 나온 contour 이미지를 만듬. #scanning 결과 나온 contour 이미지를 만듬.
image_contour = image.copy() image_contour = image.copy()
cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3) cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)
sizes = len(points) sizes = len(points)
#UI 창 띄우기 #UI 창 띄우기
win = tk.Tk() win = tk.Tk()
win.title("Ask") win.title("Ask")
win.geometry("600x800+50+100") win.geometry("600x800+50+100")
win.resizable(False, False) win.resizable(False, False)
lbl = tk.Label(win, text="마우스 입력 O/X?") lbl = tk.Label(win, text="마우스 입력 O/X?")
lbl.pack() lbl.pack()
## contour 이미지 파일을 저장하기. 폴더가 없을경우 폴더를 만듬 ## contour 이미지 파일을 저장하기. 폴더가 없을경우 폴더를 만듬
contour_path = './contour/'
if not os.path.isdir(contour_path): if not os.path.isdir(contour_path):
os.mkdir(contour_path) os.mkdir(contour_path)
cv2.imwrite(contour_path + filename, image_contour) cv2.imwrite(contour_path + filename, image_contour)
imgtk = ImageTk.PhotoImage(file = contour_path + filename, master=win) imgtk = ImageTk.PhotoImage(file = contour_path + filename, master=win)
label = tk.Label(win, image=imgtk) label = tk.Label(win, image=imgtk)
label.pack() label.pack()
## 최종 수정된 이미지를 저장하기. 폴더가 없을경우 폴더 생성 ## 최종 수정된 이미지를 저장하기. 폴더가 없을경우 폴더 생성
modified_path = './modified/'
if not os.path.isdir(modified_path): if not os.path.isdir(modified_path):
os.mkdir(modified_path) os.mkdir(modified_path)
b1 = tk.Button(win, text='마우스 입력O', command = b1event) b1 = tk.Button(win, text='마우스 입력O', command = b1event)
b2 = tk.Button(win, text='마우스 입력X', command = b2event) b2 = tk.Button(win, text='마우스 입력X', command = b2event)
b1.pack() b1.pack()
b2.pack() b2.pack()
win.mainloop() win.mainloop()
save_pdf() save_pdf()
``` ```
%% Output
./modified/bookcover.jpg
./modified/example.jpg
./modified/example2.jpg
./modified/example3.jpg
./modified/example4.jpg
./modified/framework1821.jpg
./modified/receipt.jpg
./modified/tilted_document.jpg
PDF generated successfully!
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment