Повышение скорости алгоритма коррекции видео на основе заблокированного растрового изображения, getpixel и оптимизированных вспомогательных функций - PullRequest
0 голосов
/ 14 октября 2018

Я написал этот код для удаления раздражающих шаблонов в видео из-за неисправности камеры.Проблема в том, что для кодирования 2-минутного видео этому алгоритму требуется более 2 часа .Я хочу значительно сократить необходимое время.

Алгоритм выполняет итерации по каждому изображению, просматривает каждые 4 пикселя, создает среднее значение и, если среднее значение ниже порогового значения, устанавливает текущий пиксель в белый цвет.Я мог бы использовать шаг = 2 и установить матрицу 2x2 на белый, но это ухудшает качество изображения и увеличивает скорость только вдвое.

Я уже добавил lockbitmap, lockbits и улучшил вспомогательные функции.

До и после using (d2 = reader.ReadVideoFrame()) -snippet у меня есть видеоредактор и писатель aforge на основе ffmpeg.

using (d2 = reader.ReadVideoFrame())
{
    LockBitmap lockBitmap = new LockBitmap(d2);
    lockBitmap.LockBits();

    Color v = Color.FromArgb(240, 237, 241);
    for (int x = 0; x < lockBitmap.Width-1; x = x + 1)
    {
        for (int y = 0; y < lockBitmap.Height-1; y = y + 1)
        {
            Color dus = durchschnitt(lockBitmap.GetPixel(x, y),
                lockBitmap.GetPixel(x + 1, y),
                lockBitmap.GetPixel(x, y + 1),
                lockBitmap.GetPixel(x + 1, y + 1));
            if (abstand(dus, v) < 50)
            {
                lockBitmap.SetPixel(x, y, Color.White);
            }
        }
    }
    lockBitmap.UnlockBits();
}

Вспомогательные функции:

private Color durchschnitt(Color c1, Color c2, Color c3, Color c4)
{
    return Color.FromArgb((int)((c1.R + c2.R + c3.R + c4.R) / 4),
        (int)((c1.G + c2.G + c3.G + c4.G) / 4),
        (int)((c1.B + c2.B + c3.B + c4.B) / 4));
}

и

private double abstand(Color c1, Color c2)
{
    return Math.Sqrt(Math.Pow(c2.R - c1.R, 2) + Math.Pow(c2.G - c1.G, 2) + Math.Pow(c2.B - c1.B, 2));
}

LockBitmap от здесь .

1 Ответ

0 голосов
/ 14 октября 2018

Это не так, как lockBits работает

Короче говоря, вам нужно заблокировать биты, чтобы получить доступ к линии сканирования через указатели.Лучше всего использовать 32bpp для целочисленного доступа.Вы можете вычислить пиксель в соответствующем массиве следующим образом:

. Вам нужно будет украсить свой класс или метод с помощью ключевого слова unsafe, а также установить опцию сборки проекта для использования небезопасного кода., вы используете указатели.

var w = bmp.Width;
var h = bmp.Height;

// lock the array for direct access
var data = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
var scan0Ptr = (int*)data.Scan0;

// get the stride
var stride = data.Stride / 4;

// scan all x
for (var x = 0; x < w; x++)
{
   var pX = scan0Ptr + x;

   // scan all y
   for (var y = 0; y < h; y++)
   {
      // this is now your pixel *p, which essentially is a pointer to
      // to a memory which contains your pixel
      var p = pX + y * stride;

      // or for better access to X and Y
      var p = scan0Ptr + x + y * stride;

      // or alternatively you can just access you pixel with the following notation  
      *(scan0Ptr + x + y * stride) // <== just use this like any variable 

      // example how to convert pixel *p to a Color
      var color = Color.FromArgb(*p);

      // example Convert a Color back to *p and update the pixel
      *p = Color.White.ToArgb();
   }
}
// unlock the bitmap
bmp.UnlockBits(data);

Остальные детали я оставляю на ваше усмотрение, однако это даст вам наилучшую производительность (за исключением некоторых микрооптимизаций).

Наконец, сокращение вызововвнешние методы также дадут вам повышение производительности, однако, если вам действительно это нужно, вы можете помочь CLR, используя MethodImplOptions Enum для AggressiveInlining

Например,

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Color durchschnitt(Color c1, Color c2, Color c3, Color c4)

Также вы можете получить повышение производительности, переместив компоненты, просто мысль

var r = ((*p >> 16) & 255);
var g = ((*p >> 8) & 255);
var b = ((*p >> 0) & 255);

И просто мысль, что вы могли бы, вероятно, многопоточность этой рабочей нагрузки

...