零、直接下载
百度网盘链接:https://pan.baidu.com/s/1b8IvB4q-e2VVWR2uKikuQQ
提取码:1edz
解压,双击运行RemoveWatermark.exe即可使用。
一、背景
现在B站越来越火,需要用到视频剪辑工具,我也试了几款免费的视频剪辑工具,发现免费试用,不成为会员,都会给你的视频加上水印。我平时不怎么使用视频剪辑,就偶尔用一下,因此,我就想着要去除水印,因此开发了这款小工具。
二、实现思路
1、因为视频剪辑软件的水印基本都打在上方,有如下情况:
首先要把原图像往上拓展一些黑色区域,得到如下效果:
2、把预处理好的视频送到视频剪辑软件处理,水印就打在拓展区域上了:
3、对打上水印的视频进行后处理,把带水印的上方区域裁切掉,就得到去水印后的效果:
三、代码实现:
开发环境:win10 + QT5.7.1
依赖库:opencv3.1.0 + ffmpeg-4.3
1、pro工程设置
#opencv INCLUDEPATH += C:\Opencv3.1.0\opencv\build\include\opencv\ C:\Opencv3.1.0\opencv\build\include\opencv2\ C:\Opencv3.1.0\opencv\build\include LIBS += C:\Opencv3.1.0\opencv\build\x64\vc14\lib\opencv_world310.lib #ffmpeg INCLUDEPATH += D:\3rdParty\ffmpeg-4.3\ffmpeg-4.3-win64-dev\include LIBS += D:\3rdParty\ffmpeg-4.3\ffmpeg-4.3-win64-dev\lib\*.lib
2、预处理(区域拓展)代码片段
cv::VideoWriter writer(preSaveName.toStdString(), CV_FOURCC('M', 'J', 'P', 'G'), 30, cv::Size(width, heightExtern));// cv::Mat frame; cv::Mat frameExtern = cv::Mat::zeros(heightExtern, width, CV_8UC3); while (1) { cap >> frame; if (frame.empty()) { break; } frame.copyTo(frameExtern(rect)); //cv::inpaint(frame, mask, frame, 7.0, cv::INPAINT_TELEA); writer << frameExtern; cv::imshow("frame", frameExtern); cv::waitKey(10); } cap.release();
3、后处理(crop)代码片段
av_register_all(); //ffmpeg程序的第一句,注册库 AVFormatContext *afc = NULL; int width = 0; int height = 0; int time_length = 0; //打开视频文件 int nRet = avformat_open_input(&afc, inputFileName.c_str(), 0, 0); if (nRet < 0) { std::cout << "can't find file!" << std::endl; } else { std::cout << "open file success!" << std::endl; } int durTime = afc->duration / AV_TIME_BASE; //视频时间 4分20秒 std::cout << "durTime = " << durTime << std::endl; unsigned int numberOfStream = afc->nb_streams; //包含流的个数2:一个视频流一个音频流 std::cout << "numberOfStream = " << numberOfStream << std::endl; for (int i = 0; i < afc->nb_streams; i++) { AVCodecContext *acc = afc->streams[i]->codec; if (acc->codec_type == AVMEDIA_TYPE_VIDEO) //如果是视频类型 { std::cout << "AVMEDIA_TYPE_VIDEO" << std::endl; AVCodec *codec = avcodec_find_decoder(acc->codec_id); if (!codec) { std::cout << "no decoder!" << std::endl; } width = acc->width; height = acc->height; std::cout << "width = " << width << ", height = " << height << std::endl; int ret = avcodec_open2(acc, codec, NULL); if (ret != 0) { char buf[1024] = { 0 }; av_strerror(ret, buf, sizeof(buf)); } std::cout << "open decoder success!" << std::endl; } if (acc->codec_type == AVMEDIA_TYPE_AUDIO) { std::cout << "AVMEDIA_TYPE_AUDIO" << std::endl; } } if (afc) { std::cout << "avformat_close_input" << std::endl; avformat_close_input(&afc); //关闭视频流 std::cout << "avformat_close_input close" << std::endl; } //处理 int x = 0; int y = height*0.2; time_length = durTime - 5;//去除最后5s的视频 char cmd[128] = { 0 }; //crop sprintf(cmd, "ffmpeg -i %s -vf crop='1280:720:%d:%d' -acodec copy %s", inputFileName.c_str(), x, y, outputFileName.c_str()); //crop,去除尾部 //sprintf(cmd, "ffmpeg -i expand_miao.mp4 -vf crop='1280:720:%d:%d' -acodec copy -ss 00:00:00 -t %d remove_water2.mp4", x, y, time_length); std::string str = cmd; std::cout << "str = " << str << std::endl; system(cmd);
四、使用场景
该小工具适用于所有水印在上方的情况。
五、界面
六、使用步骤
1、使用小工具先进行预处理
(1)点击“视频文件导入”按钮,选择原始视频;
(2)设置输出文件名,默认存放在D盘根目录下,avi格式(现在暂时只支持这种格式);
(3)点击开始预处理按钮,等待处理完成。
2、视频剪辑软件处理
3、使用小工具进行后处理
(1)点击“视频文件导入”按钮,选择视频剪辑软件处理好的视频;
(2)设置输出文件名,默认存放在D盘根目录下,可以支持mp4格式;
(3)点击开始后处理按钮,等待处理完成。
七、小工具下载地址
如果不想自己开发,我也提供了编译好的小工具,供大家下载使用:
百度网盘链接:https://pan.baidu.com/s/1b8IvB4q-e2VVWR2uKikuQQ
提取码:1edz
解压,双击运行RemoveWatermark.exe即可使用。
end