1
$\begingroup$

I am new to MATLAB/Digital Image Processing. So pardon me for any typing errors or wrong use of jargon.

1) I am trying to find the paste diameters for a total of 100 images in sequence. I am posting only one of the RGB images here. enter image description here

2) I have attempted using imfindcircles and regionprops to find the diameters. imfindcircles demands a min and max radius range and since I have evolving paste diameters (for 100 images) it does not seem to be applicable. After some image segmentation and applying regionprops, the diameters were also not accurate.

3) What I have achieved so far using the image segmentation techniques is: enter image description here using the following code:

A = imread('ref.jpg');
I = imsharpen(A);
I = rgb2gray(I);   
I = imadjust(I);
I = im2bw(I);
I = imcomplement(I);
I = im2bw(I, .8);
I = bwareaopen(I,2000);
nhood = true(9);
I = imclose(I,nhood);
I = imfill(I,'holes');
I = imcomplement(I);
I = bwareafilt(I,1,'largest');
imshow(I)

4) But I actually require is this (A perfect circle). With this I can find the pixel area and then the diameters:

enter image description here

5) Please suggest an alternate way to measure the diameter of the paste or help me reach step 4. I need to segment it from the mould (noise) above. Also I would like to reiterate that I have a bundle of images so any user-defined technique such as imdistline wont work.

Please let me know if you have any follow-up questions

Thankyou

$\endgroup$
0
$\begingroup$

This problem can probably be solved easier if there is a known relationship between the camera position and the metallic device that is over the paste. If the device and the camera are both fixed, for example, it would be easy to use a picture of the device without the paste to eliminate it from the other pictures.

But here is one suggestion for measuring the diameter of the paste using only this given image. I'm using DIPimage, because I know it best. I'm sure the same can be accomplished with the Image Processing Toolbox.

% Read in image:
img = readim('https://i.stack.imgur.com/5FLCs.jpg');
img = img{2}; % Use the green channel
% Alternating sequential filters to keep only the dark big circular shapes
paste = opening(img,15,'elliptic','add max');
paste = closing(paste,30,'elliptic','add max');
paste = opening(paste,60,'elliptic','add max');
paste = closing(paste,90,'elliptic','add max');
paste = opening(paste,120,'elliptic','add max');

The sequence of opening and closing are meant to remove specular reflections and much of the metallic device. Here is what the image looks like after this step:

enter image description here

There are some bulges to the left still, I didn't put any effort into trying to remove those, because there is sufficient outline for correct measurement.

% Find paste outline:
labs = label(~threshold(paste,'otsu')); % threshold and label
D = traceobjects(labs,[],2,'convex hull'); % get object outlines
[~,index] = max(cellfun(@length,D)); % find the longest outline
D = D{index}; % keep only the longest outline
% Display:
dipshow(img)
hold on
plot(D(:,1),D(:,2),'r')

This shows the convex hull of the outline over the original image, to show that the filtering didn't move the edges of the paste:

enter image description here

Next, I'll use code to list antipodal pairs that I get from this blog post. These are points on opposite side of the convex hull. This is the reason I used traceobjects with the 'convex hull' option, the algorithm to list antipodal pairs only works with a convex hull.

% Signed area of triangle
area = @(pt1,pt2,pt3) ( (pt2(1)-pt1(1))*(pt3(2)-pt1(2)) - ...
                        (pt2(2)-pt1(2))*(pt3(1)-pt1(1)) ) / 2;
% Height of triangle, pt3 is the top vertex
height = @(pt1,pt2,pt3) ( (pt2(1)-pt1(1))*(pt3(2)-pt1(2)) - ...
                          (pt2(2)-pt1(2))*(pt3(1)-pt1(1)) ) / ...
                                               norm(pt2-pt1);
% Next point along the polygon
next = @(p,N) mod(p,N)+1;

diameters = [];
N = size(D,1);
p0 = N;
p = 1;
q = 2;
while area(D(p,:),D(next(p,N),:),D(next(q,N),:)) > ...
      area(D(p,:),D(next(p,N),:),D(q,:))
   q = next(q,N);
end
q0 = q;
while p~=p0
   p = next(p,N);
   listq = q;                       % p,q is an antipodal pair
   while area(D(p,:),D(next(p,N),:),D(next(q,N),:)) > ...
         area(D(p,:),D(next(p,N),:),D(q,:))
      q = next(q,N);
      listq(end+1) = q;             % p,q is an antipodal pair
   end
   if area(D(p,:),D(next(p,N),:),D(next(q,N),:)) == ...
      area(D(p,:),D(next(p,N),:),D(q,:))
      listq(end+1) = next(q,N);     % p,q+1 is an antipodal pair
   end
   disp(listq)
   for ii=1:length(listq)
      v = D(p,:)-D(q,:);
      d = norm(v);
      diameters(end+1) = d;
   end
end

Finally, we can use these distances between antipodal pairs to find the average diameter of the paste. We'll assume that about 1/3 of the boundary is affected by the bulges on the left that I didn't completely remove. Therefore we'll use the 2/3 smallest values, and take the mean of those:

diameters = sort(diameters);
diameters = diameters(1:round(length(diameters)*2/3));
disp(mean(diameters))

This gives me 773.25 pixels. You will need to know the size of a pixel to translate this value to physical units.

$\endgroup$
  • $\begingroup$ Thankyou for your help:) 1. The camera is static, but the mould is moveable to allow the paste flow over a static plate underneath. Since I am new to MATLAB (and do not have a programming background either), I would like you to ask about this "DIPImage" Toolbox, Do I need to install it first? Can you assist me in running it in a MATLAB enviroment '.m file' ? $\endgroup$ – Usman Mahmood Apr 18 '18 at 11:06
  • $\begingroup$ By the time I try to install the DIPImage lib, can you try to fix the bulges in the second image you shared? The only purpose is displaying it flawlessly in a GUI to my collegues (Otherwise we can measure the diameter anyway). Again what you've done is very helpful. Thankyou very much! $\endgroup$ – Usman Mahmood Apr 18 '18 at 11:18
  • $\begingroup$ Yes, you need to install DIPimage to run this code. The released version is easy to install (and free for non-commercial purposes), but doesn't have the traceobjects function. The version on GitHub you need to compile yourself, but is completely free and does have the traceobjects function. I believe you can do everything I outline here with stuff from the IP Toolbox. traceobjects can be replaced with regionprops, for example. $\endgroup$ – Cris Luengo Apr 18 '18 at 17:05
  • $\begingroup$ Regarding your second comment, no, I'm not part of your team. I spent 20 minutes posting this answer because I thought it was an interesting challenge and I hoped you would learn something from it. Now you're supposed to take this and build it out. $\endgroup$ – Cris Luengo Apr 18 '18 at 17:05
  • $\begingroup$ Fair Enough, Thankyou very much for your help :) $\endgroup$ – Usman Mahmood Apr 19 '18 at 6:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.