最近工作中需要遮掉视频中出现的二维码。为了减轻工作量,所以计划开发一个可以自动检测二维码的小工具。因为是在Windows上运行的小工具,所以自然选择C#来实现。
在网上查询了一下资料,发现可以使用ffmpeg+OpenCV实现。
实现思路:使用ffmpeg将视频每一帧解码成图片,然后再使用OpenCV检测图片中是否包含二维码。
使用ffmpeg API的包装库FFmpeg.AutoGen来实现解码,将帧数据转换成图片。代码可以参考该项目中自带的Example工程:VideoFrameConverter、VideoStreamDecoder
using (var vfc = new VideoFrameConverter(sourceSize, sourcePixelFormat, destinationSize, destinationPixelFormat))
{
var frameNumber = 0;
while (vsd.TryDecodeNextFrame(out var frame))
{
var convertedFrame = vfc.Convert(frame);
using (var bitmap = new Bitmap(convertedFrame.width, convertedFrame.height,
convertedFrame.linesize[0], PixelFormat.Format24bppRgb, (IntPtr) convertedFrame.data[0]))
{
bool qr = parser.DetectQrInMat(bitmap);
if (qr)
{
bitmap.Save($"frame.{frameNumber:D8}.jpg", ImageFormat.Jpeg);
}
}
Console.WriteLine($"frame: {frameNumber}");
frameNumber++;
}
Console.WriteLine($"检测完成。");
}
2.二维码检测
使用OpenCvSharp4库,该库中已经提供了检测二维码的功能,不需要自己实现。
//Bitmap转换为Mat
MemoryStream ms = new MemoryStream();
bitmap.Save(ms, ImageFormat.Bmp);
byte[] bytes = ms.GetBuffer();
Mat mat = Mat.FromImageData(bytes, ImreadModes.AnyColor);
InputArray input = InputArray.Create(mat);
//二维码检测
QRCodeDetector detector = new QRCodeDetector();
Point2f[] points;
bool success = detector.DetectMulti(input, out points);
坑:
坑是难免的,这次就碰上一个很神奇的问题,FFmpeg.AutoGen使用时,总是提示无法加载相关的DLL文件。下载FFmpeg.AutoGen所有相关的代码,编译运行都没有问题。但是在自己的工程中使用下载的FFmpeg.AutoGen的DLL文件,就是出错。
出错在WindowsNativeMethods.LoadLibrary(libraryName),反复对比两个工程的设置,后来无意中修改了一下工程中的目标框架改为4.5 Client Profile,然后问题就神奇的消失了,再把框架改回去,问题也再复现。
就是这么神奇!
后记:
工具简单做了一个原型,小伙伴说,不仅仅要处理二维码,还要处理广告。反正都要将视频从头到尾看一遍,使用工具的必要性不是很大,所以工具就暂停了:(