-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathview.py
153 lines (121 loc) · 5.52 KB
/
view.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""
view.py
-------
Alex Robbins, Andrew Hart
Intro to AI Section 1
Final Project (Maze Solver)
This file defines the GUI. All image updates also happen here in the loop function of the
Application class.
"""
import PIL.Image
from PIL import ImageTk
from Tkinter import *
import cv2
import cam
import imaging
class Application(Frame):
def createWidgets(self):
leftframe = Frame(self.root)
leftframe.pack( side = LEFT )
rightframe = Frame(self.root)
rightframe.pack( side = RIGHT )
topframe = Frame(rightframe)
topframe.pack( side = TOP )
bottomframe = Frame(rightframe)
bottomframe.pack( side = BOTTOM )
self.ThreshSliderLbl = Label(leftframe, text="Threshold Slider", pady=0)
self.ThreshSliderLbl.grid(row=0, column=0)
self.ThreshSlider = Scale(leftframe, from_=0, to=255, orient=HORIZONTAL, length=500, variable=self.contourThreshVal)
self.ThreshSlider.grid(row=1, column=0)
self.MinBoundBoxSliderLbl = Label(leftframe, text="Minimum Allowed Bounding-Box", pady=0)
self.MinBoundBoxSliderLbl.grid(row=2, column=0)
self.MinBoundBoxSlider = Scale(leftframe, from_=0, to=100000, orient=HORIZONTAL, length=500, variable=self.minBoundBoxVal)
self.MinBoundBoxSlider.grid(row=3, column=0)
self.ErosionSliderLbl = Label(leftframe, text="Erosion Level", pady=0)
self.ErosionSliderLbl.grid(row=4, column=0)
self.ErosionSlider = Scale(leftframe, from_=0, to=55, orient=HORIZONTAL, length=500, variable=self.erosionVal)
self.ErosionSlider.grid(row=5, column=0)
self.MainImgLbl = Label(leftframe, text="Original Image", padx=10)
self.MainImgLbl.grid(row=6, column=0, sticky=W)
resW = self.vc.video.get(3)
resH = self.vc.video.get(4)
"""
Set this to whatever the Width of the Main image should be. The height will
them be set to match the aspect ratio of the web cam so the image is not
distorted
"""
self.MainImgWidth = 700 #Explained above
self.MainImgHeight = int(self.MainImgWidth*resH/resW) #Calculate height
self.SearchImgWidth = int(self.MainImgWidth*0.75)
self.SearchImageHeight = int(self.MainImgHeight*0.75)
self.MainImg = Label(leftframe, height=self.MainImgHeight, width=self.MainImgWidth, bg="lightgray")
self.MainImg.grid(row=7, column=0, sticky=W)
#self.SolveButton = Button(leftframe, text="Solve", fg="#004d1a", bg="lightgray")
#self.SolveButton.grid(row=8, column=0)
self.SearchImgLbl = Label(topframe, text="Find Maze", padx=10)
self.SearchImgLbl.grid(row=0, column=0, sticky=W)
self.SearchImg = Label(topframe, height=10, width=25, bg="lightgray")
self.SearchImg.grid(row=1, column=0, sticky=W)
self.SolvedImgLbl = Label(bottomframe, text="Solved Maze", padx=10)
self.SolvedImgLbl.grid(row=0, column=0, sticky=W)
self.SolvedImg = Label(bottomframe, height=10, width=25, bg="lightgray")
self.SolvedImg.grid(row=1, column=0, sticky=W)
def __init__(self, vc, master=None):
Frame.__init__(self, master)
self.vc = vc
self.contourThreshVal = IntVar()
self.minBoundBoxVal = IntVar()
self.erosionVal = IntVar()
self.pack()
self.root = master
self.createWidgets()
self.contourThreshVal.set(60)
self.minBoundBoxVal.set(5000)
self.erosionVal.set(20)
#This is the main loop that updates the images on the GUI
def loop(self):
#Get/Set main image from web cam
pilImage, img = self.vc.get_frame()
img2 = pilImage.resize((self.MainImgWidth, self.MainImgHeight), PIL.Image.ANTIALIAS)
img2 = ImageTk.PhotoImage(img2)
self.MainImg.config(image=img2)
self.MainImg.image = img2
#Get/Set outlined image of maze
ret = imaging.getMazeOutlineImage(img.copy(), self.contourThreshVal.get(), self.minBoundBoxVal.get())
if (len(ret) == 3):
thresh,outline,box = ret
w = self.SearchImgWidth
h = self.SearchImageHeight
self.SearchImg.config(width=w, height=h)
pilOutlineImage = PIL.Image.fromarray(cv2.cvtColor(outline,cv2.COLOR_BGR2RGB))
img2 = pilOutlineImage.resize((w, h), PIL.Image.ANTIALIAS)
img2 = ImageTk.PhotoImage(img2)
self.SearchImg.config(image=img2)
self.SearchImg.image = img2
#Get/Set solved maze!
#Get the cropped maze image
croppedImg,h_Arr = imaging.getImageFromBox(thresh, box)
#Solve it! and get solved image
solvedImg,origImgSolOverlay = imaging.getSolvedMaze(img, h_Arr, croppedImg, self.erosionVal.get())
#origImgSolOverlay is the original image with the solution overlayed on top. redisplay that in the main image location
pilOrigImgSolOverlay = PIL.Image.fromarray(cv2.cvtColor(origImgSolOverlay,cv2.COLOR_BGR2RGB))
pilOrigImgSolOverlay = pilOrigImgSolOverlay.resize((self.MainImgWidth, self.MainImgHeight), PIL.Image.ANTIALIAS)
pilOrigImgSolOverlay = ImageTk.PhotoImage(pilOrigImgSolOverlay)
self.MainImg.config(image=pilOrigImgSolOverlay)
self.MainImg.image = pilOrigImgSolOverlay
#Display cropped image
self.SolvedImg.config(width=w, height=h)
pilSolvedImage = PIL.Image.fromarray(solvedImg)
#Calculate new dimensions of maze to display it with its correct aspect ratio
solvedImgW,solvedImgH = pilSolvedImage.size
scale = min( float(w)/solvedImgW, float(h)/solvedImgH)
newW = int(solvedImgW * scale)
newH = int(solvedImgH * scale)
img2 = pilSolvedImage.resize((newW, newH), PIL.Image.ANTIALIAS)
img2 = ImageTk.PhotoImage(img2)
self.SolvedImg.config(image=img2)
self.SolvedImg.image = img2
else: #If no boxes found
self.SearchImg.config(image=None) #Set image to none (freezes it)
self.SolvedImg.config(image=None) #Set image to none (freezes it)
self.root.after(10, self.loop) # reschedule event every 0.01 seconds