FFmpeg/OpenCV 实现全屏斜体水印

实现思路 ?基于,画布的方式,创建画布 -> 水印 -> 旋转 -> 抠图 -> 叠加到图像上基于,旋转图片的方式,填充 -> 水印 -> 顺时针旋转 -> 逆时针旋转 -> 截图基于,创建画布 -> 水印 -> 仿射变换 -> 水平垂直拼接 -> 叠加图片上
经测试比对,实现方式效率是最快的
代码实现
旋转画布方式
旋转图片方式
思路:基于实现
// 填充// [in]scale=原图宽:原图高,pad=填充后宽:填充后高:填充左右大小:填充上下大小:black[out]// 四周填充,pad 输入尺寸的一半char dtext[512];snprintf(dtext, sizeof(dtext), "[in]scale=%d:%d,pad=%d:%d:%d:%d:black[out]",frameWidth, frameHeight, expandFrameWidth, expandFrameHeight, expandSize, expandSize);// 水印// inxxxx[a];[a]xxx[a];[a]xxx[out]中间传的文字标签首位对应([a] [a]). 结束没有';'. char dtext[1000];snprintf(dtext, sizeof(dtext), "[in]drawtext=fontfile=%s:text=%s:x=%d:y=%d:fontsize=%d:fontcolor=%s:alpha=%.1f[a];",kFont, txt.c_str(), start_x, start_y, kFontSize, kFontColor, italicTextInfo_.alpha);// 翻转// [in]rotate=PI* angel /180[out] char dtext[512];snprintf(dtext, sizeof(dtext), "[in]rotate=PI* %d /180[out]", angel);// 截取 // [in]crop=原图宽:原图高:截取x:截取y[out]char dtext[512];snprintf(dtext, sizeof(dtext), "[in]crop=%d:%d:%d:%d[out]", frameWidth, frameHeight, startx, starty);

FFmpeg/OpenCV 实现全屏斜体水印

文章插图
创建
int init_filter_graph(const std::string& filter) {filterGraph_ = avfilter_graph_alloc();const AVFilter* buffersrc = http://www.kingceram.com/post/avfilter_get_by_name("buffer");const AVFilter* buffersink = avfilter_get_by_name("buffersink");char args[512];snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", frameWidth_, frameHeight_, frameFormat_, 1, videoFps_, 1, 1);int ret = avfilter_graph_create_filter(&buffersrcCtx_, buffersrc, "in", args, NULL, filterGraph_);if (ret < 0){avfilter_graph_free(&filterGraph_);filterGraph_ = NULL;return -1;}// buffer video sink: to terminate the filter chain.enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12, AV_PIX_FMT_NONE };AVBufferSinkParams* buffersink_params = av_buffersink_params_alloc();buffersink_params->pixel_fmts = pix_fmts;ret = avfilter_graph_create_filter(&buffersinkCtx_, buffersink, "out", NULL, buffersink_params, filterGraph_);av_free(buffersink_params);if (ret < 0){avfilter_graph_free(&filterGraph_);filterGraph_ = NULL;return -1;}AVFilterInOut* outputs = avfilter_inout_alloc();/* Endpoints for the filter graph. */outputs->name = av_strdup("in");outputs->filter_ctx = buffersrcCtx_;outputs->pad_idx = 0;outputs->next = NULL;AVFilterInOut* inputs = avfilter_inout_alloc();inputs->name = av_strdup("out");inputs->filter_ctx = buffersinkCtx_;inputs->pad_idx = 0;inputs->next = NULL;if ((ret = avfilter_graph_parse_ptr(filterGraph_, filter.c_str(), &inputs, &outputs, NULL)) < 0)goto end;ret = avfilter_graph_config(filterGraph_, NULL);if (ret < 0)goto end;end:avfilter_inout_free(&inputs);avfilter_inout_free(&outputs);return ret;}
向滤波输入帧, 然后从中取出一个
AVFrame* overlay(AVFrame* in) {if (!isInit_)return nullptr;int ret = av_buffersrc_add_frame(buffersrcCtx_, in);if (ret < 0)return nullptr;ret = av_buffersink_get_frame(buffersinkCtx_, out_);if (ret < 0){av_frame_unref(out_);return nullptr;}return out_;}
生成对应, 然后 向滤波中输入帧
【FFmpeg/OpenCV 实现全屏斜体水印】// 大概流程思路void xxxxx(){...// 生成对应filterstd::string filter = "对应filter";init_filter_graph(filter);...while (true){ret = av_read_frame(ifmtCtx, pkt);if (ret < 0)goto end;// audioif (pkt->stream_index == aistream) {av_packet_unref(pkt);continue;}// decode encode pktret = avcodec_send_packet(deCodecCtx, pkt);if (ret