Loop takes a lot of time

2 次查看(过去 30 天)
BW = bwareaopen(I,round(PixSiz/50));
LINES2sum = zeros(PixSiz);
%Template for correlation search
tmpl = zeros(10,30);
tmpl(3:8,:) = ones(6,30);
tmpl2 = zeros(5,90);
tmpl2(3,:) = ones(1,90);
tic
for i = 1:15
bw = imfilter(double(BW),imrotate(tmpl,(i-1)*180/15),'conv');
lines = edge(bw,'sobel');
lines2 = imfilter(lines,imrotate(tmpl2,(i-1)*180/15),'conv');
LINES2sum = LINES2sum + lines2;
end
toc
Hey, so in this part of my code, the image I is to be filtered to find centres of a network structure. The loop takes around 23s, being the most time consuming part of the whole code. That's why I wanted to ask if there could be a quicker way to execute the same thing. An individual check of every line in the loop showed that the first 3 lines are the critical ones with each needing 0.5s per loop.
PixSiz is just the size of the image. In this case 2048 pixels. I could imagine that operations on such a rather large image justify more time consumption but as I need to perform this code on a lot of pictures and even bigger ones (4096) I would really appreciate any help.
  1 个评论
darova
darova 2020-6-20
i think it can't be faster. You are making a lot of filtering

请先登录,再进行评论。

采纳的回答

Walter Roberson
Walter Roberson 2020-6-22
bw = imfilter(double(BW),imrotate(tmpl,(i-1)*180/15),'conv');
For discussion, break that into three pieces,
A = double(BW);
h = imrotate(tmpl,(i-1)*180/15);
bw = imfilter(A, h, 'conv');
Then the bulk of the time is being spent in the imfilter.
When I trace through imfilter, I find that it has to do some tests to figure out which situation it has in order to determine the best way to execute the code. Those tests are a bit more expensive than you might expect: they involve calculating the rank of the filter matrix by using svd(). In your configuration, it (typically) determines that optimization cannot work and falls back to more general code.
What it ends up doing is padding the image, A, with zeros, and rotating the filter, h by 90 degrees, and then doing conv2() with 'valid' . The padding was calculated to be such that the resulting size of the conv2() is exactly the desired output size, and appears to work out to ceil(size(h)/2) (but skip the first row or column of the padded array if the size of the filter is odd in that dimension.)
conv2() is built-in, so that probably cannot be surpassed.
But what you could do is directly pad and conv2() yourself. This would not save a lot, but it would save the overhead of figuring out that conv2 is to be used, including skipping the svd.

更多回答(2 个)

Raunak Gupta
Raunak Gupta 2020-6-22
Hi,
As darova mentioned in the comments that optimization may not be possible in filtering code, but I see that code lines inside the loop to independent from iteration number. So, you may try using parfor instead of for loop. You can refer to the conditions required for using parfor loops or How to convert normal for loop to parfor for getting started. Note that you required to have Parallel Computing Toolbox installed for using parfor.

Image Analyst
Image Analyst 2020-6-22
The Sobel is a linear filter, because it's a convolution. Thus you could try it in the Fourier domain, which is often faster for large images and large kernels. To compute in the Fourier domain
  1. Convert both image and kernel to spectra with fft2().
  2. Multiply the spectra.
  3. Return to the spatial domain with ifft2().
  4. There may be small imaginary parts. Take the real part as your output image.

产品


版本

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by