Я получаю данные изображения с камеры, которая поступает в виде массива ushorts из неуправляемой библиотеки DLL.
Мне удалось передать данные в управляемую зону на довольно хорошей скорости.
// cpp .NET
static void imageCallback(unsigned short * rawData, unsigned int length) {
array<unsigned short>^ imageData = gcnew array<unsigned short>(length);
unsigned int headLength = 512; // header length in shorts
pin_ptr<unsigned short> imageDataStart = &imageData[0];
memcpy(imageDataStart, rawData + headLength, length);
callBackDelegate(imageData);
}
Данные поступают в виде шортов «RGBRGBRGB ....» для каждого цветового канала.
Затем управляемый массив отправляется на C# через делегата. Затем мне нужно преобразовать необработанные данные и вставить их в растровое изображение (с 8-битным значением) обычными методами, например так:
public static Bitmap RGBDataToBitmap(ushort[] data, int Width, int Height, int bitDepth)
{
Bitmap bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb);
var rawdata = bmp.LockBits(new Rectangle(Point.Empty, bmp.Size), ImageLockMode.ReadWrite, bmp.PixelFormat);
var pixelSize = rawdata.PixelFormat == PixelFormat.Format32bppArgb ? 4 : 3; // only works with 32 or 24 pixel-size bitmap!
var padding = rawdata.Stride - (rawdata.Width * pixelSize);
var bytes = new byte[rawdata.Height * rawdata.Stride];
var index = 0;
var pixel = 0;
// scale to 8 bits
var scalar = Math.Pow(2, -(bitDepth - 8));
for (var y = 0; y < Height; y++)
{
for (var x = 0; x < Width; x++)
{
int Rlevel = (int)Math.Round(data[pixel + 0] * scalar);
int Glevel = (int)Math.Round(data[pixel + 1] * scalar);
int Blevel = (int)Math.Round(data[pixel + 2] * scalar);
pixel += 3;
bytes[index + 3] = 255; // A component
bytes[index + 2] = Convert.ToByte(Blevel); // B component
bytes[index + 1] = Convert.ToByte(Glevel); // G component
bytes[index + 0] = Convert.ToByte(Rlevel); // R component
index += pixelSize;
}
index += padding;
}
// copy back the bytes from array to the bitmap
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, rawdata.Scan0, bytes.Length);
bmp.UnlockBits(rawdata);
return bmp;
}
Если я синхронизирую эту операцию (исходные данные с растровым изображением), она занимает ~ 0,5 секунды. Кадры поступают со скоростью ~ 12 раз в секунду, так что это слишком медленно.
Кто-нибудь видит, как я могу сделать эту операцию быстрее на C#? Или у кого-нибудь есть руководство по другому методу?
Цель состоит в том, чтобы получить живое видеоизображение на C#.
Спасибо!
Обновлено:
Согласно приведенным ниже предложениям, если я изменю цикл for на это:
// scale to 8 bits
var bitminus8 = bitDepth - 8;
var scalar = Math.Pow(2, -(bitminus8));
Parallel.For(0, Height, y =>
{
var index = y * Width;
for (var x = 0; x < Width; x++)
{
var idx = index + x;
byte Rlevel = (byte)(data[idx * 3 + 0] >> bitminus8);
byte Glevel = (byte)(data[idx * 3 + 1] >> bitminus8);
byte Blevel = (byte)(data[idx * 3 + 2] >> bitminus8);
bytes[idx * 4 + 3] = 255; // A component
bytes[idx * 4 + 2] = Blevel; // B component
bytes[idx * 4 + 1] = Glevel; // G component
bytes[idx * 4 + 0] = Rlevel; // R component
}
});
Это изменяется с 0,5 секунды до 0,04 секунды. Хороший момент в преобразовании байтов, который имел большое значение.
сначала почему var scalar = Math.Pow(2, -(bitDepth - 8)); называется х * у раз? и почему именно if (Xlevel < 0) { Xlevel= 0; }? Xlevel не может быть <0
Найдите unsafe для C#
Вы на x86?
Может ли bitDepth быть меньше 8? Может ли data содержать значения больше 255? Как Rlevel, Glevel, Blevel могут быть отрицательными? Можете ли вы использовать byte вместо ushort? Также, как сказал Селвин, кажется, что вы можете вывести расчет scalar за пределы цикла.
Вы можете легко распараллелить внешний цикл.
Всем привет, спасибо за комментарии. Я отредактировал и отвечаю всем вам: я помечаю C++, потому что у меня есть возможность манипулировать данными в неуправляемой области. Или, может быть, кто-то знаком, скажем, с OpenCV и знает, что это поможет мне. Да, скаляр не должен входить в цикл (переместил его). Я проверю небезопасно. GPU напрямую? Как? Может быть, OpenCV или Aforge.NET или что-то подобное? Да, x86. Bitdepth> = 8. Я удалил другие вещи, не относящиеся к этому вопросу (уровни не должны быть отрицательными, это было для отладки). Да, распараллелить внешний цикл. Можете ли вы указать мне пример? Спасибо.
Похоже, что параллельный и небезопасный маршрут может быть хорошим, я постараюсь реализовать это и опубликовать ответ.
Итак, теперь вы можете обрабатывать 25 кадров в секунду, верно? На сколько логических / физических ядер? Вы хотите, чтобы это было быстрее? Использование графического процессора может быть хорошим вариантом, если вы не хотите, чтобы ваша программа занимала слишком много времени процессора.
Теперь я бегаю так быстро, как драйвер камеры может выталкивать изображения. Можете ли вы указать мне на ресурс, который может помочь мне в использовании графического процессора? Мне нужно выполнить дополнительную обработку изображений.





Тогда зачем использовать теги C++? Вы привлекаете только взоры сварливых людей вроде меня, которые быстро нажимают кнопку «против».