segmentation of rice grains and sub plotting individual grains

18 views (last 30 days)
in the code attached, i want all the segmented rice images to appear in the form of subplot but this code keeps me giving the output as the last rice image in subplot.Thanks in advance.(this code was developed with the help of some codes present on the internet)
a=imread('r-1121.jpeg');
figure,imshow(a);
title('original image');
I1 = rgb2gray(a);
I1=imsharpen(I1);
I=medfilt2(I1);
b=imbinarize(I);
figure,
imshow(b);
c=imfill(b,'holes');
label=bwlabel(c);
for j=1:max(max(label))
[row,col]=find(label==j);
len=max(row)-min(row)+2;
breadth=max(col)-min(col)+2;
target=uint8(zeros([len breadth] ));
sy=min(col)-1;
sx=min(row)-1;
for i=1:size(row,1)
x=row(i,1)-sx;
y=col(i,1)-sy;
target(x,y)=a(row(i,1),col(i,1));
end
for k=1:25
mytitle=strcat('Rice number: ',num2str(j));
ax=subplot(1,25,k);
imshow(target);
end
end

Accepted Answer

DGM
DGM on 4 Jun 2021
Edited: DGM on 4 Jun 2021
You don't need the inner plot loop, and some other stuff can be simplified. I just removed the figure and imshow previews for brevity.
a=imread('rice.jpg');
I1 = rgb2gray(a);
I1=imsharpen(I1);
I=medfilt2(I1);
b=imbinarize(I);
c=imfill(b,'holes');
label=bwlabel(c);
numgrains = max(label(:));
for j=1:numgrains
[row,col]=find(label==j);
len=max(row)-min(row)+2;
breadth=max(col)-min(col)+2;
xrange = min(col)-1+(0:breadth);
yrange = min(row)-1+(0:len);
target = a(yrange,xrange) .* uint8(c(yrange,xrange)); % NOTE
mytitle=strcat('Rice number: ',num2str(j)); % not used yet
ax=subplot(1,numgrains,j);
imshow(target);
end
Alternatively, you can get the location using regionprops():
a=imread('rice.jpg');
I1 = rgb2gray(a);
I1=imsharpen(I1);
I=medfilt2(I1);
b=imbinarize(I);
c=imfill(b,'holes');
S=regionprops(c,'boundingbox');
numgrains = numel(S);
for j=1:numgrains
tp = round(S(j).BoundingBox);
xrange = tp(1)+(-1:tp(3)+1);
yrange = tp(2)+(-1:tp(4)+1);
target = a(yrange,xrange) .* uint8(c(yrange,xrange)); % NOTE
mytitle=strcat('Rice number: ',num2str(j)); % not used yet
ax=subplot(1,numgrains,j);
imshow(target);
end
You might need to tweak the subscript vectors by a pixel to get your padding exactly as you want it.
In both examples, I made a note on the same line. In your original code, the pointwise method only extracts the portion of the image selected by the mask c. If on the other hand, you wanted to select the region of the image defined by the bounding box you calculate around the image, then change that line to
target = a(yrange,xrange);
The first method truncates the edges of the grains according to the mask and makes them jagged. The second method shows the grains with their local background and natural edges. Which to use depends what your intent is for using the images of the objects.
  2 Comments
DGM
DGM on 6 Jun 2021
Edited: DGM on 6 Jun 2021
You can try something like this
a=imread('rice.jpg');
I1 = rgb2gray(a);
I1=imsharpen(I1);
I=medfilt2(I1);
b=imbinarize(I);
c=imfill(b,'holes');
S=regionprops(c,'boundingbox');
bb = vertcat(S.BoundingBox);
maxbb = max(bb(:,[4 3])); % minimal box geometry
maxbb = maxbb+5; % add some extra room
numgrains = numel(S);
for j=1:numgrains
tp = round(S(j).BoundingBox);
xrange = tp(1)+(-1:tp(3)+1);
yrange = tp(2)+(-1:tp(4)+1);
% this was from the prior answer
%target = a(yrange,xrange) .* uint8(c(yrange,xrange));
% alternatively, start out with no masking
target = a(yrange,xrange);
% maybe you could improve the range (normalize)
% this helps get the photo bg closer to black
target = mat2gray(target);
% you could use a dilated mask
tm = double(imdilate(c(yrange,xrange),ones(3)));
% or maybe soften the mask as well
tm = imfilter(tm,fspecial('gaussian'));
% apply the mask
target = im2uint8(im2double(target) .* tm);
% this pads with black to match sizes
bs = (maxbb-size(target))/2;
target = padarray(target,floor(bs),0,'pre');
target = padarray(target,ceil(bs),0,'post');
mytitle=strcat('Rice number: ',num2str(j)); % not used yet
ax=subplot(1,numgrains,j);
imshow(target);
end
I used a 5x5 subplot tiling so it's easier to fit in my window. Use whatever tiling you need.
This could probably be faster if the dilation and blurring were done on a copy of c prior to the loop, but doing it this way makes it easier to demonstrate the sequence of options in one place. I doubt the difference is really worth the extra hassle. Doing the normalization in the loop is preferred, as it only helps to compensate for local lighting variation.
sana fatima
sana fatima on 6 Jun 2021
Thank you @DGM. will further consullt you if i come across any problem.

Sign in to comment.

More Answers (2)

sana fatima
sana fatima on 5 Jun 2021
Edited: sana fatima on 5 Jun 2021
thank you so much for this code. Had been trying this for so long. just need to ask one thing,
1) can we smooth these jagged boundries(the edges)
2) can the frame size be same for all the grains, some have bigger frame and some have smaller, just need them to be in a frames of same size.
thank you so much once again.
  3 Comments
sana fatima
sana fatima on 6 Jun 2021
should i copy my question above where i had intially posted my question(the first one)?
DGM
DGM on 6 Jun 2021
eh. don't worry about it. i already just posted the followup as a comment. just keep it in mind for the future.

Sign in to comment.


sana fatima
sana fatima on 14 Jun 2021
I have made a code that gives features like major axis length, minor axis length, ecentricity etc but on average of rice grains present in an image. now i have no idea how should i implement those features on individual rice grains so that when two different varieties of rice grains are given as input it classifies those grains based on their respective features. For suppose when IRRI6 and 386 white rice are given as input in mixed form, it should classify that this grain is of IRRI6 along with its features(major axis, minor axis, ecentricity.Here, I am attaching a screenshot of my output window.

Categories

Find more on Image Processing Toolbox in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!