generating random particles effect to an image

10 views (last 30 days)
Hi!
I want to implement a code that generates random colored particles effect into an image, something like the attached image
'particles.jpg' . (the background will be bleck, eventually I want to create png image)
My idea is to generate random 2d gaussians (with random centers and radius), and then combining them to one image. After that I want to paint them with random colors (each of them will have different color).
can you please help me create this code?

Accepted Answer

DGM
DGM on 6 Aug 2022
Edited: DGM on 6 Aug 2022
This is built using MIMT tools:
% parameters
s = [500 300]; % output image size [height width]
numspots = 20; % number of spots
spotbounds = [30 70]; % allowable range of spot widths (px)
spotopacity = [0.1 0.7]; % allowable range of spot opacity
blurbounds = [0 50]; % allowable range of blur width (px)
bgcolor = [0.08 0 0.2]; % background color (unit-scale)
spotbounds = round(spotbounds/2); % convert to radius
s = [s(1:2) 3]; % output is color
padwidth = spotbounds(2) + blurbounds(2) + 2; % calculate required padding
wpict = colorpict([s(1:2)+padwidth*2 s(3)],bgcolor); % preallocate
for n = 1:numspots
% create antialiased disk (the spot)
rspot = ceil(randrange(spotbounds,[1 1]));
spotmap = simnorm(fkgen('disk',[2 2]*rspot));
% blur the spot as required
fkb = fkgen('gaussian',randrange(blurbounds,[1 1]));
spotmap = imfilter(spotmap,fkb,'full');
% find coordinates to insert the spot
rxy = ceil(rand([1 2]).*s(1:2))+padwidth;
rspot = size(spotmap,1)/2;
rangec = (rxy(1)-floor(rspot)):(rxy(1)+ceil(rspot)-1);
ranger = (rxy(2)-floor(rspot)):(rxy(2)+ceil(rspot)-1);
% composite the spot into the image
thisalpha = randrange(spotopacity,[1 1]);
thiscolor = rand(1,3);
thisbg = wpict(rangec,ranger,:);
wpict(rangec,ranger,:) = replacepixels(thiscolor,thisbg,spotmap*thisalpha);
end
outpict = imcast(cropborder(wpict,padwidth),'uint8');
imshow(outpict)
The rest is tailoring the distributions. For example:
% parameters
s = [300 500]; % output image size [height width]
numspots = 70; % number of spots
spotbounds = [15 40]; % allowable range of spot widths (px)
spotopacity = [0.1 0.7]; % allowable range of spot opacity
blurbounds = [0 50]; % allowable range of blur width (px)
bgcolor = [0.08 0 0.2]; % background color (unit-scale)
clustercenter = [1 0.5]; % cluster location in normalized coordinates [y x]
clustersigma = [0.25 0.25]; % control spread of spots away from cluster center
spotbounds = round(spotbounds/2);
s = [s(1:2) 3];
padwidth = spotbounds(2) + blurbounds(2) + 2;
wpict = colorpict([s(1:2)+padwidth*2 s(3)],bgcolor);
for n = 1:1:numspots
% create antialiased disk (the spot)
rspot = ceil(randrange(spotbounds,[1 1]));
spotmap = simnorm(fkgen('disk',[2 2]*rspot));
% blur the spot as required
fkb = fkgen('gaussian',randrange(blurbounds,[1 1]));
spotmap = imfilter(spotmap,fkb,'full');
% find coordinates to insert the spot
goodpoint = false;
while ~goodpoint
rxy = ceil((clustercenter + clustersigma.*randn([1 2])).*s(1:2))+padwidth;
goodpoint = all(rxy > padwidth) && all(rxy <= padwidth+s(1:2));
end
rspot = size(spotmap,1)/2;
rangec = (rxy(1)-floor(rspot)):(rxy(1)+ceil(rspot)-1);
ranger = (rxy(2)-floor(rspot)):(rxy(2)+ceil(rspot)-1);
% composite the spot into the image
thisalpha = randrange(spotopacity,[1 1]);
thiscolor = rand(1,3);
thisbg = wpict(rangec,ranger,:);
wpict(rangec,ranger,:) = replacepixels(thiscolor,thisbg,spotmap*thisalpha);
end
outpict = imcast(cropborder(wpict,padwidth),'uint8');
  4 Comments
DGM
DGM on 6 Aug 2022
Edited: DGM on 6 Aug 2022
If you want to simulate motion, then you'll have to take a step backward and separate the spot creation and positioning from the compositing. You'll have to keep track of each spot sub-image, its position/trajectory, its color and alpha between frames. If new spots are allowed to move into frame during the sequence, then it just becomes that much more complicated.
Consider the given examples as a simplified version of what you want. Some of the elements should still be useful. I don't have the time to write a whole thing. What I posted was an adaptation of something I had at hand.
I should add that if you want to simulate depth of field with the blur, you might want to scale the blur according to the spot size instead of allowing it to be independent and random like I did.

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 6 Aug 2022
Here's a start. I trust you can finish it. If so, see this:
% Demo by Image Analyst to create multiple Gaussians.
% Initialization Steps.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
numSpheres = 50;
windowWidth = 30;
rows = 640;
columns = 640;
grayImage = zeros(rows, columns, 'uint8');
for k = 1 : numSpheres
radius = windowWidth * rand;
g = rescale(fspecial("gaussian", windowWidth, radius), 0, 1);
g = uint8(255 * g);
subplot(1, 2, 1);
imshow(g, []);
axis('on', 'image')
caption = sprintf('One Gaussian with sigma = %.5f', radius);
title(caption, 'FontSize', fontSize)
xUpperLeft = round(rand(1) * (columns - windowWidth)) + 1;
yUpperLeft = round(rand(1) * (rows - windowWidth)) + 1;
% Paste in image
grayImage(yUpperLeft : (yUpperLeft + windowWidth - 1), xUpperLeft : (xUpperLeft + windowWidth - 1)) = g;
subplot(1, 2, 2);
imshow(grayImage, []);
axis('on', 'image')
caption = sprintf('%d Gaussians', k);
title(caption, 'FontSize', fontSize)
drawnow;
end
g = gcf;
g.WindowState = 'maximized'
I'm attaching another demo, gaussianCircles_demo.m, that produces this image.

Community Treasure Hunt

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

Start Hunting!

Translated by