mask_watermark.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. # -*- coding: utf-8 -*-
  2. # @Author: wangkun
  3. # @Time: 2023/7/21
  4. import cv2
  5. class MaskWatermark:
  6. @classmethod
  7. def find_watermark(cls, image_path):
  8. """
  9. 基于OpenCV自动识别水印并获取其位置
  10. :param image_path:水印
  11. :return:watermark_area
  12. """
  13. # 读取图像
  14. image = cv2.imread(image_path)
  15. # 将图像转换为灰度图像
  16. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  17. # 使用边缘检测算法如Canny来检测图像中的边缘信息
  18. edges = cv2.Canny(gray, 100, 200)
  19. # 使用霍夫变换检测直线,以获得边缘中的直线段
  20. lines = cv2.HoughLinesP(edges, 1, cv2.pi / 180, threshold=100, minLineLength=100, maxLineGap=10)
  21. # 对检测到的直线进行筛选,以识别可能表示水印的直线
  22. watermark_lines = []
  23. if lines is not None:
  24. for line in lines:
  25. x1, y1, x2, y2 = line[0]
  26. # 根据实际情况确定水印直线的特征,例如长度、斜率等
  27. # 这里只是一个示例,您需要根据具体情况进行调整
  28. if abs(y2 - y1) < 5 and abs(x2 - x1) > 50:
  29. watermark_lines.append(line)
  30. # 根据检测到的水印直线,计算水印区域的位置和大小
  31. if len(watermark_lines) > 1:
  32. x_coords = [line[0][0] for line in watermark_lines] + [line[0][2] for line in watermark_lines]
  33. y_coords = [line[0][1] for line in watermark_lines] + [line[0][3] for line in watermark_lines]
  34. min_x = min(x_coords)
  35. max_x = max(x_coords)
  36. min_y = min(y_coords)
  37. max_y = max(y_coords)
  38. watermark_area = (min_x, min_y, max_x - min_x, max_y - min_y) # 水印区域的位置和大小
  39. else:
  40. watermark_area = None
  41. return watermark_area
  42. @classmethod
  43. def mask_watermark(cls, input_path, output_path, watermark_area):
  44. # 读取视频
  45. video = cv2.VideoCapture(input_path)
  46. # 获取视频的宽度和高度
  47. width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
  48. height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
  49. # 创建输出视频对象
  50. fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 可根据需要更换视频编码器
  51. output = cv2.VideoWriter(output_path, fourcc, 30.0, (width, height))
  52. while True:
  53. ret, frame = video.read()
  54. if not ret:
  55. break
  56. # 在水印区域替换成其他像素或进行遮挡处理
  57. x, y, w, h = watermark_area
  58. frame[y:y + h, x:x + w] = 0 # 这里将水印区域像素设为0,可根据需要进行更复杂的像素替换或遮挡处理
  59. # 将处理后的帧写入输出视频
  60. output.write(frame)
  61. # 释放资源
  62. video.release()
  63. output.release()
  64. print("成功去除水印,并保存为", output_path)
  65. @classmethod
  66. def remove_watermark(cls, video_path, output_path):
  67. # 读取视频
  68. video = cv2.VideoCapture(video_path)
  69. # 获取视频的宽度和高度
  70. width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
  71. height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
  72. # 创建输出视频对象
  73. fourcc = cv2.VideoWriter_fourcc(*'mp4v') # 可根据需要更换视频编码器
  74. output = cv2.VideoWriter(output_path, fourcc, 30.0, (width, height))
  75. # 读取第一帧作为背景帧
  76. ret, background = video.read()
  77. if not ret:
  78. print("无法读取背景帧")
  79. return
  80. while True:
  81. ret, frame = video.read()
  82. if not ret:
  83. break
  84. # 计算当前帧与背景帧的差值
  85. diff = cv2.absdiff(frame, background)
  86. # 将差值转换为灰度图像
  87. gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
  88. # 应用阈值二值化,通过调整阈值以过滤差异
  89. _, threshold = cv2.threshold(gray, 25, 255, cv2.THRESH_BINARY)
  90. # 进行形态学操作,填充小区域,平滑边缘
  91. kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
  92. dilated = cv2.dilate(threshold, kernel, iterations=3)
  93. # 寻找轮廓
  94. contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  95. # 去除检测到的水印轮廓区域
  96. for contour in contours:
  97. # 这里只是一个示例,您可以根据具体情况进行调整,例如根据轮廓面积、形状等进行过滤
  98. if cv2.contourArea(contour) > threshold_area:
  99. # 在当前帧上用背景帧进行填充
  100. cv2.drawContours(frame, [contour], -1, (0, 0, 0), cv2.FILLED)
  101. # 将处理后的帧写入输出视频
  102. output.write(frame)
  103. # 释放资源
  104. video.release()
  105. output.release()
  106. if __name__ == "__main__":
  107. # 示例调用
  108. image_path = 'image.jpg' # 替换为待识别水印的图像路径
  109. watermark_area = MaskWatermark.find_watermark(image_path)
  110. print("水印区域的位置和大小:", watermark_area)
  111. # 示例调用
  112. input_path = 'input.mp4' # 替换为输入视频文件路径
  113. output_path = 'output.mp4' # 替换为输出视频文件路径
  114. watermark_area = (100, 100, 200, 200) # 替换为水印区域的位置和大小,表示为 (x, y, width, height)
  115. MaskWatermark.mask_watermark(input_path, output_path, watermark_area)
  116. # 示例调用
  117. video_path = 'video.mp4' # 替换为视频文件路径
  118. output_path = 'output.mp4' # 替换为输出视频文件路径
  119. threshold_area = 1000 # 轮廓区域的阈值,根据具体情况进行调整
  120. MaskWatermark.remove_watermark(video_path, output_path)
  121. print("成功去除水印,并保存为", output_path)
  122. pass