[C#] видеоданные распознавания лиц в данные изображения

Идентификация изображения

использоватьРаспознавание лиц Arcsoftстолкнулся с проблемой преобразования во время разработки

Поскольку камера не будет открыта напрямую с помощью C#, можно использовать только стороннюю dll. Я сначала пользовался Aforge, но потом обнаружил проблему, постоянно застревал в ожидании выключения камеры, поэтому забросил. Некоторое время назад я начал использовать Emgu, который инкапсулирует OpenCV, и вздохнул по пути.

1. Установите Вздох Эмгу

Сначала я скачал и установил Emgu самостоятельно, а затем, после различных тестов, я обнаружил, что мне все еще нужно то и это Наконец, я обнаружил, что можно напрямую установить пакет NuGet EMGU.CV. Конечно, чтобы открыть видео, вам также нужно сослаться на System.ServiceModel.

2. Получение видео Очень удобно использовать Emgu для получения видео

1. Определите две переменные

VideoCapture _VideoCapture;
Mat _Frame = new Mat();

2. Инициализируйте видео

_VideoCapture = new VideoCapture();//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1024); //设置宽度//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 768);//设置高度_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, 10);//设置每秒钟的帧数_VideoCapture.Start();_VideoCapture.ImageGrabbed += _VideoCapture_ImageGrabbed; //视频事件

3. Видео дисплей

private void _VideoCapture_ImageGrabbed(object sender, EventArgs e){_VideoCapture.Retrieve(_Frame, 1);this.pictureBox1.Image = _Frame.Bitmap; //很神奇的pictureBox,居然不在UI线程也能显示}

4. Получить текущий кадр
Для сравнения лица обычно в другой ветке

Mat curFrame=_VideoCapture.QueryFrame();

Все идеально, то есть _Frame.Bitmap вроде как не имеет Dispose (позже обнаружил, что адрес мата неизменен, и утечки памяти не будет), но работает нормально.

3. Вздох распознавания лиц

Я посмотрел, распознавание лиц требует Bitmap, что удобно

Mat curFrame=_VideoCapture.QueryFrame();
Bitmap bitmap=curFrame.Bitmap;

var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
int width = (bitmap.Width + 3) / 4 * 4;
var bytesCount = bmpData.Height * width * 3;
IntPtr pImageData = Marshal.AllocCoTaskMem(bytesCount);
if (width == bitmap.Width)
CopyMemory(pImageData, bmpData.Scan0, bytesCount);
else
for (int i = 0; i < bitmap.Width; i++)
CopyMemory(IntPtr.Add(pImageData, i * width * 3), IntPtr.Add(bmpData.Scan0, i * bmpData.Stride), bmpData.Stride);
bitmap.UnlockBits(bmpData);

Я получил данные изображения pImageData, необходимые для ArcFace.Хорошо протестировать его, и он может работать. Через некоторое время ошибка: "Попытка чтения или записи защищенной памяти. Обычно это указывает на то, что другая память повреждена.

Предполагается, что поток распознавания лиц конфликтует с потоком отображения видео.Я проверил исходный код Emgu и обнаружил, что QueryFrame инкапсулирует Retrieve.

Что ж, клонируйте его, Bitmap bitmap=(Bitmap)curFrame.Bitmap.Clone(); Проблема остается! Проверьте адрес и обнаружите, что Clone бесполезен!

В-четвертых, окончательное решение

Изучив Mat, я обнаружил, что GetData() может возвращать данные изображения без конфликтов Наконец, это записывается так:
1. Определение

IntPtr _PImageData;

int _ImageWidth,_ImageHeight,_ImageSize;

2. Инициализация

_ImageWidth=_VideoCapture.Width;

_ImageHeight=_VideoCapture.Height;

_ImageSize = _VideoCapture.Width * _VideoCapture.Height * 3;_PImageData = Marshal.AllocCoTaskMem(_ImageSize);

3. Конвертировать

Marshal.Copy(_Frame.GetData(), 0, _PImageData, _ImageSize);

ASFDetectFaces(pEngine,_ImageWidth, _ImageHeight,513,_PImageData, out var faceInfo);...

Все стало так легко, с долгим вздохом!

5. Другие

1. Ширина видеоизображения обычно кратна 4, поэтому описанный выше способ точно не проблема.
2. Люди часто спрашивают, как получить изображения с веб-камер и ip-камер.

videoCapture = new VideoCapture("string filename");

Например, имя файла IP-камеры tplink — «rtsp://admin:admin@192.168.0.159/stream1», а формат — rstp://имя пользователя:пароль@ip-адрес/...

Уважаемый профессионал C#, как вы его преобразовали?