多くの人がすでに持っているように見えます(このテーマについてはいくつかのスレッドがあります)。一連の画像からビデオを作成する方法を探しています。
C#で機能を実装したい!
これは私がしたくないことです:
/*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
}
Splicer( http://splicer.codeplex.com/ )というプロジェクトがあることは知っていますが、見つかりません適切なドキュメントまたは私が従うことができる明確な例( これら は私が見つけた例です)。
CodePlexでここで見つけた最も近い方法は次のとおりです。 C#で画像のディレクトリからビデオを作成するにはどうすればよいですか?
また、ffmpegについていくつかのスレッドを読みました(たとえば、これ: C#およびFFmpegはシェルコマンドなしで? およびこれ: ffmpegを使用してイメージシーケンスを変換する )が、問題を解決できる人がいないため、ffmpeg-とは思わないコマンドラインスタイルは、(画像の量のため)私にとって最適なソリューションです。
私は何らかの方法でSplicer-projectを使用できると信じています(?)。
私の場合、それは約30000以上の画像であり、各画像は約200ミリ秒(作成したいビデオストリームで)表示されるはずです。
(ビデオの内容は?成長している植物...)
誰かが私の機能を完了するのを手伝ってくれますか?
まあ、この答えは少し遅れていますが、最近私の元の質問でいくつかの活動に気づいたので(そして実用的な解決策が提供されていなかったという事実)、私は最終的に私のために働いたものを提供したいと思います。
回答を3つの部分に分けます。
(このセクションはソリューションにとって重要ではありません)
私の元々の問題は、大量の画像(つまり、膨大な量)があり、その画像がバイト配列としてデータベースに個別に保存されていたことでした。 これらすべての画像を使用してビデオシーケンスを作成したかった
私の機器のセットアップは、この一般的な図面のようなものでした:
画像は、さまざまな状態のトマト植物の成長を表しています。すべての画像は、昼間1分ごとに撮影されました。
/*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
}
画像を保存するための非常に単純なdbがあり、その中に1つのテーブル(テーブルImageSet)だけがありました
私はffmpegに関する多くの記事を読んでいました(元の質問をご覧ください)が、画像のコレクションからビデオに移行する方法が見つかりませんでした。
最後に、実用的なソリューションを得ました!その主な部分は、オープンソースプロジェクト AForge.NET から来ています。要するに、 AForge.NETはC# のコンピュータービジョンおよび人工知能ライブラリであると言えます。 (フレームワークのコピーが必要な場合は、 http://www.aforgenet.com/ から入手してください)
AForge.NETには、このVideoFileWriterクラス(ffmpegを使用してビデオファイルを書き込むためのクラス)があります。これでほぼすべての作業が完了しました。 (非常に良い例もあります here )
これは、画像データベースから画像データを取得してビデオに変換するために使用した最終クラス(縮小版)です。
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();
}
}
}
}
2013-11-29を更新(手順)(これが@Kiquenetに求めたことだと思いますか?)
AForge.NET Framework-2.2.5\Samples folder
...にビデオなどのプロジェクトを含む多くの興味深いVisual Studioソリューションが見つかります。)AForge.Video.FFMPEG
( documentation から)AForge.Video.FFMPEG
(in AForge.Video.FFMPEG.dll
)( documentation から)(AForge.Video.FFMPEG.dll
フォルダーにこのAForge.NET Framework-2.2.5\Release
があります)独自のソリューションを作成する場合は、プロジェクトにAForge.Video.FFMPEG.dll
への参照があることを確認してください。そうすれば、 VideoFileWriter クラスを簡単に使用できるはずです。クラスへの link に従うと、非常に優れた(そして簡単な例)が見つかります。コードでは、for
-ループでBitmap image
をVideoFileWriterに供給しています。
スライサーでこのコードを見つけました samples 、あなたが望むものにかなり近いように見えます:
string outputFile = "FadeBetweenImages.wmv";
using (ITimeline timeline = new DefaultTimeline())
{
IGroup group = timeline.AddVideoGroup(32, 160, 100);
ITrack videoTrack = group.AddTrack();
IClip clip1 = videoTrack.AddImage("image1.jpg", 0, 2); // play first image for a little while
IClip clip2 = videoTrack.AddImage("image2.jpg", 0, 2); // and the next
IClip clip3 = videoTrack.AddImage("image3.jpg", 0, 2); // and finally the last
IClip clip4 = videoTrack.AddImage("image4.jpg", 0, 2); // and finally the last
}
double halfDuration = 0.5;
// fade out and back in
group.AddTransition(clip2.Offset - halfDuration, halfDuration, StandardTransitions.CreateFade(), true);
group.AddTransition(clip2.Offset, halfDuration, StandardTransitions.CreateFade(), false);
// again
group.AddTransition(clip3.Offset - halfDuration, halfDuration, StandardTransitions.CreateFade(), true);
group.AddTransition(clip3.Offset, halfDuration, StandardTransitions.CreateFade(), false);
// and again
group.AddTransition(clip4.Offset - halfDuration, halfDuration, StandardTransitions.CreateFade(), true);
group.AddTransition(clip4.Offset, halfDuration, StandardTransitions.CreateFade(), false);
// add some audio
ITrack audioTrack = timeline.AddAudioGroup().AddTrack();
IClip audio =
audioTrack.AddAudio("testinput.wav", 0, videoTrack.Duration);
// create an audio envelope effect, this will:
// fade the audio from 0% to 100% in 1 second.
// play at full volume until 1 second before the end of the track
// fade back out to 0% volume
audioTrack.AddEffect(0, audio.Duration,
StandardEffects.CreateAudioEnvelope(1.0, 1.0, 1.0, audio.Duration));
// render our slideshow out to a windows media file
using (
IRenderer renderer =
new WindowsMediaRenderer(timeline, outputFile, WindowsMediaProfiles.HighQualityVideo))
{
renderer.Render();
}
}
上記の例を機能させることができませんでした。しかし、一度驚くほどうまく機能する別のライブラリを見つけました。 NuGet "accord.extensions.imaging.io"を使用してみて、次の小さな関数を作成しました。
private void makeAvi(string imageInputfolderName, string outVideoFileName, float fps = 12.0f, string imgSearchPattern = "*.png")
{ // reads all images in folder
VideoWriter w = new VideoWriter(outVideoFileName,
new Accord.Extensions.Size(480, 640), fps, true);
Accord.Extensions.Imaging.ImageDirectoryReader ir =
new ImageDirectoryReader(imageInputfolderName, imgSearchPattern);
while (ir.Position < ir.Length)
{
IImage i = ir.Read();
w.Write(i);
}
w.Close();
}
フォルダーからすべての画像を読み取り、それらからビデオを作成します。
より良いものにしたい場合は、おそらくハードコーディングの代わりに画像の寸法を読み取ることができますが、ポイントは得られました。
この関数はSplicer.Netライブラリに基づいています。このライブラリがどのように機能するかを理解するために年齢を見てください。 fps(frame per second)が正しいことを確認してください。ちなみに標準の24 f/s。
私の場合、15枚の画像があり、7秒のビデオが必要になったため、fps = 2です。 Fpsは、プラットフォームまたは開発者の使用状況によって異なる場合があります。
public bool CreateVideo(List<Bitmap> bitmaps, string outputFile, double fps)
{
int width = 640;
int height = 480;
if (bitmaps == null || bitmaps.Count == 0) return false;
try
{
using (ITimeline timeline = new DefaultTimeline(fps))
{
IGroup group = timeline.AddVideoGroup(32, width, height);
ITrack videoTrack = group.AddTrack();
int i = 0;
double miniDuration = 1.0 / fps;
foreach (var bmp in bitmaps)
{
IClip clip = videoTrack.AddImage(bmp, 0, i * miniDuration, (i + 1) * miniDuration);
System.Diagnostics.Debug.WriteLine(++i);
}
timeline.AddAudioGroup();
IRenderer renderer = new WindowsMediaRenderer(timeline, outputFile, WindowsMediaProfiles.HighQualityVideo);
renderer.Render();
}
}
catch { return false; }
return true;
}
お役に立てれば。
これは、C#を使用してVisual Studioを使用して画像シーケンスからビデオを作成するためのソリューションです。
私の出発点は以下の「Hauns TM」の答えでしたが、私の要件は要件よりも基本的であったため、このソリューションはあまり経験のないユーザー(私のような)により適しているかもしれません
図書館:
using System;
using System.IO;
using System.Drawing;
using Accord.Video.FFMPEG;
「ツール-> NuGetパッケージマネージャー->ソリューションのNuGetパッケージの管理...」でFFMPEGを検索すると、FFMPEGライブラリを取得できます。
関数に渡した変数は次のとおりです。
"C://outputFolder//outputMovie.avi"
["C://inputFolder//image_001.avi", "C://inputFolder//image_002.avi", "C://inputFolder//image_003.avi", "C://inputFolder//image_004.avi"]
関数:
private void videoMaker( string outputFileName , string[] inputImageSequence)
{
int width = 1920;
int height = 1080;
var framRate = 25;
using (var vFWriter = new VideoFileWriter())
{
// create new video file
vFWriter.Open(outputFileName, width, height, framRate, VideoCodec.Raw);
foreach (var imageLocation in inputImageSequence)
{
Bitmap imageFrame = System.Drawing.Image.FromFile(imageLocation) as Bitmap;
vFWriter.WriteVideoFrame(imageFrame);
}
vFWriter.Close();
}
}