creating video fire effect from perlin noise
7 次查看(过去 30 天)
显示 更早的评论
Hi,
Is there a way to create a script that creates fire video effect using perlin noise?
something like this?
Thanks in advance!
1 个评论
DGM
2022-8-15
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.
回答(2 个)
Yash Sharma
2023-10-27
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 个评论
DGM
2023-10-27
This doesn't do what OP asked. This doesn't even produce a noise volume. This just creates a bunch of uncorrelated frames.
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1523356/image.gif)
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)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1523361/image.gif)
... at least that has continuity between frames.
DGM
2023-10-27
编辑:DGM
2023-10-27
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)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1523366/image.gif)
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 个评论
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!