7

作为前言:这是我的第一个问题 - 我已尽力使其尽可能清晰,但如果它不符合要求的标准,我深表歉意。

作为夏季项目的一部分,我正在拍摄在冰晶内生长的内部融化图形的延时图像。对于这些图像中的每一个,我想测量所形成图形的周长和面积。下面链接是我的一张图片的示例:

在此处输入图像描述

我尝试使用的方法如下:

  1. 加载图像、裁剪并转换为灰度
  2. 降噪处理
  3. 查找边缘/周长
  4. 尝试连接边缘
  5. 用白色填充周边
  6. 使用 regionprops 测量面积和周长

这是我正在使用的代码:

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)

正是在这个阶段,我正在挣扎。无论我如何使用形态结构元素,边缘都没有完全连接。也许有更好的方法来完成边缘?链接是此代码输出的图形示例:

在此处输入图像描述

我试图加入边缘的原因是我可以用白色像素填充周边,然后使用 regionprops 输出该区域。我曾尝试使用 imfill 命令,但似乎无法填充轮廓,因为周边内有大量黑暗区域需要填充。

有没有更好的方法来获得在这种情况下更合适的这些熔化数字之一的面积?

作为背景研究:我可以使用以下代码使此方法适用于由白色背景上的黑色圆圈组成的简单图像。但是我不知道如何对其进行编辑以处理边缘不太明确的更复杂的图像。

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)
4

3 回答 3

3

我认为除了形态转换之外,您可能还有改进边缘检测效果的空间,例如,以下结果在我看来是一个相对令人满意的周边。

tyedb = edge(tywfb,'sobel',0.012);

%join edges

diskEnt1 = strel('disk',7); % radius of 4
tyjoin1 = imclose(tyedb,diskEnt1);

此外,我还使用bwfill交互方式填充了大部分内部。应该可以以编程方式填充内部,但我没有追求这一点。

% interactively fill internal regions

[ny nx] = size(tyjoin1);
figure; imshow(tyjoin1)
tyjoin2=tyjoin1;
titl = sprintf('click on a region to fill\nclick outside window to stop...')
while 1
   pts=ginput(1)
   tyjoin2 = bwfill(tyjoin2,pts(1,1),pts(1,2),8);
   imshow(tyjoin2)
   title(titl)
   if (pts(1,1)<1 | pts(1,1)>nx | pts(1,2)<1 | pts(1,2)>ny), break, end
end

这是我得到的结果

在此处输入图像描述

然而,周长的“分形”属性可能对您很重要。也许您想保留形状中的褶皱。

于 2013-08-22T18:13:38.167 回答
2

您可能需要考虑活动轮廓。这将为您提供对象的连续边界,而不是斑驳的边缘。

以下是链接

一本书:

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+布莱克%2C+迈克尔+伊萨德

演示: http ://users.ecs.soton.ac.uk/msn/book/new_demo/Snakes/

以及文件交换上的一些 Matlab 代码:http: //www.mathworks.co.uk/matlabcentral/fileexchange/28149-snake-active-contour

以及如何实现它的描述链接:http: //www.cb.uu.se/~cris/blog/index.php/archives/217

使用 File Exchange 上的实现,您可以获得如下内容:

%% 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);
于 2013-08-23T09:13:16.497 回答
0

如果最终结果是面积/直径估计,那么为什么不尝试找到适合轮廓的最大和最小形状,然后使用形状的面积来估计总面积。例如,计算边缘集周围的最小圆,然后计算边缘的最大圆。然后你可以用这些来估计实际形状的直径和面积。

优点是您的边界形状可以以最小化错误(无界边缘)的方式进行拟合,同时分别向上或向下优化内部和外部形状的尺寸。

于 2013-08-22T16:07:04.837 回答