Like many people already seem to have (there are several threads on this subject here) I am looking for ways to create video from a sequence of images.
I want to implement my functionality in C#!
Here is what I wan't to do:
/*Pseudo code*/
void CreateVideo(List<Image> imageSequence, long durationOfEachImageMs, string outputVideoFileName, string outputFormat)
{
// Info: imageSequence.Count will be > 30 000 images
// Info: durationOfEachImageMs will be < 300 ms
if (outputFormat = "mpeg")
{
}
else if (outputFormat = "avi")
{
}
else
{
}
//Save video file do disk
}
I know there's a project called Splicer (http://splicer.codeplex.com/) but I can't find suitable documentation or clear examples that I can follow (these are the examples that I found).
The closest I want to do, which I find here on CodePlex is this: How can I create a video from a directory of images in C#?
I have also read a few threads about ffmpeg (for example this: C# and FFmpeg preferably without shell commands? and this: convert image sequence using ffmpeg) but I find no one to help me with my problem and I don't think ffmpeg-command-line-style is the best solution for me (because of the amount of images).
I believe that I can use the Splicer-project in some way (?).
In my case, it is about about > 30 000 images where each image should be displayed for about 200 ms (in the videostream that I want to create).
(What the video is about? Plants growing ...)
Can anyone help me complete my function?
Well, this answer comes a bit late, but since I have noticed some activity with my original question lately (and the fact that there was not provided a working solution) I would like to give you what finally worked for me.
I'll split my answer into three parts:
(this section is not important for the solution)
My original problem was that I had a lot of images (i.e. a huge amount), images that were individually stored in a database as byte arrays. I wanted to make a video sequence with all these images.
My equipment setup was something like this general drawing:
The images depicted growing tomato plants in different states. All images were taken every 1 minute under daytime.
/*pseudo code for taking and storing images*/
while (true)
{
if (daylight)
{
//get an image from the camera
//store the image as byte array to db
}
//wait 1 min
}
I had a very simple db for storing images, there were only one table (the table ImageSet) in it:
I had read many articles about ffmpeg (please see my original question) but I couldn't find any on how to go from a collection of images to a video.
Finally, I got a working solution! The main part of it comes from the open source project AForge.NET. In short, you could say that AForge.NET is a computer vision and artificial intelligence library in C#. (If you want a copy of the framework, just grab it from http://www.aforgenet.com/)
In AForge.NET, there is this VideoFileWriter class (a class for writing videofiles with help of ffmpeg). This did almost all of the work. (There is also a very good example here)
This is the final class (reduced) which I used to fetch and convert image data into a video from my image database:
public class MovieMaker
{
public void Start()
{
var startDate = DateTime.Parse("12 Mar 2012");
var endDate = DateTime.Parse("13 Aug 2012");
CreateMovie(startDate, endDate);
}
/*THIS CODE BLOCK IS COPIED*/
public Bitmap ToBitmap(byte[] byteArrayIn)
{
var ms = new System.IO.MemoryStream(byteArrayIn);
var returnImage = System.Drawing.Image.FromStream(ms);
var bitmap = new System.Drawing.Bitmap(returnImage);
return bitmap;
}
public Bitmap ReduceBitmap(Bitmap original, int reducedWidth, int reducedHeight)
{
var reduced = new Bitmap(reducedWidth, reducedHeight);
using (var dc = Graphics.FromImage(reduced))
{
// you might want to change properties like
dc.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
dc.DrawImage(original, new Rectangle(0, 0, reducedWidth, reducedHeight), new Rectangle(0, 0, original.Width, original.Height), GraphicsUnit.Pixel);
}
return reduced;
}
/*END OF COPIED CODE BLOCK*/
private void CreateMovie(DateTime startDate, DateTime endDate)
{
int width = 320;
int height = 240;
var framRate = 200;
using (var container = new ImageEntitiesContainer())
{
//a LINQ-query for getting the desired images
var query = from d in container.ImageSet
where d.Date >= startDate && d.Date <= endDate
select d;
// create instance of video writer
using (var vFWriter = new VideoFileWriter())
{
// create new video file
vFWriter.Open("nameOfMyVideoFile.avi", width, height, framRate, VideoCodec.Raw);
var imageEntities = query.ToList();
//loop throught all images in the collection
foreach (var imageEntity in imageEntities)
{
//what's the current image data?
var imageByteArray = imageEntity.Data;
var bmp = ToBitmap(imageByteArray);
var bmpReduced = ReduceBitmap(bmp, width, height);
vFWriter.WriteVideoFrame(bmpReduced);
}
vFWriter.Close();
}
}
}
}
Update 2013-11-29 (how to) (Hope this is what you asked for @Kiquenet?)
AForge.NET Framework-2.2.5\Samples folder
...)AForge.Video.FFMPEG
(from the documentation)AForge.Video.FFMPEG
(in AForge.Video.FFMPEG.dll
) (from the documentation) (you can find this AForge.Video.FFMPEG.dll
in the AForge.NET Framework-2.2.5\Release
folder)If you want to create your own solution, make sure you have a reference to AForge.Video.FFMPEG.dll
in your project. Then it should be easy to use the VideoFileWriter class. If you follow the link to the class you will find a very good (and simple example). In the code, they are feeding the VideoFileWriter with Bitmap image
in a for
-loop