How to efficiently update an image if one matrix element is changed

I have a matrix in which I change only one element in every iteration of a loop. I want to display that matrix as an image using image or imagesc. What I am doing now is to update the CData property of the image handle so as to refresh the image of the matrix. With several thousands of iterations, it turned out that the bottleneck is the image/imagesc function according to the Profiler. So I thought of changing the color of the tile corresponding to the changed matrix entry. How can I do that? There would be no problem with the colormap since the matrix only contains zeros and ones.

9 comentarios

With several thousands of iterations, it turned out that the bottleneck is the image/imagesc function according to the Profiler.
But why is image/imagesc being called repeatedly? Don't you call it just once? You said your updates are done just by altering the CData property.
Please post your code. Without seeing the code it is impossible to guess, why image is the bottleneck, although you do not use this command, but the more efficient updating of the CData property only.
Here is the code. Matt J: I wrote it wrong, I just set the CData property. Anyway, the rest of my question holds: how can I speed it up? My other question is: how can I set black-and-white colors instead of the default purple-and-yellow? The colormap function may not be appropriate, since that is a high-level function, that overrides my axes settings.
function A = langton(A, initpos, initvalue, initdir, maxiter)
% Check input
if nargin == 4
maxiter = 10;
elseif nargin == 3
initdir = randi(4)-1;
maxiter = 10;
elseif nargin == 2
initvalue = round(rand());
initdir = randi(4)-1;
maxiter = 10;
elseif nargin == 1
initpos = [randi(size(A,1)) randi(size(A,2))];
initvalue = round(rand());
initdir = randi(4)-1;
maxiter = 10;
elseif nargin == 0
A = zeros(10);
initpos = [randi(size(A,1)) randi(size(A,2))];
initvalue = round(rand());
initdir = randi(4)-1;
maxiter = 100;
end
M = size(A,1); N = size(A,2);
x = initpos(1); y = initpos(2);
A(x,y) = initvalue;
% Define directions to turn to (0: north, 1: west, 2: south, 3: east)
direction = initdir;
fig = figure('Visible','off', 'Color','white');
ax = axes('Parent', fig, 'CLimMode','manual', 'CLim',[0 1], 'Color',[1 1 1], 'DataAspectRatio',[1 1 1], 'Xtick',[], 'YTick',[], 'XColor',[1 1 1], 'YColor',[1 1 1], 'YDir','reverse');
I = image('Parent',ax, 'CData',A, 'CDataMapping','scaled');
set(fig, 'Visible','on');
% Start the simulation
for i = 1:maxiter
% Turn the ant
if (A(x,y) == 1) % standing on a black tile, turn 90 degrees right
direction = mod(direction-1, 4);
else % standing on a white, turn 90 degrees left
direction = mod(direction+1, 4);
end
% Invert the color of the tile it was moving from
A(x,y) = mod(A(x,y)-1, 2);
% Move the ant forward
switch direction
case 0 % heading to the north
x = x-1;
case 1 % heading to the west
y = y-1;
case 2 % heading to the south
x = x+1;
case 3 % heading to the east
y = y+1;
end
% Use periodic boundary
x = mod(x-1,M)+1; y = mod(y-1,N)+1;
% Update graphics
set(I, 'CData',A);
% Pause between the steps for a while
pause(0.2);
end
end
The obvious slowdown in the above is
% Pause between the steps for a while
pause(0.2);
I'd think if you removed that it'd be blindingly fast (so to speak)
When I measured the elapsed time with the profiler, that line was of course commented. Apart from it, is there any way to speed it up?
Might try just X'or the positions that change instead of setting the whole array.
Show profiler results for the code actually run
And how could I achieve that?
If you are using R2014a or earlier, EraseMode 'xor' can be used to potentially speed up drawing. As of R2014b that is no longer an option.
Ewwww...that's a bummer, indeed! I'd also not thought of HG2 and latest releases in performance...I understand there is, so far at least, a big dropoff there.

Iniciar sesión para comentar.

 Respuesta aceptada

Don't use image. Use set(). See this demo:
grayImage = imread('moon.tif');
hImage = imshow(grayImage);
promptMessage = sprintf('Do you want to assign new pixels,\nor Quit?');
titleBarCaption = 'Continue?';
buttonText = questdlg(promptMessage, titleBarCaption, 'Continue', 'Quit', 'Continue');
if strcmpi(buttonText, 'Quit')
return;
end
for k = 1 : 50 : numel(grayImage);
grayImage(k) = 255; % Make this pixel bright white.
set(hImage, 'CData', grayImage);
end
msgbox('Done');
I think it should be fast enough for you.

2 comentarios

This is what I did as you can see it in the attached code in a few comments above. The performance drop is probably due to HG2. However, your code sample made my think of other useful things, so I accept it.
What attached code? Performance drop from what? On my system, my code was faster than a greased cheetah on steroids. So fast I couldn't even see it happen in real time - I just saw the final result.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Graphics Object Properties en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 18 de Oct. de 2015

Comentada:

el 19 de Oct. de 2015

Community Treasure Hunt

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

Start Hunting!

Translated by