MATLAB Image Processing - Find Edge and Area of Image

image-processing, matlab

Solution

You might want to consider Active Contours. This will give you a continous boundary of the object rather than patchy edges.

Below are links to

A book:

http://www.amazon.co.uk/Active-Contours-Application-Techniques-Statistics/dp/1447115570/ref=sr_1_fkmr2_1?ie=UTF8&qid=1377248739&sr=8-1-fkmr2&keywords=Active+shape+models+Andrew+Blake%2C+Michael+Isard

A demo: http://users.ecs.soton.ac.uk/msn/book/new_demo/Snakes/

and some Matlab code on the File Exchange: http://www.mathworks.co.uk/matlabcentral/fileexchange/28149-snake-active-contour

and a link to a description on how to implement it: http://www.cb.uu.se/~cris/blog/index.php/archives/217

Using the implementation on the File Exchange, you can get something like this:

%% Load the image
% You could use the segmented image obtained previously
% and then apply the snake on that (although I use the original image).
% This will probably make the snake work better and the edges
% in your image is not that well defined.
% Make sure the original and the segmented image 
% have the same size. They don't at the moment
I = imread('33kew0g.jpg');

% Convert the image to double data type
I = im2double(I); 
% Show the image and select some points with the mouse (at least 4)
% figure, imshow(I); [y,x] = getpts; 
% I have pre-selected the coordinates already
x = [  525.8445   473.3837   413.4284   318.9989   212.5783   140.6320    62.6902    32.7125    55.1957    98.6633   164.6141   217.0749   317.5000   428.4172   494.3680   527.3434   561.8177   545.3300];
y = [  435.9251  510.8691  570.8244  561.8311  570.8244  554.3367  476.3949  390.9586  311.5179  190.1085  113.6655   91.1823   98.6767  106.1711  142.1443  218.5872  296.5291      375.9698];

% Make an array with the selected coordinates
P=[x(:) y(:)];
%% Start Snake Process
% You probably have to fiddle with the parameters
% a bit more that I have
Options=struct;
Options.Verbose=true;
Options.Iterations=1000;
Options.Delta = 0.02;
Options.Alpha = 0.5;
Options.Beta = 0.2;
figure(1);
[O,J]=Snake2D(I,P,Options);

Problem

As a preface: this is my first question - I've tried my best to make it as clear as possible, but I apologise if it doesn't meet the required standards. As part of a summer project, I am taking time-lapse images of an internal melt figure growing inside a crystal of ice. For each of these images I would like to measure the perimeter of, and area enclosed by the figure formed. Linked below is an example of one of my images: The method that I'm trying to use is the following: - Load image, crop, and convert to grayscale - Process to reduce noise - Find edge/perimeter - Attempt to join edges - Fill perimeter with white - Measure Area and Perimeter using regionprops This is the code that I am using: ``` clear; close all; % load image and convert to grayscale tyrgb = imread('TyndallTest.jpg'); ty = rgb2gray(tyrgb); figure; imshow(ty) % apply a weiner filter to remove noise. % N is a measure of the window size for detecting coherent features N=20; tywf = wiener2(ty,[N,N]); tywf = tywf(N:end-N,N:end-N); % rescale the image adaptively to enhance contrast without enhancing noise tywfb = adapthisteq(tywf); % apply a canny edge detection tyedb = edge(tywfb,'canny'); %join edges diskEnt1 = strel('disk',8); % radius of 4 tyjoin1 = imclose(tyedb,diskEnt1); figure; imshow(tyjoin1) ``` It is at this stage that I am struggling. The edges do not quite join, no matter how much I play around with the morphological structuring element. Perhaps there is a better way to complete the edges? Linked is an example of the figure this code outputs: The reason that I am trying to join the edges is so that I can fill the perimeter with white pixels and then use regionprops to output the area. I have tried using the imfill command, but cannot seem to fill the outline as there are a large number of dark regions to be filled within the perimeter. Is there a better way to get the area of one of these melt figures that is more appropriate in this case? As background research: I can make this method work for a simple image consisting of a black circle on a white background using the below code. However I don't know how edit it to handle more complex images with edges that are less well defined. ``` clear all close all clc %% Read in RGB image from directory RGB1 = imread('1.jpg') ; %% Convert RPG image to grayscale image I1 = rgb2gray(RGB1) ; %% Transform Image %CROP IC1 = imcrop(I1,[74 43 278 285]); %BINARY IMAGE BW1 = im2bw(IC1); %Convert to binary image so the boundary can be traced %FIND PERIMETER BWP1 = bwperim(BW1); %Traces perimeters of objects & colours them white (1). %Sets all other pixels to black (0) %Doing the same job as an edge detection algorithm? %FILL PERIMETER WITH WHITE IN ORDER TO MEASURE AREA AND PERIMETER BWF1 = imfill(BWP1); %This opens figure and allows you to select the areas to fill with white. %MEASURE PERIMETER D1 = regionprops(BWF1, 'area', 'perimeter'); %Returns an array containing the properties area and perimeter. %D1(1) returns the perimeter of the box and an area value identical to that %perimeter? The box must be bounded by a perimeter. %D1(2) returns the perimeter and area of the section filled in BWF1 %% Display Area and Perimeter data D1(2) ```

Original source