Rice grain Segmentation in Matlab - image

I have an image of multiple rice grains in jpg format. I need to separate the individual rice grains into a separate images.
The input image is as below:
The resultant images should contain individual rice as below:
Currently I am using the following code:
close all;
BW = imread('img11_Inp','jpg');
L = bwlabel(BW)
figure
imshow(BW);
CC = bwconncomp(L);
stats = regionprops(L,'Image');
stats
%Display the first component as an image
Image1 = stats(2).Image
figure
imshow(Image1);
There are two problems with this code. Firstly, it is showing only two images rice grains in the "stats" structure and secondly it is also showing some noise. Please let me know what is the problem with this code

Look at this code with the comments
close all;
clear
I = imread('rice.jpg'); % jpg add noise. TODO: use png format
level = graythresh(I); % Global image threshold using Otsu's method
BW1 = imbinarize(I,level); % need to threshold, jpg add low level noise.
BW2 = imfill(BW1,'holes'); %fill holes inside grains
[L,n] = bwlabel(BW2); % label connected components
B = labeloverlay(I,L);
figure('Name',sprintf('NLables=%d',n)); imshow(B);
stats = regionprops(L,{'Centroid','Area'});
for i=1:length(stats)
x=stats.Centroid(i,1);
y=stats.Centroid(i,2);
area=stats.Area(i);
text(x,y,sprintf('Area=%d',area),'FontSize',8);
end

Related

for loop causing bad text segmentation in matlab

the input images are a.jpg and b.jpg
these two image stored in for example comp folder.and want to write the segmented image in segment folder.but I think for looping problem segmentation repeated for so many times for each image.And I could't solve the problem.
here is my code
Resultado='C:\Users\Nurul\Desktop\picsegment';
srcFiles = dir('C:\Users\Nurul\Desktop\comp\*.jpg');
for i = 1 : length(srcFiles)
filename = strcat('C:\Users\Nurul\Desktop\comp\',srcFiles(i).name);
a = imread(filename);
LLL=a;
s=regionprops(LLL);
figure,imshow(LLL); title('segmented Image');
hold on
for J=1:numel(s)
rectangle('Position',s(J).BoundingBox,'edgecolor','g')
end
im1=LLL;
baseFileName = sprintf('%d.jpg', i); % e.g. "1.png"
fullFileName = fullfile(Resultado, baseFileName);
imwrite(im1, fullFileName);
end
plz help
thanks
You are saving your data as jpg, big mistake!
Still, if you want to keep the data saved as jpg, remember that it will not be saved as a binary image, and that means you need to binarize it again! Otherwise, every little pixel noise will be detected as data by regionprops, thats why you get so many squares.
Just add
a = imread(filename);
a=im2bw(a,0.5); % Add this line. The fancy way would be im2bw(a,graythresh(a)), but 0.5 will do in your case
LLL=a;

dotted output after skeletonization in matlab

I wish to skeletonize this image
To do so i am using matlab's bwmorph function, Here is the snippet :
bw = bwmorph(img_bw,'skel',Inf);
However the output is not as expected. Here is the output.
Could someone suggest a better way to achieve proper results ?
EDIT: here is a stripped down relevant code
img = imread(name);
img = rgb2gray(img*4);
img_bw = img > 50;
img_bw = medfilt2(img_bw,[10 10]);
bw = bwmorph(img_bw,'skel',Inf);
What you see is aliasing, the imshow function can not display the full image because it is to large to fit the screen. To fit the screen some rows and columns are skipped, which cause the lines to be disconnected. To display an image at full resolution using a scrollpanel, use imscrollpanel
hFig = figure('Toolbar','none', 'Menubar','none');
hIm = imshow(bw);
hSP = imscrollpanel(hFig,hIm);

Compare two images and highlight differences along on the second image

Below is the current working code in python using PIL for highlighting the difference between the two images. But rest of the images is blacken.
Currently i want to show the background as well along with the highlighted image.
Is there anyway i can keep the show the background lighter and just highlight the differences.
from PIL import Image, ImageChops
point_table = ([0] + ([255] * 255))
def black_or_b(a, b):
diff = ImageChops.difference(a, b)
diff = diff.convert('L')
# diff = diff.point(point_table)
h,w=diff.size
new = diff.convert('RGB')
new.paste(b, mask=diff)
return new
a = Image.open('i1.png')
b = Image.open('i2.png')
c = black_or_b(a, b)
c.save('diff.png')
!https://drive.google.com/file/d/0BylgVQ7RN4ZhTUtUU1hmc1FUVlE/view?usp=sharing
PIL does have some handy image manipulation methods,
but also a lot of shortcomings when one wants
to start doing serious image processing -
Most Python lterature will recomend you to switch
to use NumPy over your pixel data, wich will give
you full control -
Other imaging libraries such as leptonica, gegl and vips
all have Python bindings and a range of nice function
for image composition/segmentation.
In this case, the thing is to imagine how one would
get to the desired output in an image manipulation program:
You'd have a black (or other color) shade to place over
the original image, and over this, paste the second image,
but using a threshold (i.e. a pixel either is equal or
is different - all intermediate values should be rounded
to "different) of the differences as a mask to the second image.
I modified your function to create such a composition -
from PIL import Image, ImageChops, ImageDraw
point_table = ([0] + ([255] * 255))
def new_gray(size, color):
img = Image.new('L',size)
dr = ImageDraw.Draw(img)
dr.rectangle((0,0) + size, color)
return img
def black_or_b(a, b, opacity=0.85):
diff = ImageChops.difference(a, b)
diff = diff.convert('L')
# Hack: there is no threshold in PILL,
# so we add the difference with itself to do
# a poor man's thresholding of the mask:
#(the values for equal pixels- 0 - don't add up)
thresholded_diff = diff
for repeat in range(3):
thresholded_diff = ImageChops.add(thresholded_diff, thresholded_diff)
h,w = size = diff.size
mask = new_gray(size, int(255 * (opacity)))
shade = new_gray(size, 0)
new = a.copy()
new.paste(shade, mask=mask)
# To have the original image show partially
# on the final result, simply put "diff" instead of thresholded_diff bellow
new.paste(b, mask=thresholded_diff)
return new
a = Image.open('a.png')
b = Image.open('b.png')
c = black_or_b(a, b)
c.save('c.png')
Here's a solution using libvips:
import sys
from gi.repository import Vips
a = Vips.Image.new_from_file(sys.argv[1], access = Vips.Access.SEQUENTIAL)
b = Vips.Image.new_from_file(sys.argv[2], access = Vips.Access.SEQUENTIAL)
# a != b makes an N-band image with 0/255 for false/true ... we have to OR the
# bands together to get a 1-band mask image which is true for pixels which
# differ in any band
mask = (a != b).bandbool("or")
# now pick pixels from a or b with the mask ... dim false pixels down
diff = mask.ifthenelse(a, b * 0.2)
diff.write_to_file(sys.argv[3])
With PNG images, most CPU time is spent in PNG read and write, so vips is only a bit faster than the PIL solution.
libvips does use a lot less memory, especially for large images. libvips is a streaming library: it can load, process and save the result all at the same time, it does not need to have the whole image loaded into memory before it can start work.
For a 10,000 x 10,000 RGB tif, libvips is about twice as fast and needs about 1/10th the memory.
If you're not wedded to the idea of using Python, there are a few really simple solutions using ImageMagick:
“Diff” an image using ImageMagick

How to make gif images from a set of images in matlab?

How to make '.gif' image from a set of '.jpg' images (say: I1.jpg, I2.jpg,..., I10.jpg) in matlab?
Ok here is a simple example. I got an image with a unicorn on it and remove 2 part to create 3 different images, just for the sake of creating an animated gif. Here is what it looks like:
clear
clc
%// Image source: http:\\giantbomb.com
A = rgb2gray(imread('Unicorn1.jpg'));
B = rgb2gray(imread('Unicorn2.jpg'));
C = rgb2gray(imread('Unicorn3.jpg'));
ImageCell = {A;B;C};
figure;
subplot(131)
imshow(A)
subplot(132)
imshow(B)
subplot(133)
imshow(C)
%// Just to show what the images look like (I removed spots to make sure there was an animation created):
%// Create file name.
FileName = 'UnicornAnimation.gif';
for k = 1:numel(ImageCell)
if k ==1
%// For 1st image, start the 'LoopCount'.
imwrite(ImageCell{k},FileName,'gif','LoopCount',Inf,'DelayTime',1);
else
imwrite(ImageCell{k},FileName,'gif','WriteMode','append','DelayTime',1);
end
end
As you see, its not that different from the example on the Mathworks website. Here my images are in a cell array but yours might be in a regular array or something else.That should work fine; when I open 'UnicornAnimation.gif' it is indeed a nice animation!
Hope that helps!

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

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

Resources