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

merge o x

parent 0436fe5d
No related branches found
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
from PIL import Image
from PIL import ImageTk
import os
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
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):
area = cv2.contourArea(contour) area = cv2.contourArea(contour)
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 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
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")
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)
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)
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)
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
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
# 마우스를 이용하여 책의 꼭지점을 조정한다. # 마우스를 이용하여 책의 꼭지점을 조정한다.
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
if step != 1: if step != 1:
return return
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
elif event == cv2.EVENT_LBUTTONDOWN: ##마우스버튼이 눌린상태에서, 꼭짓점과의 거리가 가깝다면 elif event == cv2.EVENT_LBUTTONDOWN: ##마우스버튼이 눌린상태에서, 꼭짓점과의 거리가 가깝다면
##press 를 Ture로 바꾼다. ##press 를 Ture로 바꾼다.
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
elif event == cv2.EVENT_LBUTTONUP: ## 마우스가 안눌려있으면, press 를 false로 바꿈 elif event == cv2.EVENT_LBUTTONUP: ## 마우스가 안눌려있으면, press 를 false로 바꿈
mouse_is_pressing = False mouse_is_pressing = False
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
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
def convert_to_tkimage():
global src
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
img = Image.fromarray(binary)
imgtk = ImageTk.PhotoImage(image=img)
label.config(image=imgtk)
label.image = imgtk
```
%% Cell type:code id: tags:
``` python
def scanning(image): def scanning(image):
#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]
#cv2.imshow('grabCut', image_grabcut) #cv2.imshow('grabCut', image_grabcut)
#cv2.waitKey(0) #cv2.waitKey(0)
#케니에지 디텍션을 이용하여 에지 검출 #케니에지 디텍션을 이용하여 에지 검출
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);
#cv2.imshow('Canny', image_canny) #cv2.imshow('Canny', image_canny)
#cv2.waitKey(0) #cv2.waitKey(0)
#모폴로지 클로즈 연산 #모폴로지 클로즈 연산
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)
cv2.imwrite('./modified/' +i, image_canny) #cv2.imwrite('./modified/' +i, image_canny)
print(i + "save image_canny!") #print(i + "save image_canny!")
cv2.imshow('morphology', image_canny) #cv2.imshow('morphology', image_canny)
cv2.waitKey(0) #cv2.waitKey(0)
# 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다. # 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다.
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)
"""
#################이부분이 잘 이해가 안감. #################이부분이 잘 이해가 안감.
#print("contours ", contours)
#print("max_index = ",max_index)
image_fixed = image.copy()
if max_index < 0: if max_index < 0:
print("max_index < 0 " +i) print("max_index < 0 " +i)
#print(points)
return points return points
"""
max_contour = contours[max_index] max_contour = contours[max_index]
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)
cv2.imwrite('./modified/' +i, image_contour) #cv2.imwrite('./modified/' +i, image_contour)
print(i + "save image_contour!") #print(i + "save image_contour!")
cv2.imshow('Contour', image_contour) #cv2.imshow('Contour', image_contour)
cv2.waitKey(0) #cv2.waitKey(0)
# 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)
image_convexhull = image.copy() #image_convexhull = image.copy()
cv2.drawContours(image_convexhull, [hull], 0, (255,255,0), 5) #cv2.drawContours(image_convexhull, [hull], 0, (255,255,0), 5)
cv2.imwrite('./modified/' +i, image_convexhull) #cv2.imwrite('./modified/' +i, image_convexhull)
print(i + "save image_convexhull!") #print(i + "save image_convexhull!")
cv2.imshow('convexHull', image_convexhull) #cv2.imshow('convexHull', image_convexhull)
cv2.waitKey(0) #cv2.waitKey(0)
size = len(max_contour) size = len(max_contour)
print(size) print("len of max_contour" ,size)
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)
print(points) #print(points)
else: # 꼭지점이 5개 이상인 경우 경계 박스를 이용한다. else: # 꼭지점이 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
###################################################################### def b1event():
#이미지파일 한번에 여러개 받는 방법?? print(sizes)
# if sizes == 4:
# cv2.namedWindow('input')
import os cv2.setMouseCallback("input", mouse_callback, 0);
step = 1
while True:
image_result = image.copy()
for point in points:
cv2.circle(image_result, tuple(point), 10, (255,0,0), 3)
cv2.imshow('input', image_result)
key = cv2.waitKey(1)
if key == 32:
break
image_final = transform(image, points)
cv2.imshow('input', image_result)
cv2.imshow('result', image_final)
cv2.imwrite('./modified/' +i, image_final)
print(i + " save final image!")
else:
cv2.imshow('input', image)
cv2.imwrite('./modified/' +i, image)
print(i + " not yet..!")
cv2.waitKey(0)
cv2.destroyAllWindows()
win.destroy()
```
%% Cell type:code id: tags:
``` python
def b2event():
if sizes == 4:
image_final = transform(image, points)
cv2.imshow('result', image_final)
cv2.imwrite('./modified/' +i, image_final)
print(i + " save thresh!")
else:
cv2.imshow('input', image)
cv2.imwrite('./modified/' +i, image)
print(i + " not yet..!")
cv2.waitKey(0)
cv2.destroyAllWindows()
win.destroy()
```
%% Cell type:code id: tags:
``` python
mouse_is_pressing = False
for i in os.listdir('./images/'): for i in os.listdir('./images/'):
path = './images/'+i path = './images/'+i
count = len(os.listdir('./images/')) count = len(os.listdir('./images/'))
image = cv2.imread(path, cv2.IMREAD_COLOR) image = cv2.imread(path, cv2.IMREAD_COLOR)
image=cv2.resize(image,(500,500)) #image=cv2.resize(image,(500,500))
points = scanning(image) points = scanning(image)
sizes = len(points)
print("size",sizes)
win = tk.Tk()
win.title("Ask")
win.geometry("500x500+50+50")
win.resizable(False, False)
lbl = tk.Label(win, text="마우스 입력 O/X?")
#lbl.grid(row=1, column=1)
lbl.pack()
cv2.imwrite('./contours/' +i, image)
imgtk = ImageTk.PhotoImage(file = './contours/' +i, master=win)
label = tk.Label(win, image=imgtk)
label.pack()
b1 = tk.Button(win, text='마우스 입력O', command = b1event)
b2 = tk.Button(win, text='마우스 입력X', command = b2event)
#b1.grid(row=3, column=1)
#b2.grid(row=3, column=2)
b1.pack()
b2.pack()
win.mainloop()
"""
size = len(points) size = len(points)
print("size" ,size)
if size == 4: if size == 4:
##############################################################
# 여기에 사용자가 마우스 사용할지 안할지에대한 GUI 넣기?
#
#
#
####################################################################
# 마우스 콜백 함수를 등록하고
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.imwrite('./modified/' +i, image_final) cv2.imwrite('./modified/' +i, image_final)
print(i + "save image_final!") print(i + "save image_final!")
cv2.imshow('input', image_result) cv2.imshow('input', image_result)
cv2.imshow('result', image_final ) cv2.imshow('result', image_final )
else: else:
cv2.imshow('input', image) cv2.imshow('input', image)
cv2.waitKey(0) cv2.waitKey(0)
cv2.destroyAllWindows() cv2.destroyAllWindows()
#cv2.imwrite('./modified/' +i, image_final) win.destroy()
################################################################ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
############영수증의 경우 이것을 사용하면 글씨가 돋보임 ( 흑백대비)
gray = cv2.cvtColor(image_final, cv2.COLOR_BGR2GRAY)
sharpen = cv2.GaussianBlur(gray, (0,0), 3) sharpen = cv2.GaussianBlur(gray, (0,0), 3)
sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0) sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0)
thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15) thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15)
cv2.imwrite('./modified/' +i, thresh) cv2.imwrite('./modified/' +i, thresh)
print(i + " save thresh!") print(i + " save thresh!")
cv2.imshow('grayscale?', thresh) cv2.imshow('final_image', thresh)
cv2.waitKey(0) cv2.waitKey(0)
#cv2.imwrite('./modified/' +i, modified) #cv2.imwrite('./modified/' +i, modified)
#cv2.imshow( "image", image) #cv2.imshow( "image", image)
#cv2.waitKey(0) #cv2.waitKey(0)
"""
``` ```
%% Output %% Output
book.jpgsave image_canny! max_index < 0 document.jpg
book.jpgsave image_contour! size 0
book.jpgsave image_convexhull! 0
7 document.jpg not yet..!
[10. 10.] [489. 10.] [489. 489.] [ 10. 489.] max_index < 0 receipt2.jpg
20.0 499.0 978.0 499.0 size 0
book.jpgsave image_final! 0
book.jpg save thresh! receipt2.jpg not yet..!
book2.jpgsave image_canny! len of max_contour 8
book2.jpgsave image_contour! size 4
book2.jpgsave image_convexhull!
6
[10. 10.] [489. 10.] [489. 489.] [ 10. 489.]
20.0 499.0 978.0 499.0
book2.jpgsave image_final!
book2.jpg save thresh!
receipt2.jpgsave image_canny!
receipt2.jpgsave image_contour!
receipt2.jpgsave image_convexhull!
4 4
[[465 362] [13. 48.] [149. 27.] [170. 218.] [ 36. 238.]
[203 463] 61.0 176.0 388.0 274.0
[ 34 125] tilted receipt.jpg save final image!
[254 34]]
[ 34. 125.] [254. 34.] [465. 362.] [203. 463.]
159.0 288.0 827.0 666.0
receipt2.jpgsave image_final!
receipt2.jpg save thresh!
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#이미지 저장 #이미지 저장
def save(image): ##################아직 안합침################################
cv2.imwrite('./modified/modified.jpg', image) from fpdf import FPDF
from PIL import Image
import os
pdf = FPDF()
imagelist = [] # Contains the list of all images to be converted to PDF.
# --------------- USER INPUT -------------------- #
folder = "" # Folder containing all the images.
name = "" # Name of the output PDF file.
# ------------- ADD ALL THE IMAGES IN A LIST ------------- #
folder = input('Enter the path of the folder containing the images : ')
for dirpath, dirnames, filenames in os.walk(folder):
for filename in [f for f in filenames if f.endswith(".jpg")]:
full_path = os.path.join(dirpath, filename)
imagelist.append(full_path)
imagelist.sort() # Sort the images by name.
for i in range(0, len(imagelist)):
print(imagelist[i])
# -------------- CONVERT TO PDF ------------ #
name = input('Enter the PDF file name : ')
for image in imagelist:
pdf.add_page()
pdf.image(image, 0, 0, 210, 297) # 210 and 297 are the dimensions of an A4 size sheet.
pdf.output(folder + name + '.pdf', "F")
print("PDF generated successfully!")
``` ```
%% Output
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-266-d25ce1a2f34d> in <module>
1 #이미지 저장
----> 2 from fpdf import FPDF
3 from PIL import Image
4 import os
5
ModuleNotFoundError: No module named 'fpdf'
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
book.jpg

27.9 KiB

book2.jpg

16.9 KiB

contours/document.jpg

23.5 KiB

contours/receipt2.jpg

7.99 KiB

contours/tilted receipt.jpg

9.7 KiB

images/book.jpg

27.9 KiB

images/book2.jpg

16.9 KiB

images/document.jpg

10.8 KiB

File moved
images/tilted receipt.jpg

4.17 KiB

modified/book.jpg

84.6 KiB

modified/book2.jpg

34.3 KiB

modified/document.jpg

23.5 KiB

modified/receipt2.jpg

31.5 KiB | W: | H:

modified/receipt2.jpg

7.99 KiB | W: | H:

modified/receipt2.jpg
modified/receipt2.jpg
modified/receipt2.jpg
modified/receipt2.jpg
  • 2-up
  • Swipe
  • Onion skin
modified/tilted receipt.jpg

9.47 KiB

%% 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
from PIL import Image
from PIL import ImageTk
import os
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
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):
area = cv2.contourArea(contour) area = cv2.contourArea(contour)
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 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
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")
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)
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)
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)
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
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
# 마우스를 이용하여 책의 꼭지점을 조정한다. # 마우스를 이용하여 책의 꼭지점을 조정한다.
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
if step != 1: if step != 1:
return return
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
elif event == cv2.EVENT_LBUTTONDOWN: ##마우스버튼이 눌린상태에서, 꼭짓점과의 거리가 가깝다면 elif event == cv2.EVENT_LBUTTONDOWN: ##마우스버튼이 눌린상태에서, 꼭짓점과의 거리가 가깝다면
##press 를 Ture로 바꾼다. ##press 를 Ture로 바꾼다.
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
elif event == cv2.EVENT_LBUTTONUP: ## 마우스가 안눌려있으면, press 를 false로 바꿈 elif event == cv2.EVENT_LBUTTONUP: ## 마우스가 안눌려있으면, press 를 false로 바꿈
mouse_is_pressing = False mouse_is_pressing = False
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
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
def convert_to_tkimage():
global src
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
img = Image.fromarray(binary)
imgtk = ImageTk.PhotoImage(image=img)
label.config(image=imgtk)
label.image = imgtk
```
%% Cell type:code id: tags:
``` python
def scanning(image): def scanning(image):
#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]
#cv2.imshow('grabCut', image_grabcut) #cv2.imshow('grabCut', image_grabcut)
#cv2.waitKey(0) #cv2.waitKey(0)
#케니에지 디텍션을 이용하여 에지 검출 #케니에지 디텍션을 이용하여 에지 검출
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);
#cv2.imshow('Canny', image_canny) #cv2.imshow('Canny', image_canny)
#cv2.waitKey(0) #cv2.waitKey(0)
#모폴로지 클로즈 연산 #모폴로지 클로즈 연산
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)
cv2.imwrite('./modified/' +i, image_canny) #cv2.imwrite('./modified/' +i, image_canny)
print(i + "save image_canny!") #print(i + "save image_canny!")
cv2.imshow('morphology', image_canny) #cv2.imshow('morphology', image_canny)
cv2.waitKey(0) #cv2.waitKey(0)
# 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다. # 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다.
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)
"""
#################이부분이 잘 이해가 안감. #################이부분이 잘 이해가 안감.
#print("contours ", contours)
#print("max_index = ",max_index)
image_fixed = image.copy()
if max_index < 0: if max_index < 0:
print("max_index < 0 " +i) print("max_index < 0 " +i)
#print(points)
return points return points
"""
max_contour = contours[max_index] max_contour = contours[max_index]
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)
cv2.imwrite('./modified/' +i, image_contour) #cv2.imwrite('./modified/' +i, image_contour)
print(i + "save image_contour!") #print(i + "save image_contour!")
cv2.imshow('Contour', image_contour) #cv2.imshow('Contour', image_contour)
cv2.waitKey(0) #cv2.waitKey(0)
# 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)
image_convexhull = image.copy() #image_convexhull = image.copy()
cv2.drawContours(image_convexhull, [hull], 0, (255,255,0), 5) #cv2.drawContours(image_convexhull, [hull], 0, (255,255,0), 5)
cv2.imwrite('./modified/' +i, image_convexhull) #cv2.imwrite('./modified/' +i, image_convexhull)
print(i + "save image_convexhull!") #print(i + "save image_convexhull!")
cv2.imshow('convexHull', image_convexhull) #cv2.imshow('convexHull', image_convexhull)
cv2.waitKey(0) #cv2.waitKey(0)
size = len(max_contour) size = len(max_contour)
print(size) print("len of max_contour" ,size)
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)
print(points) #print(points)
else: # 꼭지점이 5개 이상인 경우 경계 박스를 이용한다. else: # 꼭지점이 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
###################################################################### def b1event():
#이미지파일 한번에 여러개 받는 방법?? print(sizes)
# if sizes == 4:
# cv2.namedWindow('input')
import os cv2.setMouseCallback("input", mouse_callback, 0);
step = 1
while True:
image_result = image.copy()
for point in points:
cv2.circle(image_result, tuple(point), 10, (255,0,0), 3)
cv2.imshow('input', image_result)
key = cv2.waitKey(1)
if key == 32:
break
image_final = transform(image, points)
cv2.imshow('input', image_result)
cv2.imshow('result', image_final)
cv2.imwrite('./modified/' +i, image_final)
print(i + " save final image!")
else:
cv2.imshow('input', image)
cv2.imwrite('./modified/' +i, image)
print(i + " not yet..!")
cv2.waitKey(0)
cv2.destroyAllWindows()
win.destroy()
```
%% Cell type:code id: tags:
``` python
def b2event():
if sizes == 4:
image_final = transform(image, points)
cv2.imshow('result', image_final)
cv2.imwrite('./modified/' +i, image_final)
print(i + " save thresh!")
else:
cv2.imshow('input', image)
cv2.imwrite('./modified/' +i, image)
print(i + " not yet..!")
cv2.waitKey(0)
cv2.destroyAllWindows()
win.destroy()
```
%% Cell type:code id: tags:
``` python
mouse_is_pressing = False
for i in os.listdir('./images/'): for i in os.listdir('./images/'):
path = './images/'+i path = './images/'+i
count = len(os.listdir('./images/')) count = len(os.listdir('./images/'))
image = cv2.imread(path, cv2.IMREAD_COLOR) image = cv2.imread(path, cv2.IMREAD_COLOR)
image=cv2.resize(image,(500,500)) #image=cv2.resize(image,(500,500))
points = scanning(image) points = scanning(image)
sizes = len(points)
print("size",sizes)
win = tk.Tk()
win.title("Ask")
win.geometry("500x500+50+50")
win.resizable(False, False)
lbl = tk.Label(win, text="마우스 입력 O/X?")
#lbl.grid(row=1, column=1)
lbl.pack()
cv2.imwrite('./contours/' +i, image)
imgtk = ImageTk.PhotoImage(file = './contours/' +i, master=win)
label = tk.Label(win, image=imgtk)
label.pack()
b1 = tk.Button(win, text='마우스 입력O', command = b1event)
b2 = tk.Button(win, text='마우스 입력X', command = b2event)
#b1.grid(row=3, column=1)
#b2.grid(row=3, column=2)
b1.pack()
b2.pack()
win.mainloop()
"""
size = len(points) size = len(points)
print("size" ,size)
if size == 4: if size == 4:
##############################################################
# 여기에 사용자가 마우스 사용할지 안할지에대한 GUI 넣기?
#
#
#
####################################################################
# 마우스 콜백 함수를 등록하고
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.imwrite('./modified/' +i, image_final) cv2.imwrite('./modified/' +i, image_final)
print(i + "save image_final!") print(i + "save image_final!")
cv2.imshow('input', image_result) cv2.imshow('input', image_result)
cv2.imshow('result', image_final ) cv2.imshow('result', image_final )
else: else:
cv2.imshow('input', image) cv2.imshow('input', image)
cv2.waitKey(0) cv2.waitKey(0)
cv2.destroyAllWindows() cv2.destroyAllWindows()
#cv2.imwrite('./modified/' +i, image_final) win.destroy()
################################################################ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
############영수증의 경우 이것을 사용하면 글씨가 돋보임 ( 흑백대비)
gray = cv2.cvtColor(image_final, cv2.COLOR_BGR2GRAY)
sharpen = cv2.GaussianBlur(gray, (0,0), 3) sharpen = cv2.GaussianBlur(gray, (0,0), 3)
sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0) sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0)
thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15) thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15)
cv2.imwrite('./modified/' +i, thresh) cv2.imwrite('./modified/' +i, thresh)
print(i + " save thresh!") print(i + " save thresh!")
cv2.imshow('grayscale?', thresh) cv2.imshow('final_image', thresh)
cv2.waitKey(0) cv2.waitKey(0)
#cv2.imwrite('./modified/' +i, modified) #cv2.imwrite('./modified/' +i, modified)
#cv2.imshow( "image", image) #cv2.imshow( "image", image)
#cv2.waitKey(0) #cv2.waitKey(0)
"""
``` ```
%% Output %% Output
book.jpgsave image_canny! max_index < 0 document.jpg
book.jpgsave image_contour! size 0
book.jpgsave image_convexhull! 0
7 document.jpg not yet..!
[10. 10.] [489. 10.] [489. 489.] [ 10. 489.] max_index < 0 receipt2.jpg
20.0 499.0 978.0 499.0 size 0
book.jpgsave image_final! 0
book.jpg save thresh! receipt2.jpg not yet..!
book2.jpgsave image_canny! len of max_contour 8
book2.jpgsave image_contour! size 4
book2.jpgsave image_convexhull!
6
[10. 10.] [489. 10.] [489. 489.] [ 10. 489.]
20.0 499.0 978.0 499.0
book2.jpgsave image_final!
book2.jpg save thresh!
receipt2.jpgsave image_canny!
receipt2.jpgsave image_contour!
receipt2.jpgsave image_convexhull!
4 4
[[465 362] [13. 48.] [149. 27.] [170. 218.] [ 36. 238.]
[203 463] 61.0 176.0 388.0 274.0
[ 34 125] tilted receipt.jpg save final image!
[254 34]]
[ 34. 125.] [254. 34.] [465. 362.] [203. 463.]
159.0 288.0 827.0 666.0
receipt2.jpgsave image_final!
receipt2.jpg save thresh!
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
#이미지 저장 #이미지 저장
def save(image): ##################아직 안합침################################
cv2.imwrite('./modified/modified.jpg', image) from fpdf import FPDF
from PIL import Image
import os
pdf = FPDF()
imagelist = [] # Contains the list of all images to be converted to PDF.
# --------------- USER INPUT -------------------- #
folder = "" # Folder containing all the images.
name = "" # Name of the output PDF file.
# ------------- ADD ALL THE IMAGES IN A LIST ------------- #
folder = input('Enter the path of the folder containing the images : ')
for dirpath, dirnames, filenames in os.walk(folder):
for filename in [f for f in filenames if f.endswith(".jpg")]:
full_path = os.path.join(dirpath, filename)
imagelist.append(full_path)
imagelist.sort() # Sort the images by name.
for i in range(0, len(imagelist)):
print(imagelist[i])
# -------------- CONVERT TO PDF ------------ #
name = input('Enter the PDF file name : ')
for image in imagelist:
pdf.add_page()
pdf.image(image, 0, 0, 210, 297) # 210 and 297 are the dimensions of an A4 size sheet.
pdf.output(folder + name + '.pdf', "F")
print("PDF generated successfully!")
``` ```
%% Output
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
<ipython-input-266-d25ce1a2f34d> in <module>
1 #이미지 저장
----> 2 from fpdf import FPDF
3 from PIL import Image
4 import os
5
ModuleNotFoundError: No module named 'fpdf'
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
``` ```
......
receipt2.jpg

3.76 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment