segment object(leaf) which is on the white paper using image processing - image

I want to get only leaf from an image.
The background is a normal white paper(A4) and there is some shadow.
I apply some method (structure element,edge detection using filter) but I cannot find the general way which can apply all the image.
these are examples.
Are there better methods for this problem??
thank you
another example.
and the result I got is
By using
hsv_I = rgb2hsv(I);
Is = hsv_I(:,:,2);
Is_d = imdilate(Is,strel('diamond',4));
Is_e = imerode(Is,strel('diamond',2));
Is_de = imerode(Is_d,strel('disk',2));
Is_def = imfill(Is_de,'holes');
Is_defe = imerode(Is_def,strel('disk',5));
Then Is_defe is a mask to segment
But the method that i did is very specific. I cannot use this in general.

If you have the Image Processing Toolbox, you could do as follows:
The code below first estimates the threshold with the function graythresh, thresholds the image and fills holes with the imfill function. Suppose I is a cell containing your RGB images:
for k=1:length(I)
t=graythresh(rgb2gray(I{k}));
BW{k}=imfill(~im2bw(I{k}, t), 'holes');
subplot(length(I),1,k), imshow(BW{k});
end

Related

How to matched object from main image with the template sub-Image using normxcorr2

I try to determine the coordinates of a puzzle piece on the original image using the normxcorr2 function. Then I draw a rectangle on the correspondence of the two elements. Unfortunately, I notice that the coordinates that this match has given me are not good. Could someone have an idea how to improve the use of this feature and get some better results.
The puzzle piece has the name "cpiece" and the original picture has the name "bild"
clear all;
close all;
clc
cpiece = im2gray(imread('cpiece1.jpg'));
bild = im2gray(imread('original.jpg'));
figure(1)
montage({bild,cpiece})
c = normxcorr2(cpiece,bild);
figure(2)
surf(c)
shading flat
[ypeak,xpeak] = find(c==max(c(:)));
yoffSet = ypeak-size(cpiece,1);
xoffSet = xpeak-size(cpiece,2);
figure(3)
imshow(bild)
drawrectangle(gca,'Position',[xoffSet,yoffSet,size(cpiece,2),size(cpiece,1)],'FaceAlpha',0);
It seems, the problem returns back to the quality of your template image, And Check if the scales between original image and the template are exactly the same

Image blending with mask

I'm trying to combine the two images based on the information from the mask. I'm using the color information from the background image if the mask is 0 and color information from foreground image if the mask is 1. Because the mask and both
Images are of the same size, I would like to use logical indexing of matrices to achieve this.
My attempt:
mask = imread('mask.png');
foreground = imread('fg.jpg');
background = imread('bg.jpg');
[r,c,~]=size(mask);
A = zeros(size(mask));
for i=1:r
for j=1:c
if mask(i,j) == 0
A(i,j,:) = background(i,j,:);
end
if mask(i,j) > 0
A(i,j,:) = foreground(i,j,:);
end
end
end
imshow(A);
The result looks like a flickering blue image, but I don't want that. Please help.
You can do this a bit more concisely:
f = double(foreground).*double(mask);
b = double(background).*double(~mask);
blend = f+b;
imshow(blend, []);
Using logical indexing you could also do
foreground(logical(mask)) = 0;
background(logical(~mask)) = 0;
blend = foreground+background;
The ISNOT operator '~' inverts your matrix in the second line, so you cut out the area you would like for background.
NOTE: This works for black and white (one channel). For coloured images see rayryeng's solution.
There are two problems with your code. The first problem is that you are trying to assign colour pixels to the output image A, yet this image is only two-dimensional. You want an image with three channels, not two. In addition, the output image type you are specifying is wrong. By default, the output image A is of type double, yet you are copying values into it that aren't double... most likely unsigned 8-bit integer.
As such, cast the image to the same type as the input images. Assuming both input images are the same type, initialize your A so that:
A = zeros(size(foreground), class(foreground));
This correctly makes a colour image with the same type as any of the inputs, assuming that they're both the same type.
Now, your for loop is fine, but it's better if you do this in one shot with logical indexing. If you want to use logical indexing, create a new image that's initially blank like what you've done, but then make sure your mask has three channels to match the number of channels the other images have. After, you simply need to index into each image and set the right locations accordingly:
mask = imread('mask.png');
foreground = imread('fg.jpg');
background = imread('bg.jpg');
[r,c,d]=size(mask); %// Change
%// If your mask isn't three channels, make it so
%// Change
if d ~= 3
mask = cat(3, mask, mask, mask);
end
A = zeros(size(foreground), class(foreground)); %// Change
A(mask) = foreground(mask); %// Assign pixels to foreground
A(~mask) = background(~mask); %// Assign pixels to background
imshow(A);

Removing Noise From an image in MATLAB

I'm using Geometric mean filter to remove noise instead of median filter as image quality goes off in former case. code shown below is a part of m-file to remove noise.
fname = getappdata(0, 'fname');
[a, map] = imread(fname);
x = ind2rgb(a, map);
b = im2double(x);
w=fspecial('gaussian',[3,3]);
geom=exp(imfilter(log(b),ones(3,3),'replicate')).^(1/3/3);
fname=imfilter(b,w,'replicate');
axes(handles.axes1);
imshow(fname);
If i press push button which is named 'Remove Noise' above code get executed irrespective of image quality/property. In the sense even if no noise is present, image will be subjected to filter.
My question, is there any way to detect whether noise is present or not, so that the moment i pressed push button if no Noise in image it should display a message stating 'NO NOISE TO REMOVE' automatically.
There is no direct way to determine whether an image is noisy or not.
However, you can compare resulting image fname with the input image b in such a way that if their difference is lower than a certain threshold, then it can be decided that denoising operation has not changed image effectively and there is not much noise in the original image like:
threshold_ratio = 0.2; % to be decided experimentally
difference_ratio = sum(sum((fname - b).^2)) / sum(sum(b.^2));
if difference_ratio < threshold_ratio
disp('NO NOISE TO REMOVE');
end

Converting a grayscale image to black and white

I have a grayscale image that only has the values 60 and 117. How can I convert the image to only black and white without graylevels?
I tried the matlab function gray2ind, but didn't get the expected output.
Thanks.
Try im2bw(img, level) with level = 0.5.
This is a matlab function that takes a grayscale image img, applies a threshold of level (a value between [0,1]) and returns a black and white image.
This function is part of the Image Processing Toolbox. Your case is simple enough that you could also try something like:
bwImg = false(size(img));
bwImg(img == 117) = true;
I edited the above to set values equal to false/true to more closely mimic Matlab's im2bw() which returns a matrix of logical values rather than ints.
2nd Edit: Modified the code block to reflect improvements suggested by #Amro

Matlab: How can I display several outputs in the same image?

Let's say my image is img=zeros(100,100,3), my outputs are several ellipse which i get using a created function [ret]=draw_ellipse(x,y,a,b,angle,color,img), I can display one ellipse using imshow(ret).For the moment, I'm trying to show serval ellipse in the image. But i don't know how to code it. will ‘for loop’ work or I need to hold them?
If this is related to what you were doing in your previous question, then what you need to do is to pass the result of one iteration as input to the next.
So assuming that the function [ret]=draw_ellipse(x,y,a,b,angle,color,img) you mentioned takes as input an image img and returns the same image with an ellipse drawn on it, you could do this:
%# ellipses parameters
%#x = {..}; y = {..};
%#a = {..}; b = {..};
%#angle = {..}; color = {..};
img = zeros(200,100,'uint8'); %# image to start with
for i=1:10
img = draw_ellipse(x{i},y{i}, a{i},b{i}, angle{i}, color{i}, img);
end
imshow(img)
I'm a bit unsure of what you want. You want to show several ellipse in one image, like plotting several graphs with hold on?
There is no equivalent command for images, but a simple solution is to add the ellipses into one image and show that one:
several_ellipse = ellipse1 + ellipse2 + ellipse3;
imshow(several_ellipse)
Presumably you want to pass ret as the final input to the next call to draw_ellipse.

Resources