# -*- coding: utf-8 -*- # @Author: wangkun # @Time: 2023/7/21 import cv2 class MaskWatermark: @classmethod def find_watermark(cls, image_path): """ 基于OpenCV自动识别水印并获取其位置 :param image_path:水印 :return:watermark_area """ # 读取图像 image = cv2.imread(image_path) # 将图像转换为灰度图像 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 使用边缘检测算法如Canny来检测图像中的边缘信息 edges = cv2.Canny(gray, 100, 200) # 使用霍夫变换检测直线,以获得边缘中的直线段 lines = cv2.HoughLinesP(edges, 1, cv2.pi / 180, threshold=100, minLineLength=100, maxLineGap=10) # 对检测到的直线进行筛选,以识别可能表示水印的直线 watermark_lines = [] if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] # 根据实际情况确定水印直线的特征,例如长度、斜率等 # 这里只是一个示例,您需要根据具体情况进行调整 if abs(y2 - y1) < 5 and abs(x2 - x1) > 50: watermark_lines.append(line) # 根据检测到的水印直线,计算水印区域的位置和大小 if len(watermark_lines) > 1: x_coords = [line[0][0] for line in watermark_lines] + [line[0][2] for line in watermark_lines] y_coords = [line[0][1] for line in watermark_lines] + [line[0][3] for line in watermark_lines] min_x = min(x_coords) max_x = max(x_coords) min_y = min(y_coords) max_y = max(y_coords) watermark_area = (min_x, min_y, max_x - min_x, max_y - min_y) # 水印区域的位置和大小 else: watermark_area = None return watermark_area @classmethod def mask_watermark(cls, input_path, output_path, watermark_area): # 读取视频 video = cv2.VideoCapture(input_path) # 获取视频的宽度和高度 width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 创建输出视频对象 fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 可根据需要更换视频编码器 output = cv2.VideoWriter(output_path, fourcc, 30.0, (width, height)) while True: ret, frame = video.read() if not ret: break # 在水印区域替换成其他像素或进行遮挡处理 x, y, w, h = watermark_area frame[y:y + h, x:x + w] = 0 # 这里将水印区域像素设为0,可根据需要进行更复杂的像素替换或遮挡处理 # 将处理后的帧写入输出视频 output.write(frame) # 释放资源 video.release() output.release() print("成功去除水印,并保存为", output_path) @classmethod def remove_watermark(cls, video_path, output_path): # 读取视频 video = cv2.VideoCapture(video_path) # 获取视频的宽度和高度 width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 创建输出视频对象 fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 可根据需要更换视频编码器 output = cv2.VideoWriter(output_path, fourcc, 30.0, (width, height)) # 读取第一帧作为背景帧 ret, background = video.read() if not ret: print("无法读取背景帧") return while True: ret, frame = video.read() if not ret: break # 计算当前帧与背景帧的差值 diff = cv2.absdiff(frame, background) # 将差值转换为灰度图像 gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY) # 应用阈值二值化,通过调整阈值以过滤差异 _, threshold = cv2.threshold(gray, 25, 255, cv2.THRESH_BINARY) # 进行形态学操作,填充小区域,平滑边缘 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) dilated = cv2.dilate(threshold, kernel, iterations=3) # 寻找轮廓 contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 去除检测到的水印轮廓区域 for contour in contours: # 这里只是一个示例,您可以根据具体情况进行调整,例如根据轮廓面积、形状等进行过滤 if cv2.contourArea(contour) > threshold_area: # 在当前帧上用背景帧进行填充 cv2.drawContours(frame, [contour], -1, (0, 0, 0), cv2.FILLED) # 将处理后的帧写入输出视频 output.write(frame) # 释放资源 video.release() output.release() if __name__ == "__main__": # 示例调用 image_path = 'image.jpg' # 替换为待识别水印的图像路径 watermark_area = MaskWatermark.find_watermark(image_path) print("水印区域的位置和大小:", watermark_area) # 示例调用 input_path = 'input.mp4' # 替换为输入视频文件路径 output_path = 'output.mp4' # 替换为输出视频文件路径 watermark_area = (100, 100, 200, 200) # 替换为水印区域的位置和大小,表示为 (x, y, width, height) MaskWatermark.mask_watermark(input_path, output_path, watermark_area) # 示例调用 video_path = 'video.mp4' # 替换为视频文件路径 output_path = 'output.mp4' # 替换为输出视频文件路径 threshold_area = 1000 # 轮廓区域的阈值,根据具体情况进行调整 MaskWatermark.remove_watermark(video_path, output_path) print("成功去除水印,并保存为", output_path) pass