Suite QOL
This commit is contained in:
parent
5b1b25bc13
commit
3ae6b41c62
@ -5,6 +5,7 @@
|
|||||||
<property name="height">800</property>
|
<property name="height">800</property>
|
||||||
<property name="title" translatable="yes">Tree Recogniser 7000</property>
|
<property name="title" translatable="yes">Tree Recogniser 7000</property>
|
||||||
<property name="width">200</property>
|
<property name="width">200</property>
|
||||||
|
<bind sequence="<Destroy>" handler="on_quit" add="" />
|
||||||
<containerlayout manager="pack">
|
<containerlayout manager="pack">
|
||||||
<property name="propagate">false</property>
|
<property name="propagate">false</property>
|
||||||
</containerlayout>
|
</containerlayout>
|
||||||
@ -175,9 +176,9 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="ttk.Button" id="button1">
|
<object class="ttk.Button" id="prev" named="True">
|
||||||
<property name="text" translatable="yes">Next img</property>
|
<property name="text" translatable="yes">Prev img</property>
|
||||||
<bind sequence="<ButtonPress>" handler="img_next" add="" />
|
<bind sequence="<ButtonPress>" handler="img_prev" add="" />
|
||||||
<layout manager="grid">
|
<layout manager="grid">
|
||||||
<property name="column">1</property>
|
<property name="column">1</property>
|
||||||
<property name="ipadx">10</property>
|
<property name="ipadx">10</property>
|
||||||
@ -186,9 +187,9 @@
|
|||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="ttk.Button" id="button2">
|
<object class="ttk.Button" id="next" named="True">
|
||||||
<property name="text" translatable="yes">Prev img</property>
|
<property name="text" translatable="yes">Next img</property>
|
||||||
<bind sequence="<ButtonPress>" handler="img_prev" add="" />
|
<bind sequence="<ButtonPress>" handler="img_next" add="" />
|
||||||
<layout manager="grid">
|
<layout manager="grid">
|
||||||
<property name="column">2</property>
|
<property name="column">2</property>
|
||||||
<property name="ipadx">10</property>
|
<property name="ipadx">10</property>
|
||||||
@ -213,7 +214,7 @@
|
|||||||
<bind sequence="<ButtonPress>" handler="apply" add="" />
|
<bind sequence="<ButtonPress>" handler="apply" add="" />
|
||||||
<layout manager="grid">
|
<layout manager="grid">
|
||||||
<property name="column">2</property>
|
<property name="column">2</property>
|
||||||
<property name="columnspan">2</property>
|
<property name="columnspan">1</property>
|
||||||
<property name="ipadx">0</property>
|
<property name="ipadx">0</property>
|
||||||
<property name="row">6</property>
|
<property name="row">6</property>
|
||||||
</layout>
|
</layout>
|
||||||
@ -238,6 +239,22 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="tk.Text" id="dataset" named="True">
|
||||||
|
<property name="height">10</property>
|
||||||
|
<property name="pady">0</property>
|
||||||
|
<property name="state">disabled</property>
|
||||||
|
<property name="text" translatable="yes">Image metadata should appear here</property>
|
||||||
|
<property name="width">25</property>
|
||||||
|
<property name="wrap">word</property>
|
||||||
|
<layout manager="grid">
|
||||||
|
<property name="column">3</property>
|
||||||
|
<property name="columnspan">1</property>
|
||||||
|
<property name="row">0</property>
|
||||||
|
<property name="rowspan">8</property>
|
||||||
|
</layout>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
172
src/suite.py
172
src/suite.py
@ -8,11 +8,18 @@ import numpy as np
|
|||||||
import cv2
|
import cv2
|
||||||
import time
|
import time
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
import json
|
||||||
|
|
||||||
|
## UI config load
|
||||||
PROJECT_PATH = pathlib.Path(__file__).parent
|
PROJECT_PATH = pathlib.Path(__file__).parent
|
||||||
PROJECT_UI = "./src/helpers/gui/main.ui"
|
PROJECT_UI = "./src/helpers/gui/main.ui"
|
||||||
CONFIG_PATH = "./src/config/config.json"
|
|
||||||
|
|
||||||
|
## Config file load
|
||||||
|
CONFIG_PATH = "./src/config/config.json"
|
||||||
|
config_file = open(CONFIG_PATH)
|
||||||
|
config_json = json.load(config_file)
|
||||||
|
|
||||||
|
## UI class setup
|
||||||
class MainApp:
|
class MainApp:
|
||||||
def __init__(self, master=None):
|
def __init__(self, master=None):
|
||||||
self.builder = builder = pygubu.Builder()
|
self.builder = builder = pygubu.Builder()
|
||||||
@ -22,38 +29,51 @@ class MainApp:
|
|||||||
# Main widget
|
# Main widget
|
||||||
self.mainwindow = builder.get_object("main", master)
|
self.mainwindow = builder.get_object("main", master)
|
||||||
|
|
||||||
|
# Canvas for output images
|
||||||
self.canvas = builder.get_object("output_canvas")
|
self.canvas = builder.get_object("output_canvas")
|
||||||
self.tk_imgs = []
|
self.tk_imgs = [] # Required or python will forget
|
||||||
|
self.output = [[] for x in range(2)]
|
||||||
self.canny_thr1 = None
|
self.meta = builder.get_object("dataset")
|
||||||
self.canny_thr2 = None
|
|
||||||
|
# Keep track of images in dataset
|
||||||
self.img_path = None
|
|
||||||
self.img_current = 0
|
self.img_current = 0
|
||||||
self.img_max = 0
|
self.img_max = 0
|
||||||
|
|
||||||
# Plots
|
# Plots
|
||||||
self.axs = self.createPlot(2, 2)
|
self.axs = self.createPlot(2, 2)
|
||||||
|
|
||||||
# UI
|
# UI Variables
|
||||||
|
self.canny_thr1 = None
|
||||||
|
self.canny_thr2 = None
|
||||||
|
self.img_path = None
|
||||||
self.blur_rate = None
|
self.blur_rate = None
|
||||||
self.img_size = 100
|
self.img_size = None
|
||||||
self.sobel_select = None
|
self.sobel_select = None
|
||||||
self.export_id = None
|
self.export_id = None
|
||||||
builder.import_variables(self,
|
builder.import_variables(self, ['canny_thr1','canny_thr2','img_path','blur_rate','img_size', 'sobel_select', 'export_id'])
|
||||||
['canny_thr1',
|
|
||||||
'canny_thr2',
|
|
||||||
'img_path',
|
|
||||||
'blur_rate',
|
|
||||||
'img_size',
|
|
||||||
'sobel_select',
|
|
||||||
'export_id'])
|
|
||||||
builder.connect_callbacks(self)
|
builder.connect_callbacks(self)
|
||||||
|
|
||||||
|
# Load values from config after UI has been initialised
|
||||||
|
self.img_path.set(config_json["path"])
|
||||||
|
self.img_size.set(config_json["size"])
|
||||||
|
|
||||||
|
def on_quit(self, event=None):
|
||||||
|
'''
|
||||||
|
Close PLT windows on main app quit
|
||||||
|
'''
|
||||||
|
plt.close()
|
||||||
|
self.mainwindow.quit();
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
'''
|
||||||
|
Run loop
|
||||||
|
'''
|
||||||
self.mainwindow.mainloop()
|
self.mainwindow.mainloop()
|
||||||
|
|
||||||
def img_prev(self, event=None):
|
def img_prev(self, event=None):
|
||||||
|
'''
|
||||||
|
Open previous image from path
|
||||||
|
'''
|
||||||
if self.img_current == 0:
|
if self.img_current == 0:
|
||||||
self.img_current = self.img_max - 1
|
self.img_current = self.img_max - 1
|
||||||
else:
|
else:
|
||||||
@ -61,6 +81,9 @@ class MainApp:
|
|||||||
self.update(self)
|
self.update(self)
|
||||||
|
|
||||||
def img_next(self, event=None):
|
def img_next(self, event=None):
|
||||||
|
'''
|
||||||
|
Open next image from path
|
||||||
|
'''
|
||||||
if self.img_current == (self.img_max - 1):
|
if self.img_current == (self.img_max - 1):
|
||||||
self.img_current = 0
|
self.img_current = 0
|
||||||
else:
|
else:
|
||||||
@ -68,6 +91,9 @@ class MainApp:
|
|||||||
self.update(self)
|
self.update(self)
|
||||||
|
|
||||||
def apply(self, event=None):
|
def apply(self, event=None):
|
||||||
|
'''
|
||||||
|
Export current dataset
|
||||||
|
'''
|
||||||
img_arr = self.tk_imgs
|
img_arr = self.tk_imgs
|
||||||
img_id = self.export_id.get()
|
img_id = self.export_id.get()
|
||||||
|
|
||||||
@ -76,10 +102,58 @@ class MainApp:
|
|||||||
else:
|
else:
|
||||||
print("Nothing to export!")
|
print("Nothing to export!")
|
||||||
|
|
||||||
|
def add_output(self, data, name: str):
|
||||||
|
'''
|
||||||
|
Add CV2 image to canvas output
|
||||||
|
'''
|
||||||
|
self.output[0].append(data)
|
||||||
|
self.output[1].append(name)
|
||||||
|
|
||||||
|
def draw_output(self, size):
|
||||||
|
# Check if size of canvas has updated
|
||||||
|
drawW = self.canvas.winfo_width()
|
||||||
|
|
||||||
|
# Reset drawing position
|
||||||
|
drawX = 0
|
||||||
|
drawY = 0
|
||||||
|
|
||||||
|
# Clear previously printed images
|
||||||
|
self.tk_imgs = []
|
||||||
|
|
||||||
|
self.meta.config(state=NORMAL)
|
||||||
|
self.meta.delete(1.0, END)
|
||||||
|
|
||||||
|
# Draw all output images
|
||||||
|
for idx, data in enumerate(self.output[0]):
|
||||||
|
# Create ui image
|
||||||
|
tk_img = cv2.cvtColor(data, cv2.COLOR_BGR2RGB)
|
||||||
|
tk_img = ImageTk.PhotoImage(image=Image.fromarray(tk_img))
|
||||||
|
self.tk_imgs.append(tk_img)
|
||||||
|
|
||||||
|
## Check if next item will be out of range
|
||||||
|
if (drawX + size >= drawW):
|
||||||
|
drawY += size
|
||||||
|
drawX = 0
|
||||||
|
self.canvas.configure(height=(drawY+size))
|
||||||
|
|
||||||
|
self.canvas.create_image(drawX,drawY,anchor=NW,image=self.tk_imgs[idx],tags="og")
|
||||||
|
drawX += size
|
||||||
|
|
||||||
|
# Add name to text box
|
||||||
|
self.meta.insert(END, F"{idx}: {self.output[1][idx]}\n")
|
||||||
|
|
||||||
|
# Clear output
|
||||||
|
self.output = [[] for x in range(2)]
|
||||||
|
self.meta.config(state=DISABLED)
|
||||||
|
|
||||||
|
# Draw canvas
|
||||||
|
# TODO IDK volgens mij moet je deze wel callen maar het programma doet het nog (geen vragen stellen)
|
||||||
|
# self.canvas.draw()
|
||||||
|
|
||||||
def createPlot(self, columns, rows):
|
def createPlot(self, columns, rows):
|
||||||
fig, axs = plt.subplots(columns, rows)
|
fig, axs = plt.subplots(columns, rows)
|
||||||
return axs
|
return axs
|
||||||
|
|
||||||
def drawHist(self, image, labels, column, row):
|
def drawHist(self, image, labels, column, row):
|
||||||
self.axs[column, row].clear()
|
self.axs[column, row].clear()
|
||||||
for i,lab in enumerate(labels):
|
for i,lab in enumerate(labels):
|
||||||
@ -121,11 +195,6 @@ class MainApp:
|
|||||||
|
|
||||||
def update(self, event=None):
|
def update(self, event=None):
|
||||||
path = self.img_path.get()
|
path = self.img_path.get()
|
||||||
print(path)
|
|
||||||
|
|
||||||
drawW = self.canvas.winfo_width()
|
|
||||||
drawX = 0
|
|
||||||
drawY = 0
|
|
||||||
|
|
||||||
if path != None and path != "":
|
if path != None and path != "":
|
||||||
# Get all images at current path
|
# Get all images at current path
|
||||||
@ -142,31 +211,24 @@ class MainApp:
|
|||||||
sxy = self.sobel_select.get()
|
sxy = self.sobel_select.get()
|
||||||
size = self.img_size.get()
|
size = self.img_size.get()
|
||||||
|
|
||||||
# Keep array of cv2 images to output
|
|
||||||
output = []
|
|
||||||
|
|
||||||
# Clear previously printed images
|
|
||||||
self.tk_imgs = []
|
|
||||||
|
|
||||||
# Import and resize image
|
# Import and resize image
|
||||||
img = cv2.imread(images[self.img_current])
|
img = cv2.imread(images[self.img_current])
|
||||||
img = cv2.resize(img, (size, size), interpolation = cv2.INTER_AREA)
|
img = cv2.resize(img, (size, size), interpolation = cv2.INTER_AREA)
|
||||||
output.append(img) # First output image is original
|
self.add_output(img, "Original")
|
||||||
|
|
||||||
# Set grayscale
|
# Set grayscale
|
||||||
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
output.append(img_gray) # Second output is grayscale
|
self.add_output(img_gray, "Grayscale")
|
||||||
|
|
||||||
# Blurred edition
|
# Blurred edition
|
||||||
if (br == 0):
|
if (br == 0):
|
||||||
# Disable
|
|
||||||
img_blur = img_gray
|
img_blur = img_gray
|
||||||
elif (br % 2 == 1):
|
elif (br % 2 == 1):
|
||||||
img_blur = cv2.GaussianBlur(img_gray, (br, br), 0)
|
img_blur = cv2.GaussianBlur(img_gray, (br, br), 0)
|
||||||
else:
|
else:
|
||||||
print(f"Blur rate changed to {br - 1}")
|
print(f"Blur rate changed to {br - 1}")
|
||||||
img_blur = cv2.GaussianBlur(img_gray, (br-1, br-1), 0)
|
img_blur = cv2.GaussianBlur(img_gray, (br-1, br-1), 0)
|
||||||
output.append(img_blur)
|
self.add_output(img_blur, "Blurred")
|
||||||
|
|
||||||
# Sobel edge
|
# Sobel edge
|
||||||
if sxy in ['x', 'y', 'both']:
|
if sxy in ['x', 'y', 'both']:
|
||||||
@ -182,49 +244,37 @@ class MainApp:
|
|||||||
|
|
||||||
img_sobel = cv2.Sobel(src=img_blur, ddepth=cv2.CV_8U, dx=dx, dy=dy, ksize=5)
|
img_sobel = cv2.Sobel(src=img_blur, ddepth=cv2.CV_8U, dx=dx, dy=dy, ksize=5)
|
||||||
else:
|
else:
|
||||||
img_sobel = img_gray
|
img_sobel = img_gray
|
||||||
output.append(img_sobel)
|
self.add_output(img_sobel, "Sobel Edge")
|
||||||
|
|
||||||
# Canny edge
|
# Canny edge
|
||||||
img_canny = cv2.Canny(image=img_blur,threshold1=ct1,threshold2=ct2)
|
img_canny = cv2.Canny(image=img_blur,threshold1=ct1,threshold2=ct2)
|
||||||
output.append(img_canny)
|
self.add_output(img_canny, "Canny Edge")
|
||||||
|
|
||||||
# BGR
|
# BGR
|
||||||
output.append(img[:, :, 0]) # B
|
self.add_output(img[:, :, 0], "BGR B")
|
||||||
output.append(img[:, :, 1]) # G
|
self.add_output(img[:, :, 1], "BGR G")
|
||||||
output.append(img[:, :, 2]) # R
|
self.add_output(img[:, :, 2], "BGR R")
|
||||||
|
|
||||||
if img is not None:
|
if img is not None:
|
||||||
self.drawHist(img, ('B', 'G', 'R'), 0, 0)
|
self.drawHist(img, ('B', 'G', 'R'), 0, 0)
|
||||||
|
|
||||||
# HSV
|
# HSV
|
||||||
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
|
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
|
||||||
output.append(img_hsv)
|
self.add_output(img_hsv, "HSV")
|
||||||
output.append(img_hsv[:, :, 0]) # H
|
self.add_output(img_hsv[:, :, 0], "HSV H") # H
|
||||||
output.append(img_hsv[:, :, 1]) # S
|
self.add_output(img_hsv[:, :, 1], "HSV S") # S
|
||||||
output.append(img_hsv[:, :, 2]) # V
|
self.add_output(img_hsv[:, :, 2], "HSV V") # V
|
||||||
|
|
||||||
if img_hsv is not None:
|
if img_hsv is not None:
|
||||||
self.drawHist(img_hsv, ('H', 'S', 'V'), 0, 1)
|
self.drawHist(img_hsv, ('H', 'S', 'V'), 0, 1)
|
||||||
|
|
||||||
|
# Canny Heatmap
|
||||||
self.drawCannyHM(img, 1, 1)
|
self.drawCannyHM(img, 1, 1)
|
||||||
|
|
||||||
plt.show(block=False)
|
|
||||||
|
|
||||||
# Draw all output images
|
# Show all data
|
||||||
for idx, data in enumerate(output):
|
plt.show(block=False) ## Graphs
|
||||||
# Create ui image
|
self.draw_output(size) ## Images
|
||||||
tk_img = cv2.cvtColor(data, cv2.COLOR_BGR2RGB)
|
|
||||||
tk_img = ImageTk.PhotoImage(image=Image.fromarray(tk_img))
|
|
||||||
self.tk_imgs.append(tk_img)
|
|
||||||
|
|
||||||
## Check if next item will be out of range
|
|
||||||
if (drawX + size >= drawW):
|
|
||||||
drawY += size
|
|
||||||
drawX = 0
|
|
||||||
self.canvas.configure(height=(drawY+size))
|
|
||||||
|
|
||||||
self.canvas.create_image(drawX,drawY,anchor=NW,image=self.tk_imgs[idx],tags="og")
|
|
||||||
drawX += size
|
|
||||||
self.canvas.draw()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = MainApp()
|
app = MainApp()
|
||||||
|
Loading…
Reference in New Issue
Block a user