2016-03-14 4 views
1

Моя цель состоит в том, чтобы иметь возможность взять строку из 70 пикселей, проанализировать все 70 пикселей для определенного цвета и затем перебросить в другую функцию, если критерии выполнены. Это должно происходить по крайней мере один раз каждые 50 миллисекунд, и желательно даже быстрее, чем это.Как я могу быстро захватить данные растровых изображений в C#

Мой текущий код выглядит так

public void CaptureArea() 
    { 
     using (Bitmap capture = new Bitmap(70, 35)) 
     { 
      using (Graphics g = Graphics.FromImage(capture)) 
      { 
       for (int i = 0; i < 10; i++) 
       { 
        g.CopyFromScreen(copyPoint, pastePoint, new Size(70, 35)); 
        evaluteBitmap(capture); 
       } 
      } 
     } 
    } 
    public void evaluteBitmap(Bitmap scanArea) 
    { 
     Rectangle rect = new Rectangle(0, 0, 70, 35); 
     BitmapData data = scanArea.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); 

     IntPtr ptr = data.Scan0; 

     int bytes = data.Stride * scanArea.Height; 
     byte[] rgbValues = new byte[bytes]; 
     byte[] r = new byte[bytes/3]; 
     byte[] g = new byte[bytes/3]; 
     byte[] b = new byte[bytes/3]; 

     Marshal.Copy(ptr, rgbValues, 0, bytes); 

     int count = 0; 
     int stride = data.Stride; 

     for (int column = 0; column < 30; column++) 
     { 
      b[count] = (byte)(rgbValues[(column * stride) + (34 * 3)]); 
      g[count] = (byte)(rgbValues[(column * stride) + (34 * 3) + 1]); 
      r[count++] = (byte)(rgbValues[(column * stride) + (34 * 3) + 2]); 
     } 

     scanArea.UnlockBits(data); 
    } 

Just CaptureArea() может упасть около 60 растровых изображений в памяти каждую секунду, и это хорошо, но в настоящее время он занимает около 600 миллисекунд для EvaluateBitmap(), чтобы захватить пиксель и разделить его на RGB-значения 70 раз.

Конечным результатом является то, что один кадр данных занимает более 500 миллисекунд для обработки, когда он должен быть намного ближе к 50 миллисекундам. Такое решение проблем выходит за рамки меня, и я недостаточно опытен с таким кодом, чтобы иметь возможность решения для глазного яблока и знать, что в конечном итоге будет быстрее или медленнее и насколько.

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

+0

Чувак, ваш код выдает исключение. –

+0

Позвольте мне исправить это здесь. Я отредактировал его для удобочитаемости и должен был ввести проблему при этом. – mkautzm

+0

Если вы закомментируете функцию calculateBitmap, время будет почти таким же. Настолько ясно, что CopyFromScreen является самым медленным. И, к сожалению, она имеет одинаковую скорость независимо от того, какая большая часть экрана вам нужна. Но он может обеспечить ок. 60fps ~ 16ms, поэтому он должен быть достаточно быстрым для вашей цели. Если вы скажете, что оценкаBitmap медленнее, чем CopyFromScreen, это просто неверно для представленного кода, и вы кое-что допустили. –

ответ

1

Профилирование сессии для данного кода дает однозначный результат:

CopyFromScreen - 40,00% эксклюзивные образцы
Bitmap..ctor - 15,00% эксклюзивные образцы
clr.dll - 11,67% эксклюзивные образцы
KernelBase.dll - 8,33% эксклюзивные образцы
gdiplus.dll - 6,67% эксклюзивные образцы
LockBits - 6,67% эксклюзивные образцы
Image.Dispose - 5,00% эксклюзивный образец S
....
....
EvaluateBitmap - 1,67% эксклюзивные образцы
....
....
CaptureArea - 0,0% эксклюзивные образцы

Самая большая часть времени тратится на .NET-методы, которые не могут быть улучшены.

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

+0

Ну, это перерывы. Я очень ценю анализ, хотя! Спасибо за ваше время! – mkautzm