This is the product of BALIGE ACADEMY TEAM: Vivian Siahaan and Rismon Hasiholan Sianipar.
#main_program.py
import tkinter as tk
from main_form import Main_Form
from plot_utils import Plot_Utils
class Main_Program():
def __init__(self, root):
self.initialize(root)
def initialize(self, root):
self.root = root
width = 1520
height = 400
self.root.geometry(f"{width}x{height}")
self.root.title("START FROM FROM SCRATCH DIGITAL IMAGE PROCESSING WITH TKINTER")
#Creates necessary objects
self.obj_main_form = Main_Form()
self.obj_plot_utils = Plot_Utils()
#Places widgets in root
self.obj_main_form.add_widgets(self.root)
#Binds events
self.binds_event()
def binds_event(self):
self.obj_plot_utils.binds_fundamentals(self.obj_main_form)
if __name__ == "__main__":
root = tk.Tk()
app = Main_Program(root)
root.mainloop()
#main_form.py
import tkinter as tk
from tkinter import ttk
class Main_Form:
def add_widgets(self, root):
#Adds menu
self.add_menu(root)
def add_menu(self, root):
self.menu_bar = tk.Menu(root)
#Creates a image fundamentals menu
self.fundamentals = tk.Menu(self.menu_bar, tearoff=0)
self.fundamentals.add_command(label="Color Space")
self.fundamentals.add_command(label="Fast Fourier Transform")
self.fundamentals.add_command(label="Discrete Cosine Transform")
self.fundamentals.add_command(label="Discrete Sine Transform")
self.fundamentals.add_command(label="Discrete Wavelet Transform")
self.menu_bar.add_cascade(label="Fundamentals", menu=self.fundamentals)
root.config(menu=self.menu_bar)
#plot_utils.py
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import *
import seaborn as sns
import numpy as np
import pandas as pd
from form_histogram import Form_Histogram
from fundamental_utils import Fundamental_Utils
class Plot_Utils:
def __init__(self):
self.fund_utils = Fundamental_Utils()
def plot_histogram(self):
win = tk.Toplevel()
form_hist = Form_Histogram(win)
win.title("Histogram of Color Space")
def binds_fundamentals(self, window):
window.fundamentals.entryconfigure("Color Space",
command =lambda:self.plot_histogram())
#fundamental_utils.py
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import *
import seaborn as sns
import numpy as np
import pandas as pd
import tkinter as tk
from tkinter import filedialog
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from PIL import Image, ImageTk
import colorsys
import cv2
class Fundamental_Utils:
def __init__(self):
pass
def open_image(self, ax, figure, canvas):
file_path = filedialog.askopenfilename(filetypes=[("Image files", "*.png;*.jpg;*.jpeg;*.gif;*.bmp")])
if file_path:
image = Image.open(file_path)
photo = ImageTk.PhotoImage(image)
ax.imshow(image)
ax.axis('off')
ax.set_title("RGB Color Space")
figure.tight_layout()
canvas.draw()
return image
def extract_rgb(self, image):
# Convert the image to a NumPy array
image_array = np.array(image)
# Separate the channels
r_channel = image_array[:, :, 0]
g_channel = image_array[:, :, 1]
b_channel = image_array[:, :, 2]
return r_channel, g_channel, b_channel
def histogram_rgb(self, image, range_val):
r_channel, g_channel, b_channel = self.extract_rgb(image)
# Calculate histograms for each channel
r_hist, ch1_bins = np.histogram(r_channel, bins=range_val, range=(0, range_val))
g_hist, ch2_bins = np.histogram(g_channel, bins=range_val, range=(0, range_val))
b_hist, ch3_bins = np.histogram(b_channel, bins=range_val, range=(0, range_val))
return r_hist, g_hist, b_hist
def extract_hsv(self, image):
img2 = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
img_hsv = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)
# Separate the channels
h_channel = img_hsv[:, :, 0]
s_channel = img_hsv[:, :, 1]
v_channel = img_hsv[:, :, 2]
return h_channel, s_channel, v_channel
def histogram_hsv(self, image, range_val):
h_channel, s_channel, v_channel = self.extract_hsv(image)
h_hist, h_bins = np.histogram(h_channel, bins=range_val, range=(0, range_val))
s_hist, s_bins = np.histogram(s_channel, bins=range_val, range=(0, range_val))
v_hist, v_bins = np.histogram(v_channel, bins=range_val, range=(0, range_val))
return h_hist, s_hist, v_hist
def extract_yuv(self, image):
img_yuv = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2YUV)
# Separate the channels
y_channel = img_yuv[:, :, 0]
u_channel = img_yuv[:, :, 1]
v_channel = img_yuv[:, :, 2]
return y_channel, u_channel, v_channel
def histogram_yuv(self, image, range_val):
y_channel, u_channel, v_channel = self.extract_yuv(image)
y_hist, h_bins = np.histogram(y_channel, bins=range_val, range=(0, range_val))
u_hist, s_bins = np.histogram(u_channel, bins=range_val, range=(0, range_val))
v_hist, v_bins = np.histogram(v_channel, bins=range_val, range=(0, range_val))
return y_hist, u_hist, v_hist
def extract_hsl(self, image):
img_hsl = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2HLS)
# Separate the channels
h_channel = img_hsl[:, :, 0]
s_channel = img_hsl[:, :, 1]
l_channel = img_hsl[:, :, 2]
return h_channel, s_channel, l_channel
def histogram_hsl(self, image, range_val):
h_channel, s_channel, l_channel = self.extract_hsl(image)
h_hist, h_bins = np.histogram(h_channel, bins=range_val, range=(0, range_val))
s_hist, s_bins = np.histogram(s_channel, bins=range_val, range=(0, range_val))
l_hist, v_bins = np.histogram(l_channel, bins=range_val, range=(0, range_val))
return h_hist, s_hist, l_hist
def show_histogram_bins(self, ch1, ch2, ch3, label1, label2, label3, title, num_bins, ax, figure, canvas):
# Plot histograms for each channel
ax.bar(range(num_bins), ch1, color='red', alpha=0.5, label=label1)
ax.bar(range(num_bins), ch2, color='green', alpha=0.5, label=label2)
ax.bar(range(num_bins), ch3, color='blue', alpha=0.5, label=label3)
ax.set_title(title)
ax.set_xlabel('Pixel Value')
ax.set_ylabel('Frequency')
ax.grid(True)
ax.set_facecolor('#F0F0F0')
ax.legend()
figure.tight_layout()
canvas.draw()
def show_histogram_line(self, ch1, ch2, ch3, label1, label2, label3, title, num_bins, ax, figure, canvas):
# Plot histograms for each channel
ax.plot(range(num_bins), ch1, color='red', alpha=0.75, label=label1)
ax.plot(range(num_bins), ch2, color='green', alpha=0.75, label=label2)
ax.plot(range(num_bins), ch3, color='blue', alpha=0.75, label=label3)
ax.set_title(title)
ax.set_xlabel('Pixel Value')
ax.set_ylabel('Frequency')
ax.grid(True)
ax.set_facecolor('#F0F0F0')
ax.legend()
figure.tight_layout()
canvas.draw()
def display_hsv_image(self, image, ax, figure, canvas):
# Convert to HSV color space
img_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
# Convert to display format
hsv_image = Image.fromarray(img_hsv)
# Display the image on the canvas
ax.imshow(hsv_image)
ax.axis('off')
ax.set_title("HSV Color Space")
figure.tight_layout()
canvas.draw()
def display_yuv_image(self, image, ax, figure, canvas):
# Convert to YUV color space
img_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
img_yuv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2YUV)
# Convert to display format
yuv_image = Image.fromarray(img_yuv)
# Display the image on the canvas
ax.imshow(yuv_image)
ax.axis('off')
ax.set_title("YUV Color Space")
figure.tight_layout()
canvas.draw()
def display_hsl_image(self, image, ax, figure, canvas):
# Convert to RGB color space (if not already in RGB)
img_rgb = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB)
# Convert to HSL color space
img_hsl = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HLS)
# Convert to display format
hsl_image = Image.fromarray(img_hsl)
# Display the image on the canvas
ax.imshow(hsl_image)
ax.axis('off')
ax.set_title("HSL Color Space")
figure.tight_layout()
canvas.draw()
def plot_each_channel(self, ch, title, ax, cmap, figure, canvas):
# Convert to display format
ret_im = Image.fromarray(ch)
# Display the image on the canvas
ax.imshow(ret_im, cmap=cmap)
ax.axis('off')
ax.set_title(title)
figure.tight_layout()
canvas.draw()
#form_histogram.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from fundamental_utils import Fundamental_Utils
from form_channel import Form_Channel
class Form_Histogram:
def __init__(self, window):
self.window = window
width = 1520
height = 770
self.window.geometry(f"{width}x{height}")
#Adds label widgets
self.add_utilities(self.window)
#Adds canvasses
self.add_canvas(self.window)
#Creates necessary objects
self.fund_utils = Fundamental_Utils()
#Initial value
self.image = None
#Binds events
self.binds_event()
def add_labels(self, master):
# Create two labels
self.label1 = tk.Label(master, text="MAX INTENSITY")
self.label1.grid(row=1, column=0, padx=5, pady=5, sticky="w")
self.label2 = tk.Label(master, text="COLOR SPACE")
self.label2.grid(row=3, column=0, padx=5, pady=5, sticky="w")
def add_button(self, master):
#Adds button
self.btn1 = tk.Button(master, height=2, width=17, text="CHOOSE IMAGE",
command=lambda:self.show_rgb_image())
self.btn1.grid(row=0, column=0, padx=5, pady=5, sticky="w")
def add_entries(self, master):
# Create entry widgets
self.num_bins = tk.Entry(master, width=20, bg="cyan")
self.num_bins.grid(row=2, column=0, padx=5, pady=5, sticky="w")
self.num_bins.insert(0, "256")
self.num_bins.bind('<Return>', self.choose_color_space)
def add_combobox(self, root):
# Create ComboBoxes
self.combo_space = ttk.Combobox(root, width=20)
self.combo_space["values"] = ["RGB", "HSV", "YUV", "HSL"]
self.combo_space.grid(row=4, column=0, padx=5, pady=5, sticky="w")
def add_utilities(self, master):
# Create a frame for canvas1 with a border
frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
frame1.grid(row=0, column=0, padx=5, pady=10, sticky="n")
self.add_button(frame1)
self.add_labels(frame1)
self.add_entries(frame1)
self.add_combobox(frame1)
def add_canvas(self, master):
# Create a frame for canvas1 with a border
frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
frame1.grid(row=0, column=1, padx=5, pady=5, sticky="n")
# Adds canvas1 widget to frame1
self.figure1 = Figure(figsize=(3.7, 3.7), dpi=100)
self.figure1.patch.set_facecolor('#F0F0F0')
self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1)
self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True)
# Create a frame for canvas2 with a border
frame2 = ttk.Frame(master, borderwidth=3, relief="groove")
frame2.grid(row=1, column=1, padx=5, pady=5, sticky="n")
# Adds canvas2 widget to frame2
self.figure2 = Figure(figsize=(3.7, 3.7), dpi=100)
self.figure2.patch.set_facecolor('#F0F0F0')
self.canvas2 = FigureCanvasTkAgg(self.figure2, master=frame2)
self.canvas2.get_tk_widget().pack(fill=tk.BOTH, expand=True)
# Create a frame for canvas3 with a border
frame3 = ttk.Frame(master, borderwidth=3, relief="groove")
frame3.grid(row=0, column=2, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")
# Adds canvas3 widget to frame3
self.figure3 = Figure(figsize=(9.5, 7.55), dpi=100)
self.figure3.patch.set_facecolor('#F0F0F0')
self.canvas3 = FigureCanvasTkAgg(self.figure3, master=frame3)
self.canvas3.get_tk_widget().pack(fill=tk.BOTH, expand=True)
def show_rgb_image(self):
# Create figure and subplot
self.figure1.clear()
ax1 = self.figure1.add_subplot(1, 1, 1)
self.image = self.fund_utils.open_image(ax1, self.figure1, self.canvas1)
#Plot histogram of RGB channel
self.plot_rgb_histogram()
def read_and_check_input(self, bins):
try:
num_bins = int(bins)
except ValueError:
num_bins = 256
self.num_bins.delete(0, tk.END)
self.num_bins.insert(0, "256")
return num_bins
def plot_rgb_histogram(self):
#Reads param
bins = self.num_bins.get()
num_bins = self.read_and_check_input(bins)
#Extract histogram of RGB channel
r_channel, g_channel, b_channel = self.fund_utils.histogram_rgb(self.image, num_bins)
# Create figure and subplot
self.figure3.clear()
ax1 = self.figure3.add_subplot(2, 1, 1)
ax2 = self.figure3.add_subplot(2, 1, 2)
self.fund_utils.show_histogram_bins(r_channel, g_channel, b_channel,
"Red", "Green", "Blue", "Histogram of RGB Channel", num_bins,
ax1, self.figure3, self.canvas3)
self.fund_utils.show_histogram_line(r_channel, g_channel, b_channel,
"Red", "Green", "Blue", "Histogram of RGB Channel", num_bins,
ax2, self.figure3, self.canvas3)
def plot_rgb_channel(self):
win = tk.Toplevel()
form_ch = Form_Channel(win)
win.title("Each Channel of RGB Color Space")
form_ch.figure1.clear()
ax1 = form_ch.figure1.add_subplot(1, 3, 1)
ax2 = form_ch.figure1.add_subplot(1, 3, 2)
ax3 = form_ch.figure1.add_subplot(1, 3, 3)
r_channel, g_channel, b_channel = self.fund_utils.extract_rgb(self.image)
self.fund_utils.plot_each_channel(r_channel, "Red Channel", ax1, 'Reds',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(g_channel, "Green Channel", ax2, 'Greens',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(b_channel, "Blue Channel", ax3, 'Blues',
form_ch.figure1, form_ch.canvas1)
def plot_hsv_histogram(self):
#Reads param
bins = self.num_bins.get()
num_bins = self.read_and_check_input(bins)
#Extract histogram of HSV channel
h_channel, s_channel, v_channel = self.fund_utils.histogram_hsv(self.image, num_bins)
# Create figure and subplot
self.figure3.clear()
ax1 = self.figure3.add_subplot(2, 1, 1)
ax2 = self.figure3.add_subplot(2, 1, 2)
self.fund_utils.show_histogram_bins(h_channel, s_channel, v_channel,
"Hue", "Saturation", "Value", "Histogram of HSV Channel", num_bins,
ax1, self.figure3, self.canvas3)
self.fund_utils.show_histogram_line(h_channel, s_channel, v_channel,
"Hue", "Saturation", "Value", "Histogram of HSV Channel", num_bins,
ax2, self.figure3, self.canvas3)
def plot_hsv_channel(self):
win = tk.Toplevel()
form_ch = Form_Channel(win)
win.title("Each Channel of HSV Color Space")
form_ch.figure1.clear()
ax1 = form_ch.figure1.add_subplot(1, 3, 1)
ax2 = form_ch.figure1.add_subplot(1, 3, 2)
ax3 = form_ch.figure1.add_subplot(1, 3, 3)
h_channel, s_channel, v_channel = self.fund_utils.extract_hsv(self.image)
self.fund_utils.plot_each_channel(h_channel, "Hue Channel", ax1, 'Reds',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(s_channel, "Saturation Channel", ax2, 'Greens',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(v_channel, "Value Channel", ax3, 'Blues',
form_ch.figure1, form_ch.canvas1)
def plot_hsl_histogram(self):
#Reads param
bins = self.num_bins.get()
num_bins = self.read_and_check_input(bins)
#Extract histogram of HSL channel
h_channel, s_channel, l_channel = self.fund_utils.histogram_hsl(self.image, num_bins)
# Create figure and subplot
self.figure3.clear()
ax1 = self.figure3.add_subplot(2, 1, 1)
ax2 = self.figure3.add_subplot(2, 1, 2)
self.fund_utils.show_histogram_bins(h_channel, s_channel, l_channel,
"Hue", "Saturation", "Lightness", "Histogram of HSL Channel", num_bins,
ax1, self.figure3, self.canvas3)
self.fund_utils.show_histogram_line(h_channel, s_channel, l_channel,
"Hue", "Saturation", "Lightness", "Histogram of HSL Channel", num_bins,
ax2, self.figure3, self.canvas3)
def plot_hsl_channel(self):
win = tk.Toplevel()
form_ch = Form_Channel(win)
win.title("Each Channel of HSL Color Space")
form_ch.figure1.clear()
ax1 = form_ch.figure1.add_subplot(1, 3, 1)
ax2 = form_ch.figure1.add_subplot(1, 3, 2)
ax3 = form_ch.figure1.add_subplot(1, 3, 3)
h_channel, s_channel, l_channel = self.fund_utils.extract_hsl(self.image)
self.fund_utils.plot_each_channel(h_channel, "Hue Channel", ax1, 'Reds',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(s_channel, "Saturation Channel", ax2, 'Greens',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(l_channel, "Lightness Channel", ax3, 'Blues',
form_ch.figure1, form_ch.canvas1)
def plot_yuv_histogram(self):
#Reads param
bins = self.num_bins.get()
num_bins = self.read_and_check_input(bins)
#Extract histogram of YUV channel
y_channel, u_channel, v_channel = self.fund_utils.histogram_yuv(self.image, num_bins)
# Create figure and subplot
self.figure3.clear()
ax1 = self.figure3.add_subplot(2, 1, 1)
ax2 = self.figure3.add_subplot(2, 1, 2)
self.fund_utils.show_histogram_bins(y_channel, u_channel, v_channel,
"Y (Luma)", "U (Chrominance Blue)", "V (Chrominance Red)", "Histogram of YUV Channel", num_bins,
ax1, self.figure3, self.canvas3)
self.fund_utils.show_histogram_line(y_channel, u_channel, v_channel,
"Y (Luma)", "U (Chrominance Blue)", "V (Chrominance Red)", "Histogram of YUV Channel", num_bins,
ax2, self.figure3, self.canvas3)
def plot_yuv_channel(self):
win = tk.Toplevel()
form_ch = Form_Channel(win)
win.title("Each Channel of YUV Color Space")
form_ch.figure1.clear()
ax1 = form_ch.figure1.add_subplot(1, 3, 1)
ax2 = form_ch.figure1.add_subplot(1, 3, 2)
ax3 = form_ch.figure1.add_subplot(1, 3, 3)
y_channel, u_channel, v_channel = self.fund_utils.extract_yuv(self.image)
self.fund_utils.plot_each_channel(y_channel, "Y (Luma) Channel", ax1, 'Greens',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(u_channel, "U (Chrominance Blue)", ax2, 'Blues',
form_ch.figure1, form_ch.canvas1)
self.fund_utils.plot_each_channel(v_channel, "V (Chrominance Red)", ax3, 'Reds',
form_ch.figure1, form_ch.canvas1)
def choose_color_space(self, event):
#Reads color space
self.chosen_space = self.combo_space.get()
if self.chosen_space == "RGB":
self.plot_rgb_histogram()
self.plot_rgb_channel()
if self.chosen_space == "HSV":
self.figure2.clear()
ax = self.figure2.add_subplot(1, 1, 1)
self.fund_utils.display_hsv_image(self.image, ax, self.figure2, self.canvas2)
self.plot_hsv_histogram()
self.plot_hsv_channel()
if self.chosen_space == "YUV":
self.figure2.clear()
ax = self.figure2.add_subplot(1, 1, 1)
self.fund_utils.display_yuv_image(self.image, ax, self.figure2, self.canvas2)
self.plot_yuv_histogram()
self.plot_yuv_channel()
if self.chosen_space == "HSL":
self.figure2.clear()
ax = self.figure2.add_subplot(1, 1, 1)
self.fund_utils.display_hsl_image(self.image, ax, self.figure2, self.canvas2)
self.plot_hsl_histogram()
self.plot_hsl_channel()
def binds_event(self):
# Binds combo_wavelet to choose_wavelet()
self.combo_space.bind("<<ComboboxSelected>>", self.choose_color_space)
if __name__ == "__main__":
window = tk.Tk()
Form_Histogram(window)
window.mainloop()
#form_channel.py
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class Form_Channel:
def __init__(self, window):
self.window = window
width = 1500
height = 540
self.window.geometry(f"{width}x{height}")
#Adds canvas
self.add_canvas(self.window)
def add_canvas(self, master):
# Create a frame for canvas3 with a border
frame1 = ttk.Frame(master, borderwidth=3, relief="groove")
frame1.grid(row=0, column=0, columnspan=1, rowspan=25, padx=5, pady=5, sticky="n")
# Adds canvas1 widget to frame1
self.figure1 = Figure(figsize=(14.7, 5), dpi=100)
self.figure1.patch.set_facecolor('#F0F0F0')
self.canvas1 = FigureCanvasTkAgg(self.figure1, master=frame1)
self.canvas1.get_tk_widget().pack(fill=tk.BOTH, expand=True)
if __name__ == "__main__":
window = tk.Tk()
Form_Channel(window)
window.mainloop()