Add push button to GUI to be able to change image for color thresholding in image processing and save button to save images
9 次查看(过去 30 天)
显示 更早的评论
I am doing an image processing project for myself to seperate fruits from the background by using a range of the hue value and the saturation value. However, I want to add a push button to the GUI, to be able to interactively change the image and process multiple images for color thresholding. I have a main script and a function called myGUI().
At this moment, in the main script, I am reading the image, change the image dimensions, shift the color model to hsv and pass the hue value, saturation value and the resized image to the function myGUI().
In the function myGUI(), four sliders are added to find the ranges for the hue and saturation in order to get only the fruit and a push button to change the image. However, the newly uploaded image should undergo the preprocessing steps (new image dimensions, shift the color model to hsv and pass the hue value, saturation value and get the resized image, which is in the main script) and be passed to the function myGUI(). At this moment I get the following error after uploading the new image (succesfully, however without the preprocessing steps propably) and clicking on one of the slider bars:
Invalid or deleted object.
Error in myGUI>Slider (line 153)
set(h.h_im, 'CData', maskedRGBImage);
Error while evaluating UIControl Callback.
Moreover, I want to add a save button to be able to save both images as a .jpg, besides saving some important parameters.
%Main script
addpath('Measurements 15 november')
RGB_Image = imread('42.jpg');
[rows, columns, numberOfColorChannels] = size(RGB_Image);
scale = 1/2;
RGB_Image_Re = imresize(RGB_Image,scale);
HSV_B = rgb2hsv(RGB_Image_Re);
hImage = HSV_B(:, :, 1)*360;
sImage = HSV_B(:, :, 2);
vImage = HSV_B(:, :, 3);
myGUI(hImage, sImage, RGB_Image_Re);
function [] = myGUI(hImage, sImage, RGB_Image_Re)
h=struct; %Create structure to put all handles and data in
h.hImage = hImage;
h.sImage = sImage;
h.RGB_Image_Re = RGB_Image_Re;
h.f = figure(1);
set(gcf, 'Position',[450, 150, 800, 550]); %[450, 300, 800, 400])
h.ax = axes('Parent',h.f,'units','pixels','position',[120 290 290 215]);
h.h_im = imshow(h.RGB_Image_Re,'Parent',h.ax);
title(h.ax,'Initial color seperation: fruit');
h.ax2 = axes('Parent',h.f,'units','pixels','position',[450 290 290 215]);
h.h_im2 = imshow(h.RGB_Image_Re,'Parent',h.ax2);
title(h.ax2,'Initial color seperation: leaves, sky and logs');
%% Hue
%Initial values
Hue_min = 0;
Hue_max = 360;
% Slider for the lower limit of hue
h.min_Slider = uicontrol('Parent',h.f,'Style','slider', ... % Create user interface control
'Units','Pixels','Position',[221,260,419,23],...
'value', Hue_min, 'min',0, 'max',360, ...
'Callback', @Slider);
%Slider for the upper limit of hue
h.max_Slider = uicontrol('Parent',h.f,'Style','slider',... % Create user interface control
'Units','Pixels','Position',[221,195,419,23],...
'value', Hue_max, 'min',0, 'max',360,...
'Callback', @Slider);
%% Saturation
%Initial values
Sat_min = 0;
Sat_max = 1;
%Slider for the lower limit of hue
h.min_Slider2 = uicontrol('Parent',h.f,'Style','slider', ... % Create user interface control
'Units','Pixels','Position',[221,135,419,23],...
'value', Sat_min, 'min',0, 'max',1,...
'Callback', @Slider);
%Slider for the upper limit of hue
h.max_Slider2 = uicontrol('Parent',h.f,'Style','slider',... % Create user interface control
'Units','Pixels','Position',[221,75,419,23],...
'value', Sat_max, 'min',0, 'max',1,...
'Callback', @Slider);
% Label upper limit of slider
bu1 = uicontrol('Parent',h.f,'Style','text','Position',[190,75,23,23],...
'String','0');
bu2 = uicontrol('Parent',h.f,'Style','text','Position',[640,75,23,23],...
'String','1');
bu3 = uicontrol('Parent',h.f,'Style','text','Position',[275,45,200,23],...
'String','Upper limit saturation:');
PushButton = uicontrol(gcf,'Style', 'pushbutton', ...
'String', 'Upload picture', ...
'Position', [325,15,200,23], ...
'Callback', {@Pushbutton, h});
guidata(h.f,h); %Store all handles to the GUI
end
%% Callbacks
function Pushbutton(hObj,~,h)
% hObj is the button handle
[FileName, PathName] = uigetfile({'*.JPG'});
RGB_Image = imshow([PathName, FileName],'Parent',h.ax);
RGB_Image2 = imshow([PathName, FileName],'Parent',h.ax2);
end
function Slider(hObj,~)
h = guidata(hObj);
Hue_min = round(h.min_Slider.Value,3);
Hue_max = round(h.max_Slider.Value,3);
Sat_min = round(h.min_Slider2.Value,3);
Sat_max = round(h.max_Slider2.Value,3);
% Mask
mask = (h.hImage >= Hue_min) & (h.hImage <= Hue_max) & ...
(h.sImage >= Sat_min) & (h.sImage <= Sat_max);
% Create variable masked image (output) based on RGB image (input).
maskedRGBImage = h.RGB_Image_Re;
maskedRGBImage(repmat(~mask,[1 1 3])) = 0;
%Update image values
set(h.h_im, 'CData', maskedRGBImage);
Leaves = h.RGB_Image_Re.*cast(~mask, 'like', h.RGB_Image_Re);
%Update image values
set(h.h_im2, 'CData', Leaves);
end
0 个评论
回答(3 个)
Voss
2022-3-8
When the function Pushbutton is executed, the selected file is read and new images are created in each of the two axes, using imshow(), which deletes the old images in those axes. However, h.h_im still refers to the old image in h.ax, so when the Slider function is next executed, it tries to update h.h_im, which has been deleted and you get that error.
The solution is to have the program treat a newly uploaded image exactly the same as it treats the initial image that comes in as an input argument. I mean, it should go through all the same steps in each of those two situations (initializing from an image and loading in a new image). The best thing would probably be to make those steps into a function which is called from both places.
However, I'll just copy and paste some code from the main script (which does the preprocessing that you mentioned was likely missing in this case) and from the beginning of myGUI, which sets up the relevant GUI handles, and show what the pushbutton callback Pushbutton should look like:
function Pushbutton(hObj,~,h)
% hObj is the button handle
[FileName, PathName] = uigetfile({'*.JPG'});
if isequal(FileName,0)
return
end
RGB_Image = imread([PathName, FileName]);
% [rows, columns, numberOfColorChannels] = size(RGB_Image);
scale = 1/2;
RGB_Image_Re = imresize(RGB_Image,scale);
HSV_B = rgb2hsv(RGB_Image_Re);
hImage = HSV_B(:, :, 1)*360;
sImage = HSV_B(:, :, 2);
% vImage = HSV_B(:, :, 3);
h.hImage = hImage;
h.sImage = sImage;
h.RGB_Image_Re = RGB_Image_Re;
h.h_im = imshow(h.RGB_Image_Re,'Parent',h.ax);
h.h_im2 = imshow(h.RGB_Image_Re,'Parent',h.ax2);
guidata(h.f,h);
end
yanqi liu
2022-3-8
clc; clear all; close all;
%Main script
% addpath('Measurements 15 november')
RGB_Image = imread('football.jpg');
[rows, columns, numberOfColorChannels] = size(RGB_Image);
scale = 1/2;
RGB_Image_Re = imresize(RGB_Image,scale);
HSV_B = rgb2hsv(RGB_Image_Re);
hImage = HSV_B(:, :, 1)*360;
sImage = HSV_B(:, :, 2);
vImage = HSV_B(:, :, 3);
myGUI(hImage, sImage, RGB_Image_Re);
function [] = myGUI(hImage, sImage, RGB_Image_Re)
h=struct; %Create structure to put all handles and data in
h.hImage = hImage;
h.sImage = sImage;
h.RGB_Image_Re = RGB_Image_Re;
h.f = figure(1);
set(gcf, 'Position',[450, 150, 800, 550]); %[450, 300, 800, 400])
h.ax = axes('Parent',h.f,'units','pixels','position',[120 290 290 215]);
h.h_im = imshow(h.RGB_Image_Re,'Parent',h.ax);
title(h.ax,'Initial color seperation: fruit');
h.ax2 = axes('Parent',h.f,'units','pixels','position',[450 290 290 215]);
h.h_im2 = imshow(h.RGB_Image_Re,'Parent',h.ax2);
title(h.ax2,'Initial color seperation: leaves, sky and logs');
%% Hue
%Initial values
Hue_min = 0;
Hue_max = 360;
% Slider for the lower limit of hue
h.min_Slider = uicontrol('Parent',h.f,'Style','slider', ... % Create user interface control
'Units','Pixels','Position',[221,260,419,23],...
'value', Hue_min, 'min',0, 'max',360, ...
'Callback', @Slider);
%Slider for the upper limit of hue
h.max_Slider = uicontrol('Parent',h.f,'Style','slider',... % Create user interface control
'Units','Pixels','Position',[221,195,419,23],...
'value', Hue_max, 'min',0, 'max',360,...
'Callback', @Slider);
%% Saturation
%Initial values
Sat_min = 0;
Sat_max = 1;
%Slider for the lower limit of hue
h.min_Slider2 = uicontrol('Parent',h.f,'Style','slider', ... % Create user interface control
'Units','Pixels','Position',[221,135,419,23],...
'value', Sat_min, 'min',0, 'max',1,...
'Callback', @Slider);
%Slider for the upper limit of hue
h.max_Slider2 = uicontrol('Parent',h.f,'Style','slider',... % Create user interface control
'Units','Pixels','Position',[221,75,419,23],...
'value', Sat_max, 'min',0, 'max',1,...
'Callback', @Slider);
% Label upper limit of slider
bu1 = uicontrol('Parent',h.f,'Style','text','Position',[190,75,23,23],...
'String','0');
bu2 = uicontrol('Parent',h.f,'Style','text','Position',[640,75,23,23],...
'String','1');
bu3 = uicontrol('Parent',h.f,'Style','text','Position',[275,45,200,23],...
'String','Upper limit saturation:');
PushButton = uicontrol(gcf,'Style', 'pushbutton', ...
'String', 'Upload picture', ...
'Position', [325,15,200,23], ...
'Callback', {@Pushbutton, h});
guidata(h.f,h); %Store all handles to the GUI
end
%% Callbacks
function Pushbutton(hObj,~,h)
% hObj is the button handle
[FileName, PathName] = uigetfile({'*.JPG'});
% RGB_Image = imshow([PathName, FileName],'Parent',h.ax);
% RGB_Image2 = imshow([PathName, FileName],'Parent',h.ax2);
RGB_Image = imread([PathName, FileName]);
scale = 1/2;
RGB_Image_Re = imresize(RGB_Image,scale);
HSV_B = rgb2hsv(RGB_Image_Re);
hImage = HSV_B(:, :, 1)*360;
sImage = HSV_B(:, :, 2);
vImage = HSV_B(:, :, 3);
h.hImage = hImage;
h.sImage = sImage;
h.RGB_Image_Re = RGB_Image_Re;
h.h_im = imshow(h.RGB_Image_Re,'Parent',h.ax);
title(h.ax,'Initial color seperation:image');
h.h_im2 = imshow(h.RGB_Image_Re,'Parent',h.ax2);
title(h.ax2,'Initial color seperation: leaves, sky and logs');
guidata(h.f,h);
end
function Slider(hObj,~)
h = guidata(hObj);
Hue_min = round(h.min_Slider.Value,3);
Hue_max = round(h.max_Slider.Value,3);
Sat_min = round(h.min_Slider2.Value,3);
Sat_max = round(h.max_Slider2.Value,3);
% Mask
mask = (h.hImage >= Hue_min) & (h.hImage <= Hue_max) & ...
(h.sImage >= Sat_min) & (h.sImage <= Sat_max);
% Create variable masked image (output) based on RGB image (input).
maskedRGBImage = h.RGB_Image_Re;
maskedRGBImage(repmat(~mask,[1 1 3])) = 0;
%Update image values
set(h.h_im, 'CData', maskedRGBImage);
Leaves = h.RGB_Image_Re.*cast(~mask, 'like', h.RGB_Image_Re);
%Update image values
set(h.h_im2, 'CData', Leaves);
end
6 个评论
yanqi liu
2022-3-10
just modify
rect = [size(f,2)*0.1 size(f,1)*0.05 size(f,2)*0.8 size(f,1)*0.5];
to get target image rect
DGM
2022-3-24
Try the attached. I kind of made a mess, but I slapped a save button in there that'll just save the four parameters and two images to a .mat file.
I changed the import process to use a common import function. The GUI is now called with no arguments. That way the workflow and code is consistent regardless of whether it's the first task or subsequent tasks loaded from the "upload" button in the GUI.
0 个评论
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!