これは、フレーム/画像をハードディスクに保存するコードです。
画像を 180 度で 2 回、次に 90 度で 2 回回転します。
しかし、ビデオは左から右に歩いている女性を示していますが、回転後、鏡のように右から左に移動するtrackBarスクロールを使用してpictureBoxに表示されます。
回転後はこんな感じ。
彼女は右から左に歩き始めます。オリジナルでは左から右にあるはずの顔が左を向いています。
元のビデオ ファイルでも同じように 180 度回転すると、次のようになります。
私が望むのは、彼女が最初の画像のように左から右に歩いているのを見ることです。2 番目の画像のように、彼女の顔は右を向いています。
これは私が使用しているコードです:
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
// bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
if (SaveToDisc)
{
String tempFile = _outFolder+ _frameId.ToString("D6") + ".bmp";
if (File.Exists(tempFile))
{
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
else
{
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
_frameId++;
}
else
{
if (Images == null)
Images = new List<Bitmap>();
Images.Add((Bitmap)bitmap.Clone());
}
}
return 0;
}
今度は 180 度回転させ、さらに 90 度回転させ、さらに 180 度回転させようとしましたが、うまくいきませんでした。
2番目の画像を右に90度回転させたいので、試してみました:
bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
しかし、それはしませんでした。
どうすればできますか?
回転にこの関数を使用しようとしています:
public static Image RotateImage(Image img, float rotationAngle)
{
//create an empty Bitmap image
Bitmap bmp = new Bitmap(img.Width, img.Height);
//turn the Bitmap into a Graphics object
Graphics gfx = Graphics.FromImage(bmp);
//now we set the rotation point to the center of our image
gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
//now rotate the image
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
//set the InterpolationMode to HighQualityBicubic so to ensure a high
//quality image once it is transformed to the specified size
gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
//now draw our new image onto the graphics object
gfx.DrawImage(img, new Point(0, 0));
//dispose of our Graphics object
gfx.Dispose();
//return the image
return bmp;
}
次に、次のように使用します。
Bitmap t = new Bitmap(RotateImage(bitmap, 180));
t.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
ただし、右に 180 度または 90 度回転することはありません。それを鏡にします。2 番目の画像で彼女の顔が右を向いている場合、画像を右に 90 度回転させて、顔が右を向いて立つようにします !!! しかし、代わりに、彼女が鏡のように左に顔を向けていることが常にわかります。
なんで ?
これは、ビデオ ファイルからフレームを抽出し、ハード ディスクに保存するクラスです。
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using DirectShowLib;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
namespace Polkan.DataSource
{
internal class WmvAdapter : ISampleGrabberCB, IDisposable
{
#region Fields
//public Image img;
private IFilterGraph2 _filterGraph;
private IMediaControl _mediaCtrl;
private IMediaEvent _mediaEvent;
private int _width;
private int _height;
private readonly string _outFolder;
private int _frameId;
private Label lbl1;
public bool done;
#endregion
#region Constructors and Destructors
public WmvAdapter(string file, string outFolder , Label lbl)
{
_outFolder = outFolder;
lbl1 = lbl;
try
{
SetupGraph(file);
}
catch
{
Dispose();
MessageBox.Show("A codec is required to load this video file. Please use http://www.headbands.com/gspot/ or search the web for the correct codec");
throw;
}
}
~WmvAdapter()
{
CloseInterfaces();
}
#endregion
public void Dispose()
{
CloseInterfaces();
}
public void Start()
{
int hr = _mediaCtrl.Run();
WaitUntilDone();
DsError.ThrowExceptionForHR(hr);
}
public void WaitUntilDone()
{
int hr;
const int eAbort = unchecked((int)0x80004004);
do
{
System.Windows.Forms.Application.DoEvents();
EventCode evCode;
hr = _mediaEvent.WaitForCompletion(100, out evCode);
} while
(hr == eAbort);
DsError.ThrowExceptionForHR(hr);
lbl1.ForeColor = Color.Red;
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
done = true;
}
/// <summary> build the capture graph for grabber. </summary>
private void SetupGraph(string file)
{
ISampleGrabber sampGrabber = null;
IBaseFilter capFilter = null;
IBaseFilter nullrenderer = null;
_filterGraph = (IFilterGraph2)new FilterGraph();
_mediaCtrl = (IMediaControl)_filterGraph;
_mediaEvent = (IMediaEvent)_filterGraph;
var mediaFilt = (IMediaFilter)_filterGraph;
try
{
// Add the video source
int hr = _filterGraph.AddSourceFilter(file, "Ds.NET FileFilter", out capFilter);
DsError.ThrowExceptionForHR(hr);
// Get the SampleGrabber interface
sampGrabber = new SampleGrabber() as ISampleGrabber;
var baseGrabFlt = sampGrabber as IBaseFilter;
ConfigureSampleGrabber(sampGrabber);
// Add the frame grabber to the graph
hr = _filterGraph.AddFilter(baseGrabFlt, "Ds.NET Grabber");
DsError.ThrowExceptionForHR(hr);
// ---------------------------------
// Connect the file filter to the sample grabber
// Hopefully this will be the video pin, we could check by reading it's mediatype
IPin iPinOut = DsFindPin.ByDirection(capFilter, PinDirection.Output, 0);
// Get the input pin from the sample grabber
IPin iPinIn = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Input, 0);
hr = _filterGraph.Connect(iPinOut, iPinIn);
DsError.ThrowExceptionForHR(hr);
// Add the null renderer to the graph
nullrenderer = new NullRenderer() as IBaseFilter;
hr = _filterGraph.AddFilter(nullrenderer, "Null renderer");
DsError.ThrowExceptionForHR(hr);
// ---------------------------------
// Connect the sample grabber to the null renderer
iPinOut = DsFindPin.ByDirection(baseGrabFlt, PinDirection.Output, 0);
iPinIn = DsFindPin.ByDirection(nullrenderer, PinDirection.Input, 0);
hr = _filterGraph.Connect(iPinOut, iPinIn);
DsError.ThrowExceptionForHR(hr);
// Turn off the clock. This causes the frames to be sent
// thru the graph as fast as possible
hr = mediaFilt.SetSyncSource(null);
DsError.ThrowExceptionForHR(hr);
// Read and cache the image sizes
SaveSizeInfo(sampGrabber);
}
finally
{
if (capFilter != null)
{
Marshal.ReleaseComObject(capFilter);
}
if (sampGrabber != null)
{
Marshal.ReleaseComObject(sampGrabber);
}
if (nullrenderer != null)
{
Marshal.ReleaseComObject(nullrenderer);
}
GC.Collect();
}
}
private void SaveSizeInfo(ISampleGrabber sampGrabber)
{
// Get the media type from the SampleGrabber
var media = new AMMediaType();
int hr = sampGrabber.GetConnectedMediaType(media);
DsError.ThrowExceptionForHR(hr);
if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
{
throw new NotSupportedException("Unknown Grabber Media Format");
}
// Grab the size info
var videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
_width = videoInfoHeader.BmiHeader.Width;
_height = videoInfoHeader.BmiHeader.Height;
DsUtils.FreeAMMediaType(media);
GC.Collect();
}
private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
{
var media = new AMMediaType
{
majorType = MediaType.Video,
subType = MediaSubType.RGB24,
formatType = FormatType.VideoInfo
};
int hr = sampGrabber.SetMediaType(media);
DsError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(media);
GC.Collect();
hr = sampGrabber.SetCallback(this, 1);
DsError.ThrowExceptionForHR(hr);
}
private void CloseInterfaces()
{
try
{
if (_mediaCtrl != null)
{
_mediaCtrl.Stop();
_mediaCtrl = null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
if (_filterGraph != null)
{
Marshal.ReleaseComObject(_filterGraph);
_filterGraph = null;
}
GC.Collect();
}
int ISampleGrabberCB.SampleCB(double sampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}
//add a boolean property to indicate the save-mode
public bool SaveToDisc { get; set; }
//the list for the bitmaps
public List<Bitmap> Images { get; set; }
int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
//bitmap.RotateFlip(RotateFlipType.RotateNoneFlipXY);
// bitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
// Bitmap t = new Bitmap(RotateImage(bitmap, 180));
if (SaveToDisc)
{
String tempFile = _outFolder+ _frameId.ToString("D6") + ".bmp";
if (File.Exists(tempFile))
{
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
else
{
bitmap.Save(Path.Combine(_outFolder, _frameId.ToString("D6") + ".bmp"));
if (lbl1.InvokeRequired)
{
lbl1.Invoke(new MethodInvoker(delegate { lbl1.Text = _frameId.ToString(); }));
}
}
_frameId++;
}
else
{
if (Images == null)
Images = new List<Bitmap>();
Images.Add((Bitmap)bitmap.Clone());
}
}
return 0;
}
public static Image RotateImage(Image img, float rotationAngle)
{
//create an empty Bitmap image
Bitmap bmp = new Bitmap(img.Width, img.Height);
//turn the Bitmap into a Graphics object
Graphics gfx = Graphics.FromImage(bmp);
//now we set the rotation point to the center of our image
gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
//now rotate the image
gfx.RotateTransform(rotationAngle);
gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
//set the InterpolationMode to HighQualityBicubic so to ensure a high
//quality image once it is transformed to the specified size
gfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
//now draw our new image onto the graphics object
gfx.DrawImage(img, new Point(0, 0));
//dispose of our Graphics object
gfx.Dispose();
//return the image
return bmp;
}
/*int ISampleGrabberCB.BufferCB(double sampleTime, IntPtr pBuffer, int bufferLen)
{
using (var bitmap = new Bitmap(_width, _height, _width * 3, PixelFormat.Format24bppRgb, pBuffer))
{
bitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
MemoryStream myStream = new MemoryStream(1000000);
bitmap.Save(myStream, ImageFormat.Bmp);
//bitmap.Save(Path.Combine(_outFolder, _frameId + ".bmp"));
img = new Bitmap(myStream);
}
return 0;
}*/
}
}
Form1 では、次のようなクラスを使用しています。
private void button5_Click(object sender, EventArgs e)
{
button5.Enabled = false;
button1.Enabled = false;
wmv = new Polkan.DataSource.WmvAdapter(@"d:\VIDEO0040.3gp", sf,label2);
wmv.SaveToDisc = true;
wmv.Start();
if (wmv.done == true)
{
button1.Enabled = true;
}
}