How best to change the colors of pixels in an image with known X (column) Y (row) coordinates?
3 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
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 Commenti
Risposta accettata
DGM
il 16 Feb 2023
Modificato: DGM
il 16 Feb 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 Commenti
Più risposte (0)
Vedere anche
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!