function varargout = myLabel(varargin)
% myLabel - image sequencies labeling tool
% developed by Nick Chumerin in the framework of EU MCCOOP project
% myLabel.support@gmail.com
% version 0.04
% 2008-01-09
% TODO:
% - flexible label description
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @myLabel_OpeningFcn, ...
'gui_OutputFcn', @myLabel_OutputFcn, ...
'gui_LayoutFcn', [], ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
gui_mainfcn(gui_State, varargin{:});
% if nargout
% [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
% else
% gui_mainfcn(gui_State, varargin{:});
% end
%% --------------------------------------------------------------------
function [filenames, pathname] = uigetfiles(directory)
% based on uigetfiles by shanrong.zhang@utsouthwestern.edu
if ~nargin || isempty(directory),
directory = pwd;
end
filechooser = javax.swing.JFileChooser(directory);
filechooser.setMultiSelectionEnabled(true);
filechooser.setFileSelectionMode(filechooser.FILES_ONLY);
selectionStatus = filechooser.showOpenDialog(com.mathworks.mwswing.MJFrame);
if selectionStatus == filechooser.APPROVE_OPTION
pathname = [char(filechooser.getCurrentDirectory.getPath), ...
java.io.File.separatorChar];
selectedfiles = filechooser.getSelectedFiles;
for k = 1:size(selectedfiles)
filenames{k} = char(selectedfiles(k).getName);
end
else
pathname = pwd;
filenames = {};
end
%% --------------------------------------------------------------------
function Init_Picture
global picture
picture.list = {};
picture.dir = {};
picture.list_length = 0;
picture.current = 0;
picture.previous = 0;
picture.data = [];
picture.output_dir = getpref('myLabel', 'default_output_dir'); %fullfile(pwd, 'output');
picture.rows = 0;
picture.cols = 0;
%% --------------------------------------------------------------------
function Set_Labels_Default_Values
global labels
labels.changed = 0;
labels.max_number = 10;
labels.std_colors = ...
[1, 0 , 0; ... % red for label1
0, 1 , 0; ... % green for label2
0, 0 , 1; ... % blue for label3
1, 1 , 0; ... % yellow for label4
0, 1 , 1; ... % ??? for label5
1, 0 , 1; ... % ??? for label6
1, 1 , 1; ... % white for label7
.5, 0 , 1; ... % ??? for label8
0, .5 , 1; ... % ??? for label9
.5, 1, 0]; % ??? for label10
labels.colors = labels.std_colors;
labels.visible = zeros(labels.max_number, 1);
if length(labels.values)<labels.max_number,
labels.values(end:labels.max_number) = uiny16(1);
end
if length(labels.std_values)<labels.max_number
labels.std_values = uint16([1 2 3 4 21 22 61 62 131 132]);
end
%% --------------------------------------------------------------------
function Init_Labels
global labels
labels.dir = getpref('myLabel', 'default_labels_dir'); %fullfile(pwd, 'labels');
labels.filename = [];
labels.short_filename = [];
labels.filename_ext = [];
labels.number = 1;
labels.active = 1;
labels.data = uint16([]);
labels.layer = [];
labels.std_values = uint16([1 2 3 4 21 22 61 62 131 132]);
labels.values = labels.std_values;
Set_Labels_Default_Values
labels.colormap = zeros(256, 3);
labels.alpha = .4;
labels.alphaData = 0;
labels.operation = 1; % 1 - set, 2 - inverse, 3 - clear
%% --------------------------------------------------------------------
function Init_Interpolation
global interpolation
interpolation.first.mask = [];
interpolation.first.frame_n = 0;
interpolation.last.mask = [];
interpolation.last.frame_n = 0;
interpolation.label = 0;
%% --------------------------------------------------------------------
function Init_Cursor
global cursor
cursor.x = 0;
cursor.y = 0;
cursor.prev_x = 0;
cursor.prev_y = 0;
cursor.mb_pressed = 0;
cursor.size = 2;
cursor.max_size = 32;
%% --------------------------------------------------------------------
function Init_Undo
global undo
undo = [];
%% --------------------------------------------------------------------
function Init_Clipboard
global clipboard
clipboard = [];
%% --------------------------------------------------------------------
function Init_Zoom
global zoom
zoom.picture = [];
zoom.labels = [];
zoom.active = 0;
%% --------------------------------------------------------------------
function Init_Myhandles(handles);
global myhandles labels
myhandles.picture = imshow(0);
hold on
myhandles.labels = imshow(0);
myhandles.brush = rectangle('Position', [0 0 1 1], 'Visible', 'off');
hold off
set(myhandles.picture, 'Visible', 'off');
set(myhandles.labels, 'Visible', 'off');
myhandles.Image_Axes = handles.Image_Axes;
myhandles.hLA = eval(['[' sprintf('handles.Label%g_Active ', 1:labels.max_number) ']']);
myhandles.hLV = eval(['[' sprintf('handles.Label%g_Visible ', 1:labels.max_number) ']']);
%% --------------------------------------------------------------------
function myLabel_OpeningFcn(hObject, eventdata, handles, varargin)
global picture labels cursor undo zoom clipboard myhandles interpolation info
info.version = 0;
info.subversion = 4;
info.release_date = '2008-01-09';
if ~ispref('myLabel'),
addpref('myLabel', {'version', 'subversion', 'release_date'}, {0, 0, ''});
addpref('myLabel', {'default_labels_dir', 'default_pix_dir', 'default_output_dir', 'default_states_dir'}, {'', '', '', ''});
end
setpref('myLabel', {'version', 'subversion', 'release_date'}, {info.version, info.subversion, info.release_date});
if ~ispref('myLabel', 'default_labels_dir') || isempty(getpref('myLabel', 'default_labels_dir')),
if isunix,
setpref('myLabel', 'default_labels_dir', '/huge_sidonia/nick/sequences');
else
setpref('myLabel', 'default_labels_dir', './labels');
end
end
if ~ispref('myLabel', 'default_pix_dir') || isempty(getpref('myLabel', 'default_pix_dir')),
if isunix,
setpref('myLabel', 'default_pix_dir', '/huge_sidonia/nick/sequences');
else
setpref('myLabel', 'default_pix_dir', '.');
end
end
if ~ispref('myLabel', 'default_output_dir') || isempty(getpref('myLabel', 'default_output_dir')),
setpref('myLabel', 'default_output_dir', './output');
end
if ~ispref('myLabel', 'default_states_dir') || isempty(getpref('myLabel', 'default_states_dir')),
setpref('myLabel', 'default_states_dir', './states');
end
Init_Picture
Init_Labels
Init_Cursor
Init_Clipboard
Init_Undo
Init_Zoom
Init_Myhandles(handles)
Init_Interpolation
if exist('autosave.mat', 'file'),
load('autosave.mat', 'picture', 'labels', 'undo', 'zoom', 'clipboard');
Set_Labels_Default_Values
Init_Myhandles(handles)
set(handles.Transparency_Slider, 'Enable', 'on', 'Value', labels.alpha);
Update_Images_List(handles)
Update_Labels_List(handles)
end
set(handles.myLabel, 'WindowButtonUpFcn', 'Button_Released');
% set(handles.myLabel, 'KeyPressFcn', 'myLabel(''KeyPressFcn'', gcbo, [], guidata(gcbo))');
set(handles.Labels_Directory_Text, 'String', labels.dir);
set(handles.Output_Dir_Text, 'String', picture.output_dir);
set(handles.Cursor_Size_Text, 'Enable', 'off', 'String', num2str(cursor.size));
set(handles.Cursor_Size_Slider, 'Min', 0);
set(handles.Cursor_Size_Slider, 'Max', cursor.max_size);
set(handles.Cursor_Size_Slider, 'Enable', 'off', 'Value', cursor.size);
set(handles.Transparency_Edit, 'String', num2str(labels.alpha));
fprintf('myLabel %g.%02g (%s)\n', info.version, info.subversion, info.release_date);
% % set(hObject, 'NumberTitle', 'off', 'Name', sprintf('myLabel %g.%02g %s\n', version, subversion, release_date));
handles.output = hObject;
guidata(hObject, handles);
Update_Window(handles)
%% --------------------------------------------------------------------
function varargout = myLabel_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
%% --------------------------------------------------------------------
function CloseMenuItem_Callback(hObject, eventdata, handles)
selection = questdlg('Close myLabel?', 'Close myLabel...', 'Yes', 'No', 'Yes');
if strcmp(selection, 'No')
return;
end
delete(handles.myLabel)
%% --------------------------------------------------------------------
function Images_List_Callback(hObject, eventdata, handles)
global picture labels
% stat('Images_List_Callback started')
if get(handles.Images_List, 'Value')~=picture.current,
Update_Window(handles);
else
Update_Labels_Transparency;
Update_Labels_Layer;
end
% stat('Images_List_Callback finished')
%% --------------------------------------------------------------------
function Update_Images_List(handles)
global picture
% stat('Update_Images_List started')
picture.list_length = length(picture.list);
if picture.current>picture.list_length,
picture.current = 1;
end
if picture.current,
set(handles.Images_List, 'Value', picture.current);
else
set(handles.Images_List, 'Value', 1);
end
set(handles.Images_List, 'String', picture.list);
if picture.list_length
set(handles.Images_List, 'Enable', 'on');
set(handles.Clear_Images_List, 'Enable', 'on');
set(handles.Del_Image_From_List, 'Enable', 'on');
set(handles.Save_State, 'Enable', 'on');
set(handles.Save_For_Training, 'Enable', 'on');
set(handles.Copy, 'Enable', 'on');
set(handles.Next_Image, 'Enable', 'on');
set(handles.Previous_Image, 'Enable', 'on');
set(handles.First_Image, 'Enable', 'on');
set(handles.Last_Image, 'Enable', 'on');
set(handles.Ten_Images_Back, 'Enable', 'on');
set(handles.Ten_Images_Forward, 'Enable', 'on');
else
set(handles.Images_List, 'Enable', 'off');
set(handles.Clear_Images_List, 'Enable', 'off');
set(handles.Del_Image_From_List, 'Enable', 'off');
set(handles.Save_State, 'Enable', 'off');
set(handles.Save_For_Training, 'Enable', 'off');
set(handles.Copy, 'Enable', 'off');
set(handles.Next_Image, 'Enable', 'off');
set(handles.Previous_Image, 'Enable', 'off');
set(handles.First_Image, 'Enable', 'off');
set(handles.Last_Image, 'Enable', 'off');
set(handles.Ten_Images_Back, 'Enable', 'off');
set(handles.Ten_Images_Forward, 'Enable', 'off');
end
% stat('Update_Images_List finished')
%% --------------------------------------------------------------------
function Change_Labels_Dir_Callback(hObject, eventdata, handles)
global labels
% stat('Change_Labels_Dir_Callback started')
labels.dir = uigetdir(getpref('myLabel', 'default_labels_dir'), 'Pick a new labels directory');
if ~ischar(labels.dir),
labels.dir = fullfile(pwd, 'labels');
end
set(handles.Labels_Directory_Text, 'String', labels.dir);
% stat('Change_Labels_Dir_Callback finished')
%% --------------------------------------------------------------------
function Change_Output_Dir_Callback(hObject, eventdata, handles)
global picture
% stat('Change_Images_Dir_Callback started')
picture.output_dir = uigetdir(getpref('myLabel', 'default_output_dir'), 'Pick a new output directory');
if ~ischar(picture.output_dir),
picture.output_dir = fullfile(pwd, 'output');
end
set(handles.Output_Dir_Text, 'String', picture.output_dir);
% stat('Change_Images_Dir_Callback finished')
%% --------------------------------------------------------------------
function Update_Window(handles)
global picture myhandles labels
% stat('Update_Window started')
Load_Image_and_Labels(handles)
Parse_Labels(handles);
Update_Labels_List(handles);
Update_Labels_Transparency;
if picture.current,
myhandles.picture = imshow(picture.data); % Show_Image;
set(myhandles.picture, 'CDataMapping', 'direct')
Create_Labels_Layer(handles);
Update_Labels_Layer;
end
picture.previous = picture.current;
if labels.changed,
Autosave
end
% stat('Update_Window finished')
%% --------------------------------------------------------------------
function Load_Image_and_Labels(handles)
%% Load picture data and (if possible) Labels data
global labels picture undo myhandles info
% stat('Load_Image_and_Labels started')
set(handles.Cursor_Size_Text, 'Enable', 'off');
set(handles.Cursor_Size_Slider, 'Enable', 'off');
% im_list = get(handles.Images_List, 'String');
im_list = picture.list;
im_index = get(handles.Images_List, 'Value');
if ~isempty(picture.list) && im_index, % if pix list isn't empty and current pix is selected
if isa(picture.list, 'cell'),
picture.filename = fullfile(picture.dir{im_index}, picture.list{im_index});
else
picture.filename = im_list;
end
set(handles.myLabel, 'Name', sprintf('myLabel %g.%02g - %s', info.version, info.subversion, picture.filename));
[picture.dir{im_index}, picture.short_filename, picture.filename_ext] = ...
fileparts(picture.filename);
if (picture.list_length) & (picture.current~= im_index),
picture.current = im_index;
picture.data = imread(picture.filename);
picture.rows = size(picture.data, 1);
picture.cols = size(picture.data, 2);
Save_Current_Labels(handles);
set(handles.Cropped_Checkbox, 'Enable', 'on');
set(handles.Masked_Checkbox, 'Enable', 'on');
Masked_or_Cropped_Checkbox_Callback(handles.Masked_Checkbox, [], handles)
% trying to read corresponding labels file
labels.filename = fullfile(labels.dir, [picture.short_filename '_labels.mat']);
if exist(labels.filename, 'file'),
data = load(labels.filename);
labels.data = uint16(data.l);
% stat('Labels data loaded.');
set(handles.Transparency_Slider, 'Enable', 'on', 'Value', labels.alpha);
if get(handles.Autoresize_Checkbox, 'Value') && ...
(size(labels.data, 1)~=picture.rows || ...
size(labels.data, 2)~=picture.cols),
stat('Resizing labels')
labels.data = uint16(imresize(labels.data, [picture.rows picture.cols]));
labels.changed = 1;
end
else
labels.data = zeros(picture.rows, picture.cols, 'uint16');
set(handles.Transparency_Slider, 'Enable', 'off');
end
labels.colors = labels.std_colors;
end
set(handles.Labels_Directory_Text, 'String', labels.dir);
else % there is no picture
if ishandle(myhandles.picture)
delete(myhandles.picture)
end
picture.data = 0;
picture.rows = size(picture.data, 1);
picture.cols = size(picture.data, 2);
labels.data = 0;
labels.alphaData= 0;
set(handles.Transparency_Slider, 'Enable', 'off');
set(handles.Cropped_Checkbox, 'Enable', 'off');
set(handles.Masked_Checkbox, 'Enable', 'off');
set(handles.Autorewrite_Checkbox, 'Enable', 'off');
set(handles.Autoresize_Checkbox, 'Enable', 'off');
Masked_or_Cropped_Checkbox_Callback(handles.Masked_Checkbox, [], handles)
end
labels.alphaData= zeros(picture.rows, picture.cols);
% stat('Load_Image_and_Labels finished')
%% --------------------------------------------------------------------
function Save_Current_Labels(handles)
global labels
if ~isempty(labels.filename) && labels.changed,
stat(['Labels were changed, saving in ' labels.filename]);
l = labels.data;
save_it = 1;
if ~get(handles.Autorewrite_Checkbox, 'Value') && exist(labels.filename),
save_it = strcmp(questdlg(['Overwrite ' labels.filename '?']), 'Yes');
end
if save_it,
if ~exist(labels.dir, 'dir'), mkdir(labels.dir); end
save(labels.filename, 'l');
% stat('Labels data saved.');
labels.changed = 0;
undo = [];
set(handles.Undo, 'Enable', 'off');
set(handles.Undo, 'Enable', 'off');
end
end
%% --------------------------------------------------------------------
function Create_Labels_Layer(handles)
%% Creat Labels Layer for current picture (not yet show it)
global labels picture cursor myhandles
% stat('Create_Labels_Layer started')
% preparing labels layer
labels.layer = zeros(picture.cols, picture.rows, 3);
if ishandle(myhandles.labels),
delete(myhandles.labels);
end
if ishandle(myhandles.brush),
delete(myhandles.brush);
end
hold on
myhandles.labels = imshow(labels.layer);
% set(myhandles.labels, 'alphaData', labels.alpha*(labels.data==0));
myhandles.brush = rectangle('Position', [cursor.x-.5 cursor.y-.5 2*cursor.size+1 2*cursor.size+1]);
hold off
if labels.operation==3,
set(myhandles.brush, 'Visible', 'off')
end
set(myhandles.labels, 'ButtonDownFcn', 'myLabel(''Labels_ButtonDown'', gcbo, [], guidata(gcbo))')
set(handles.myLabel, 'WindowButtonMotionFcn', 'Mouse_Moved');
set(handles.Cursor_Size_Text, 'Enable', 'on');
set(handles.Cursor_Size_Slider, 'Enable', 'on');
set(handles.Copy, 'Enable', 'on')
set(handles.Copy, 'Enable', 'on')
set(handles.Autorewrite_Checkbox, 'Enable', 'on');
set(handles.Autoresize_Checkbox, 'Enable', 'on');
% stat('Create_Labels_Layer finished')
%% --------------------------------------------------------------------
function Update_Labels_Transparency
%% Prepare labels layer transparency
global labels
% stat('Update_Labels_Transparency started')
for i = 1:labels.number,
labels.colormap(labels.values(i)+1, :) = labels.colors(i, :);
% labels.colormap(labels.values(i)+1, :) = labels.colors(i, :) * labels.visible(i);
labels.alphaData(labels.data == labels.values(i)) = labels.visible(i);
end
labels.alphaData = labels.alpha * labels.alphaData;
% stat('Update_Labels_Transparency finished')
%% Parsing labels data ------------------------------------------------
function Parse_Labels(handles)
global labels
% stat('Parse_Labels started')
labels.colors = labels.std_colors;
% ul = unique(labels.data);
% ul = ul(find(ul~=0));
% ul = unique_labels(labels.data);
ul = unique_labels(uint16(labels.data));
n_ul= length(ul);
if n_ul>labels.max_number,
% error('Too many labels! Sorry...');
n_ul = labels.max_number;
end
i = 1;
while (i<=labels.number) && (n_ul<labels.max_number),
% ul = unique([ul; labels.values(i)]);
% ul = unique_labels([ul; labels.values(i)]);
ul = unique_labels(uint16([ul; labels.values(i)]));
n_ul= length(ul);
i = i + 1;
end
labels.number = n_ul;
labels.values(1:n_ul) = ul;
% stat('Parse_Labels finished')
%% Update labels list ------------------------------------------------
function Update_Shifts_and_Saves(handles)
global labels
if any(labels.visible),
set(handles.Shift_Left, 'Enable', 'On');
set(handles.Shift_Right, 'Enable', 'On');
set(handles.Shift_Up, 'Enable', 'On');
set(handles.Shift_Down, 'Enable', 'On');
set(handles.Save_For_Training, 'Enable', 'on');
set(handles.Save_Set, 'Enable', 'on');
set(handles.Percentage_Edit, 'Enable', 'on');
set(handles.Set_Size_Edit, 'Enable', 'on');
else
set(handles.Shift_Left, 'Enable', 'Off');
set(handles.Shift_Right, 'Enable', 'Off');
set(handles.Shift_Up, 'Enable', 'Off');
set(handles.Shift_Down, 'Enable', 'Off');
set(handles.Save_For_Training, 'Enable', 'off');
set(handles.Save_Set, 'Enable', 'off');
set(handles.Percentage_Edit, 'Enable', 'off');
set(handles.Set_Size_Edit, 'Enable', 'off');
end
%% Update labels list ------------------------------------------------
function Update_Labels_List(handles)
global labels picture myhandles
Update_Shifts_and_Saves(handles)
% stat('Update_Labels_List started')
if picture.list_length,
set(handles.Add_New_Label, 'Enable', 'On');
set(handles.Edit_Active_Label, 'Enable', 'On');
else
set(handles.Add_New_Label, 'Enable', 'Off');
set(handles.Edit_Active_Label, 'Enable', 'Off');
end
if labels.number>1,
set(handles.Del_Active_Label, 'Enable', 'On');
else
set(handles.Del_Active_Label, 'Enable', 'Off');
end
for i = 1:labels.max_number,
if i<=labels.number,
set(myhandles.hLA(i), ...
'Enable', 'On', 'Value', 0, ...
'BackgroundColor', labels.colors(i, :), ...
'String', num2str(labels.values(i)));
set(myhandles.hLV(i), ...
'Enable', 'On', ...
'BackgroundColor', labels.colors(i, :), ...
'Value', labels.visible(i));
else
set(myhandles.hLA(i), ...
'Enable', 'Off', 'Value', 0, ...
'BackgroundColor', [.7 .7 .7], ...
'String', '');
set(myhandles.hLV(i), ...
'Enable', 'Off', ...
'BackgroundColor', [.7 .7 .7], ...
'Value', labels.visible(i));
end
set(myhandles.hLA(labels.active), 'Value', 1);
end
% stat('Update_Labels_List finished')
%% --------------------------------------------------------------------
function Next_Image_Callback(hObject, eventdata, handles)
global labels picture
if picture.list_length,
im_index = get(handles.Images_List, 'Value');
if im_index==picture.list_length,
set(handles.Images_List, 'Value', 1);
else
set(handles.Images_List, 'Value', im_index+1);
end
Update_Window(handles);
end
% stat('Go to next picture')
%% --------------------------------------------------------------------
function Previous_Image_Callback(hObject, eventdata, handles)
global labels picture
if picture.list_length,
im_index = get(handles.Images_List, 'Value');
if im_index==1,
set(handles.Images_List, 'Value', picture.list_length);
else
set(handles.Images_List, 'Value', im_index-1);
end
Update_Window(handles);
end
% stat('Go to prev picture')
%% --- Executes on button press in First_Image.
function First_Image_Callback(hObject, eventdata, handles)
global picture
if (picture.list_length) && (get(handles.Images_List, 'Value')~=1),
set(handles.Images_List, 'Value', 1);
Update_Window(handles);
end
% stat('Go to first picture')
%% --------------------------------------------------------------------
function Last_Image_Callback(hObject, eventdata, handles)
global picture
if (picture.list_length) && (get(handles.Images_List, 'Value')~=picture.list_length),
set(handles.Images_List, 'Value', picture.list_length);
Update_Window(handles);
end
% stat('Go to last picture')
%% --------------------------------------------------------------------
function Close_MenuItem_Callback(hObject, eventdata, handles)
selection = questdlg(['Close ' get(handles.myLabel, 'Name') '?'], ...
['Close ' get(handles.myLabel, 'Name') '...'], ...
'Yes', 'No', 'Yes');
if strcmp(selection, 'No')
return;
end
delete(handles.myLabel)
%% Some stupid callbcks
function Change_Active_Label(hObject, eventdata, handles, new_active_label)
global labels myhandles
labels.active = new_active_label;
% stat(['Now ' num2str(new_active_label) ' is active label']);
set(myhandles.hLA(labels.active), 'Value', 1);
%% --------------------------------------------------------------------
function Toggle_Label_Visibility(hObject, eventdata, handles, label_num)
global labels picture myhandles
% stat(['Toggle visibility of label ' num2str(label_num)]);
labels.visible(label_num) = get(myhandles.hLV(label_num), 'Value');
labels.alphaData(labels.data == labels.values(label_num)) = labels.visible(label_num)*labels.alpha;
Update_Shifts_and_Saves(handles);
% Update_Labels_Transparency;
Update_Labels_Layer;
% get(myhandles.picture, 'CDataMapping')
% get(myhandles.labels, 'CDataMapping')
% get(myhandles.labels, 'AlphaDataMapping')
%% --------------------------------------------------------------------
%% Labels Add/Edit/Del
function Add_New_Label_Callback(hObject, eventdata, handles)
global labels
labels.max_number
if labels.number<labels.max_number,
labels.number = labels.number + 1;
labels.colors(labels.number, :) = labels.std_colors(labels.number, :);
labels.values(labels.number) = labels.std_values(labels.number);
Update_Labels_List(handles);
% stat('New label added');
else
stat('Too many labels, sorry...');
end
% -------------
function Edit_Active_Label_Callback(hObject, eventdata, handles)
global labels
al = labels.active
old_l = labels.values(al);
notOK = true;
while notOK,
dlg_title = ['Value of label ' num2str(al)];
prompt = {'Enter new value (nonzero uint8):'};
num_lines = 1;
def = {num2str(labels.values(al))};
answer = inputdlg(prompt, dlg_title, num_lines, def);
if ~isempty(answer),
try
new_l = uint8(str2num(answer{1}));
labels.values(al) = new_l;
labels.data(find(labels.data==old_l)) = new_l;
notOK = false;
catch
% stat('Check your values...');
end
else
notOK = false;
end
end
labels.changed = 1;
Update_Labels_List(handles);
guidata(hObject, handles);
% -------------
function Del_Active_Label_Callback(hObject, eventdata, handles)
global labels
if labels.number>1,
% h = strcmp(questdlg('Are you sure?'), 'Yes')
if strcmp(questdlg('Are you sure?'), 'Yes'),
% erase data from labels data
labels.data(find(labels.data==labels.values(labels.active))) = 0;
% scroll up labels
for i = labels.active:(labels.number-1),
labels.values(i) = labels.values(i+1);
labels.colors(i, :) = labels.colors(i+1, :);
labels.visible(i) = labels.visible(i+1);
end
% adjust the last label (now it should be free)
labels.visible(labels.number) = 0;
labels.values(labels.number) = labels.std_values(labels.number);
labels.colors(labels.number, :) = labels.std_colors(labels.number, :);
labels.number = labels.number - 1;
if labels.active>labels.number,
labels.active = labels.number;
end
Update_Labels_List(handles);
Update_Labels_Transparency;
Update_Labels_Layer;
end
labels.changed = 1;
end
%% --- Executes on button press in Ten_Images_Back.
function Ten_Images_Back_Callback(hObject, eventdata, handles)
global labels picture
if picture.list_length,
im_index = get(handles.Images_List, 'Value');
if im_index-10 < 1,
set(handles.Images_List, 'Value', 1);
else
set(handles.Images_List, 'Value', im_index-10);
end
Update_Window(handles);
end
% stat('Skip by 10 picture backward')
%% --- Executes on button press in Ten_Images_Forward.
function Ten_Images_Forward_Callback(hObject, eventdata, handles)
global labels picture
if picture.list_length,
im_index = get(handles.Images_List, 'Value');
if im_index+10 > picture.list_length,
set(handles.Images_List, 'Value', picture.list_length);
else
set(handles.Images_List, 'Value', im_index+10);
end
Update_Window(handles);
end
% stat('Skip by 10 picture forward')
%% ---------------------------------------------------------------------
function Add_Images_To_List_Callback(hObject, eventdata, handles)
% --- Executes on button press in Add_Images_To_List.
global labels picture
% stat('Add_Images_To_List_Callback started')
if isempty(picture.dir),
[filenames, pathname] = uigetfiles(getpref('myLabel', 'default_pix_dir'));
else
[filenames, pathname] = uigetfiles(picture.dir{end});
end
n_files = length(filenames);
if n_files>0,
if isempty(picture.list),
picture.list = {};
picture.dir = {};
end
p_list = cell(1, n_files);
p_dir = cell(1, n_files);
p_list_length = 0;
h = waitbar(0, 'Adding images to list...');
for i=1:n_files,
try
info = imfinfo(fullfile(pathname, filenames{i}));
p_list_length = p_list_length + 1;
p_list{p_list_length} = filenames{i};
p_dir{p_list_length} = pathname;
waitbar(i/n_files, h)
catch
fprintf('File %s not recognized as picture, skipping.\n', filenames{i});
end
end
close(h)
% picture.current = 0;
picture.list = [picture.list p_list(1:p_list_length)];
picture.dir = [picture.dir p_dir(1:p_list_length)];
Update_Images_List(handles);
Update_Window(handles);
end
% stat('Load_Images_Callback finished')
%% ---------------------------------------------------------------------
function Clear_Images_List_Callback(hObject, eventdata, handles)
% stat('Clear_Images_List_Callback started')
Save_Current_Labels(handles);
Init_Picture
Init_Labels
Init_Cursor
Init_Clipboard
Init_Undo
Init_Zoom
Init_Myhandles(handles)
Update_Window(handles)
Update_Images_List(handles)
% stat('Clear_Images_List_Callback finished')
%% ---------------------------------------------------------------------
% --- Executes on button press in Load_State.
function Load_State_Callback(hObject, eventdata, handles)
global labels picture
default_path = getpref('myLabel', 'default_states_dir');
[filename, pathname] = uigetfile([default_path '/*.mat'], 'Pick state ...');
if ischar(filename) && ~isempty(filename),
load(fullfile(pathname, filename), 'picture', 'labels', 'undo', 'zoom', 'clipboard');
Set_Labels_Default_Values
Init_Myhandles(handles)
set(handles.Images_List, 'String', picture.list);
set(handles.Images_List, 'Value', 1);
picture.current = 0;
Update_Window(handles);
Update_Images_List(handles)
end
%% ---------------------------------------------------------------------
function Save_State_Callback(hObject, eventdata, handles)
% --- Executes on button press in Save_State.
global labels picture undo zoom clipboard
[filename, pathname] = uiputfile('*.mat', 'Save state as...');
if ~isempty(filename),
save(fullfile(pathname, filename), 'picture', 'labels', 'undo', 'zoom', 'clipboard');
end
%% ---------------------------------------------------------------------
function Autosave
global labels picture undo zoom clipboard
save(fullfile(pwd, 'autosave.mat'), 'picture', 'labels', 'undo', 'zoom', 'clipboard');
%% ---------------------------------------------------------------------
function Image_Axes_CreateFcn(hObject, eventdata, handles)
% --- Executes during object creation, after setting all properties.
%% ---------------------------------------------------------------------
function Labels_ButtonDown(hObject, eventdata, handles)
global labels cursor undo
% stat('Labels_ButtonDown started')
cursor.mb_pressed = 1;
undo = labels.data;
set(handles.Undo, 'Enable', 'on');
Action
% stat('Labels_ButtonDown finished')
%% ---------------------------------------------------------------------
function Change_Operation(hObject, eventdata, handles, new_operation)
global labels myhandles
labels.operation = new_operation;
% new_operation
% stat(['Current operation is ' num2str(new_operation)]);
% set(handles.myLabel, 'WindowButtonMotionFcn', 'Mouse_Moved');
if labels.operation==3,
set(myhandles.brush, 'Visible', 'off');
else
set(myhandles.brush, 'Visible', 'on');
end
set(hObject, 'Value', 1);
% --- Executes on slider movement.
function Cursor_Size_Slider_Callback(hObject, eventdata, handles)
global cursor
cursor.size = round(get(hObject, 'Value'));
set(handles.Cursor_Size_Text, 'String', num2str(cursor.size))
% --- Executes during object creation, after setting all properties.
function Cursor_Size_Slider_CreateFcn(hObject, eventdata, handles)
global cursor
% Hint: slider controls usually have a light gray background.
if isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor'))
set(hObject, 'BackgroundColor', [.9 .9 .9]);
end
% --------------------------------------------------------------------
function Cursor_Size_Text_Callback(hObject, eventdata, handles)
global cursor
% Hints: get(hObject, 'String') returns contents of Cursor_Size_Text as text
% str2double(get(hObject, 'String')) returns contents of Cursor_Size_Text as a double
new_pointer_size = str2double(get(hObject, 'String'));
if isfinite(new_pointer_size),
new_pointer_size = min(new_pointer_size, cursor.max_size);
new_pointer_size = max(new_pointer_size, 0);
cursor.size = round(new_pointer_size);
end
set(hObject, 'String', num2str(cursor.size))
set(handles.Cursor_Size_Slider, 'String', num2str(cursor.size))
% --- Executes during object creation, after setting all properties.
function Cursor_Size_Text_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor'))
set(hObject, 'BackgroundColor', 'white');
end
% --------------------------------------------------------------------
function Copy_Callback(hObject, eventdata, handles)
global clipboard labels
% stat('Copy_Callback started')
clipboard = labels.data;
set(handles.Paste, 'Enable', 'on')
set(handles.Overlay, 'Enable', 'on')
set(handles.Overlay, 'Enable', 'on')
set(handles.Paste, 'Enable', 'on')
for i = 1:labels.number,
if ~labels.visible(i),
clipboard(find(clipboard==labels.values(i)))=0;
end
end
% stat('Copy_Callback finished')
% --------------------------------------------------------------------
function Paste_Callback(hObject, eventdata, handles)
global clipboard labels
% stat('Paste_Callback started')
temp = clipboard;
if size(temp, 1)<size(labels.data, 1),
temp(size(labels.data, 1), 1) = 0; % add rows
else
temp = temp(1:size(labels.data, 1), :); % del extra rows
end
if size(temp, 2)<size(labels.data, 2),
temp(1, size(labels.data, 1)) = 0; % add cols
else
temp = temp(:, 1:size(labels.data, 2)); % del extra cols
end
labels.data = temp; % paste
labels.changed = 1;
Update_Window(handles);
% stat('Paste_Callback finished')
% --- Executes on button press in Undo.
function Undo_Callback(hObject, eventdata, handles)
global undo labels
if ~isempty(undo),
labels.data = undo;
set(handles.Undo, 'Enable', 'off');
set(handles.Undo, 'Enable', 'off');
labels.changed = 1;
Update_Window(handles);
end
% --------------------------------------------------------------------
function Overlay_Callback(hObject, eventdata, handles)
global clipboard labels
% stat('Overlay_Callbackstarted')
temp = clipboard;
if size(temp, 1)<size(labels.data, 1),
temp(size(labels.data, 1), 1) = 0; % add rows
else
temp = temp(1:size(labels.data, 1), :); % del extra rows
end
if size(temp, 2)<size(labels.data, 2),
temp(1, size(labels.data, 1)) = 0; % add cols
else
temp = temp(:, 1:size(labels.data, 2)); % del extra cols
end
labels.data = labels.data .* uint16(~temp); % clear
labels.data = labels.data + uint16(temp); % overlay
labels.changed = 1;
Update_Window(handles);
% stat('Overlay_Callback finished')
% --- Executes on slider movement.
function Transparency_Slider_Callback(hObject, eventdata, handles)
global labels
labels.alpha = get(hObject, 'Value');
set(handles.Transparency_Edit, 'String', sprintf('%04.2f', labels.alpha));
% labels.changed = 1;
Update_Labels_Transparency;
Update_Labels_Layer;
% --- Executes during object creation, after setting all properties.
function Transparency_Slider_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor'))
set(hObject, 'BackgroundColor', [.9 .9 .9]);
end
% --- Executes during object creation, after setting all properties.
function Transparency_Edit_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor'))
set(hObject, 'BackgroundColor', 'white');
end
% -------------------------------------------------------------------------
function Save_Image_Pushbutton_Callback(hObject, eventdata, handles)
% --- Executes on button press in Save_Image_Pushbutton.
global labels picture
% prepare temp mask
[mask vl]= Get_Mask;
filename = fullfile(picture.output_dir, picture.short_filename);
data_2_save = picture.data;
if get(handles.Masked_Checkbox, 'Value'),
filename = [filename '_masked'];
data_2_save = data_2_save .* mask;
end
if get(handles.Cropped_Checkbox, 'Value'),
filename = [filename '_cropped'];
cols = find(sum(mask(:, :, 1)));
rows = find(sum(mask(:, :, 1), 2));
data_2_save = data_2_save(min(rows):max(rows), min(cols):max(cols), :);
end
filename = [filename vl picture.filename_ext];
if ~exist(picture.output_dir, 'dir'), mkdir(picture.output_dir); end
imwrite(data_2_save, filename);
stat(['Image saved in ' filename]);
% --- Executes on button press in Masked_Checkbox.
function Masked_or_Cropped_Checkbox_Callback(hObject, eventdata, handles)
if ~get(handles.Zoom_Togglebutton, 'Value') && ...
(get(handles.Masked_Checkbox, 'Value')+get(handles.Cropped_Checkbox, 'Value')),
set(handles.Save_Image_Pushbutton, 'Enable', 'on');
else
set(handles.Save_Image_Pushbutton, 'Enable', 'off');
end
% --- Executes on button press in Zoom_Togglebutton.
function Zoom_Togglebutton_Callback(hObject, eventdata, handles)
global picture labels zoom
zoom.active = get(handles.Zoom_Togglebutton, 'Value');
if zoom.active,
% Store main data
zoom.picture = picture;
zoom.labels = labels;
% Store some controls states
zoom.events.WindowButtonMotionFcn = get(handles.myLabel, 'WindowButtonMotionFcn');
set(handles.myLabel, 'WindowButtonMotionFcn', ''); % forget about mousemove
% Disable some controls
set(handles.Save_Image_Pushbutton, 'Enable', 'off');
set(handles.Images_List, 'Enable', 'off');
set(handles.First_Image, 'Enable', 'off');
set(handles.Last_Image, 'Enable', 'off');
set(handles.Ten_Images_Back, 'Enable', 'off');
set(handles.Ten_Images_Forward, 'Enable', 'off');
set(handles.Next_Image, 'Enable', 'off');
set(handles.Previous_Image, 'Enable', 'off');
Masked_or_Cropped_Checkbox_Callback(hObject, eventdata, handles);
region = round(getrect(handles.Image_Axes))
zoom.col1 = region(1);
zoom.row1 = region(2);
zoom.col2 = region(1) + region(3);
zoom.row2 = region(2) + region(4);
% check boundaries
if zoom.col1<1, zoom.col1 = 1; end
if zoom.col1>picture.cols, zoom.col1 = picture.cols; end
if zoom.col2<1, zoom.col2 = 1; end
if zoom.col2>picture.cols, zoom.col2 = picture.cols; end
if zoom.row1<1, zoom.row1 = 1; end
if zoom.row1>picture.rows, zoom.row1 = picture.rows; end
if zoom.row2<1, zoom.row2 = 1; end
if zoom.row2>picture.rows, zoom.row2 = picture.rows; end
% cut data
labels.data = labels.data(zoom.row1:zoom.row2, zoom.col1:zoom.col2);
labels.alphaData= labels.alphaData(zoom.row1:zoom.row2, zoom.col1:zoom.col2);
picture.data = picture.data(zoom.row1:zoom.row2, zoom.col1:zoom.col2);
% restore events
set(handles.myLabel, 'WindowButtonMotionFcn', zoom.events.WindowButtonMotionFcn);
% let the show begins...
% Update_Window(handles);
myhandles.picture = imshow(picture.data); % Show_Image;
Create_Labels_Layer(handles);
Update_Labels_Layer;
Autosave
else
% Paste new data
zoom.labels.changed = labels.changed;
zoom.picture.data(zoom.row1:zoom.row2, zoom.col1:zoom.col2) = picture.data;
zoom.labels.data(zoom.row1:zoom.row2, zoom.col1:zoom.col2) = labels.data;
zoom.labels.alphaData(zoom.row1:zoom.row2, zoom.col1:zoom.col2) = labels.alphaData;
% Retore main data
picture = zoom.picture;
labels = zoom.labels;
% Restore some controls states
set(handles.myLabel, 'WindowButtonMotionFcn', zoom.events.WindowButtonMotionFcn);
Update_Images_List(handles);
Masked_or_Cropped_Checkbox_Callback(hObject, eventdata, handles);
Update_Window(handles);
end
% --------------------------------------------------------------------
function Del_Image_From_List_Callback(hObject, eventdata, handles)
global picture
if picture.list_length <= 1,
Init_Picture;
else
list = {};
dir = {};
j = 0;
for i = 1:picture.list_length,
if i~=picture.current,
j = j + 1;
list{j} = picture.list{i};
dir{j} = picture.dir{i};
end
end
picture.list = list;
picture.dir = dir;
picture.list_length = picture.list_length - 1;
if picture.current>picture.list_length,
picture.current = picture.list_length;
end
end
Update_Images_List(handles);
Update_Window(handles);
% --- Executes on key press over myLabel with no controls selected.
function KeyPressFcn(hObject, eventdata, handles)
global myhandles labels zoom
key = get(handles.myLabel, 'CurrentCharacter');
% fprintf('KeyPressFcn called by %s\n', get(hObject, 'Tag'));
% stat('KeyPressFcn')
if ~isempty(key),
uikey = uint16(key);
% fprintf(' uikey=%g\n', uikey);
switch uikey
case {29, 31} % right down
if ~zoom.active && hObject~=handles.Images_List,
Next_Image_Callback(hObject, eventdata, handles);
end
case {28, 30} % left up
if ~zoom.active && hObject~=handles.Images_List,
Previous_Image_Callback(hObject, eventdata, handles);
end
case 32 % space key
if strcmp(get(myhandles.hLV(labels.active), 'Enable'), 'on'),
labels.visible(labels.active) = 1 - labels.visible(labels.active);
Update_Labels_List(handles);
Update_Labels_Transparency;
Update_Labels_Layer;
end
case {48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, % '0' .. '9'
numkey = uikey - 48;
if numkey==0, numkey = 10; end
if labels.number >= numkey,
labels.visible(numkey) = 1 - labels.visible(numkey);
Update_Labels_List(handles);
Update_Labels_Transparency;
Update_Labels_Layer;
Update_Labels_List(handles);
end
case {33, 35, 36, 37}, % Shift+'1', '3'..'5'
numkey = uikey - 32;
if labels.number >= numkey,
labels.active = numkey;
Update_Labels_List(handles);
end
case 64, % Shift+'2'
if labels.number >= 2,
labels.active = 2;
Update_Labels_List(handles);
end
case 94, % Shift+'6'
if labels.number >= 6,
labels.active = 6;
Update_Labels_List(handles);
end
case 38, % Shift+'7'
if labels.number >= 7,
labels.active = 7;
Update_Labels_List(handles);
end
case 42, % Shift+'8'
if labels.number >= 8,
labels.active = 8;
Update_Labels_List(handles);
end
case {83, 115} % 'S' 's' - operation set
labels.operation = 1;
set(myhandles.brush, 'Visible', 'on');
set(handles.Operation_Set, 'Value', 1);
set(handles.Operation_Clear, 'Value', 0);
set(handles.Operation_Fill, 'Value', 0);
case {67, 99} % 'C' 'c' - operation clear
labels.operation = 2;
set(myhandles.brush, 'Visible', 'on');
set(handles.Operation_Set, 'Value', 0);
set(handles.Operation_Clear, 'Value', 1);
set(handles.Operation_Fill, 'Value', 0);
case {70, 102} % 'F' 'f' - operation fill
labels.operation = 3;
set(myhandles.brush, 'Visible', 'off');
set(handles.Operation_Set, 'Value', 0);
set(handles.Operation_Clear, 'Value', 0);
set(handles.Operation_Fill, 'Value', 1);
case {90, 122} % 'Z' 'z' - zoom
set(handles.Zoom_Togglebutton, 'Value', 1-get(handles.Zoom_Togglebutton, 'Value'));
Zoom_Togglebutton_Callback(handles.Zoom_Togglebutton, eventdata, handles)
case 65 % 'A' - shift left by 10 pixels
Shift_Visible_Labels(hObject, eventdata, handles, 1, 10);
case 97 % 'a' - shift left by 1 pixel
Shift_Visible_Labels(hObject, eventdata, handles, 1);
case 68 % 'D' - shift right by 10 pixels
Shift_Visible_Labels(hObject, eventdata, handles, 2, 10);
case 100 % 'd' - shift right by 1 pixel
Shift_Visible_Labels(hObject, eventdata, handles, 2);
case 87 % 'W' - shift up by 10 pixels
Shift_Visible_Labels(hObject, eventdata, handles, 3, 10);
case 119 % 'w' - shift up by 1 pixel
Shift_Visible_Labels(hObject, eventdata, handles, 3);
case 88 % 'X' - shift down by 10 pixels
Shift_Visible_Labels(hObject, eventdata, handles, 4, 10);
case 120 % 'X' 'x' - shift down by 1 pixel
Shift_Visible_Labels(hObject, eventdata, handles, 4);
case {84, 116} % 'T' 't' - Save_For_Training
Save_For_Training_Callback(hObject, eventdata, handles);
end
end
% --- Executes on button press in Shift_Left.
function Shift_Visible_Labels(hObject, eventdata, handles, direction, value)
global labels
if nargin<5,
value = 1;
end
if any(labels.visible),
mask = false(size(labels.data));
for i = 1:labels.number,
if labels.visible(i),
mask = mask | labels.data==labels.values(i);
end
end
temp = labels.data .* uint16(mask);
labels.data = labels.data .* uint16(~mask); % clear visible labels
switch direction,
case 1, % left
mask(:, 1:(end-value)) = mask(:, (1+value):end); mask(:, (end-value+1):end) = 0;
temp(:, 1:(end-value)) = temp(:, (1+value):end); temp(:, (end-value+1):end) = 0;
case 2, % right
mask(:, (1+value):end) = mask(:, 1:(end-value)); mask(:, 1:value) = 0;
temp(:, (1+value):end) = temp(:, 1:(end-value)); temp(:, 1:value) = 0;
case 3, % up
mask(1:(end-value), :) = mask((1+value):end, :); mask((end-value+1):end, :) = 0;
temp(1:(end-value), :) = temp((1+value):end, :); temp((end-value+1):end, :) = 0;
case 4, % down
mask((1+value):end, :) = mask(1:(end-value), :); mask(1:value, :) = 0;
temp((1+value):end, :) = temp(1:(end-value), :); temp(1:value, :) = 0;
end
labels.data = labels.data .* uint16(~mask); % clear again
labels.data = labels.data + temp;
labels.changed = 1;
Update_Labels_Transparency;
Update_Labels_Layer
end
function [mask vl] = Get_Mask
global labels picture
% prepare temp mask
mask = uint8(labels.data>0);
vl = '';
for i = 1:labels.number,
if ~labels.visible(i),
mask(find(labels.data==labels.values(i)))=0;
else
vl = [vl '_' num2str(labels.values(i))];
end
end
% transform it to needed format
if ndims(picture.data)==3,
mask = repmat(mask, [1 1 3]);
end
% --- Executes on button press in Save_For_Training.
function Save_For_Training_Callback(hObject, eventdata, handles)
global labels picture
[mask vl]= Get_Mask;
filename = picture.short_filename;
im = picture.data;
if get(handles.Masked_Checkbox, 'Value'),
filename = [filename '_masked'];
im = im .* mask;
end
cols = find(sum(mask(:, :, 1)));
rows = find(sum(mask(:, :, 1), 2));
y1 = min(rows);
y2 = max(rows);
x1 = min(cols);
x2 = max(cols);
if get(handles.Cropped_Checkbox, 'Value'),
filename = [filename '_cropped'];
im = im(y1:y2, x1:x2, :);
end
stat(['Saving for training in: ' filename]);
cut_object(im, [x1 y1 x2 y2], vl, picture.output_dir, filename);
stat('done');
% --- Executes on button press in Save_Set.
function Save_Set_Callback(hObject, eventdata, handles)
global labels picture
stat(['Saving set of images:']);
percentage = str2double(get(handles.Percentage_Edit, 'String'));
images2save = str2double(get(handles.Set_Size_Edit, 'String'));
[mask vl] = Get_Mask;
filename = picture.short_filename;
min_size_ratio = 1/5;
% im = picture.data;
cut_slices(picture.data, mask, [], picture.output_dir, picture.short_filename, [], min_size_ratio, percentage, images2save, [], [], 2, 0, 4)
% stat('done');
% --- Executes when user edit Percentage edit control
function Percentage_Edit_Callback(hObject, eventdata, handles)
Percentage = str2double(get(hObject, 'String'));
if ~isfinite(Percentage) || Percentage<0 || Percentage>=100,
set(hObject, 'String', '75')
else
set(hObject, 'String', num2str(round(Percentage)));
end
% --- Executes during object creation, after setting all properties.
function Percentage_Edit_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor'))
set(hObject, 'BackgroundColor', 'white');
end
% --- Executes when user edit Set_Size_Edit edit control.
function Set_Size_Edit_Callback(hObject, eventdata, handles)
SetSize = str2double(get(hObject, 'String'));
if ~isfinite(SetSize) || SetSize <=0 || SetSize>=100,
set(hObject, 'String', '10')
else
set(hObject, 'String', num2str(ceil(SetSize)));
end
% --- Executes during object creation, after setting all properties.
function Set_Size_Edit_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor'))
set(hObject, 'BackgroundColor', 'white');
end
function Update_Interpolate_and_Track_Buttons(handles)
if get(handles.Toggle_Starting_Mask, 'Value') && get(handles.Toggle_Ending_Mask, 'Value'),
set(handles.Interpolate, 'Enable', 'on')
set(handles.Track, 'Enable', 'on')
else
set(handles.Interpolate, 'Enable', 'off')
set(handles.Track, 'Enable', 'off')
end
% --- Executes on button press in Toggle_Starting_Mask.
function Toggle_Starting_Mask_Callback(hObject, eventdata, handles)
global labels picture interpolation
Update_Interpolate_and_Track_Buttons(handles)
if get(hObject, 'Value'),
interpolation.label = labels.values(labels.active);
mask = labels.data==interpolation.label;
cols = find(sum(mask));
rows = find(sum(mask, 2));
interpolation.first.row = min(rows);
interpolation.first.height = max(rows) - min(rows) + 1;
interpolation.first.col = min(cols);
interpolation.first.width = max(cols) - min(cols) + 1;
interpolation.first.mask = mask(min(rows):max(rows), min(cols):max(cols));
interpolation.first.frame_n = picture.current;
object = picture.data( min(rows):max(rows), min(cols):max(cols) );
if ndims(object)==3,
interpolation.first.object = rgb2gray(object);
else
interpolation.first.object = object;
end
interpolation.first.object = double(interpolation.first.object)/255 .* double(interpolation.first.mask);
% stat(sprintf('first_frame:%g, label:%g, row:%g, col:%g, mask size:%gx%g\n', interpolation.first.frame_n, interpolation.label, interpolation.first.row, interpolation.first.col, size(interpolation.first.mask)));
end
% --- Executes on button press in Toggle_Ending_Mask.
function Toggle_Ending_Mask_Callback(hObject, eventdata, handles)
global labels picture interpolation
Update_Interpolate_and_Track_Buttons(handles);
if get(hObject, 'Value'),
% interpolation.label = labels.values(labels.active);
interpolation.label = labels.values(labels.active);
mask = labels.data==interpolation.label;
cols = find(sum(mask));
rows = find(sum(mask, 2));
interpolation.last.row = min(rows);
interpolation.last.height = max(rows) - min(rows) + 1;
interpolation.last.col = min(cols);
interpolation.last.width = max(cols) - min(cols) + 1;
interpolation.last.mask = mask(min(rows):max(rows), min(cols):max(cols));
interpolation.last.frame_n = picture.current;
object = picture.data( min(rows):max(rows), min(cols):max(cols) );
if ndims(object)==3,
interpolation.last.object = rgb2gray(object);
else
interpolation.last.object = object;
end
interpolation.last.object = double(interpolation.last.object)/255 .* double(interpolation.last.mask);
stat(sprintf('last_frame:%g, label:%g, row:%g, col:%g, mask size:%gx%g\n', interpolation.last.frame_n, interpolation.label, interpolation.last.row, interpolation.last.col, size(interpolation.last.mask)));
end
% --- Executes on button press in Interpolate.
function Interpolate_or_Track(hObject, eventdata, handles, track)
global labels picture interpolation
search_radius = 6;
momentum = 8;
if ~exist('track', 'var') || isempty(track),
track = 0;
end
if interpolation.first.frame_n<interpolation.last.frame_n,
start_frame = interpolation.first.frame_n;
start_mask = double(interpolation.first.mask);
end_frame = interpolation.last.frame_n;
end_mask = double(interpolation.last.mask);
prev_obj = interpolation.first.object;
else
start_frame = interpolation.last.frame_n;
start_mask = double(interpolation.last.mask);
end_frame = interpolation.first.frame_n;
end_mask = double(interpolation.first.mask);
prev_obj = interpolation.last.object;
end
frames2interpolate = end_frame - start_frame - 1;
fprintf('start_frame: %g, end_frame: %g, frames2interpolate: %g, label: %g\n', start_frame, end_frame, frames2interpolate, interpolation.label);
% figure(2);
% subplot(1, frames2interpolate+2, 1); imagesc(start_mask)
% subplot(1, frames2interpolate+2, frames2interpolate+2); imagesc(end_mask)
first_x = (1:interpolation.first.width)-1;
first_x = first_x / max(first_x);
first_y = (1:interpolation.first.height)-1;
first_y = first_y / max(first_y);
[first_x, first_y] = meshgrid(first_x, first_y);
last_x = (1:interpolation.last.width)-1;
last_x = last_x / max(last_x);
last_y = (1:interpolation.last.height)-1;
last_y = last_y / max(last_y);
[last_x, last_y] = meshgrid(last_x, last_y);
prev_row = interpolation.first.row;
prev_col = interpolation.first.col;
picture.data(prev_row + (1:interpolation.first.height) - 1, prev_col + (1:interpolation.first.width) - 1);
if frames2interpolate,
for frame_i = 1:frames2interpolate,
fprintf('processing frame #%g\n', start_frame+frame_i);
lambda = frame_i / (frames2interpolate+1);
if 0 && track,
row = prev_row;
col = prev_col;
else
row = round((1-lambda)*interpolation.first.row + lambda*interpolation.last.row);
col = round((1-lambda)*interpolation.first.col + lambda*interpolation.last.col);
end
width = round((1-lambda)*interpolation.first.width + lambda*interpolation.last.width);
height = round((1-lambda)*interpolation.first.height + lambda*interpolation.last.height);
if track,
prev_obj= imresize(prev_obj, [height width], 'bicubic');
if frame_i<frames2interpolate/2,
warped_obj = imresize(interpolation.first.object, [height width], 'bicubic');
else
warped_obj = imresize(interpolation.last.object, [height width], 'bicubic');
end
figure(2);
subplot(231); imshow(interpolation.first.object);
subplot(232); imshow(warped_obj);
subplot(233); imshow(interpolation.last.object);
drawnow;
end
curr_x = (1:width)-1;
curr_x = curr_x / max(curr_x);
curr_y = (1:height)-1;
curr_y = curr_y / max(curr_y);
[curr_x, curr_y] = meshgrid(curr_x, curr_y);
first_warped_mask = interp2(first_x, first_y, interpolation.first.mask, curr_x, curr_y);
last_warped_mask = interp2(last_x, last_y, interpolation.last.mask, curr_x, curr_y);
mask = ((1-lambda) * first_warped_mask + lambda * last_warped_mask);
mask = mask>=.5;
if track,
figure(2);
subplot(234); imshow(prev_obj); drawnow
best_SSD = inf;
best_object = [];
best_row = 0;
best_col = 0;
% fprintf('min_col=%g, max_col=%g\n', max(1, col-search_radius), min(col+search_radius, picture.cols-width+1))
for r = max(1, row-search_radius):min(row+search_radius, picture.rows-height+1),
for c = max(1, col-search_radius):min(col+search_radius, picture.cols-width+1),
cutted_object = picture.data(r-1+(1:height), c-1+(1:width));
if ndims(cutted_object)==3,
cutted_object = rgb2gray(cutted_object);
end
cutted_object = double(cutted_object)/255 .* double(mask);
SSD = sum(sum((cutted_object - prev_obj).^2)) + momentum*sum(sum((warped_obj - cutted_object).^2));
figure(2);
if SSD<best_SSD,
best_SSD = SSD;
best_object = cutted_object;
best_row = r;
best_col = c;
subplot(235); imshow(best_object)
end
subplot(236); imshow(cutted_object);
drawnow
end
end
row = best_row;
col = best_col;
prev_obj = best_object;
end
set(handles.Images_List, 'Value', start_frame+frame_i);
Load_Image_and_Labels(handles);
fullmask= zeros(size(labels.data), 'uint16');
fullmask(row-1+(1:height), col-1+(1:width)) = mask;
labels.data = labels.data .* uint16(1-fullmask);
labels.data = labels.data + uint16(fullmask)*uint16(interpolation.label);
labels.changed = 1;
end
% masks = masks * interpolation.label;
Load_Image_and_Labels(handles);
end
set(handles.Toggle_Starting_Mask, 'Value', 0);
set(handles.Toggle_Ending_Mask, 'Value', 0);
set(handles.Interpolate, 'Enable', 'off')
set(handles.Track, 'Enable', 'off')
% --------------------------------------------------------------------
function Set_Default_Labels_Dir_Callback(hObject, eventdata, handles)
default_dir = uigetdir(getpref('myLabel', 'default_labels_dir'), 'Pick a default labels directory');
if ischar(default_dir),
setpref('myLabel', 'default_labels_dir', default_dir);
end
% --------------------------------------------------------------------
function Set_Default_images_dir_Callback(hObject, eventdata, handles)
default_dir = uigetdir(getpref('myLabel', 'default_pix_dir'), 'Pick a default images directory');
if ischar(default_dir),
setpref('myLabel', 'default_pix_dir', default_dir);
end
% --------------------------------------------------------------------
function Set_Default_Output_Dir_Callback(hObject, eventdata, handles)
default_dir = uigetdir(getpref('myLabel', 'default_output_dir'), 'Pick a default output directory');
if ischar(default_dir),
setpref('myLabel', 'default_output_dir', default_dir);
end
% --------------------------------------------------------------------
function About_Callback(hObject, eventdata, handles)
global info
% helpdlg
text = {'myLabel - images labeling tool for Matlab', ...
'by Nikolay Chumerin (myLabel.support@gmail.com)', ...
sprintf('\nVersion: %g.%02g\nLast update %s', info.version, info.subversion, info.release_date)};
msgbox(text, 'About myLabel', 'Help', 'modal');
% myLabel - image sequencies labeling tool