How best to change the colors of pixels in an image with known X (column) Y (row) coordinates?
3 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
James Akula
el 15 de Feb. de 2023
The obvious way is to loop over every XY pair and change the color of the identified pixel, but this is very slow. I can do a lot better using indexing, but it is a clumsy approach, as it does the same thing three times. Is there a better, more intuitive way (even if it's not much faster)?
Image = uint8(repmat(randi(100, [9, 9]), [1, 1, 3]));
Image2 = Image;
Image3 = Image;
Color = uint8([1, 0.25, 0.1] .* 255);
Xs = [2; 2; 3; 3; 3; 4; 5; 6; 7; 7; 7; 8; 8];
Ys = [3; 6; 2; 3; 7; 8; 8; 8; 2; 3; 7; 3; 6];
% Adding lots of duplicates to make this simple problem harder.
Xs = repmat(Xs, [1000000, 1]);
Ys = repmat(Ys, [1000000, 1]);
% Looping is slow.
tic
for ii = 1:numel(Xs)
Image(Ys(ii), Xs(ii), :) = Color;
end
t1 = toc;
% The best I could come up with. It's faster, but inelegant.
tic
idx = sub2ind(size(Image2, [1, 2]), Ys, Xs);
Image2(idx) = Color(1);
Image2(idx + prod(size(Image3, [1, 2]))) = Color(2);
Image2(idx + 2.*prod(size(Image3, [1, 2]))) = Color(3);
t2 = toc;
% Is there a better way?
tic
% Do something...
t3 = toc;
montage({Image, Image2, Image3}, 'Size', [1, 3])
disp(['Loop time = ', num2str(t1, 3), ' seconds.'])
disp(['Index time = ', num2str(t2, 2), ' seconds.'])
disp(['New time = ', num2str(t3, 2), ' seconds.'])
disp(['Indexing is ~', num2str(round(t1./t2), '%d'), ' times faster than looping.'])
0 comentarios
Respuesta aceptada
DGM
el 16 de Feb. de 2023
Editada: DGM
el 16 de Feb. de 2023
Normally, you'd do region replacement using a mask of some sort.
Image = uint8(repmat(randi(100, [9, 9]), [1, 1, 3]));
Image2 = Image;
Image3 = Image;
Color = uint8([1, 0.25, 0.1] .* 255);
Xs = [2; 2; 3; 3; 3; 4; 5; 6; 7; 7; 7; 8; 8];
Ys = [3; 6; 2; 3; 7; 8; 8; 8; 2; 3; 7; 3; 6];
% Adding lots of duplicates to make this simple problem harder.
Xs = repmat(Xs, [1000000, 1]);
Ys = repmat(Ys, [1000000, 1]);
% Looping is slow.
tic
for ii = 1:numel(Xs)
Image(Ys(ii), Xs(ii), :) = Color;
end
t1 = toc;
% The best I could come up with. It's faster, but inelegant.
tic
idx = sub2ind(size(Image2, [1, 2]), Ys, Xs);
Image2(idx) = Color(1);
Image2(idx + prod(size(Image3, [1, 2]))) = Color(2);
Image2(idx + 2.*prod(size(Image3, [1, 2]))) = Color(3);
t2 = toc;
% use a mask
tic
sz = size(Image2, [1, 2]);
idx = sub2ind(sz, Ys, Xs);
mask = false(sz);
mask(idx) = true;
% IPT imoverlay() can work with I/RGB images
% BG must be an image, FG must be an RGB tuple
% mask can only be binarized
% and FG color must be unit-scale float
Image3 = imoverlay(Image3,mask,im2double(Color));
% MIMT replacepixels() can work with I/IA/RGB/RGBA/RGBAAA images
% FG/BG can be images or tuples
% mask can be binarized or smooth, I/RGB
% color can be anything so long as it's correctly-scaled for its class
%Image3 = replacepixels(Color,Image3,mask);
t3 = toc;
montage({Image, Image2, Image3}, 'Size', [1, 3])
disp(['Loop time = ', num2str(t1, 3), ' seconds.'])
disp(['Index time = ', num2str(t2, 2), ' seconds.'])
disp(['New time = ', num2str(t3, 2), ' seconds.'])
disp(['Indexing is ~', num2str(round(t1./t2), '%d'), ' times faster than looping.'])
disp(['Masking is ~', num2str(round(t1./t3), '%d'), ' times faster than looping.'])
If all you need are binary selections and you're replacing the regions with a single color, then IPT imoverlay() works. If the selected regions are to be replaced by another image, then imoverlay() won't work.
Filling with another image, using only basic tools:
0 comentarios
Más respuestas (0)
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!