использоватьРаспознавание лиц 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#, как вы его преобразовали?