Оптимизация обработки изображений


Я использую приложения WinForms на C# .Нетто 3.5. Я получаю кадры, и это, как я справиться с ними:

    delegate void videoStream_NewFrameDelegate(object sender, NewFrameEventArgs eventArgs);
    public void videoStream_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        if (ready)
        {
            if (this.InvokeRequired)
            {
                videoStream_NewFrameDelegate del = new videoStream_NewFrameDelegate(videoStream_NewFrame);
                this.Invoke(del, new object[] {sender, eventArgs} );
            }
            else
            {
                Rectangle rc = ClientRectangle;
                Bitmap bmp = new Bitmap(rc.Width, rc.Height);
                Graphics g = Graphics.FromImage((Image)bmp);
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
                g.DrawImage((Bitmap)eventArgs.Frame, rc.X+10, rc.Y+10, rc.Width-20, rc.Height-20);

                g.Dispose();
                this.Image = (Image)bmp;
            }
        }
    }

Есть ли способ, чтобы оптимизировать или улучшить производительность?

Я получаю низкую производительность, когда мое изображение 320х240 и я растягивая его до 1280х1024, но то же изображение на 640х480 и 1280х1024 на растяжку, чтобы не получить больших потерь в производительности.

Я пытался использовать WPF и все же потеря производительности. Это странно, поскольку WPF предполагается использовать DirectX и быть быстрым в обработке изображений.

Вот мой код WPF:

    delegate void videoStream_NewFrameDelegate(object sender, NewFrameEventArgs eventArgs);
    public void videoStream_NewFrame(object sender, NewFrameEventArgs eventArgs)
    {
        if (ready)
        {
            if (!this.Frame.Dispatcher.CheckAccess())
            {
                videoStream_NewFrameDelegate del = new videoStream_NewFrameDelegate(videoStream_NewFrame);
                this.Frame.Dispatcher.Invoke(del, new object[] { sender, eventArgs });
            }
            else
            {
                Bitmap bmp = (Bitmap)eventArgs.Frame.Clone();
                IntPtr hBitmap = bmp.GetHbitmap();
                BitmapSource img = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
                bmp.Dispose();
                GC.Collect();

                this.Frame.Source = img;
            }
        }
    }


7416
3
задан 13 сентября 2011 в 09:09 Источник Поделиться
Комментарии
1 ответ


Я пытался использовать WPF и все же preformence потерять.. это странно, поскольку WPF, предполагают, чтобы использовать DirectX и быть быстрым в обработки изображения.

Кроме того, в WPF версии, клонируется растрового изображения (которая не имеет ничего общего с WPF) и затем вызывая воображения.CreateBitmapFromHBitmap, которая в конечном итоге преобразуется в вызов:

[DllImport("WindowsCodecs.dll", EntryPoint="IWICImagingFactory_CreateBitmapFromHBITMAP_Proxy")]
internal static extern int CreateBitmapFromHBITMAP(IntPtr THIS_PTR, IntPtr hBitmap, IntPtr hPalette, WICBitmapAlphaChannelOption options, out BitmapSourceSafeMILHandle ppIBitmap);

Теперь я не знаю, что этот метод делает, но очень может быть копирование данных снова, но, возможно, не. В любом случае, ваш метод WPF выполняет по крайней мере один клон изображения в целом и вашей версии WinForms нет.

Это не совсем то, хотя мясо его. Вы даже не выложили результаты тестов, так что вы должны сделать, прежде чем предполагая какую-то одну часть кода "медленное", и вы будете иметь трудное время на оптимизацию, пока у вас есть, что ответить. Ты два варианта не идентичны по продукции; приложения WinForms версии выполняет HighQualityBilinear интерполяции, которая, безусловно, будет занимать значительное время.

Вы должны сказать нам, что вам требования. Я бежал быстрый тест с помощью следующего кода с помощью размер изображения 320х240, а потом снова на 640x480:

public Form1()
{
InitializeComponent();
}

private TimeSpan RunTest( int sampleSize )
{
var sw = Stopwatch.StartNew();
var baseImg = new Bitmap( @"C:\TestImage.jpg" );
Bitmap bmp = null;
for( int i = 0; i < sampleSize; ++i )
{
var rect = picBox.ClientRectangle;
bmp = new Bitmap( rect.Width, rect.Height );
using( Graphics g = Graphics.FromImage( bmp ) )
{
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImage( baseImg, rect );
}

picBox.Image = bmp;
// the call to Invalidate() that you have is not needed.
}

sw.Stop();
return TimeSpan.FromMilliseconds( sw.ElapsedMilliseconds );
}

private void picBox_Click( object sender, EventArgs e )
{
int iterations = 100;
var time = RunTest( iterations );
MessageBox.Show( String.Format(
"Elapsed: {0}, Average: {1}",
time.TotalMilliseconds,
time.TotalMilliseconds / iterations ) );
}

Затем я выполнил еще один тест, используя по умолчанию InterpolationMode. В рамках построения выпуска, который дал мне следующие результаты:

320х240
1. Высокое качество интерполяции: общая: 3122ms, средний: 31.22 МС, ФПС: 32
2. Интерполяция по умолчанию: общая: 2165ms, средний: 21.65 МС, ФПС: 46

640х480
1. Высокое качество интерполяции: общая: 3963ms, средний: 39.63 МС, кадров в секунду: 25
2. Интерполяция по умолчанию: общая: 2256ms, средний: 22.56 МС, ФПС: 44

Вы говорили, что 32 кадров в секунду не достаточно хорошо для вашего приложения? Это 42 ОК и это хорошо, чтобы удалить высокое качество рендеринга? Вы должны предоставить более подробную информацию. Вы не можете ожидать от нас, чтобы оптимизировать ваш код без целевого требования. Также, Как видите, ваше утверждение, что производительность лучше, с большими изображениями не появляются, чтобы быть правдой, хотя разница без высококачественной билинейной перевода ничтожна.

Если вы можете отказаться от билинейной интерполяции можно просто установить StretchMode из элемента управления PictureBox , чтобы растянуть и просто установить изображения собственность на раме свойство события объекта args и покончим с этим. Это будет значительно быстрее.

3
ответ дан 13 сентября 2011 в 09:09 Источник Поделиться