Unable to do subtraction of images in GUI

Hi,
I have built a matlab GUi where I load two separate sets of images in two different axes. I want to subtract each of the both sets of images from each other and display the result in another image axes(axes3). I would browse through each set of images from the first two image axes using a image slider. Their corresponding subtraction result would be displayed in the third axes. However , I am getting an error message.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
value1=handles.value1;
orig_imgs1 = handles.InputImage1;
output_img1=handles.InputImage2;
handles.dblSubtractedImage = {};
[rowsorig_imgs1 colsorig_imgs1 numberOfColorChannelsorig_imgs1]=size(orig_imgs1);
[rowsoutput_img1 colsoutput_img1 numberOfColorChannelsoutput_img1]=size(output_img1);
if rowsoutput_img1 ~= rowsorig_imgs1 || colsorig_imgs1 ~= colsoutput_img1
output_img1 = imresize(output_img1, [rowsorig_imgs1 colsorig_imgs1]);
end
dblSubtractedImage = (orig_imgs1{value1}) - (output_img1{value1});
imshow(dblSubtractedImage,'parent',handles.axes3);
handles.dblSubtractedImage{end+1}= dblSubtractedImage;
guidata(hObject, handles);
end
I get the following error message:
Error using imresize>parsePreMethodArgs (line 379)
Invalid input syntax; input image missing from argument list.
Error in imresize>parseInputs (line 273)
parsePreMethodArgs(varargin, method_arg_idx, first_param_string_idx);
Error in imresize (line 152)
params = parseInputs(args{:});
Error in ng>pushbutton3_Callback (line 226)
output_img1 = imresize(output_img1, [rowsorig_imgs1 colsorig_imgs1]);
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in ng (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)ng('pushbutton3_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback.

 Accepted Answer

What is this????
InputImage2 = imresize(InputImage2(value1), [rowsInputImage1 colsInputImage1]);
You're saying the image is InputImage2(value1). So what is value1? Is it an integer or a vector? So if value1 is an integer then you're basically using it as the linear index into the InputImage2 image, which gives you only a single pixel. Then you blow up this pixel to a whole image with imresize - so now you have a totally uniform image. Now you subtract that from InputImage1 and it will just look like a dark version of InputImage1. However you used [] in imshow() to scale the image to fit the dynamic range so of course it will look identical to InputImage1.
Try
InputImage2 = imresize(InputImage2, [rowsInputImage1 colsInputImage1]);
and when you subtract, cast the images to double or else negative numbers will get clipped.
dblSubtractedImage = double(InputImage1) - double(InputImage2);
or you can use imabsdiff(), which essentially flips negative numbers positive.
dblSubtractedImage = imabsdiff(InputImage1, InputImage2);

12 Comments

The subtraction worked partially. The result is displayed in the image axes 3. The centre region is black which is fine. However, the background is white. I am trying to display the result that looks quite similar to Capture2.jpg with the background similar to the Input Image1. Input Image2 is the result of the segementation of the Input Image 1. I just want to remove the ROI from the initial region and display the original result without the ROI. Please note that Capture 2.jpg is not the result of the subtraction that is shown in Capture .jpg. I just used that image to explain my problem.
You have the mask, and ~mask, shown. Just use the one that is white in the center and erase that part of your grayscale image like this:
grayImage(mask) = 0;
I tried the above line but I am getting the following error:
Array indices must be positive integers or logical values.
Error in ng>pushbutton3_Callback (line 234)
InputImage1(InputImage2)=0;
Your InputImage2 is not a logical() array. It might be double() or uint8()
I checked that both my InputImage 1 and InputImage 2 are uint8. I converted them by the following method to logical.
InputImage1=logical(InputImage1);
InputImage2=logical(InputImage2);
After using the line below:
InputImage1(InputImage2) = 0;
I get the result that is shown in the attached image.
The ROI is black which is absolutely fine. However, The background is white. I want the region outside the ROi same as the original image.
I have completely lost track of what your two images are intended to be relative to each other.
If you want to subtract one grayscale image from another, then
subimage = double(FirstImage) = double(SecondImage);
If the original images are uint8 then the result will have values that are potentially in the range -255 to +255 -- it will have both positive and negative areas. But what you do with the result afterwards...
Or is one of the images intended to be a background image and the intent is to subtract out the background?
Below are the two images. FP1.jpg is the original image. After applying segmentation technique, I get the ROi as defined as segFP1.jpg. I intend to remove the ROI from the original image. That is my resultant image would display the original image without the ROI.
Your segmented image is not the same size as the original image. Do you have the coordinates of segFP1 relative to FP1 ? I tried doing a cross-correlation to find the segmented image within the original, but there were over 30000 places in the image that were equally likely to be the original version of that segmentation.
I tried the process separately. I am getting the result. However, the problem is that I am unable to implement the process in GUI. Please find the code below:
I= rgb2gray(imread('TM19.jpg'));
figure,imshow(I)
x=300; y=340;
a=imgaussfilt(I,2);
b=adapthisteq(a);
m=regiongrowing_MLT(b,x,y,12);
m=imfill(m,'holes');
% figure,imshow(m)
bw=imbinarize(m);
bw=bwareafilt(bw,1);
% figure,imshow(bw)
I1 = imresize(m,.5); %-- make image smaller
m1 = imresize(bw,.5); % for fast computation
seg = region_seg(I1, m1, 30); %-- Run segmentation
img_class=class(I);
fill=cast(seg,img_class);
seg1=fill.*I1;
figure,imshow(seg1); title('Global Region-Based Segmentation');
[rowsI colsI numberOfColorChannelsI]=size(I);
[rowsseg1 colsseg1 numberOfColorChannelsseg1]=size(seg1);
if rowsseg1 ~= rowsI || colsI ~= colsseg1
seg1 = imresize(seg1, [rowsI colsI]);
end
dblSubtractedImage = (I) - (seg1);
figure, imshow(dblSubtractedImage, []);
While implementing the process in the GUi, I get the the ROi as black but the background is white. Whereas, while using this code separately, I get the desired result. The ng.fig and ng.m in the initial attachment is my GUI.
I have attached a cleaner version of ng.m that prevents some of the error messages, and is smarter about remembering directories.
You would have seen all-black for the result if the original image and the segmented image were the same. In the case of TM19, you did not happen to provide the segmented image, but I accidentally reproduced that problem because I had been a bit careless when I adapted the directory controls. I modified the code so that in the case that the two are identical, that a specific warning message is raised.
You might notice that some of the buttons are not always available. This was done because you set up variables in some pushbuttons that are needed by later pushbuttons: in such a case you should disable the pushbuttons until conditions are right for the buttons to work.
The directory prompts were a bit confusing for the case where the hard-coded directories were not found. I cleaned that code up some, making it clearer in the prompt as to which directory was being asked for.
That really helped a lot. I have one last query. I tried to save the image displayed in image axes 3 everytime when I browse through the slider. I used a SAVE button to do the operation. However, I am getting an error message.
function pushbutton4_Callback(hObject, eventdata, handles)
handles = guidata(hObject);
value1=handles.value1;
dblSubtractedImage=handles.dblSubtractedImage;
startingFolder = 'D:\regionGrowing_MLT'; % Or "pwd" or wherever you want.
if ~isfolder(startingFolder)
startingFolder = pwd;
end
defaultFileName = fullfile(startingFolder, '*.jpg');
[baseFileName, folder] = uiputfile(defaultFileName, 'Specify a file');
if baseFileName == 0
% User clicked the Cancel button.
return;
end
% If they entered an extension, throw it away because (for some reason)
% we want to force it to be JPG format, not whatever other format they may have entered.
[~, baseFileNameNoExt, ext] = fileparts(baseFileName);
fullFileName = fullfile(folder, [baseFileNameNoExt, '.jpg']);
% Now save the JPG image.
imwrite(dblSubtractedImage{value1}, fullFileName);
guidata(hObject, handles);
end
I get the following error message:
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)ng('pushbutton4_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback.
Index exceeds the number of array elements (1).
Error in ng>pushbutton4_Callback (line 280)
imwrite(dblSubtractedImage{value1}, fullFileName);
Error in gui_mainfcn (line 95)
feval(varargin{:});
Error in ng (line 42)
gui_mainfcn(gui_State, varargin{:});
Error in
matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)ng('pushbutton4_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating UIControl Callback.
I have figured out the solution for the above problem. Thank you very much for your suggestions. It was really helpful.

Sign in to comment.

More Answers (1)

I think that the problem is that you are trying to resize an image in a cell array
value1=handles.value1; (this is the index of the image in the cell array i geuss)
orig_imgs1 = handles.InputImage1; (this is a cell array of images)
output_img1=handles.InputImage2; (this is a cell array of images)
handles.dblSubtractedImage = {};
[rowsorig_imgs1 colsorig_imgs1 numberOfColorChannelsorig_imgs1]=size(orig_imgs1);
[rowsoutput_img1 colsoutput_img1 numberOfColorChannelsoutput_img1]=size(output_img1);
if rowsoutput_img1 ~= rowsorig_imgs1 || colsorig_imgs1 ~= colsoutput_img1
output_img1 = imresize(output_img1{value1}, [rowsorig_imgs1 colsorig_imgs1]); (here you must specify which image you want to resize)
end
dblSubtractedImage = (orig_imgs1{value1}) - (output_img1{value1});
imshow(dblSubtractedImage,'parent',handles.axes3);
handles.dblSubtractedImage{end+1}= dblSubtractedImage;
guidata(hObject, handles);
end

7 Comments

I tried the above method but it gives the following error:
Brace indexing is not supported for variables of this type.
Error in ng>pushbutton3_Callback (line 229)
dblSubtractedImage = (orig_imgs1{value1}) - (output_img1{value1});
Then I changed the above line of code as below:
dblSubtractedImage = (orig_imgs1(value1)) - (output_img1(value1));
I get the following error:
Operator '-' is not supported for operands of type 'cell'.
Error in ng>pushbutton3_Callback (line 229)
dblSubtractedImage = (orig_imgs1(value1)) - (output_img1(value1));
value1 = handles.value1; %(this is the index of the image in the cell array i geuss)
orig_imgs1 = handles.InputImage1{value1}; %(this is one image)
output_img1 = handles.InputImage2{value1}; %(this is one image)
It is possible that it is sometimes a matrix when it's only one image, and a cell array when it is more.
try to add this line before the subtraction:
and make sure that the variable "value1" is not empty.
if ~iscell(orig_imgs1)
orig_imgs1 = {orig_imgs1};
end
if ~iscell(orig_imgs2)
orig_imgs1 = {orig_imgs2};
end
You can also pause set the app to pause at errors to check this out or add a line that prints out the class of your variables
disp(class(orig_imgs1))
disp(class(orig_imgs2))
I modified the code according to your suggestion. The error has been solved. However, I am not getting any image on the 3rd image axes. It's just a white background.
Try
imshow(dblSubtractedImage, [], 'parent', handles.axes3);
Hi Walter,
I tried but no image is being displayed.
I managed to solve the issue as I am getting a result in the 3rd image axes.
value1=handles.value1;
InputImage1 = handles.InputImage1{value1};
InputImage2=handles.InputImage2{value1};
InputImage2=imresize(InputImage2,0.5);
handles.dblSubtractedImage = {};
[rowsInputImage1 colsInputImage1 numberOfColorChannelsInputImage1]=size(InputImage1);
[rowsInputImage2 colsInputImage2 numberOfColorChannelsInputImage2]=size(InputImage2);
if rowsInputImage2 ~= rowsInputImage1 || colsInputImage1 ~= colsInputImage2
InputImage2 = imresize(InputImage2(value1), [rowsInputImage1 colsInputImage1]);
end
dblSubtractedImage = (InputImage1) - (InputImage2);
imshow(dblSubtractedImage,[],'parent',handles.axes3);
handles.dblSubtractedImage{end+1}= dblSubtractedImage;
guidata(hObject, handles);
end
However, I think the subtraction has not worked properly, as the result in axes 3 is the same as axes 1. Any suggestions would be appreciated.

Sign in to comment.

Products

Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!