creating video fire effect from perlin noise
9 views (last 30 days)
Show older comments
Hi,
Is there a way to create a script that creates fire video effect using perlin noise?
something like this?
Thanks in advance!
1 Comment
DGM
on 15 Aug 2022
I'm sorry that this isn't really an answer, but I haven't been (and probably won't be) around the computer much for a while. It's been a long time since I wrapped my head around perlin() or perlin3(), so I don't really have an answer.
The two functions do similar things, but perlin() was an attempt to improve speed through vectorization, whereas perlin3() does it more like it would be done in C (i.e. the pointwise way which is painfully slow in m-code). With that in mind, perlin3() is more general and may be closer in concept to other examples of fire effects you might find elsewhere; whether that can be translated into a vectorized approach (like perlin()) which manages to retain any advantages in the end isn't something I'm going to guess at without testing it myself. I'm assuming this is some sort of volumetric effect, but I haven't had the time to wrap my head around the concept and translate it.
It's an idea I might play with someday, but I'm kind of covered-in-fiberglass-and-mud busy at the moment. I doubt I'll be able to get to it in time for the outcome to be useful for your needs.
Answers (2)
Yash Sharma
on 27 Oct 2023
Hi David,
I understand that you want to create a fire like effect using perlin noise. The basic idea is to generate Perlin noise frames and then color them in a way that resembles fire. Here is a simple example of how you might do this in MATLAB:
% Set parameters
numFrames = 100; % number of frames in the video
height = 100; % height of the video
width = 100; % width of the video
% Create a VideoWriter object
v = VideoWriter('fire.avi');
open(v);
% Generate the frames
for i = 1:numFrames
% Generate a Perlin noise frame
frame = perlin([height, width]);
% Shift and scale the frame to the range [0, 1]
frame = frame - min(frame(:));
frame = frame / max(frame(:));
% Apply a colormap to create the fire effect
cmap = hot(256); % or use another colormap if you prefer
frame = ind2rgb(im2uint8(frame), cmap);
% Write the frame to the video
writeVideo(v, frame);
end
% Close the video file
close(v);
To create a more realistic fire effect, you might need to use more advanced techniques, such as varying the noise parameters over time, applying different colormaps, or using a more complex noise function.
Please find below some function which I believe will be helpful for your implementation.
- Hot: https://in.mathworks.com/help/matlab/ref/hot.html
- Ind2rgb: https://in.mathworks.com/help/matlab/ref/ind2rgb.html
- Im2uint8: https://in.mathworks.com/help/images/ref/im2uint8.html
Hope this helps!
1 Comment
DGM
on 27 Oct 2023
This doesn't do what OP asked. This doesn't even produce a noise volume. This just creates a bunch of uncorrelated frames.
I'd be interested to know what noise parameters you're suggesting should be varied when using perlin() to produce single-channel outputs, because there aren't any.
If the goal were to create a plain noise volume (still not what OP is asking for), you wouldn't use perlin(), as I already mentioned.
% Set parameters
numFrames = 100; % number of frames in the video
height = 100; % height of the video
width = 100; % width of the video
cmap = hot(256); % this doesn't belong in the loop
% generate a noise volume
instack = perlin3([height width numFrames]);
% preallocate
outstack = zeros([height width 3 numFrames],'uint8');
% Generate the frames
for f = 1:numFrames
% if we're already using MIMT and want the frames normalized
% then gray2pcolor() already does that by default
thisframe = gray2pcolor(instack(:,:,f),cmap);
outstack(:,:,:,f) = im2uint8(thisframe);
end
% write as a GIF
gifwrite(outstack,'fire2.gif',0.05)
... at least that has continuity between frames.
DGM
on 27 Oct 2023
Edited: DGM
on 27 Oct 2023
If we don't care about efficiency, we can just create an excess of noise and sample it.
% Set parameters
numFrames = 100; % number of frames in the video
height = 100; % height of the video
width = 100; % width of the video
yoversample = 2; % how much extra noise volume to start with
yscale = 2; % how much the noise should appear stretched
cmap = hot(256); % this doesn't belong in the loop
% generate a noise volume
instack = perlin3([height*yoversample width numFrames]);
% preallocate
outstack = zeros([height width 3 numFrames],'uint8');
% Generate the frames
sampleh = floor(height/yscale);
for f = 1:numFrames
% sample the noise volume with an offset window
yoffset = floor((f-1)/(numFrames-1)*(size(instack,1)-sampleh))
yrange = yoffset+1:yoffset+sampleh;
thisframe = instack(yrange,:,f);
% resize the sample to the expected frame geometry
thisframe = imresize(thisframe,[height width]);
% if we're already using MIMT and want the frames normalized
% then gray2pcolor() already does that by default
thisframe = gray2pcolor(thisframe,cmap);
outstack(:,:,:,f) = im2uint8(thisframe);
end
% write as a GIF
gifwrite(outstack,'fire3.gif',0.05)
Of course, I never went this route because it's a bit more wasteful than I think is appropriate, and I can't be bothered to rewrite a custom version of perlin3(). Depends what's tolerable.
0 Comments
See Also
Categories
Find more on Convert Image Type in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!