FFmpeg+OpenCV 读取摄像头

news/2024/12/21 11:02:50/

FFmpeg+OpenCV 读取摄像头

提供两种方式使用 FFmpeg 从摄像头中读取数据,并使用 OpenCV 显示视频帧。

读取摄像头

方法一

void VideoCapture() {avdevice_register_all();AVFormatContext *context = avformat_alloc_context();AVInputFormat *inputFormat = av_find_input_format("dshow");// 这里的 video=Logitech Webcam C930e 需要填写你自己的摄像头信息// 可以在终端下使用 ffmpeg -list_devices true -f dshow -i dummy 查看avformat_open_input(&context, "video=Logitech Webcam C930e", inputFormat, nullptr);int video_index = av_find_best_stream(context, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);if (video_index == -1) {printf("Could not find a video stream");avformat_close_input(&context);return;}// 获取流参数AVCodecParameters *params = context->streams[video_index]->codecpar;// 获取解码器AVCodec *codec = avcodec_find_decoder(params->codec_id);// 初始化一个解码器的上下文AVCodecContext *codecContext = avcodec_alloc_context3(codec);if (avcodec_parameters_to_context(codecContext, params) != 0) {printf("Could not copy codec context");avformat_close_input(&context);return;}avcodec_open2(codecContext, codec, nullptr);AVFrame *frame = av_frame_alloc();AVFrame *frameYUV = av_frame_alloc();int width = codecContext->width;int height = codecContext->height;// 声明图像的空间用以保存 YUV 图像auto* out_buffer = (unsigned char*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, width, height, 1));av_image_fill_arrays(frameYUV->data, frameYUV->linesize, (const uint8_t*)out_buffer,AV_PIX_FMT_YUV420P, width, height, 1);AVPacket packet;struct SwsContext *swsContext;swsContext = sws_getContext(width, height, codecContext->pix_fmt,width, height, AV_PIX_FMT_YUV420P, SWS_BICUBIC,nullptr, nullptr, nullptr);while (av_read_frame(context, &packet) >= 0) {if (packet.stream_index == video_index) {avcodec_send_packet(codecContext, &packet);while (avcodec_receive_frame(codecContext, frame) == 0) {// 将解码后的图片转换为 YUV 格式sws_scale(swsContext, (const unsigned char* const *)frame->data, frame->linesize, 0,height, frameYUV->data, frameYUV->linesize);int size = width * height;// FFmpeg frame 转换为 OpenCV Matcv::Mat img = cv::Mat::zeros(height * 3 / 2, width, CV_8UC1);memcpy(img.data, frameYUV->data[0], size);memcpy(img.data + width * height, frameYUV->data[1], size / 4);memcpy(img.data + width * height * 5 / 4, frameYUV->data[2], size / 4);cv::cvtColor(img, img, CV_YUV2BGR_I420);cv::imshow("__main__", img);cv::waitKey(1);}}av_packet_unref(&packet);}// 释放资源av_frame_free(&frame);avcodec_close(codecContext);avcodec_parameters_free(&params);avformat_close_input(&context);
}

方法二

void VideoCapture() {AVFormatContext *context = avformat_alloc_context();AVInputFormat *inputFormat = av_find_input_format("dshow");avformat_open_input(&context, "video=Logitech Webcam C930e", inputFormat, nullptr);int video_index = av_find_best_stream(context, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);if (video_index == -1) {printf("Could not find a video stream");avformat_close_input(&context);return;}// 获取流参数AVCodecParameters *params = context->streams[video_index]->codecpar;// 获取解码器AVCodec *codec = avcodec_find_decoder(params->codec_id);// 初始化一个解码器的上下文AVCodecContext *codecContext = avcodec_alloc_context3(codec);if (avcodec_parameters_to_context(codecContext, params) != 0) {printf("Could not copy codec context");avformat_close_input(&context);return;}avcodec_open2(codecContext, codec, nullptr);AVFrame *frame = av_frame_alloc();int width = codecContext->width;int height = codecContext->height;AVPacket packet;while (av_read_frame(context, &packet) >= 0) {if (packet.stream_index == video_index) {avcodec_send_packet(codecContext, &packet);while (avcodec_receive_frame(codecContext, frame) == 0) {// AVFrameToCVMat 的实现可以看下方 FFmpeg 转为 Mat 中的代码cv::Mat img(AVFrameToCVMat(frame));cv::imshow("__main__", img);cv::waitKey(1);}}av_packet_unref(&packet);}av_frame_free(&frame);avcodec_close(codecContext);avcodec_parameters_free(&params);avformat_close_input(&context);
}

FFmpeg frame 转换为 OpenCV Mat

方法一

AVFrame* frameYUV;
/**
*	... 处理 YUV 格式的 AVFrame
*/
cv::Mat img = cv::Mat::zeros(height * 3 / 2, width, CV_8UC1);
memcpy(img.data, frameYUV->data[0], size);
memcpy(img.data + width * height, frameYUV->data[1], size / 4);
memcpy(img.data + width * height * 5 / 4, frameYUV->data[2], size / 4);

方法二

转载自 https://zhuanlan.zhihu.com/p/80350418

cv::Mat AVFrameToCVMat(const AVFrame* frame) {int width = frame->width;int height = frame->height;cv::Mat image(height, width, CV_8UC3);int cv_lines_sizes[1];cv_lines_sizes[0] = image.step1();SwsContext* conversion = sws_getContext(width, height, (AVPixelFormat)frame->format,width, height, AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR,nullptr, nullptr, nullptr);sws_scale(conversion, frame->data, frame->linesize, 0, height, &image.data, cv_lines_sizes);sws_freeContext(conversion);return image;
}

声明一个 YUV 图像的空间

声明一个 YUV 图像的空间,该空间用作将读取的视频帧转换为 YUV 格式。如果没有这个空间会显示 bad dst image pointer

 // 声明图像的空间用以保存 YUV 图像auto* out_buffer = (unsigned char*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, width, height, 1));av_image_fill_arrays(frameYUV->data, frameYUV->linesize, (const uint8_t*)out_buffer,AV_PIX_FMT_YUV420P, width, height, 1);

显示效果

image-20210125171014493


http://www.ppmy.cn/news/485489.html

相关文章

成功解决win10下某些文件路径不存在问题

成功解决win10下某些文件路径不存在问题 目录 解决问题 解决思路 解决方法 解决问题 win10下某些文件路径不存在问题 解决思路 有好多软件,打开或解压的时候,会出现没有该文件或者解压出来该文件瞬间就没了,是因为win10自带的McAfee迈克…

android app整包更新,Android App应用包增量升级(one)

Android增量升级这东西很不错,当时我们这运营的人把百度的一个管理软件拿过来说他们这个升级包提示可以节省流量是怎么回事,当时各种猜测,难道是有什么特殊算法将包压缩了?特意试了一下压缩,根本大小就没变化~后来开发…

这是一款走心的最新测评:英伟达史上最便宜AI硬件抗造不?

Raspberry Pi是制造商选择的单板计算机,但AI不是它的强项。 Nvidia新推出的99美元Jetson Nano开发套件可以让业余爱好者和程序员都有机会以实惠的价格玩深度学习和神经网络。 Nvidia多年来一直在生产其Jetson系列AI电脑,但它们的价格远远超出了大多数消…

【数据科学】使用Python建立你的数据处理肌肉记忆

数据预处理流程 在搜索语法时,您是否因为破坏数据分析流而感到沮丧?为什么你在第三次查找之后仍然不记得它?这是因为你还没有足够的练习来为它建立肌肉记忆。 现在,想象一下,当您编写代码时,Python语法和函…

利用opencv从USB摄像头获取图片 获得摄像头编号

本文转自博客园-Arkenstone 由于opencv自带的VideoCapture函数直接从usb摄像头获取视频数据,所以用这个来作为实时的图像来源用于实体检测识别是很方便的。 安装opencv 安装的步骤可以按照之前这个文章操作。如果在测试的时候: cam cv2.VideoCapture(…

Forest

正常运行会遇到一些小麻烦,但只要使用前几个例程的解决方法就能解决。这里要讲的是如何把默认的DERBY数据库换成MySQL,为此需要修改几个地方,第一个是web.xml中的数据源配置,如下: <data-source> <name>java:global/ForestDataSource</name> …

Microsoft Teams Rooms Content Camera 革命性更新

原计划在下周一把这个文章分享给大家,不过好东西迫不及待想跟大家分享,就提前发这篇文章了!! 在完成上一次4.0.105.0的版本更新后我已经觉得Teams Rooms变得非常好用了,效果也非常棒,先来看下我们当前成都体验中心的Demo,开会体验棒棒哒

数据科学 python_如何使用Python为数据科学建立肌肉记忆

数据科学 python by Zhen Liu 刘震 首先&#xff1a;数据预处理 (Up first: data preprocessing) Do you feel frustrated by breaking your data analytics flow when searching for syntax? Why do you still not remember it after looking up it for the third time?? …