From: Kumar on
Hi,

I have an image with a object that has two bays: one on left side and other on the right. Now i want to fill the bay with a convex edge, which is only in right automatically. Can someone suggest me how to do this. Thanks
From: ImageAnalyst on
Kumar
Use the convex hull function.
Write back (and post your image somewhere) if you can't figure it out.
-ImageAnalyst
From: Kumar on
ImageAnalyst <imageanalyst(a)mailinator.com> wrote in message <0931727d-815f-48b7-a25f-921312f7fcd6(a)i1g2000vbk.googlegroups.com>...
> Kumar
> Use the convex hull function.
> Write back (and post your image somewhere) if you can't figure it out.
> -ImageAnalyst

Hi,
Thanks for the reply. How to implement using complex hull. I have posted my image. The image has two bays. I want to fill the bottom bay only. and is it possible to do it automatically.
http://img210.imageshack.us/img210/9296/bayk.png
Thank You
From: ImageAnalyst on
Here's a demo I wrote. Read the comments and follow along. It
demonstrates how to take the convex hull of individual blobs as well
as the convex hull of a group of blobs. Some important items to
note: The newsreader will split lines that are too long into separate
lines. You must join those together. And you must have the Image
Processing Toolbox and correct the filename to the proper folder if
you don't have the R2010a version of MATLAB. After you've pasted the
code in, you may have to save the file as an m-file called
"convexhulldemo.m" (This is because it has another function in it so
it can't be a simple script which could have any name.)

In your case, once you have the convex hull, you'd need to subtract
your original binary image from the convex hull image to get an image
of your two bays. Then label and call regionprops and find the
centroids to get the lowe blob (bay). Then use the PixelIdxList to
add those pixels of the bottom bay back into the original binary
image.
-ImageAnalyst

% Demo to show a use case for the overall convex hull of a group/
cluster/collection of binary blobs,
% as well as a demo of two different ways to do the convex hull of the
group (mine and Steve Eddin's),
% and a way to do convex hull of individual blobs rather than the
whole collection of them.
function convexhulldemo()
% Clean up.
clc;
clear all;
close all;
workspace;

% Open up an image -- the standard MATLAB demo image of the coins.
filename = 'C:\Program Files\MATLAB\R2010a\toolbox\images\imdemos
\coins.png'; % Standard demo image.
originalImage = imread(filename);
subplot(3, 3, 1);
imshow(originalImage, []);
title('Original Image');
set(gcf, 'Position', get(0, 'ScreenSize')); % Maximize figure.

% Threshold the image.
binaryImage = originalImage > 100;
subplot(3, 3, 2);
imshow(binaryImage, []);
title('Thresholded Image');

% Take the convex hull of all 10 coins.
[convexHullImage hullVerticesX hullVerticesY] =
imConvexHull(binaryImage);
subplot(3, 3, 3);
imshow(convexHullImage, []);
title('Convex Hull of All 10 Coins');

% Show original image with convex hull outline plotted over it.
subplot(3, 3, 4);
imshow(originalImage, []);
hold on;
plot(hullVerticesX, hullVerticesY, 'r');
title('Convex Hull Outline of All 10 Coins');

% Calculate the Euclidean Distance Map.
edmImage = bwdist(binaryImage);
subplot(3, 3, 5);
imshow(edmImage, []);
title('Original EDM Image - note high values in corners');

% Mask it by the convex hull.
edmImage2 = edmImage .* single(convexHullImage);
maxDistance = max(max(edmImage2));
edmImageNorm = edmImage2 / maxDistance;
subplot(3, 3, 6);
imshow(edmImage2, []);
title('Masked EDM Image');

% Get the histogram of the masked EDM Image.
[counts gls] = imhist(edmImageNorm, 40);
maxY = max(counts(2:end));
subplot(3, 3, 7);
bar(gls, counts);
ylim([0 maxY * 1.05]);
xlim([0 1]);
title('Histogram of Masked EDM Image');

% Skeletonize it so that we get just the ridgelines of the EDM.
skeletonImage = edmImage2>0;
skeletonImage2 = bwmorph(skeletonImage, 'skel', inf);
subplot(3, 3, 8);
imshow(skeletonImage2, []);
title('Skeleton of the Masked EDM Image');

% Multiply the masked EDM by the skeleton so we have ONLY ridgeline
pixels.
ridgeImage = (edmImage2 .* single(skeletonImage2)) / maxDistance;
[counts gls] = imhist(ridgeImage, 40);
maxY = max(counts(2:end));
subplot(3, 3, 9);
bar(gls, counts);
ylim([0 maxY * 1.05]);
xlim([0 1]);
title('Histogram of only the Ridgelines of the Masked EDM Image');

%-------------------------------------------------------------
% Now let's try Steve Eddins's function.
hFig2 = figure; % Open up new, separate figure window.
set(gcf, 'Position', 0.75 * get(0, 'ScreenSize')); % Maximize figure.
CenterFigure(hFig2);

% Open up an image.
subplot(2, 3, 1);
imshow(originalImage, []);
title('Original Image');

% Cut some notches in the coins so we can see the effect of individual
convex hulls.
notchedCoinsImage = originalImage;
notchedCoinsImage(40:60, 40:82) = 65;
notchedCoinsImage(20:40, 130:180) = 65;
notchedCoinsImage(60:80, 200:250) = 65;
notchedCoinsImage(140:160, 80:130) = 65;
notchedCoinsImage(110:130, 160:210) = 65;
notchedCoinsImage(60:90, 100:120) = 65;
notchedCoinsImage(140:180, 230:240) = 65;
notchedCoinsImage(100:140, 30:40) = 65;
notchedCoinsImage(100:140, 30:40) = 65;
notchedCoinsImage(200:220, 80:140) = 65;
subplot(2, 3, 2);
imshow(notchedCoinsImage, []);
title('Notched Coins Image');

% Threshold the image.
binaryImage2 = notchedCoinsImage > 100;
subplot(2, 3, 3);
imshow(binaryImage2, []);
title('Thresholded Image');

% Take the convex hull using Steve's function (returns CH of all 10
coins.)
convexHullImage = bwconvhull(binaryImage2);
subplot(2, 3, 5);
imshow(convexHullImage, []);
title('Convex Hull of All 10 Coins');

% Label the image.
labeledImage = bwconncomp(binaryImage2);
% Call regionprops
blobMeasurements = regionprops(labeledImage, 'all');
numberOfBlobs = length(blobMeasurements);
[rows columns] = size(binaryImage2);

% Get convex hull of each blob in the image independently.
% It would sure be nice if this were easier.
% The "ConvexImage" returned by regionprops doesn't return full size
images, just subimages.
% So if we want the convex hull of each blob independently, we have to
loop over all blobs
% getting the CH for each blob one at a time, then adding it to the
cumulative CH image.
CHofEachBlob = zeros(rows, columns);
for blob = 1 : numberOfBlobs
CHofThisBlob = [blobMeasurements(blob).ConvexHull];
CHImageForThisBlob = poly2mask(CHofThisBlob(:,1), CHofThisBlob(:,2),
rows, columns);
CHofEachBlob = CHofEachBlob + CHImageForThisBlob;
end
subplot(2, 3, 6);
imshow(CHofEachBlob, []);
title('Convex Hull of each coin independently');

return; % End of the main convexhulldemo() routine.


%-------------------------------------------------------------------------------------
% Mark Hayworth's version to get the convex hull of the entire group
of blobs.
function [convexHullImage hullVerticesX hullVerticesY] =
imConvexHull(binaryImage)
[rows columns] = size(binaryImage);
boundaries = bwboundaries(binaryImage);
numberOfBlobs = size(boundaries, 1);
blobVertices = [];
for k = 1 : numberOfBlobs
thisBoundary = boundaries{k};
blobVertices = [blobVertices; thisBoundary];
hold on;
plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 2);
end
hullIndexes = convhull(blobVertices(:,2), blobVertices(:,1));
hullVerticesX = blobVertices(hullIndexes,2);
hullVerticesY = blobVertices(hullIndexes,1);
convexHullImage = poly2mask(hullVerticesX, hullVerticesY, rows,
columns);
return;


%-------------------------------------------------------------------------------------
% Steven L. Eddins's version to get the convex hull of the entire
group of blobs.
function out = bwconvhull(in)
%BWCONVHULL Convex hull of binary image
% bw2 = bwconvhull(bw) computes the convex hull of the input binary
image, bw,
% and returns it as another binary image, bw2. bw2 has the same
size as bw.
%
% bw must be two-dimensional.

% Steven L. Eddins
% Copyright 2009 The MathWorks, Inc.

if ~islogical(in)
in = in ~= 0;
end

% Convert input from logical to uint8. This will cause regionprops to
treat
% it as a label matrix, and so every foreground pixel will be treated
as part of
% the same object.
in = uint8(in);

s = regionprops(in, 'BoundingBox', 'ConvexImage');

% regionprops returns an image only big enough to just cover the
bounding box of
% the "object." Compute the row and column indices corresponding to
that
% bounding box.
m = s.BoundingBox(4);
n = s.BoundingBox(3);
r1 = s.BoundingBox(2) + 0.5;
c1 = s.BoundingBox(1) + 0.5;
r = (1:m) + r1 - 1;
c = (1:n) + c1 - 1;

out = false(size(in));
out(r,c) = s.ConvexImage;


%-------------------------------------------------------------------------------------
% Function to center a figure on the screen (if it's not maximized).
function CenterFigure(handleToFigure)
% The figure Position property
% does not include the window borders, so this example uses a width
of 5 pixels
% on the sides and bottom and 30 pixels on the top.
borderWidth = 5;
titleBarWidth = 30;
% Ensure root units are pixels and get the size of the screen:
set(0, 'Units', 'pixels');
set(handleToFigure, 'Units', 'pixels');
% Get the screen size in pixels.
screenSize = get(0,'ScreenSize');
% Get the size of the window.
initialFigurePosition = get(handleToFigure, 'Position');
% Create an array that will center it.
centeredX = (screenSize(3) - initialFigurePosition(3)) / 2;
centeredY = (screenSize(4) - initialFigurePosition(4)) / 2;
centeredPosition = [centeredX,...
centeredY,...
initialFigurePosition(3),...
initialFigurePosition(4)];
set(handleToFigure, 'Position', centeredPosition);
return; % from CenterFigure()

From: Kumar on
Hi,
Thanks a lot for the demo. I understood the concept of convhull and also i got the convex hull of my image. I find difficulty in selecting only the lower blob (blue in attached pic 1) and adding with the original one. I have attached the original,convexhulled image and also the centroid found images. I also used the PixelIdxList to find the Pixel Ids. But dont know how to slelect the lower blob alone and add to the original image .

http://img690.imageshack.us/img690/7730/79787570.png
http://img820.imageshack.us/img820/5778/44339530.png
http://img17.imageshack.us/img17/4452/59463564.png

Can you tell me how to do this.
Thank You.