受另一个问题的启发,我想使用图像处理技术来实现这个模拟。具体来说,我们可以使用形态扩张来扩散癌细胞。
这个想法是使用如下结构元素来扩展每个像素:
1 0 0
0 1 0
0 0 0
其中中心是固定的,另一个1
随机放置在其余八个位置之一。这将有效地沿该方向扩展像素。
执行膨胀的方式是创建一个空白图像,只有一个像素集,然后使用简单的 OR 运算累积所有结果。
为了加快速度,我们不需要考虑每个像素,只需要考虑由癌细胞簇形成的当前块周边的像素。里面的像素点已经被癌细胞包围了,再放大就没有效果了。
为了进一步加快速度,我们在一次调用中对所有被选择沿相同方向扩展的像素执行膨胀。因此,每次迭代,我们最多执行 8 次扩张操作。
这使得代码相对较快(我测试了高达 1000x1000 的网格)。此外,它在所有迭代中保持相同的时间(不会随着网格开始填满而减慢)。
这是我的实现:
%# initial grid
img = false(500,500);
%# pick 10 random cells, and set them as cancerous
img(randi(numel(img),[10 1])) = true;
%# show initial image
hImg = imshow(img, 'Border','tight', 'InitialMag',100);
%# build all possible structing elements
%# each one dilates in one of the 8 possible directions
SE = repmat([0 0 0; 0 1 0; 0 0 0],[1 1 8]);
SE([1:4 6:9] + 9*(0:7)) = 1;
%# run simulation until all cells have cancer
BW = false(size(img));
while ~all(img(:)) && ishandle(hImg)
%# find pixels on the perimeter of all "blocks"
on = find(bwperim(img,8));
%# percentage chance of division
on = on( rand(size(on)) > 0.5 ); %# 50% probability of cell division
if isempty(on), continue; end
%# decide on a direction for each pixel
d = randi(size(SE,3),[numel(on) 1]);
%# group pixels according to direction chosen
dd = accumarray(d, on, [8 1], @(x){x});
%# dilate each group of pixels in the chosen directions
%# to speed up, we perform one dilation for all pixels with same direction
for i=1:8
%# start with an image with only those pixels set
BW(:) = false;
BW(dd{i}) = true;
%# dilate in the specified direction
BW = imdilate(BW, SE(:,:,i));
%# add results to final image
img = img | BW;
end
%# show new image
set(hImg, 'CData',img)
drawnow
end
我还在 500x500 网格上创建了一个模拟动画,其中包含 10 个随机初始癌细胞(警告:.gif 图像大小约为 1MB,因此根据您的连接可能需要一些时间来加载)