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

add extra image, add resize huge image, simplize code

parent 32b8c0bd
No related branches found
No related tags found
No related merge requests found
Showing
with 113 additions and 179 deletions
%% Cell type:code id: tags:
``` python
import numpy as np
import cv2
import glob
from matplotlib import pyplot as plt
import tkinter as tk
from PIL import Image
from PIL import ImageTk
import os
from fpdf import FPDF
from PIL import Image
import os
```
%% Cell type:code id: tags:
``` python
# 두 점 사이의 거리를 구한다.
# param : point1, point2 - 거리를 구할 두 점이다.
# return : point1, point2 사이의 거리이다.
def distance(point1, point2):
x1,y1 = point1
x2,y2 = point2
return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))
```
%% Cell type:code id: tags:
``` python
# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.
# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다,
# flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,
# param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.
# return : none
def mouse_callback(event,x,y,flags,param):
global mouse_is_pressing, points
# step == 1 이면,마우스 콜백 함수가 등록된 것이다.
# step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.
if step != 1:
return
# CASE 1 - 마우스가 움직이고
if event == cv2.EVENT_MOUSEMOVE:
# 눌린상태일때
if mouse_is_pressing == True:
points[i][0] = x
#마우스의 좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다
for i,point in enumerate(points):
if distance((x,y), point) < 15:
points[i][0] = x
points[i][1] = y
break
# CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때,
elif event == cv2.EVENT_LBUTTONDOWN:
# 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다. ##press 를 Ture로 바꾼다.
# 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.
for point in points:
if distance((x,y), point) < 10:
mouse_is_pressing = True
break
# CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈
elif event == cv2.EVENT_LBUTTONUP:
mouse_is_pressing = False
```
%% Cell type:code id: tags:
``` python
# 두 벡터 사이의 각도를 구한다.
# param : A, B - 벡터를 표현한 ndarray이다.
# return : angle - 벡터 A와 B 사이의 각도이다.
def angle_between(A, B):
x1 = A[0]
y1 = A[1]
x2 = B[0]
y2 = B[1]
dot = x1*x2 + y1*y2
det = x1*y2 - y1*x2
angle = np.arctan2(det, dot) * 180/np.pi
return angle
```
%% Cell type:code id: tags:
``` python
# 다음 순서를 갖도록 꼭짓점을 정렬한다.
# top left, top right, bottom right, bottom left
# param : points - 정렬되기 전의 꼭짓점의 ndarray이다.
# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.
def sort_points(points):
points = points.astype(np.float32)
new_points = np.zeros((4, 2), dtype = "float32")
# top left를 구한다.
s = points.sum(axis = 1)
min_index = np.argmin(s)
new_points[0] = points[min_index]
points = np.delete(points, min_index, axis = 0)
# bottom right를 구한다.
s = points.sum(axis = 1)
max_index = np.argmax(s)
new_points[2] = points[max_index]
points = np.delete(points, max_index, axis = 0)
# top right, bottom left를 구한다.
v0 = points[0] - new_points[0]
v1 = points[1] - new_points[0]
angle = angle_between(v0, v1)
# angle_between() : 벡터 사이의 각도를 구한다.
if angle < 0:
new_points[1] = points[1]
new_points[3] = points[0]
else:
new_points[1] = points[0]
new_points[3] = points[1]
return new_points
```
%% Cell type:code id: tags:
``` python
# 이미지(문서 영역)를 정면 방향으로 변환한다.
# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.
# return : img_warped - 정면 방향으로 변환된 이미지이다.
def transform(img_input, points):
# 다음 순서롤 갖도록 꼭지점을 정렬한다.
# top left, top right, bottom right, bottom left
points = sort_points(points)
topLeft, topRight, bottomRight, bottomLeft = points
print(topLeft, topRight, bottomRight, bottomLeft)
print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],
bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])
#print(topLeft, topRight, bottomRight, bottomLeft)
#print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],
#bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])
# 변환 후 책의 너비와 높이를 결정한다.
topWidth = distance(bottomLeft, bottomRight)
bottomWidth = distance(topLeft, topRight)
maxWidth = max(int(topWidth), int(bottomWidth))
leftHeight = distance(topLeft, bottomLeft)
rightHeight = distance(topRight, bottomRight)
maxHeight = max(int(leftHeight), int(rightHeight))
# 정면에서 바라본 책의 좌표를 결정한다.
dst = np.array([[0, 0],[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32")
H = cv2.getPerspectiveTransform(points, dst)
img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))
return img_warped
```
%% Cell type:code id: tags:
``` python
# 가장 큰 영역을 갖는 컨투어를 찾는다.
# param : contours - 컨투어들의 리스트이다.
# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.
def findMaxArea(contours):
max_area = -1
max_index = -1
# 가장 큰 영역을 갖는 컨투어를 찾는다.
for i,contour in enumerate(contours):
# cv2.contourArea : 컨투어의 넓이를 얻는다.
area = cv2.contourArea(contour)
# cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.
x,y,w,h = cv2.boundingRect(contour)
if (w*h)*0.4 > area:
continue
if w > h:
continue
if area > max_area:
max_area = area
max_index = i
if max_area < 10000:
max_index = -1
return max_index
```
%% Cell type:code id: tags:
``` 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):
global contours
global max_index
global max_contour
#grabcut , 배경 제거
points = []
height,width =image.shape[:2]
image_mask = np.zeros(image.shape[:2], np.uint8)
bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)
rect = (10,10,width-30,height-30)
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_grabcut = image*image_mask[:,:,np.newaxis]
#cv2.imshow('grabCut', image_grabcut)
#cv2.waitKey(0)
#케니에지 디텍션을 이용하여 에지 검출
image_gray = cv2.cvtColor(image_grabcut, cv2.COLOR_BGR2GRAY);
image_canny = cv2.Canny(image_gray, 30, 90);
#cv2.imshow('Canny', image_canny)
#cv2.waitKey(0)
#모폴로지 클로즈 연산
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1)
#cv2.imwrite('./modified/' +i, image_canny)
#print(i + "save image_canny!")
global contours
global max_index
global max_contour
#cv2.imshow('morphology', image_canny)
#cv2.waitKey(0)
# 캐니 에지 결과에서 컨투어를 검출하여 가장 큰 영역을 차지하는 컨투어를 찾는다.
contours, hierarchy = cv2.findContours(image_canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
max_index = findMaxArea(contours)
#################이부분이 잘 이해가 안감.
#print("contours ", contours)
#print("max_index = ",max_index)
image_fixed = image.copy()
if max_index < 0:
print("max_index < 0, return points ")
points = np.array([[10,10], [290, 10], [290, 390], [290, 390]])
## 꼭짓점을 찾지 못한경우, 마우스 입력을 받기위해 임의로 네개의 꼭짓점을 이미지 가장자리로 배정한다.
points = np.array([[10,10], [width-10, 10], [width-10, height-10], [10, height-10]])
return points
max_contour = contours[max_index]
#image_contour = image.copy()
#cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)
#cv2.imshow('Contour', image_contour)
#cv2.waitKey(0)
# approxPolyDP 함수를 사용하여 컨투어를 근사화하고 convex hull을 구한다.
## approxPolyDP 함수를 사용하여 convex hull을 구한다.
max_contour = cv2.approxPolyDP(max_contour,0.02*cv2.arcLength(max_contour,True),True)
hull = cv2.convexHull(max_contour)
#image_convexhull = image.copy()
#cv2.drawContours(image_convexhull, [hull], 0, (255,255,0), 5)
#cv2.imwrite('./modified/' +i, image_convexhull)
#print(i + "save image_convexhull!")
#cv2.imshow('convexHull', image_convexhull)
#cv2.waitKey(0)
size = len(max_contour)
print("len of max_contour" ,size)
if size == 4: # 책의 꼭지점을 구한다.
if size == 4:
## 책의 꼭지점을 구한다.
for c in hull:
points.append(c[0])
points = np.array(points)
#print(points)
else: # 꼭지점이 5개 이상인 경우 경계 박스를 이용한다.
else:
## 꼭지점이 5개 이상인 경우 경계 박스를 이용한다.
rect = cv2.minAreaRect(hull)
box = cv2.boxPoints(rect)
points = np.int0(box.tolist())
# 검출된 꼭지점이 이미지 범위를 벗어난 경우 책 꼭지점 처리
## 검출된 꼭지점이 이미지 범위를 벗어난 경우 책 꼭지점 처리
found = False
for p in points:
if p[0] < 0 or p[0] > width-1 or p[1] < 0 or p[1] > height -1:
found = True
break
if found:
points = np.array([[10,10], [width-11, 10], [width-11, height-11], [10, height-11]])
return points
```
%% Cell type:code id: tags:
``` python
#pdf로 이미지 저장
def save_pdf():
pdf = FPDF()
imagelist = []
# ------------- ADD ALL THE IMAGES IN A LIST ------------- #
folder = './modified/'
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 ------------ #
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 + "image_list" + '.pdf', "F")
print("PDF generated successfully!")
```
%% Cell type:code id: tags:
``` python
# o 버튼(마우스 사용)을 눌렀을 때,
def b1event():
global step
if sizes == 4:
cv2.namedWindow('input')
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_path +i, image_final)
print(i + " i got 4 edges!!")
cv2.imwrite(modified_path + filename, image_final)
#print(filename + " i got 4 edges!!")
else:
cv2.imshow('input', image)
cv2.imwrite(modified_path +i, image)
print(i + " i don't got 4 edges!")
cv2.imwrite(modified_path + filename, image)
#print(filename + " i don't got 4 edges!")
cv2.waitKey(0)
cv2.destroyAllWindows()
win.destroy()
```
%% Cell type:code id: tags:
``` python
#x 버튼(마우스입력을 안함)을 눌렀을 때
def b2event():
## 꼭지점 4개를 찾은경우
if sizes == 4:
image_final = transform(image, points)
cv2.imshow('result', image_final)
cv2.imwrite(modified_path +i, image_final)
print(i + " i got 4 edges!!/no button")
cv2.imwrite(modified_path +filename, image_final)
#print(i + " i got 4 edges!!/no button")
else:
cv2.imshow('input', image)
cv2.imwrite(modified_path +i, image)
print(i + " i don't got 4 edges!/no button")
cv2.imwrite(modified_path +filename, image)
#print(i + " i don't got 4 edges!/no button")
cv2.waitKey(0)
cv2.destroyAllWindows()
win.destroy()
```
%% Cell type:code id: tags:
``` python
mouse_is_pressing = False
image_path = './images/'
if not os.path.isdir(image_path):
os.mkdir(image_path)
for i in os.listdir(image_path):
path = image_path + i
## image 폴더안에 있는 이미지파일들을 하나씩 탐색.
for filename in os.listdir(image_path):
path = image_path + filename
count = len(os.listdir(image_path))
##이미지 파일이 하나도 없는경우
if count == 0:
print("there are no images")
image = cv2.imread(path, cv2.IMREAD_COLOR)
image=cv2.resize(image,(300,400))
##이미지가 너무 큰경우, 적당한 크기로 줄임
height, width, channel = image.shape
if height > 720 or width > 540:
height,width = 720,540
image=cv2.resize(image,(width,height))
#print(height, width , channel)
points = scanning(image)
#scanning 결과 나온 contour 이미지를 만듬.
image_contour = image.copy()
cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)
sizes = len(points)
print("size",sizes)
#UI 창 띄우기
win = tk.Tk()
win.title("Ask")
win.geometry("600x600+50+50")
win.geometry("600x800+50+100")
win.resizable(False, False)
lbl = tk.Label(win, text="마우스 입력 O/X?")
#lbl.grid(row=1, column=1)
lbl.pack()
image_contour = image.copy()
cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)
## contour 이미지 파일을 저장하기. 폴더가 없을경우 폴더를 만듬
contour_path = './contour/'
if not os.path.isdir(contour_path):
os.mkdir(contour_path)
cv2.imwrite(contour_path +i, image_contour)
cv2.imwrite(contour_path + filename, image_contour)
imgtk = ImageTk.PhotoImage(file = contour_path +i, master=win)
imgtk = ImageTk.PhotoImage(file = contour_path + filename, master=win)
label = tk.Label(win, image=imgtk)
label.pack()
## 최종 수정된 이미지를 저장하기. 폴더가 없을경우 폴더 생성
modified_path = './modified/'
if not os.path.isdir(modified_path):
os.mkdir(modified_path)
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()
save_pdf()
```
%% Output
len of max_contour 4
size 4
[20. 39.] [213. 14.] [277. 322.] [ 76. 303.]
59.0 227.0 599.0 379.0
document.jpg i got 4 edges!!
len of max_contour 4
size 4
[36. 43.] [265. 40.] [275. 377.] [ 21. 375.]
79.0 305.0 652.0 396.0
example.jpg i got 4 edges!!
len of max_contour 4
size 4
[54. 42.] [256. 57.] [266. 347.] [ 44. 349.]
96.0 313.0 613.0 393.0
example2.jpg i got 4 edges!!
len of max_contour 4
size 4
[53. 24.] [267. 58.] [267. 379.] [ 10. 318.]
77.0 325.0 646.0 328.0
example2.png i got 4 edges!!
len of max_contour 4
size 4
[43. 30.] [263. 27.] [272. 360.] [ 52. 365.]
73.0 290.0 632.0 417.0
example3.jpg.png i got 4 edges!!
len of max_contour 5
size 4
[75. 8.] [237. 11.] [229. 381.] [ 68. 377.]
83.0 248.0 610.0 445.0
receipt.jpg i got 4 edges!!
len of max_contour 4
size 4
[ 20. 100.] [152. 27.] [279. 290.] [131. 371.]
120.0 179.0 569.0 502.0
receipt2.jpg i got 4 edges!!
len of max_contour 8
size 4
[25. 73.] [208. 51.] [242. 333.] [ 60. 355.]
98.0 259.0 575.0 415.0
tilted receipt.jpg i got 4 edges!!
%% Cell type:code id: tags:
``` python
#이미지 저장
##################아직 안합침################################
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
---------------------------------------------------------------------------
KeyboardInterrupt Traceback (most recent call last)
<ipython-input-150-0a916bbbf96e> in <module>
16 # ------------- ADD ALL THE IMAGES IN A LIST ------------- #
17
---> 18 folder = input('Enter the path of the folder containing the images : ')
19 for dirpath, dirnames, filenames in os.walk(folder):
20 for filename in [f for f in filenames if f.endswith(".jpg")]:
~\anaconda3\lib\site-packages\ipykernel\kernelbase.py in raw_input(self, prompt)
858 "raw_input was called, but this frontend does not support input requests."
859 )
--> 860 return self._input_request(str(prompt),
861 self._parent_ident,
862 self._parent_header,
~\anaconda3\lib\site-packages\ipykernel\kernelbase.py in _input_request(self, prompt, ident, parent, password)
902 except KeyboardInterrupt:
903 # re-raise KeyboardInterrupt, to truncate traceback
--> 904 raise KeyboardInterrupt("Interrupted by user") from None
905 except Exception as e:
906 self.log.warning("Invalid Message:", exc_info=True)
KeyboardInterrupt: Interrupted by user
./modified/bookcover.jpg
./modified/example.jpg
./modified/example2.jpg
./modified/example3.jpg
./modified/framework1821.jpg
./modified/receipt.jpg
./modified/tilted_document.jpg
PDF generated successfully!
%% Cell type:code id: tags:
``` python
```
......
contour/bookcover.jpg

56.7 KiB

contour/document.jpg

50.8 KiB

contour/example.jpg

51.4 KiB | W: | H:

contour/example.jpg

143 KiB | W: | H:

contour/example.jpg
contour/example.jpg
contour/example.jpg
contour/example.jpg
  • 2-up
  • Swipe
  • Onion skin
contour/example2.jpg

36.7 KiB | W: | H:

contour/example2.jpg

96.8 KiB | W: | H:

contour/example2.jpg
contour/example2.jpg
contour/example2.jpg
contour/example2.jpg
  • 2-up
  • Swipe
  • Onion skin
contour/example2.png

174 KiB

contour/example3.jpg

167 KiB

contour/example3.jpg.png

217 KiB

contour/framework1821.jpg

132 KiB

contour/receipt.jpg

54.3 KiB | W: | H:

contour/receipt.jpg

137 KiB | W: | H:

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

28.7 KiB

contour/tilted receipt.jpg

30 KiB

contour/tilted_document.jpg

91.6 KiB

images/bookcover.jpg

38.7 KiB

images/document.jpg

10.8 KiB

images/example2.jpg

3.77 MiB | W: | H:

images/example2.jpg

595 KiB | W: | H:

images/example2.jpg
images/example2.jpg
images/example2.jpg
images/example2.jpg
  • 2-up
  • Swipe
  • Onion skin
images/example2.png

595 KiB

File moved
images/framework1821.jpg

116 KiB

images/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