1

我编写了一个将图像转换为文本文件以进行光刻的代码。图片为高分辨率(26.5kx 26.5k),文本文件超过 2MB。我的问题是代码需要很长时间才能工作,我怀疑它与内存碎片有关(我不是经验丰富的程序员,特别是刚开始使用 MATLAB)。它在两个地方滞后:在您必须选择要使用的特定图像之前,以及在处理它之后。

在处理部分,我从 MATLAB 中得到以下评论:

指示的变量或数组的大小似乎随着每次循环迭代而变化。通常,出现此消息是因为数组通过赋值或连接而增长......

但是还有这部分:

如果满足以下任一条件,则可能适合禁止显示此消息,如调整代码分析器消息指示器和消息中所述: 循环代码包含数组增长的条件块。(在这种情况下,只有在循环找到这样的条件时才增长数组是合理的。)对于循环中的每次迭代,连接的长度会有所不同(例如具有可变长度的字符向量)。在进入循环之前,数组的总大小是无法计算的。

输出文本文件很大程度上取决于提供的图像和其中的黑白像素数。

所以我想知道是否有任何方法可以提高代码的性能?

在选择图像文件之前,几乎没有任何计算,携带的也很简单,不知道为什么这么慢。

对于第一个函数,就在调用打开图像文件的第二个函数之前:

function print_contacts(pixl, size, xRd, yRd, zRd, xRu, yRu, zRu)

meas_L=3960.05; % the lateral and veritcal measured distance e.g. 4900.5 between large pluses, 3960.05 between dots in corners
%%
conv=(size*1000)/pixl;%0.267;%0.4215; % pixel to microns
siz=pixl*conv;
xLd=0.0;
yLd=0.0;
zLd=0.0;

%%
delta_x_H=xLd-xRd;
delta_y_H=yLd-yRd;
delta_z_V=-(zLd-zRd);

delta_x_V=xRu-xRd;
delta_y_V=yRu-yRd;
delta_z_H=-(zRu-zRd);

%% find x-y angle of rotation teta (if teta is positive then rotation is clockwise)

if yRd > 0
    teta_xy=atand(-xRd/yRd)-90;
else
    teta_xy=atand(-xRd/yRd)+90;
end

%% find x-z angle of rotation teta (if teta is positive then rotation is clockwise)

teta_xz=atand(delta_z_H/delta_x_H);

%% find y-z angle of rotation teta (if teta is positive then rotation is clockwise)

teta_yz=atand(delta_z_V/delta_y_V);

%%
del_z_H=delta_z_H/meas_L*conv*pixl;
del_z_V=delta_z_V/meas_L*conv*pixl;

vec_xz=linspace(0,del_z_H,pixl);
vec_yz=linspace(0,del_z_V,pixl);
[X,Y] = meshgrid(vec_yz,vec_xz);
Z1=(X + Y);
shift=Z1(pixl/2,pixl/2);
valZ=round((Z1-shift),2);
%surf(valZ);
con=[conv];
R = [cosd(teta_xy) -sind(teta_xy); sind(teta_xy) cosd(teta_xy)];

PPM.Y=con;
PPM.X=con;

regionpropsApply(PPM, valZ, siz, R, conv)

之后是regionpropsApply允许您选择图像文件并将其分割成单个图像的函数,每个图像将由第三个也是最后一个函数处理成一个文本文件,其中我有这个命令收集一个长字符串,它将进入文本文件:

str2File = [str2File;cmdJump;cmdZ;cmdMov];

其中cmdJump和是在此特定迭代中创建的命令cmdZcmdMov在迭代之前,我已经知道所需的迭代次数。每次迭代都将始终包含这 3 个命令。每个图像(从原始图像中分割出来的)都被单独处理。我应该什么时候预分配内存以及如何预分配内存?

目前,执行代码需要 40 多分钟,考虑到输出文件只有 2MB 的事实,我真的希望它不到几分钟。

4

1 回答 1

4

在您的第一段代码中,我认为这是缓慢的部分:

vec_xz=linspace(0,del_z_H,pixl);
vec_yz=linspace(0,del_z_V,pixl);
[X,Y] = meshgrid(vec_yz,vec_xz);
Z1=(X + Y);
shift=Z1(pixl/2,pixl/2);
valZ=round((Z1-shift),2);

由于您正在处理非常大的图像,因此我认为pixl这里的数量很大。您生成 4 个图像大小的矩阵。但是其中 3 个包含中间数据,仅在上面的代码中使用。不要将每个计算结果分配给一个新变量,而是重用变量以避免使用过多的内存。例如,调用一个函数x = func(x)允许函数就地工作,修改x而不是复制它。现在你应该不再需要Z1占用内存了。

图像XY完全是多余的。从 R2016b 开始,您可以简单地添加两个正交向量,并且在此之前的 10 年中我们已经bsxfun进行了这种类型的操作。这不仅可以节省内存,还可以通过更好地使用缓存来加快计算速度。

因此,您可以通过以下方式执行与上述相同的操作:

vec_xz = linspace(0, del_z_H, pixl);
vec_yz = linspace(0, del_z_V, pixl);
valZ = vec_xz + vec_yz.';
shift = valZ(pixl/2, pixl/2);
valZ = round(valZ-shift, 2);

如果您有旧版本的 MATLAB,请将第 3 行替换为:

valZ = bsxfun(@plus, vec_xz, vec_yz.');

最后,我们可以通过改变它们的顺序来减少操作的数量:我们不是shift从每个像素中减去,而是从两个向量中的每一个中减去一部分:

vec_xz = linspace(0, del_z_H, pixl);
vec_xz = vec_xz - vec_xz(pixl/2);
vec_yz = linspace(0, del_z_V, pixl);
vec_yz = vec_yz - vec_yz(pixl/2);
valZ = vec_xz + vec_yz.';
valZ = round(valZ, 2);

至于你问题的第二部分,我不知道那里还有什么以及你对你构建的字符串做了什么,但如果你所做的只是构建这个长字符串然后将它写入文件,你应该改为写随时归档:

file = fopen('name.txt', 'wt');
for ...
   fwrite(file, [cmdJump;cmdZ;cmdMov];
end
fclose(file);

如果您需要在写入之前以某种方式修改字符串,您可以将它们存储在一个单元格数组中,您可以预先分配它,因为您知道循环的迭代次数:

str2File = cell(N,1);
for ii=1:N
   str2File{ii} = [cmdJump;cmdZ;cmdMov];
end
于 2019-06-23T14:26:56.393 回答