|
a |
|
b/program.py |
|
|
1 |
from tkinter import * |
|
|
2 |
from tkinter import filedialog |
|
|
3 |
import tkinter.messagebox |
|
|
4 |
import cv2 as cv |
|
|
5 |
from cv2 import * |
|
|
6 |
import inspection as myModule |
|
|
7 |
import sys |
|
|
8 |
|
|
|
9 |
|
|
|
10 |
def nothing(x): |
|
|
11 |
x |
|
|
12 |
|
|
|
13 |
|
|
|
14 |
def do_nothing(): |
|
|
15 |
print("Doing absolutely nothing") |
|
|
16 |
|
|
|
17 |
|
|
|
18 |
def set_ROI(filepath): |
|
|
19 |
global ref_point |
|
|
20 |
ref_point = [] |
|
|
21 |
|
|
|
22 |
def shape_selection(event, x, y, flags, param): |
|
|
23 |
global ref_point |
|
|
24 |
if event == cv2.EVENT_LBUTTONDOWN: |
|
|
25 |
ref_point = [(x, y)] |
|
|
26 |
elif event == cv2.EVENT_LBUTTONUP: |
|
|
27 |
ref_point.append((x, y)) |
|
|
28 |
cv2.rectangle(img, ref_point[0], ref_point[1], (0, 255, 0), 2) |
|
|
29 |
|
|
|
30 |
img = cv.imread(filepath) |
|
|
31 |
cv.namedWindow("Set ROI") |
|
|
32 |
cv.setMouseCallback("Set ROI", shape_selection) |
|
|
33 |
while 1: |
|
|
34 |
k = cv.waitKey(1) |
|
|
35 |
if k!=-1: |
|
|
36 |
break |
|
|
37 |
cv.imshow("Set ROI", img) |
|
|
38 |
cv.destroyAllWindows() |
|
|
39 |
global x_min, x_max, y_min, y_max |
|
|
40 |
if ref_point!=[]: |
|
|
41 |
x_min = ref_point[0][0] |
|
|
42 |
x_max = ref_point[1][0] |
|
|
43 |
y_min = ref_point[0][1] |
|
|
44 |
y_max = ref_point[1][1] |
|
|
45 |
else: |
|
|
46 |
x_min = -1 |
|
|
47 |
x_max = -1 |
|
|
48 |
y_min = -1 |
|
|
49 |
y_max = -1 |
|
|
50 |
|
|
|
51 |
|
|
|
52 |
def canny_threshold(smooth_size, filepath): |
|
|
53 |
img = cv.imread(filepath) |
|
|
54 |
imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) |
|
|
55 |
filter_img = cv.medianBlur(imgray, smooth_size) |
|
|
56 |
cv.namedWindow("CANNY") |
|
|
57 |
cv.createTrackbar("MIN", "CANNY", 0, 255, nothing) |
|
|
58 |
cv.createTrackbar("MAX", "CANNY", 0, 255, nothing) |
|
|
59 |
while 1: |
|
|
60 |
k = cv.waitKey(1) |
|
|
61 |
if k != -1: |
|
|
62 |
break |
|
|
63 |
t1 = cv.getTrackbarPos("MIN", "CANNY") |
|
|
64 |
t2 = cv.getTrackbarPos("MAX", "CANNY") |
|
|
65 |
current_img = cv.Canny(filter_img, t1, t2) |
|
|
66 |
cv.imshow("CANNY", current_img) |
|
|
67 |
cv.destroyAllWindows() |
|
|
68 |
global min_threshold |
|
|
69 |
global max_threshold |
|
|
70 |
min_threshold = t1 |
|
|
71 |
max_threshold = t2 |
|
|
72 |
|
|
|
73 |
|
|
|
74 |
def read_settings(): |
|
|
75 |
with open("settings\\program_settings.txt", "r") as f: |
|
|
76 |
settings = f.readlines() |
|
|
77 |
settings = [x.strip() for x in settings] |
|
|
78 |
output = [] |
|
|
79 |
for line in settings: |
|
|
80 |
parts = line.split(';') |
|
|
81 |
output.append(parts) |
|
|
82 |
return output |
|
|
83 |
|
|
|
84 |
|
|
|
85 |
def load_image(path): |
|
|
86 |
global filepath |
|
|
87 |
filepath=path |
|
|
88 |
print("Loading image: "+filepath) |
|
|
89 |
img = PhotoImage(file=filepath) |
|
|
90 |
display_image.my_image=img |
|
|
91 |
root_width=img.width()+40 |
|
|
92 |
root_height=img.height()+40+24+20 |
|
|
93 |
root_posX=int(round(root.winfo_screenwidth()/2))-int(round(root_width/2)) |
|
|
94 |
root_posY=int(round(root.winfo_screenheight()/2))-int(round(root_height/2))-20 |
|
|
95 |
root_geometry = str(root_width)+"x"+str(root_height)+"+"+str(root_posX)+"+"+str(root_posY) |
|
|
96 |
root.geometry(root_geometry) |
|
|
97 |
display_image.config(image=display_image.my_image) |
|
|
98 |
button_settings.config(state=NORMAL) |
|
|
99 |
button_run.config(state=NORMAL) |
|
|
100 |
|
|
|
101 |
|
|
|
102 |
# def tool_load_image(): |
|
|
103 |
# window_load_image = Tk() |
|
|
104 |
# window_load_image.geometry("240x100+550+325") |
|
|
105 |
# window_load_image.title("Load image") |
|
|
106 |
# |
|
|
107 |
# path = 'images\\' |
|
|
108 |
# path_display = Label(window_load_image, text=path) |
|
|
109 |
# path_display.grid(row=0, column=0, pady=15, sticky=E) |
|
|
110 |
# |
|
|
111 |
# entry_load_image = Entry(window_load_image) |
|
|
112 |
# entry_load_image.insert(END, '') |
|
|
113 |
# entry_load_image.grid(row=0, column=1, pady=15, sticky=W) |
|
|
114 |
# |
|
|
115 |
# button_load_function = Button(window_load_image, text="Load", |
|
|
116 |
# command=lambda: load_image(path + entry_load_image.get()), width=15) |
|
|
117 |
# button_load_function.grid(columnspan=2, pady=5, padx=65) |
|
|
118 |
# |
|
|
119 |
# status.config(text="Adjust settings or run inspection") |
|
|
120 |
# window_load_image.mainloop() |
|
|
121 |
|
|
|
122 |
def tool_load_image(): |
|
|
123 |
path = filedialog.askopenfilename(initialdir="images\\", title = "Select TOFD image", |
|
|
124 |
filetypes=[("Image", "*.png")]) |
|
|
125 |
load_image(path) |
|
|
126 |
status.config(text="Adjust settings or run inspection") |
|
|
127 |
|
|
|
128 |
|
|
|
129 |
def tool_run(): |
|
|
130 |
print("Inspection running...") |
|
|
131 |
settings = read_settings() |
|
|
132 |
settings_names=[] |
|
|
133 |
settings_values=[] |
|
|
134 |
for i in range(len(settings)): |
|
|
135 |
settings_names.append(settings[i][0]) |
|
|
136 |
for j in range(1,len(settings[i])): |
|
|
137 |
settings_values.append(settings[i][j]) |
|
|
138 |
for i in range(len(settings_values)): |
|
|
139 |
settings_values[i]=int(settings_values[i]) |
|
|
140 |
global x, y, w, h, images |
|
|
141 |
acceptance, x,y,w,h, filepath_inspected, images = \ |
|
|
142 |
myModule.inspect(filepath, settings_values, 3, 12) |
|
|
143 |
if images == 0: |
|
|
144 |
status.config(text="Try loading file again") |
|
|
145 |
else: |
|
|
146 |
status.config(text=" Main defect size: "+str(w)+" x "+str(h) + " / Coordinates: ("+str(x)+";"+str(y)+")" |
|
|
147 |
+ " / Acceptance: " + str(acceptance)) |
|
|
148 |
load_image(filepath_inspected) |
|
|
149 |
button_display_process.config(state=NORMAL) |
|
|
150 |
|
|
|
151 |
|
|
|
152 |
def tool_settings(): |
|
|
153 |
def save_on_closing(): |
|
|
154 |
if_save = tkinter.messagebox.askquestion("Quit", "Do you want to save these settings?") |
|
|
155 |
if if_save=="yes": |
|
|
156 |
print("Saving settings...") |
|
|
157 |
with open("settings\\program_settings.txt", "w") as f: |
|
|
158 |
f.write(label_0["text"]+";"+str(setting_0_return.get())+"\n") |
|
|
159 |
try: |
|
|
160 |
f.write(label_1["text"] + ";" + str(min_threshold) + ";" + str(max_threshold) + "\n") |
|
|
161 |
except: |
|
|
162 |
print(sys.exc_info()[0]) |
|
|
163 |
print(label_1["text"]+": Setting default value: 20 - 77") |
|
|
164 |
f.write(label_1["text"] + ";" + "20;77\n") |
|
|
165 |
f.write(label_2["text"] + ";" + str(setting_2_return.get()) + "\n") |
|
|
166 |
f.write(label_3["text"] + ";" + setting_3.get() + "\n") |
|
|
167 |
try: |
|
|
168 |
f.write(label_4["text"] + ";" + str(x_min) + ";" + str(x_max) + ";" + str(y_min) + ";" + str(y_max) + "\n") |
|
|
169 |
except: |
|
|
170 |
print(sys.exc_info()[0]) |
|
|
171 |
print(label_4["text"]+": Setting dynamic region of interest") |
|
|
172 |
f.write(label_4["text"] + ";" + "-1;-1;-1;-1\n") |
|
|
173 |
tkinter.messagebox.showinfo("Quit", "Settngs saved in:\nsettings\\program_settings.txt") |
|
|
174 |
window_settings.destroy() |
|
|
175 |
|
|
|
176 |
print("Accessing settings...") |
|
|
177 |
settings = read_settings() |
|
|
178 |
settings_names = [] |
|
|
179 |
settings_values = [] |
|
|
180 |
for i in range(len(settings)): |
|
|
181 |
settings_names.append(settings[i][0]) |
|
|
182 |
for j in range(1, len(settings[i])): |
|
|
183 |
settings_values.append(settings[i][j]) |
|
|
184 |
print(settings_values) |
|
|
185 |
window_settings = Tk() |
|
|
186 |
window_settings.geometry("400x200+450+280") |
|
|
187 |
|
|
|
188 |
window_settings.title("Settings") |
|
|
189 |
|
|
|
190 |
label_title_default = Label(window_settings, text="Default settings", font='Helvetica 10 bold') |
|
|
191 |
label_0 = Label(window_settings, text="Filter size") |
|
|
192 |
label_1 = Label(window_settings, text="Canny threshold") |
|
|
193 |
label_2 = Label(window_settings, text="Morphology - kernel size") |
|
|
194 |
label_3 = Label(window_settings, text="Morphology - iterations") |
|
|
195 |
label_4 = Label(window_settings, text="Region of interest") |
|
|
196 |
|
|
|
197 |
label_title_current = Label(window_settings, text="Current settings", font='Helvetica 10 bold') |
|
|
198 |
label_0_1 = Label(window_settings, text=str(settings_values[0])) |
|
|
199 |
label_1_1 = Label(window_settings, text=str(settings_values[1])+"-"+str(settings_values[2])) |
|
|
200 |
label_2_1 = Label(window_settings, text=str(settings_values[3])) |
|
|
201 |
label_3_1 = Label(window_settings, text=str(settings_values[4])) |
|
|
202 |
if settings_values[5]=="-1" and settings_values[6]=="-1" and settings_values[7]=="-1" and settings_values[8]=="-1": |
|
|
203 |
label_4_1 = Label(window_settings,text="Dynamic") |
|
|
204 |
else: |
|
|
205 |
label_4_1 = Label(window_settings, text="x: "+str(settings_values[5])+" - "+str(settings_values[6])+" ; y: "+str(settings_values[7])+" - "+str(settings_values[8])) |
|
|
206 |
|
|
|
207 |
label_title_default.grid(row=0,columnspan=2) |
|
|
208 |
label_0.grid(row=1, column=0, sticky=E) |
|
|
209 |
label_1.grid(row=2, column=0, sticky=E) |
|
|
210 |
label_2.grid(row=3, column=0, sticky=E) |
|
|
211 |
label_3.grid(row=4, column=0, sticky=E) |
|
|
212 |
label_4.grid(row=5, column=0, sticky=E) |
|
|
213 |
|
|
|
214 |
label_title_current.grid(row=0, column=2) |
|
|
215 |
label_0_1.grid(row=1, column=2) |
|
|
216 |
label_1_1.grid(row=2, column=2) |
|
|
217 |
label_2_1.grid(row=3, column=2) |
|
|
218 |
label_3_1.grid(row=4, column=2) |
|
|
219 |
label_4_1.grid(row=5, column=2) |
|
|
220 |
|
|
|
221 |
filterType = [3, 5, 7, 9] |
|
|
222 |
setting_0_return = IntVar(window_settings) |
|
|
223 |
setting_0_return.set(filterType[3]) |
|
|
224 |
setting_0 = OptionMenu(window_settings, setting_0_return, *filterType) |
|
|
225 |
setting_0.grid(row=1, column=1) |
|
|
226 |
|
|
|
227 |
setting_1 = Button(window_settings, text="SET", width=15, command=lambda: canny_threshold(setting_0_return.get(), filepath)) |
|
|
228 |
setting_1.grid(row=2, column=1) |
|
|
229 |
|
|
|
230 |
morphologyKernel = [3, 5, 7, 9] |
|
|
231 |
setting_2_return = IntVar(window_settings) |
|
|
232 |
setting_2_return.set(morphologyKernel[0]) |
|
|
233 |
setting_2 = OptionMenu(window_settings, setting_2_return, *morphologyKernel) |
|
|
234 |
setting_2.grid(row=3, column=1, sticky=W) |
|
|
235 |
|
|
|
236 |
setting_3 = Entry(window_settings) |
|
|
237 |
setting_3.insert(END, "3") |
|
|
238 |
setting_3.grid(row=4, column=1, sticky=W) |
|
|
239 |
|
|
|
240 |
setting_4_current = Label(window_settings, text="Current ROI:") |
|
|
241 |
setting_4_current.grid(row=5, column=1) |
|
|
242 |
setting_4 = Button(window_settings, text="SET", width=15, command=lambda:set_ROI(filepath)) |
|
|
243 |
setting_4.grid(row=6, column=1, pady=5) |
|
|
244 |
|
|
|
245 |
window_settings.protocol("WM_DELETE_WINDOW", save_on_closing) |
|
|
246 |
window_settings.mainloop() |
|
|
247 |
|
|
|
248 |
|
|
|
249 |
root = Tk() |
|
|
250 |
root.title("Program") |
|
|
251 |
root.geometry("500x500+400+100") |
|
|
252 |
|
|
|
253 |
toolbar = Frame(root, bd=1, relief=RIDGE) |
|
|
254 |
toolbar.pack(side=TOP, fill=X) |
|
|
255 |
|
|
|
256 |
inspection_frame = Frame(root) |
|
|
257 |
inspection_frame.pack(side=BOTTOM, fill=X) |
|
|
258 |
|
|
|
259 |
status = Label(inspection_frame, text="Load image to inspect...", bd=1, relief=SUNKEN, anchor=W, font="Calibri 12", height=2) # bd-border, relief-how border appears, anchor-where |
|
|
260 |
status.pack(side=BOTTOM, fill=X) |
|
|
261 |
|
|
|
262 |
button_load = Button(toolbar, text="Load image", command=tool_load_image) |
|
|
263 |
button_load.pack(side=LEFT, padx=2, pady=2) |
|
|
264 |
|
|
|
265 |
button_settings = Button(toolbar, text="Settings", command=tool_settings) |
|
|
266 |
button_settings.pack(side=LEFT, padx=2,pady=2) |
|
|
267 |
|
|
|
268 |
button_run = Button(toolbar, text="Run", state=DISABLED, command=tool_run) |
|
|
269 |
button_run.pack(side=LEFT, padx=2, pady=2) |
|
|
270 |
|
|
|
271 |
button_display_process = Button(toolbar, text="Show process", state=DISABLED, command=lambda:myModule.display_process(images)) |
|
|
272 |
button_display_process.pack(side=LEFT, padx=2, pady=2) |
|
|
273 |
|
|
|
274 |
display_image = Label(inspection_frame) |
|
|
275 |
display_image.pack(padx=20, pady=20) |
|
|
276 |
|
|
|
277 |
root.mainloop() |