PDA

View Full Version : سوال: فریم ، فریم کردن ویدئو



Mohsen229266
چهارشنبه 07 اردیبهشت 1390, 22:31 عصر
با سلام خدمت دوستان

یک ویدئو تشکیل شده از تعدادی فریم(تصویر)حالا با C# چطوری میشه frame ها رو ازیک ویدئو جدا کرد
مثلا 500 عکس از یک ترک ویدئو 20 ثانیه ای بتوانیم ذخیره کنیم و باز با این فریم ها یا تصاویر ویدئو را تشکیل دهیم

Amir Oveisi
پنج شنبه 08 اردیبهشت 1390, 09:42 صبح
ویدئو تشکیل شده از یک stream و وقتی شما از یک video device میخواید data بگیرید اون رو به شکل stream دریافت می کنید.

برای این کار روش های مختلفی وجود داره، میتونین از library هایی مثل AForge.NET، OpenCV و ... استفاده کنید، اما به نظر من بهترین راه که سرعتش هم از همشون بالاتره (خودم تست کردم) استفاده از DirectShow هست.

Mohsen229266
پنج شنبه 08 اردیبهشت 1390, 22:27 عصر
با تشکر از پاسختون من در مورد DirectShow جستجو کردم برنامه هایی که پیدا کردم فقط برنامه های پخش ویدئو بودند
میشه لطفا یک نمونه برنامه برای جدا کردن فریم ها از یک ویدئو بزارید
باز هم ممنون از پاسختون

Mohsen229266
جمعه 09 اردیبهشت 1390, 23:30 عصر
لطفا اگر ممکنه یک نمونه برنامه ضمیمه کنید

Amir Oveisi
شنبه 10 اردیبهشت 1390, 10:24 صبح
این نمونه با استفاده از DirectShowLib-2005 نوشته شده که در واقع یک Wrapper برای Native DirectShow هست. یک sample هست تو این library به اسم playCap که ویدئو رو با استفاده از direct show نشون میده، من یک SampleGrabber بهش اضافه کردم و یک کلاس SampleGrabberCallBack نوشتم که در هر فریم که receive میشه، فریم رو به شکل Bitmap تبدیل می کنه و اونو دریک pictureBox نشون میده.

کلاس SampleGrabberCallBack :
public class SampleGrabberCallBack : ISampleGrabberCB
{
public int snapShotWidth = 0;
public int snapShotHeight = 0;
public int snapShotImageSize = 0;
public bool snapShotValid = false;
public delegate void HeFrame(System.Drawing.Bitmap BM);
public event HeFrame FrameEvent2;
public byte[] savedArray;
public int bufferedSize;
int framerate = 0;

PictureBox p = (Application.OpenForms[0].Controls["panel2"].Controls["pictureBox1"] as PictureBox);
public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
if (framerate++ % 5 == 0)
{

this.bufferedSize = BufferLen;

int stride = this.snapShotWidth * 3;

Marshal.Copy(pBuffer, this.savedArray, 0, BufferLen);

GCHandle handle = GCHandle.Alloc(this.savedArray, GCHandleType.Pinned);
int scan0 = (int)handle.AddrOfPinnedObject();
scan0 += (this.snapShotHeight - 1) * stride;
Bitmap b = new Bitmap(this.snapShotWidth, this.snapShotHeight, -stride,
System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)scan0);

p.BackgroundImage = b;

handle.Free();
}
return 0;
}

public int SampleCB(double SampleTime, IMediaSample pSample)
{
throw new NotImplementedException();
}
}


نمیدونم با نحوه کار direc show آشنا هستید یا خیر، اما در کل به این شیوه هست که یک Graph داریم که ویدئو در اون قرار می گیره و برای کارهای مختلف با این ویدئو به اون گراف، فیلتر اضافه می کنیم که برای کار فعلی، من فیلتر ISampleGrabber رو که از اینترفیس های خود DirectShow هست استفاده کردم:
ISampleGrabber sampleGrabber = null;

کدها به صورت کامل در برنامه ضمیمه شده وجود دارند، فقط چون تو چند دقیقه نوشتم کدها مقداری شلخته است که عذر میخوام پیشاپیش :)

http://www.4shared.com/file/IbgBsS87/DirectShowFrameGrabber.html

بعد از اجرای برنامه، سمت چپ ویدیو نشون داده میشه، با کلیلک بر روی دکمه Set، از هر 5 فریم یک فریم Grab شده و در picturebox سمت راست نشون داده میشه. اگر خواستید تعداد فریم ها رو کنترل کنید این کد رو تغییر بدید در SampleGrabberCallBack :
if (framerate++ % 5 == 0)

لینک اصلاح شد

موفق باشید
موفق باشید

Mohsen229266
پنج شنبه 22 اردیبهشت 1390, 00:52 صبح
با تشکر فراوان از شما فقط اگه لطف کنید لینک دانلود نمونه برنامه ای را که گذاشته اید رو اصلاح کنید ممنون میشم

Mohsen229266
سه شنبه 27 اردیبهشت 1390, 17:14 عصر
حالا چطوری میتونم این عکس های رو که در pixtureBox نمایش میده رو تو یه مسیر ذخیره کرد؟
من خواستم عکس های bitmap رو ذخیره کنم ولی فقط 1عکس ذخیره میشه بعدش برنامه خطا میگیره

mc_avr
سه شنبه 27 اردیبهشت 1390, 18:08 عصر
کدها به صورت کامل در برنامه ضمیمه شده وجود دارند، فقط چون تو چند دقیقه نوشتم کدها مقداری شلخته است که عذر میخوام پیشاپیش :)


سلام
لینک دانلود خرابه
اگه درستش کنید ممنون میشم.

Amir Oveisi
چهارشنبه 28 اردیبهشت 1390, 10:42 صبح
حالا چطوری میتونم این عکس های رو که در pixtureBox نمایش میده رو تو یه مسیر ذخیره کرد؟
من خواستم عکس های bitmap رو ذخیره کنم ولی فقط 1عکس ذخیره میشه بعدش برنامه خطا میگیره

این کد که تو کدهای بالا هست همین کار رو انجام میده و فریم جاری رو در picturebox نشون میده:
p.BackgroundImage = b;

اگر خطا میده بفرمایید چه خطایی میده :) (بدون دونستن اینکه چه خطایی میده که نمیشه راهنمایی کرد)


لینک دانلود خرابه
اصلاح شد :)

Mohsen229266
یک شنبه 01 خرداد 1390, 09:18 صبح
وقتی کد Save عکس رو اضافه میکنم


p.BackgroundImage = b;

b.Save(@"c:\1\" + framerate.ToString() + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

handle.Free();


بعد از زدن کلید Set از کلاس Program.cs از new کرن فرم اشکال می گیره میگه شی هم اکنون در حال استفاده است

Mohsen229266
یک شنبه 01 خرداد 1390, 09:25 صبح
وقتی کد save عکس رو اضافه میکنم


p.BackgroundImage = b;

b.Save(@"c:\1\" + framerate.ToString() + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

handle.Free();



بعد از زدن دکمه Set از کلاس Program.cs از new کردن فرم اشکال می گیره میگه آبجکت در حال استفاده است
70193