使用python 去除视频中的水印
1. 需要安装的包
pip install moviepy
pip install numpy
pip install opencv_python
pip install tqdm
2. 代码
import cv2
import numpy as np
import glob
from moviepy.editor import VideoFileClip
import os
from tqdm import tqdm# 判断输入是否为视频
def is_valid_video_file(file):try:with VideoFileClip(file) as video_clip:return Trueexcept Exception as e:print(f"Invalid video file: {file}, Error: {e}")return Falsedef get_first_valid_frame(video_clip, threshold=10, num_frames=10):total_frames = int(video_clip.fps * video_clip.duration)frame_indices = [int(i * total_frames / num_frames) for i in range(num_frames)]for idx in frame_indices:frame = video_clip.get_frame(idx / video_clip.fps)if frame.mean() > threshold:return framereturn video_clip.get_frame(0)def select_roi_for_mask(video_clip):frame = get_first_valid_frame(video_clip)# 将视频帧调整为720p显示display_height = 720scale_factor = display_height / frame.shape[0]display_width = int(frame.shape[1] * scale_factor)display_frame = cv2.resize(frame, (display_width, display_height))#instructions = "Select ROI and press SPACE or ENTER"#font = cv2.FONT_HERSHEY_SIMPLEX#cv2.putText(display_frame, instructions, (10, 30), font, 1, (255, 255, 255), 2, cv2.LINE_AA)r = cv2.selectROI(display_frame)cv2.destroyAllWindows()r_original = (int(r[0] / scale_factor), int(r[1] / scale_factor), int(r[2] / scale_factor), int(r[3] / scale_factor))print("r_original: ", r_original)return r_original#return (18, 28, 230, 43)
def detect_watermark_adaptive(frame, roi):roi_frame = frame[roi[1]:roi[1] + roi[3], roi[0]:roi[0] + roi[2]]gray_frame = cv2.cvtColor(roi_frame, cv2.COLOR_BGR2GRAY)_, binary_frame = cv2.threshold(gray_frame, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)mask = np.zeros_like(frame[:, :, 0], dtype=np.uint8)mask[roi[1]:roi[1] + roi[3], roi[0]:roi[0] + roi[2]] = 255 #binary_framereturn maskdef generate_watermark_mask(video_clip, num_frames=10, min_frame_count=7):total_frames = int(video_clip.duration * video_clip.fps)frame_indices = [int(i * total_frames / num_frames) for i in range(num_frames)]frames = [video_clip.get_frame(idx / video_clip.fps) for idx in frame_indices]r_original = select_roi_for_mask(video_clip)masks = [detect_watermark_adaptive(frame, r_original) for frame in frames]final_mask = sum((mask == 255).astype(np.uint8) for mask in masks)# 根据像素点在至少min_frame_count张以上的帧中的出现来生成最终的遮罩final_mask = np.where(final_mask >= min_frame_count, 255, 0).astype(np.uint8)kernel = np.ones((5, 5), np.uint8)return cv2.dilate(final_mask, kernel)def process_video(video_clip, output_path, apply_mask_func):total_frames = int(video_clip.duration * video_clip.fps)progress_bar = tqdm(total=total_frames, desc="Processing Frames", unit="frames")#num=0def process_frame(frame):result = apply_mask_func(frame)progress_bar.update(1000)#global num#num += 1#result.save('0%5d.png' % num)return resultprocessed_video = video_clip.fl_image(process_frame, apply_to=["each"])processed_video.write_videofile(f"{output_path}.mp4", codec="libx264")if __name__ == "__main__":video = "1476212253-1-192.mp4"output_video_path = "output/1476212253-1-192.mp4"if is_valid_video_file(video):video_clip = VideoFileClip(video)watermark_mask = generate_watermark_mask(video_clip)mask_func = lambda frame: cv2.inpaint(frame, watermark_mask, 3, cv2.INPAINT_NS)video_name = os.path.basename(video)process_video(video_clip, output_video_path, mask_func)print(f"Successfully processed {video_name}")
3. 运行
使用鼠标框选水印,回车继续。
开始处理
4. 完成后效果对比
去除前:
1476212253-1-192_o
去除后:
1476212253-1-192.mp4