When we move videos, we often encounter the problem of video watermarks
as follows
The following uses python to remove video watermarks
Create a new project in pycharm and create the image and video directories. No other need exists
Necessary conditions
Download related dependency packages in the terminal
pip install moviepy==1.0.3 pip installnumpy==1.21.5 pip install opencv_python==4.5.5.62
Place the video you want to remove the watermark in the video directory and run it
Use the mouse to remove the part and press Enter.
The video with the watermark removed is output to the output folder.
Check the effect, not bad
Code
import us import sys import cv2 import numpy from moviepy import editor VIDEO_PATH = 'video' OUTPUT_PATH = 'output' TEMP_VIDEO = 'temp.mp4' class WatermarkRemover(): def __init__(self, threshold: int, kernel_size: int): self.threshold = threshold #Threshold used for threshold segmentation self.kernel_size = kernel_size #Expansion operation core size def select_roi(self, img: numpy.ndarray, hint: str) -> list: ''' Frame select the watermark or subtitle position, press SPACE or ENTER to exit :param img: display image :return: coordinates of the selected area ''' MEMORY = 0.7 w, h = int(MEMORY * img.shape[1]), int(MEMORY * img.shape[0]) resize_img = cv2.resize(img, (w, h)) roi = cv2.selectROI(hint, resize_img, False, False) cv2.destroyAllWindows() watermark_roi = [int(roi[0] / MEMORY), int(roi[1] / MEMORY), int(roi[2] / MEMORY), int(roi[3] / MEMORY)] return watermark_roi def dilate_mask(self, mask: numpy.ndarray) -> numpy.ndarray: ''' Dilate the mask :param mask: mask image :return: mask after expansion processing ''' kernel = numpy.ones((self.kernel_size, self.kernel_size), numpy.uint8) mask = cv2.dilate(mask, kernel) return mask def generate_single_mask(self, img: numpy.ndarray, roi: list, threshold: int) -> numpy.ndarray: ''' Generating a watermark mask of a single frame image from a manually selected ROI area :param img: single frame image :param roi: Manually select area coordinates :param threshold: Binarization threshold :return: watermark mask ''' #The area is invalid and the program exits if len(roi) != 4: print('NULL ROI!') sys.exit() #Copy the pixels in the ROI of a single frame grayscale image roi_img = numpy.zeros((img.shape[0], img.shape[1]), numpy.uint8) start_x, end_x = int(roi[1]), int(roi[1] + roi[3]) start_y, end_y = int(king[0]), int(king[0] + king[2]) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) roi_img[start_x:end_x, start_y:end_y] = gray[start_x:end_x, start_y:end_y] #threshold segmentation _, mask = cv2.threshold(roi_img, threshold, 255, cv2.THRESH_BINARY) return mask def generate_watermark_mask(self, video_path: str) -> numpy.ndarray: ''' Intercept multiple frames of images in the video to generate multiple watermark masks, and generate the final watermark mask through logic and calculation. :param video_path: video file path :return: watermark mask ''' video = cv2.VideoCapture(video_path) success, frame = video.read() roi = self.select_roi(frame, 'select watermark ROI') mask = numpy.ones((frame.shape[0], frame.shape[1]), numpy.uint8) mask.fill(255) step = video.get(cv2.CAP_PROP_FRAME_COUNT) // 5 index = 0 while success: if index % step == 0: mask = cv2.bitwise_and(mask, self.generate_single_mask(frame, roi, self.threshold)) success, frame = video.read() index += 1 video.release() return self.dilate_mask(mask) def generate_subtitle_mask(self, frame: numpy.ndarray, roi: list) -> numpy.ndarray: ''' Generate single-frame image subtitle masks by manually selecting ROI areas :param frame: single frame image :param roi: Manually select area coordinates :return: subtitle mask ''' mask = self.generate_single_mask(frame, [0, roi[1], frame.shape[1], roi[3]], self.threshold) #Only use the ROI abscissa area return self.dilate_mask(mask) def inpaint_image(self, img: numpy.ndarray, mask: numpy.ndarray) -> numpy.ndarray: ''' Repair image :param img: single frame image :parma mask: mask :return: Repaired image ''' telea = cv2.inpaint(img, mask, 1, cv2.INPAINT_TELEA) return a lot def merge_audio(self, input_path: str, output_path: str, temp_path: str): ''' Merge audio and processed video :param input_path: Original video file path :param output_path: file path after encapsulating audio and video :param temp_path: Silent video file path ''' with editor.VideoFileClip(input_path) as video: audio = video.audio with editor.VideoFileClip(temp_path) as opencv_video: clip = opencv_video.set_audio(audio) clip.to_videofile(output_path) def remove_video_watermark(self): ''' Remove video watermark ''' if not os.path.exists(OUTPUT_PATH): os.makedirs(OUTPUT_PATH) filenames = [os.path.join(VIDEO_PATH, i) for i in os.listdir(VIDEO_PATH)] mask = None for i, name in enumerate(filenames): if i == 0: #Generate watermark mask mask = self.generate_watermark_mask(name) #Create file object to be written video = cv2.VideoCapture(name) fps = video.get(cv2.CAP_PROP_FPS) size = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))) video_writer = cv2.VideoWriter(TEMP_VIDEO, cv2.VideoWriter_fourcc(*'mp4v'), fps, size) #Process images frame by frame success, frame = video.read() while success: frame = self.inpaint_image(frame, mask) video_writer.write(frame) success, frame = video.read() video.release() video_writer.release() #packagevideo (_, filename) = os.path.split(name) output_path = os.path.join(OUTPUT_PATH, filename.split('.')[0] + '_no_watermark.mp4')#Output file path self.merge_audio(name, output_path, TEMP_VIDEO) if os.path.exists(TEMP_VIDEO): os.remove(TEMP_VIDEO) def remove_video_subtitle(self): ''' Remove video subtitles ''' if not os.path.exists(OUTPUT_PATH): os.makedirs(OUTPUT_PATH) filenames = [os.path.join(VIDEO_PATH, i) for i in os.listdir(VIDEO_PATH)] roi = [] for i, name in enumerate(filenames): #Create file object to be written video = cv2.VideoCapture(name) fps = video.get(cv2.CAP_PROP_FPS) size = (int(video.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))) video_writer = cv2.VideoWriter(TEMP_VIDEO, cv2.VideoWriter_fourcc(*'mp4v'), fps, size) #Process images frame by frame success, frame = video.read() if i == 0: roi = self.select_roi(frame, 'select subtitle ROI') while success: mask = self.generate_subtitle_mask(frame, roi) frame = self.inpaint_image(frame, mask) video_writer.write(frame) success, frame = video.read() video.release() video_writer.release() #packagevideo (_, filename) = os.path.split(name) output_path = os.path.join(OUTPUT_PATH, filename.split('.')[0] + '_no_sub.mp4')#Output file path self.merge_audio(name, output_path, TEMP_VIDEO) if os.path.exists(TEMP_VIDEO): os.remove(TEMP_VIDEO) if __name__ == '__main__': #Remove video watermark remover = WatermarkRemover(threshold=80, kernel_size=5) remover.remove_video_watermark() #Remove video subtitles remover = WatermarkRemover(threshold=80, kernel_size=10) remover.remove_video_subtitle()