视频去除水印、台标和logo,并重新在生成新的视频
视频去除水印、台标和logo
对于图片的水印和logo的去除,网上有很多办法,最直接的办法,打开photoshop,PS就可搞定,还有其他的图像处理软件效果也都不错,但是对视频的的水印、台标和logo处理,网上相关的技术博客比较少,相关的代码和开源项目也很少啊。求人不如求己,看来只能动手自己搞啦。
需要用到opencv,我首先是在VS2013+opencv2.4.10的平台上,实现了视频的读取,图像抽取;然后调用inpaint( InputArray src, InputArray inpaintMask,OutputArray dst, double inpaintRadius, int flags )函数,将当前帧和掩膜图像进行融合,即可消除固定位置的水印或LOGO,不过掩膜图像要自己手动制作,当然也可采用选定参考帧,然后和后面的图像逐帧对应位置像素点相与为一的办法来做,20帧图像过后就可求得掩膜图像,得到的掩膜图像有毛刺,效果不是很好,还是需要进一步羽化修正一下;如果logo位置不固定的话,把logo截取出来,可以用图像模板匹配的办法或sift特征点匹配,找到logo或水印的位置,这个方法比较烦,要划窗检测,要构建图像金字塔,能自动检测到logo,实用效果不是太好,要进一步优化才好。
具体步骤如下:
1、制作掩膜图像
a、PS手工制作,掩膜图像要和视频分辨率大小一致。
b、前景背景求差法,代码如下:(也包括相关的去logo完整算法)
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include "opencv2/photo/photo.hpp"#include <iostream>using namespace std;
using namespace cv;int main(int argc, char** argv)
{cv::VideoCapture cap("C:/Users/zyy/Desktop/test_logs/test.mp4");if (!cap.isOpened()){cout << "Failed!" << endl;return -1;}Mat result, mask, dst1;Mat inpaintMask1;Mat inpaintMask = imread("C:/Users/zyy/Desktop/test_logs/log5.jpg");cv::cvtColor(inpaintMask, inpaintMask, CV_BGR2GRAY);cv::namedWindow("Result", 1);cv::namedWindow("Frame", 1);int i = 0;for (;;){Mat frame;cap >> frame;if (!frame.data){cout << "Over!" << endl;break;}if (i <= 2) //看视频,自己调试确定这个值,二十几帧之后左上角那个小图才出来,所以选了30{if (i == 2){mask = frame;cv::cvtColor(mask, mask, CV_BGR2GRAY);//Mat inpaintMask1(mask.rows, mask.cols, CV_32FC1, 1);inpaintMask1 = mask;}}else{cv::bitwise_and(result, mask, mask);//<span style="font-size:18px;">前景背景求差法</span>if (i > 2 && i <= 40){cv::cvtColor(frame, result, CV_BGR2GRAY);cv::bitwise_and(result, mask, mask);//<span style="font-size:18px;">前景背景求差法</span>inpaintMask1 = mask;imwrite("C:/Users/zyy/Desktop/test_logs/www.jpg", inpaintMask1);}Mat inpainted;inpaint(frame, inpaintMask, inpainted, 8, CV_INPAINT_TELEA);imshow("inpainted image", inpainted);imshow("Frame", frame);imshow("Result", mask);//waitKey();if (cv::waitKey(33) >= 0) break;}i++;}waitKey();return 0;
}
2、logo和水印位置检测
#include <iostream>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
using namespace std;
int main()
{IplImage *src = cvLoadImage("C:/Users/zyy/Desktop/test_logs/22.jpg", 0);IplImage *srcResult = cvLoadImage("C:/Users/zyy/Desktop/test_logs/22.jpg", 3); //用来显示IplImage *templat = cvLoadImage("C:/Users/zyy/Desktop/test_logs/yk2.jpg", 0);IplImage *result;if (!src || !templat){cout << "打开图像失败" << endl;return 0;}int srcW, srcH, templatW, templatH, resultH, resultW;srcW = src->width;srcH = src->height;templatW = templat->width;templatH = templat->height;if (srcW < templatW || srcH < templatH){cout << "模板不能比原图像小" << endl;return 0;}resultW = srcW - templatW + 1;resultH = srcH - templatH + 1;result = cvCreateImage(cvSize(resultW, resultH), 32, 1);cvMatchTemplate(src, templat, result, CV_TM_SQDIFF_NORMED);//CV_TM_SQDIFF_NORMEDdouble minValue, maxValue;CvPoint minLoc, maxLoc;cvMinMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);cout << "最小值:" << minValue << " 最大值:" << maxValue << endl;cvRectangle(srcResult, minLoc, cvPoint(minLoc.x + templatW, minLoc.y + templatH), cvScalar(0, 0, 255));cvNamedWindow("srcResult", 0);cvNamedWindow("templat", 0);cvShowImage("srcResult", srcResult);cvShowImage("templat", templat);cvWaitKey(0);cvReleaseImage(&result);cvReleaseImage(&templat);cvReleaseImage(&srcResult);cvReleaseImage(&src);return 0;
}
3、在已经求得掩膜图像的情况下,就可以进行下一步的去logo操作了。
a、c/c++代码实现:
///
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/photo/photo.hpp"#include <iostream>using namespace std;
using namespace cv;
int main()
{clock_t start, finish;start = clock();cout << "start!!" << endl;string video_path = "/home/dyx/Desktop/test_logs/";VideoCapture capture(video_path + "test.mp4");if (!capture.isOpened())cout << "fail to open!" << endl;//获取帧率double fps =capture.get( CV_CAP_PROP_FPS);cout << "帧率为:" << fps << endl;Size videoSize(capture.get( CV_CAP_PROP_FRAME_WIDTH),capture.get( CV_CAP_PROP_FRAME_HEIGHT));int tem=CV_FOURCC('F', 'L', 'V', '1');cout<<tem<<endl;VideoWriter writer(video_path + "VideoTest.avi", CV_FOURCC('D', 'I', 'V', 'X') , fps, videoSize);// VideoWriter writer(video_path + "VideoTest.avi", CV_FOURCC('F', 'L', 'V', '1'), fps, videoSize);//VideoWriter writer(video_path + "VideoTest264.avi", CV_FOURCC('X', '2', '6', '4'), fps, videoSize);Mat frame;Mat inpainted;Mat inpaintMask = imread("/home/dyx/Desktop/test_logs/log5.jpg");cv::cvtColor(inpaintMask, inpaintMask, CV_BGR2GRAY);int i = 0;while (capture.isOpened()){i++;cout << i << endl;capture >> frame;if (!capture.read(frame)||i>=10000)// get a new frame from camera or video{cout<<"finlish!"<<endl;break;}inpaint(frame, inpaintMask, inpainted, 8, CV_INPAINT_TELEA);writer << inpainted;//cvWaitKey(1000 / fps);if (cvWaitKey(20) == 27){break;}imshow("video", inpainted);}finish = clock();long time = (double)(finish - start) / CLOCKS_PER_SEC;cout << time << endl;printf("时间:%f seconds\n", time);return 0;
}
b、java代码实现:
package main;import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import org.opencv.photo.Photo;
import org.opencv.video.Video;
import org.opencv.highgui.VideoCapture;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoWriter;
//import org.opencv.imgcodecs.Imgcodecs;
//import org.opencv.videoio.VideoCapture;
//import org.opencv.videoio.VideoWriter;
//import org.opencv.videoio.Videoio; public class Remove_video_watermark {static final int CV_CAP_PROP_FPS=5;static final int CV_FOURCC_XVID=1482049860;static final int CV_FOURCC_FLV1=827739206;static String video_path="/home/dyx/Desktop/test_logs/";public static void main(String[] args) {System.loadLibrary("opencv_java2410"); Mat inpaintMask = new Mat();Mat inpainted=new Mat();Mat template = Highgui.imread("/home/dyx/Desktop/test_logs/log5.jpg");Imgproc.cvtColor(template, inpaintMask,Imgproc.COLOR_BGR2GRAY); Mat frame = new Mat();VideoCapture cap = new VideoCapture("/home/dyx/Desktop/test_logs/test.mp4");if(!cap.isOpened()) // check if we succeededreturn;String fileName=video_path+"VideoTest12.avi";Size size = new Size(cap.get(Highgui.CV_CAP_PROP_FRAME_WIDTH), cap.get(Highgui.CV_CAP_PROP_FRAME_HEIGHT));double fps = cap.get(CV_CAP_PROP_FPS);
// VideoWriter vw = new VideoWriter(fileName, VideoWriter.fourcc('X', 'V', 'I', 'D'), fps, size, true);VideoWriter vw1 = new VideoWriter(fileName, CV_FOURCC_FLV1, fps, size, true);int ord=0;while(cap.isOpened()){if (!cap.read(frame))// get a new frame from camera or video{System.out.println("finlish!");break;}Photo.inpaint(frame, inpaintMask, inpainted, 8, Photo.INPAINT_TELEA); vw1.write(inpainted);ord++;System.out.println(ord);} }
}
注意:java需要调用opencv的java接口才可以,我采用的是opencv-2.4.10版本的,此版本有一个缺陷,没有VideoWriter类,要修改opencv源码,重新编译生成opencv2410.jar才可以。其他版本好像只有最新的opencv3.1.0的java接口有VideoWriter类。
源码需要修改两个地方:1、打开opencv-2.4.10=>modules=>java=>generator=>gen_java.py,找到
class_ignore_list = (
#core
"FileNode", "FileStorage", "KDTree",
#highgui
#"VideoWriter",
)
把VideoWriter前面添加“#”,注释掉这行代码;
2、找到196行,添加一行“ "char" : { "j_type" : "char", "jn_type" : "char", "jni_type" : "jchar", "suffix" : "C" },”,然后利用Ant重新编译opencv,生成jar包。
# c_type : { java/jni correspondence }
type_dict = {
# "simple" : { j_type : "?", jn_type : "?", jni_type : "?", suffix : "?" },
"" : { "j_type" : "", "jn_type" : "long", "jni_type" : "jlong" }, # c-tor ret_type
"void" : { "j_type" : "void", "jn_type" : "void", "jni_type" : "void" },
"env" : { "j_type" : "", "jn_type" : "", "jni_type" : "JNIEnv*"},
"cls" : { "j_type" : "", "jn_type" : "", "jni_type" : "jclass"},
"bool" : { "j_type" : "boolean", "jn_type" : "boolean", "jni_type" : "jboolean", "suffix" : "Z" },
"char" : { "j_type" : "char", "jn_type" : "char", "jni_type" : "jchar", "suffix" : "C" },
"int" : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
"long" : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
"float" : { "j_type" : "float", "jn_type" : "float", "jni_type" : "jfloat", "suffix" : "F" },
"double" : { "j_type" : "double", "jn_type" : "double", "jni_type" : "jdouble", "suffix" : "D" },
"size_t" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
"__int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
"int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
"double[]": { "j_type" : "double[]", "jn_type" : "double[]", "jni_type" : "jdoubleArray", "suffix" : "_3D" },
视频去除水印、台标和logo,并重新在生成新的视频相关推荐
- 视频去水英视频去除水印工具今日头条自媒体运营推广视频教程学习资料短视频运营从零到精通...
视频上的水印怎么去掉批量处理去重消重去水印去logo软件 ps去除水印视频教程批量处理去重消重去水印去logo软件 手机怎么去掉视频水印批量处理去重消重去水印去logo软件 手机去视频水印免费版批量处 ...
- 手机怎么给视频去除水印
在休息的时候,相信有很多人的都是会拿着手机躺在床上或者是趴在桌子上去追剧.无论是偶像剧还是古装剧,总会有哪些比较甜甜的镜头,有的会选择保存那个部分的视频片段,再去分享到一些地方,有的平台对要上传的视频 ...
- 自制腾讯视频去除水印Chrome插件!厉害吧!
前景提要 前几期写了一篇关于谷歌插件制作的文章,但是因为没有正经的小实战,一直鸽了这么多期文章,这里写一篇比较受关注的腾讯视频的水印去除的文章,方便各位日后爬取腾讯视频的时候总带其水印爬虫. 学习制作 ...
- Python自制腾讯视频去除水印Chrome插件
前景提要 前几期写了一篇关于谷歌插件制作的文章,但是因为没有正经的小实战,一直鸽了这么多期文章,这里写一篇比较受关注的腾讯视频的水印去除的文章,方便各位日后爬取腾讯视频的时候总带其水印爬虫. 学习制作 ...
- 自制腾讯视频去除水印Chrome插件
前景提要 前几期写了一篇关于谷歌插件制作的文章,但是因为没有正经的小实战,一直鸽了这么多期文章,这里写一篇比较受关注的腾讯视频的水印去除的文章,方便各位日后爬取腾讯视频的时候总带其水印爬虫. 学习制作 ...
- 视频去除水印,只需两分钟随时学会
我们在生活中会有喜欢的照片或者视频,但是上面有水印,严重影响了美观,那我们应该怎么去除呢?别担心跟我一起来,小编手把手教您,很简单喔. 一.视频怎么去水印 步骤一:在浏览器上搜索"水印云&q ...
- 教你如何将视频去除水印
很多时候我们看到一个好的视频想保存下来分享到自己的朋友圈,总是会发现上面又水印,首先我来讲讲如何视频去水印,而现在呢一般都是通过软件来完成去水印,而我呢,一直都是在使用"水印云", ...
- python 新媒体素材_干货满文!用python做新媒体视频生成器
最近网上很火的段子是各种新媒体账号的文案,比方说下面的段子:核桃核不能吞下去是怎么回事呢?核桃核相信大家都很熟悉,但是核桃核不能吞下去是怎么回事呢,下面就让小编带大家一起了解吧.核桃核不能吞下去,其实 ...
- 基于python实现去除视频的水印
我们再搬运视频的时候常常会遇到视频有水印的问题 如下 下面就通过python来实现对视频水印的去除 在pycharm新建一个项目,创建image,video目录其他不用 必要条件 在终端下载相关依赖包 ...
最新文章
- Hi3516ampp编译错误之ls: cannot access '/hiwork/osdrvhi3516a.C02': No such file or directory
- mysql_5.6.21_安装使用说明
- 软件性能测试关注点,盘点性能测试必须掌握的技术点
- Git 版本管理工具命令速查
- Python-Pandas之两个Dataframe的差异比较
- 德国 IT 薪酬大揭秘!
- Php 中如何将内容写入log日志中
- 【优化算法】非支配排序遗传算法(NSGA)【含Matlab源码 176期】
- matlab软件进行仿真验证,matlab仿真软件
- 2018年TI杯大学生电子设计竞赛题C-无线充电电动小车 题目加答案,非常详细
- 微软开始彻底封杀IE浏览器
- [资讯]同济DI出品 | 绝对是史上最萌的机器人教具!!!
- ubuntu18.04 网络配置 ipv4ipv6DNS路由
- 地质体剖面从构建到Web三维展示
- RHEL6 或CentOS 6配置共享存储--使用iSCSI
- php7.1.6验证码错误,steam输入验证码不正确怎么办
- 论天龙八部和程序员的关系
- Vimeo 开启VR内容付费模式,真的能让消费者主动掏钱包吗?
- Symbian和C++ SDK入门之开发工具(转)
- 数学建模-偏最小二乘回归模型