Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ ffmpeg AVFrame到opencv Mat的转换_C++_Opencv_Ffmpeg_Video Streaming - Fatal编程技术网

C++ ffmpeg AVFrame到opencv Mat的转换

C++ ffmpeg AVFrame到opencv Mat的转换,c++,opencv,ffmpeg,video-streaming,C++,Opencv,Ffmpeg,Video Streaming,我目前正在进行一个项目,该项目使用ffmepg解码接收到的帧,解码后,我想将AVFrame转换为opencv Mat帧,以便我可以在imShow函数上播放它 我得到的是字节流,我将其读入缓冲区,解码为AVFrame: f = fopen(filename, "rb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } frame = avcodec_alloc_frame(); if

我目前正在进行一个项目,该项目使用ffmepg解码接收到的帧,解码后,我想将AVFrame转换为opencv Mat帧,以便我可以在imShow函数上播放它

我得到的是字节流,我将其读入缓冲区,解码为AVFrame:

f = fopen(filename, "rb");
if (!f) {
    fprintf(stderr, "Could not open %s\n", filename);
    exit(1);
}

frame = avcodec_alloc_frame();
if (!frame) {
    fprintf(stderr, "Could not allocate video frame\n");
    exit(1);
}

framergb = avcodec_alloc_frame();
if (!framergb) {
    fprintf(stderr, "Could not allocate video frame\n");
    exit(1);
}

bytes=avpicture_get_size(PIX_FMT_RGB24, CAMER_WIDTH, CAMER_HEIGHT);
buffer=(uint8_t *)av_malloc(bytes*sizeof(uint8_t));
avpicture_fill((AVPicture *)framergb, buffer, PIX_FMT_RGB24,
                CAMER_WIDTH, CAMER_HEIGHT);

frame_count = 0;
for(;;) {
    avpkt.size = fread(inbuf, 1, INBUF_SIZE, f);
    if (avpkt.size == 0)
        break;

    avpkt.data = inbuf;
    while (avpkt.size > 0)
        if (decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 0) < 0)
            exit(1);
}

avpkt.data = NULL;
avpkt.size = 0;
decode_write_frame(outfilename, c, frame, &frame_count, &avpkt, 1);
f=fopen(文件名,“rb”);
如果(!f){
fprintf(stderr,“无法打开%s\n”,文件名);
出口(1);
}
frame=avcodec_alloc_frame();
如果(!帧){
fprintf(stderr,“无法分配视频帧”\n);
出口(1);
}
framergb=avcodec_alloc_frame();
如果(!framergb){
fprintf(stderr,“无法分配视频帧”\n);
出口(1);
}
字节=avpicture\U get\U大小(PIX\U FMT\U RGB24、相机宽度、相机高度);
缓冲区=(uint8_t*)av_malloc(字节*大小(uint8_t));
avpicture_fill((avpicture*)帧RGB、缓冲区、PIX_FMT_RGB24、,
摄像头宽度、摄像头高度);
帧计数=0;
对于(;;){
avpkt.size=fread(inbuf,1,inbuf_size,f);
如果(avpkt.size==0)
打破
avpkt.data=inbuf;
而(avpkt.size>0)
if(解码/写入/帧(输出文件名、c、帧和帧计数、avpkt、0)<0)
出口(1);
}
avpkt.data=NULL;
avpkt.size=0;
解码/写入/帧(输出文件名、c、帧、帧计数和avpkt,1);
解码写入帧定义如下:

static int decode_write_frame(const char *outfilename, AVCodecContext *avctx,AVFrame *frame, int *frame_count, AVPacket *pkt, int last)
{
int len, got_frame;
char buf[1024];
struct SwsContext *convert_ctx;

len = avcodec_decode_video2(avctx, frame, &got_frame, pkt);
if (len < 0) {
    fprintf(stderr, "Error while decoding frame %d\n", *frame_count);
    return len;
}
if (got_frame) {
    printf("Saving %sframe %3d\n", last ? "last " : "", *frame_count);
    fflush(stdout);

int w = avctx->width;
int h = avctx->height;
convert_ctx = sws_getContext(w, h, avctx->pix_fmt,
                    w, h, PIX_FMT_RGB24, SWS_BICUBIC,
                    NULL, NULL, NULL);

if(convert_ctx == NULL) {
    fprintf(stderr, "Cannot initialize the conversion context!\n");
    exit(1);
}

sws_scale(convert_ctx, frame->data,
            frame->linesize, 0,
            h,
            framergb->data, framergb->linesize);

    /* the picture is allocated by the decoder, no need to free it */
    snprintf(buf, sizeof(buf), outfilename, *frame_count);

    bmp_save(framergb->data[0], framergb->linesize[0],
             avctx->width, avctx->height, buf);
    (*frame_count)++;
}
if (pkt->data) {
    pkt->size -= len;
    pkt->data += len;
}
return 0;
}
static int decode\u write\u frame(常量字符*outfilename,AVCodecContext*avctx,AVFrame*frame,int*frame\u计数,AVPacket*pkt,int last)
{
int len,得到了一个框架;
char-buf[1024];
struct SwsContext*convert_ctx;
len=avcodec\u decode\u video2(avctx,frame,&got\u frame,pkt);
if(len<0){
fprintf(stderr,“解码帧%d\n时出错,*帧计数);
回程透镜;
}
如果(得到了框架){
printf(“保存%s帧%3d\n”,最后一个?“最后一个”:“*”帧计数);
fflush(stdout);
int w=avctx->宽度;
int h=avctx->高度;
convert_ctx=sws_getContext(w,h,avctx->pix_fmt,
w、 h,PIX_FMT_RGB24,SWS_双三次曲线,
空,空,空);
if(convert_ctx==NULL){
fprintf(stderr,“无法初始化转换上下文!\n”);
出口(1);
}
sws\U比例(转换ctx、帧->数据、,
框架->线条尺寸,0,
H
framergb->data,framergb->linesize);
/*图片由解码器分配,无需释放*/
snprintf(buf、sizeof(buf)、出料口名称、*架数);
bmp_保存(framergb->data[0],framergb->linesize[0],
avctx->宽度,avctx->高度,buf);
(*帧_计数)+;
}
if(pkt->data){
包装->尺寸-=长度;
pkt->data+=len;
}
返回0;
}
这里的bmp\u save()是由原始代码作者定义的,用于实现AVFrame到bmp图片的转换。我想在这里修改,以便让AVFrame转换为opencv Mat frame。我应该如何进行转换

提前感谢。

使用适当的,将bmp\u保存行替换为:

Mat mat(avctx->height, avctx->width, CV_8UC3, framergb->data[0], framergb->linesize[0]);
imshow("frame", mat);
waitKey(10);

另外,将sws_getContext中的PIX_FMT_RGB24标志替换为PIX_FMT_BGR24,因为OpenCV在内部使用BGR格式。

谢谢您的回答,我也通过这种方式解决了:

假设AVFrame*frame是准备转换的原始ffmepg帧

Mat m;
AVFrame dst;
int w = frame->width;
int h = frame->height;
m = cv::Mat(h, w, CV_8UC3);
dst.data[0] = (uint8_t *)m.data;
avpicture_fill( (AVPicture *)&dst, dst.data[0], PIX_FMT_BGR24, w, h);

enum PixelFormat src_pixfmt = (enum PixelFormat)frame->format;
enum PixelFormat dst_pixfmt = PIX_FMT_BGR24;
convert_ctx = sws_getContext(w, h, src_pixfmt, w, h, dst_pixfmt,
                    SWS_FAST_BILINEAR, NULL, NULL, NULL);

if(convert_ctx == NULL) {
    fprintf(stderr, "Cannot initialize the conversion context!\n");
    exit(1);
}

sws_scale(convert_ctx, frame->data, frame->linesize, 0, h,
                    dst.data, dst.linesize);
imshow("MyVideo", m);
waitKey(30);

工作得很好

但是,
framergb->data[0]
只是第一个元素,而不是指针-请再试二次;)类型参数的观点很好,谢谢,我太快了;-)对于数据,我想我是对的,avframe中的数据字段是指针数组,而不是指针。不是100%确定这是正确的,因为我还没有测试代码,但这是我最好的猜测。哦,对不起,没有看到,数组中实际上是什么;)这段代码为更一般的情况提供了一个很好的示例。请注意,如果Mat构造函数选择的线宽与avpicture_fill选择的线宽不同,则此操作可能会失败。我不知道这个值是如何在avpicture_fill中选择的,所以我不能告诉您这是否可能发生,但这是一种可能性。