作为序言:这是我的第一个问题 - 我已尽力使其尽可能明确,但如果不符合要求的标准我会道歉。
作为夏季项目的一部分,我正在拍摄一张在冰晶中生长的内部融化图像的延时图像。对于这些图像中的每一个,我想测量所形成的图形的周长和面积。以下链接是我的一张图片的示例:
我正在尝试使用的方法如下:
这是我正在使用的代码:
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)
正是在这个阶段,我正在挣扎。无论我如何使用形态结构元素,边缘都不会完全连接。也许有更好的方法来完成边缘? Linked是此代码输出的数字示例:
我尝试连接边缘的原因是我可以用白色像素填充周边,然后使用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)
答案 0 :(得分: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
这是我获得的结果
然而,周长的“分形”属性对您来说可能很重要。也许你想保留你的形状折叠。
答案 1 :(得分:2)
您可能需要考虑活动轮廓。这将为您提供对象的连续边界,而不是曲面边缘。
以下是
的链接一本书:
演示: 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);
答案 2 :(得分:0)
如果最终结果是面积/直径估计,那么为什么不尝试找到适合轮廓的最大和最小形状,然后使用形状区域来估计总面积。例如,计算边缘集周围的最小圆,然后计算边缘内的最大圆 。然后你可以用这些来估算实际形状的直径和面积。
优点是您的边界形状可以适合最小化误差(无界边缘)的方式,同时分别优化内部和外部形状的向上或向下尺寸。