diff --git a/README.md b/README.md index 18ea989..d97b6a8 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # OpenCV-GUI -A graphical interface for the OpenCV functions and more. This let you create interactively a pipeline of transformation for the seleted image. +A graphical interface for the OpenCV functions and more. This let you create an interactive pipeline of transformation for the selected image. -**The pipeline of transformation can be exported to python code by just pressing a button !!** +**You can export the pipeline to python code or download the images by just pressing a button !!** # Getting started -Just download the latest release and execute the *.exe* file. Make sure that the *commands.txt* file is in the same directory as the *.exe* file (You can create a shortcut by right clicking). +Just download the latest release and execute the *.exe* file. Make sure that the *commands.txt* file is in the same directory as the *.exe* file. ### Create the environment : ``` @@ -17,7 +17,7 @@ conda env create -f environment/environment.yml ![GUI Explained](assets/gui_explained.jpg) # A detail -If you want to use some functions that only apply to 1 channel image like Canny, Threshold, Gradient, Morph... You need to transform a RGB image to a 1 channel image using "COLOR - Colorspace (grayscale)" or "COLOR - Channel". +If you want to use some functions that only apply to 1 channel image like Canny, Threshold, Gradient, Morph... You need to transform your RGB image to a 1 channel image using "COLOR - Colorspace (grayscale)" or "COLOR - Channel". # Want to help the project ? You can clone or fork the repo as you wish. The pulls request still need the approval of the admin for security. @@ -28,7 +28,7 @@ Don't hesitate to ask in the github page of this project. # Command file The command file located in the same directory as the *.exe* file contains all the functions that transform the image. -This file is made to be modified by the user if needed. For now the code still need to be modified by hand for each new transformation that the user add. The user can still modify the current transforamtions. There is a particular structure that needs to be followed. +This file is made to be modified by the user if needed. There is a particular structure that needs to be followed. This file contains a series of nested python dictionnary that provide information about how the image is transformed, with which parameters and at what condition. Because of the nature of Python dictionnaries, each name must be differents from another in the same level of dictionnaries @@ -76,3 +76,51 @@ Here is the structure : # Other transformations ... } ``` + +And here is an example : + +```python +{ + 'THRESH - Simple': { + 'command': 'cv.threshold(image, thresh_value, max_value, thresh_type)', + 'number_parameters' : 4, # 4 parameters : 1 image, 2 sliders, 1 menu + 'condition': 'len(image.shape)==2', # Image in 1 dimension + 'gui':{ + 'slider':{ + 'number_slider': 2, + 'slider0': { + 'name': 'Thresh Value', # visual name + 'variable_name': 'thresh_value', # name used in 'command' + 'min_value': '0', + 'max_value': '255', + 'step':'1', + 'default_value': '128' + }, + 'slider1': { + 'name': 'Max Value', + 'variable_name': 'max_value', + 'min_value': '0', + 'max_value': '255', + 'step':'1', + 'default_value': '255' + } + }, + 'menu':{ + 'number_menu': 1, + 'menu0': { + 'name': 'Threshold Type', + 'variable_name': 'thresh_type', + 'menu_item':{ + 'Binary' : cv.THRESH_BINARY, + 'Binary Inverted': cv.THRESH_BINARY_INV, + 'Truncate': cv.THRESH_TRUNC, + 'To Zero': cv.THRESH_TOZERO, + 'To Zero Inverted': cv.THRESH_TOZERO_INV, + 'Otsu': cv.THRESH_OTSU + } + } + } + } + }, ...# Other transformations ... +} +``` \ No newline at end of file diff --git a/src/main.py b/src/main.py index 6282e08..0fd35e5 100644 --- a/src/main.py +++ b/src/main.py @@ -5,6 +5,7 @@ from cv2 import cvtColor, imdecode, imencode, COLOR_BGR2RGB, IMREAD_UNCHANGED from numpy import fromfile, uint8 from sys import argv, exit +from functools import partial from transformermanager import TransformerManager from transformer import Transformer @@ -427,7 +428,7 @@ def update_transformation_buttons(self): image = self.pipeline[self.index_current_img].img_array # used for eval(condition) if eval(condition_str): button = QPushButton(transformation) - button.clicked.connect(self.transformer_manager.list_function_transformation[index]) + button.clicked.connect(partial(self.transformer_manager.transformation_saver,transformation)) # send "transformation" to the function "transformation_saver" self.container_transformation_buttons_layout.addWidget(button) def update_transformation_parameters_frame(self): diff --git a/src/pipeline.py b/src/pipeline.py index c570a38..143c89e 100644 --- a/src/pipeline.py +++ b/src/pipeline.py @@ -21,7 +21,7 @@ def execute_transformation(self, index): try: item_current.img_array = self.transformer.transform(item_before, item_current) except: - self.function_to_call_error("An error occured in the transformation pipeline ("+ str(index-2)+ "->"+ str(index-1) +"). Action cancelled.") + self.function_to_call_error("An error occured in the transformation pipeline ("+ str(index-1)+ "->"+ str(index) +"). Action cancelled.") raise Exception("Error in the pipeline."+ str(index-2)+ "->"+ str(index-1)) def update_from_index(self, index=1): diff --git a/src/transformermanager.py b/src/transformermanager.py index a2fa1a0..fdfa0d3 100644 --- a/src/transformermanager.py +++ b/src/transformermanager.py @@ -8,32 +8,6 @@ def __init__(self, main_window, pipeline, transformer): self.main_window = main_window self.pipeline = pipeline self.transformer = transformer - self.list_function_transformation = [ # Used from main.py to connect to the transformation button to the right function below - self.alert_draw_line, - self.alert_draw_rectangle, - self.alert_draw_circle, - self.alert_draw_ellipse, - self.alert_crop, - self.alert_rotation_zoom, - self.alert_select_channel, - self.alert_colorspacechange, - self.alert_simple_blur, - self.alert_gaussian_blur, - self.alert_median_blur, - self.alert_bilateral_filtering, - self.alert_luminosity_contrast, - self.alert_gaussian_noise, - self.alert_salt_pepper_noise, - self.alert_poisson_noise, - self.alert_speckle_noise, - self.alert_filter2d, - self.alert_threshold1d, - self.alert_adaptive_threshold1d, - self.alert_gradient_laplacian, - self.alert_gradient_sobel, - self.alert_gradient_canny, - self.alert_morph - ] def transformation_saver(self, key_command): """Modify the transformation in pipeline""" @@ -85,102 +59,4 @@ def get_default_transformation_parameters(self, key_command): default_value = list(current_slider['menu_item'].values())[0] dict_default_values[var_name] = default_value - return dict_default_values - -# All these functions takes the main name of the commands file and send it to the 'transformation_saver' method - - def alert_draw_line(self): - key_command = list(self.main_window.transformer.commands.keys())[0] - self.transformation_saver(key_command) - - def alert_draw_rectangle(self): - key_command = list(self.main_window.transformer.commands.keys())[1] - self.transformation_saver(key_command) - - def alert_draw_circle(self): - key_command = list(self.main_window.transformer.commands.keys())[2] - self.transformation_saver(key_command) - - def alert_draw_ellipse(self): - key_command = list(self.main_window.transformer.commands.keys())[3] - self.transformation_saver(key_command) - - def alert_crop(self): - key_command = list(self.main_window.transformer.commands.keys())[4] - self.transformation_saver(key_command) - - def alert_rotation_zoom(self): - key_command = list(self.main_window.transformer.commands.keys())[5] - self.transformation_saver(key_command) - - def alert_select_channel(self): - key_command = list(self.main_window.transformer.commands.keys())[6] - self.transformation_saver(key_command) - - def alert_colorspacechange(self): - key_command = list(self.main_window.transformer.commands.keys())[7] - self.transformation_saver(key_command) - - def alert_simple_blur(self): - key_command = list(self.main_window.transformer.commands.keys())[8] - self.transformation_saver(key_command) - - def alert_gaussian_blur(self): - key_command = list(self.main_window.transformer.commands.keys())[9] - self.transformation_saver(key_command) - - def alert_median_blur(self): - key_command = list(self.main_window.transformer.commands.keys())[10] - self.transformation_saver(key_command) - - def alert_bilateral_filtering(self): - key_command = list(self.main_window.transformer.commands.keys())[11] - self.transformation_saver(key_command) - - def alert_luminosity_contrast(self): - key_command = list(self.main_window.transformer.commands.keys())[12] - self.transformation_saver(key_command) - - def alert_gaussian_noise(self): - key_command = list(self.main_window.transformer.commands.keys())[13] - self.transformation_saver(key_command) - - def alert_salt_pepper_noise(self): - key_command = list(self.main_window.transformer.commands.keys())[14] - self.transformation_saver(key_command) - - def alert_poisson_noise(self): - key_command = list(self.main_window.transformer.commands.keys())[15] - self.transformation_saver(key_command) - - def alert_speckle_noise(self): - key_command = list(self.main_window.transformer.commands.keys())[16] - self.transformation_saver(key_command) - - def alert_filter2d(self): - key_command = list(self.main_window.transformer.commands.keys())[17] - self.transformation_saver(key_command) - - def alert_threshold1d(self): - key_command = list(self.main_window.transformer.commands.keys())[18] - self.transformation_saver(key_command) - - def alert_adaptive_threshold1d(self): - key_command = list(self.main_window.transformer.commands.keys())[19] - self.transformation_saver(key_command) - - def alert_gradient_laplacian(self): - key_command = list(self.main_window.transformer.commands.keys())[20] - self.transformation_saver(key_command) - - def alert_gradient_sobel(self): - key_command = list(self.main_window.transformer.commands.keys())[21] - self.transformation_saver(key_command) - - def alert_gradient_canny(self): - key_command = list(self.main_window.transformer.commands.keys())[22] - self.transformation_saver(key_command) - - def alert_morph(self): - key_command = list(self.main_window.transformer.commands.keys())[23] - self.transformation_saver(key_command) + return dict_default_values \ No newline at end of file