Python使用OpenCV图片去水印多种方案实现

[复制链接]
发表于 2025-11-3 06:39:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1. 前言

本文为作者学习记录,使用Python联合OpenCV,总结了几种常见的水印去除方式,简单图片去水印效果良好,但是复杂图片有点一言难尽,本文部分代码仅供参考,并不能针对全部水印通用,须要根据详细水印颜色、位置等环境举行分析调解代码。
2. 颜色先容

本文统共使用了两种格式的颜色,一种是BGR,另一种是HSV。
关于怎样获取BGR的颜色,可以直接使用截图大概罗致颜色的工具罗致即可。如下图:
有一点须要注意:Python内里用的是BGR,截图工具给的是RGB,这个使用的使用须要调解下次序

HSV是由色调(H),饱和度(S),亮度(V)构成,怎样获取HSV的值,这里提供一段Python的代码获取。此中'image/3_water.jpg'更换成你的图片路径。详细如下:
  1. import cv2
  2. import numpy as np
  3. from matplotlib import pyplot as plt
  4. image=cv2.imread('image/3_water.jpg')
  5. HSV=cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
  6. def getpos(event,x,y,flags,param):
  7.     if event==cv2.EVENT_LBUTTONDOWN: #定义一个鼠标左键按下去的事件
  8.         print(HSV[y,x])
  9. cv2.imshow("imageHSV",HSV)
  10. cv2.imshow('image',image)
  11. cv2.setMouseCallback("imageHSV",getpos)
  12. cv2.waitKey(0)
复制代码
效果图如下,左边的为原图,右边的为转为HSV的图片,点击你须要获取颜色的位置,会在控制台打印对应的颜色值。

3. 添加水印

先准备几张测试图片,给这些图片打上水印。这里以下面的图片经行演示。

添加水印代码如下:
  1. import cv2
  2. import numpy as np
  3. def create_watermark(image_path):
  4.     # 读取图像
  5.     image = cv2.imread(image_path)
  6.    
  7.     # 设置水印文本
  8.     watermark_text = 'www.xiaoxiaofeng.com'
  9.    
  10.     # 设置字体
  11.     font = cv2.FONT_HERSHEY_SIMPLEX
  12.     # 设置字体大小
  13.     font_scale = 0.5
  14.     # 注意,这里是BGR 蓝色(B)、绿色(G)和红色(R)
  15.     font_color = (62, 62, 187)  
  16.     # 设置字体粗细
  17.     thickness = 1
  18.    
  19.     # 获取图像的高度和宽度
  20.     height, width = image.shape[:2]
  21.     # 设置文本位置(右下角)
  22.     text_position = ( width - 200, height - 20 )  # 例如,在右下角
  23.    
  24.     # 添加水印文本
  25.     cv2.putText(image, watermark_text, text_position, font, font_scale, font_color, thickness, cv2.LINE_AA)
  26.    
  27.     # 显示图像
  28.     cv2.imshow('Watermarked Image', image)
  29.     cv2.waitKey(0)
  30.     cv2.destroyAllWindows()
  31.    
  32.     # 保存图像
  33.     cv2.imwrite('image/2_water.jpg', image)
  34. create_watermark('image/2.jpg')
复制代码
添加完水印的效果如下图:

4. 去除水印

关于去除水印,效果最好的应该还是练习模子,用模子去除效果肯定比力好,但是对于简单的水印,也没须要去练习模子,而且练习模子的门槛比力高,自己的"超配00年代"的电脑就别想了。
这里针对几种常见的水印,简单的形貌下去水印的头脑,以及实今世码。
4.1 文档类图片去水印

关于图片准备,这里直接用word创建了一个带水印的文档,然后截图,图片如下:

实现目的:去除中央配景的中的【笑小枫】的水印。
实现头脑:配景为白色,字体颜色为玄色,水印颜色为灰色,因此可以将水印的灰色更换为白色即可
方案一:
通过观测,水印的颜色大多为(214, 214, 214),但是边沿的锯齿处有部分颜色为214-245之间,这里界说3个色彩相加之和位于 640-740之间的,全部更换为白色,固然如许大概会误伤一部分颜色,详细须要针对多种方案比力选用。
  1. import numpy as np
  2. import cv2
  3. def remote_water_mark_1(image):
  4.     # 读取图像
  5.     image = cv2.imread(image)
  6.     # 显示原始图像
  7.     cv2.imshow('Original Image', image)
  8.     # 设置替换颜色为白色
  9.     replace_color = (255, 255, 255)
  10.     # 获取图片大小
  11.     height, width = image.shape[:2]
  12.     for i in range(height):
  13.         for j in range(width):
  14.             # 获取当前像素点的颜色值
  15.             varP = image[i, j]
  16.             # 如果当前像素点的颜色值总和在640到760之间,则替换为白色
  17.             if sum(varP) > 640 and sum(varP) < 740:
  18.                 image[i, j] = replace_color
  19.     # 显示处理后的图像
  20.     cv2.imshow('Result Image', image)
  21.     cv2.waitKey(0)
  22.    
  23. remote_water_mark_1('image/3.jpg')
复制代码
去水印后的效果图如下:

可以看到,图片底部的水印去掉了,细致看图片中的笔墨颜色有点眇小变革,这就是由于部分像素颜色被误伤了导致的。下面看下方案二,可以办理这个标题。
方案二:
和方案一的头脑同等,但是不再使用BGR的颜色处理处罚图片,而是使用HSV对图片举行处理处罚。通过创建颜色范围的掩码,更换掉对应像素的颜色,详细代码如下:
  1. import numpy as np
  2. import cv2
  3. def remote_water_mark_2(image):
  4.     # 读取图像
  5.     image = cv2.imread(image)
  6.     # 显示原始图像
  7.     cv2.imshow('Original Image', image)
  8.     # 将图像从BGR颜色空间转换为HSV颜色空间
  9.     hsv_image  = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
  10.     # 定义要替换的颜色范围(在 HSV 空间中)
  11.     lower_blue = np.array([0, 0, 214])
  12.     upper_blue = np.array([0, 0, 245])
  13.     # 在HSV图像中,根据定义的颜色范围创建掩码
  14.     mask = cv2.inRange(hsv_image, lower_blue, upper_blue)
  15.    
  16.     # 显示掩码图像
  17.     cv2.imshow('mask Image', mask)
  18.     # 将掩码中对应位置的颜色替换为红色(在 HSV 空间中),白底在HSV空间就是红色。
  19.     hsv_image[mask > 0] = [0, 0, 255]
  20.     # 如果需要,将图片转换回 BGR 颜色空间
  21.     result_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)
  22.     # 显示结果图像
  23.     cv2.imshow('Result Image', result_image)
  24.     cv2.waitKey(0)
  25.    
  26. remote_water_mark_2('image/3.jpg')
复制代码
去水印后的效果图如下,可以通过mask掩码图像(玄色配景,白色水印图)清楚的看到水印的形状。这里可以根据mask掩码调解颜色区间的参数。可以看到右边图片乐成去除水印,而且笔墨颜色同等。

4.2 固定位置水印去除方式

上文提到了,水印配景颜色如果和图片颜色范例,大概会误伤,出现意向不到标题。全部针对可以确认固定位置的水印,我们只管处理处罚固定位置,淘汰对图片的损伤。
如下图:水印固定在右下角,颜色和字体颜色根本同等,如许如果全图处理处罚,整张图片就面目一新了。以是我们可以针对右下角固定的位置,特殊处理处罚。

代码如下:
  1. import numpy as np
  2. import cv2
  3. def remote_water_mark_3(image):
  4.     # 读取图像
  5.     image = cv2.imread(image)
  6.     # 显示原始图像
  7.     cv2.imshow('Original Image', image)
  8.     # 获取图像的高度和宽度
  9.     height, width = image.shape[:2]
  10.     # 定义 ROI 的坐标和大小
  11.     x, y, w, h = width-280, height-40, 280, 40
  12.     roi = image[y:y+h, x:x+w]
  13.     # 将 ROI 从 BGR 颜色空间转换为 HSV 颜色空间
  14.     hsv_image  = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
  15.     # 定义要替换的颜色范围,范围尽量越小越好(在 HSV 空间中)
  16.     lower_blue = np.array([0, 0, 0])
  17.     upper_blue = np.array([0, 0, 240])
  18.     # 创建掩码
  19.     mask = cv2.inRange(hsv_image, lower_blue, upper_blue)
  20.     # 替换颜色
  21.     hsv_image[mask > 0] = [0, 0, 255]  # 将匹配的颜色替换为红色(在 HSV 空间中)
  22.     # 如果需要,将图片转换回 BGR 颜色空间
  23.     roi = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)
  24.     # 将处理后的 ROI 放回原图
  25.     image[y:y+h, x:x+w] = roi
  26.     # 显示处理后的图像
  27.     cv2.imshow('Result Image', image)
  28.     cv2.waitKey(0)
  29.    
  30. remote_water_mark_2('image/1_water.jpg')
复制代码
处理处罚后的效果如下图所示

可以瞥见水印已经去掉了。由于这里配景是白色,以是很长处理处罚,但如果配景不是白色,而是一些其他颜色改怎么处理处罚呢?接下来看下面
4.3 复杂配景致的水印处理处罚

针对复杂配景致的图片,处理处罚时肯定会肯定水平的损伤图片了,如果须要相对精准,可以练习模子处理处罚,单纯使用代码,还是有肯定步调限定。如果水印位置不固定,数量不固定,巨细不固定等等,代码范围性就很大了,纯openCV代码暂还没找到方案,这里还是以简单的示例。
先看下面这张相对简单的图片

方案一:
使用inpaint函数修复图片,代码如下:
  1. import numpy as np
  2. import cv2
  3. def remote_water_mark_6(image):
  4.     # 读取图像
  5.     image = cv2.imread(image)
  6.     # 显示原始图像
  7.     cv2.imshow('Original Image', image)
  8.     height, width = image.shape[:2]
  9.     # 创建一个掩码,标记水印区域
  10.     mask = np.zeros(image.shape[:2], np.uint8)
  11.     height, width = image.shape[:2]
  12.     # 假设水印在这个区域,绘制矩形掩码
  13.     cv2.rectangle(mask, (width-220, height-50), (width, height), 255, -1)
  14.     # 使用inpaint函数修复图像
  15.     denoised_image = cv2.inpaint(image, mask, 1, cv2.INPAINT_TELEA)
  16.     # 显示结果图像
  17.     cv2.imshow('Result Image', denoised_image)
  18.     cv2.waitKey(0)
  19.    
  20. remote_water_mark_6('image/2_water.jpg')
复制代码
处理处罚后的效果图如下,可以看到水印处理处罚掉了,但是图片水印处有略微变形。

针对下面这张图片举行测试:

可以看到水印固然去掉了,但是水印出糊的很锋利

方案二:
此方案为自己写的,暂未经大量图片测试,但测试了部分图片,效果还可,因此放在这里做个比力
实现头脑:实现步调根本于上面同等,针对水印颜色区间像素举行颜色更换,更换的颜色值,这里取周边像素颜色出现次数最多的颜色做更换。然后对地区图片举行噪点处理处罚,只管中和处理处罚部分于原图像的匹配度,如果水印下方是笔墨范例,不可以举行噪点处理处罚。
详细代码如下:
详细使用时须要根据水印位置和颜色调解对应的参数
  1. import numpy as np
  2. import cv2
  3. from collections import Counter
  4. def find_most_frequent_color(color_list):
  5.     """
  6.     找到颜色列表中出现频率最高的颜色。
  7.     Args:
  8.         color_list (list): 颜色列表,每个颜色可以是一个包含三个整数的列表,分别表示RGB值。
  9.     Returns:
  10.         tuple: 出现频率最高的颜色,以元组形式返回,包含三个整数,分别表示RGB值。
  11.     """
  12.         # 将颜色列表中的每个颜色转换为元组形式
  13.     color_list = [tuple(color) for color in color_list]  
  14.         # 使用 Counter 统计每种颜色出现的次数
  15.     color_counts = Counter(color_list)
  16.         # 获取出现次数最多的颜色,并返回该颜色
  17.     return color_counts.most_common(1)[0][0]
  18. def remote_water_mark_5(image):
  19.     # 读取图像
  20.     image = cv2.imread(image)
  21.     # 显示原始图像
  22.     cv2.imshow('Original Image', image)
  23.     height, width = image.shape[:2]
  24.     # 定义 ROI(水印的位置,需要根据实际情况调整)
  25.     x, y, w, h = width-200, height-35, 200, 35  # ROI 的坐标和大小
  26.     roi = image[y:y+h, x:x+w]
  27.     for yy in range(25, -1, -1):
  28.         for xx in range(195):
  29.             # 获取当前像素的颜色
  30.             pixel_color = roi[yy, xx]
  31.             pixel_color_sum = sum(pixel_color[:3])
  32.             # 检查当前像素的颜色是否与要替换的颜色匹配,需要根据实际情况调整
  33.             if (pixel_color_sum > 300 and pixel_color_sum < 650):
  34.                 if sum(roi[yy, xx]) == sum(roi[yy, xx-1]) and sum(roi[yy, xx]) == sum(roi[yy+1, xx]):
  35.                     continue
  36.                 is_fix = False
  37.                 color_set = [roi[yy, xx]]
  38.                 for i in range(5, -1, -1):
  39.                     if is_fix:
  40.                         break
  41.                     temp = roi[yy + i, xx + i]
  42.                     temp1 = roi[yy - i, xx - i]
  43.                     color_set.append(temp)
  44.                     color_set.append(temp1)
  45.                     color_set.append( roi[yy + i, xx + 2])
  46.                     color_set.append( roi[yy + 2, xx + i])
  47.                     color_set.append( roi[yy - i, xx - 2])
  48.                     color_set.append( roi[yy - 2, xx - i])
  49.                     color_set.append( roi[yy + i, xx - i])
  50.                     color_set.append( roi[yy - i, xx + i])
  51.                     if sum(temp) == sum(temp1):
  52.                         roi[yy, xx] = temp
  53.                         is_fix = True
  54.                     elif i == 1:
  55.                         most_frequent_color = find_most_frequent_color(color_set)
  56.                         roi[yy, xx] = most_frequent_color
  57.     # 滤波窗口大小,如果背景处是文字,不可以进行噪点处理,不然会糊掉
  58.     kernel_size = 3
  59.     # 对 ROI 进行中值滤波
  60.     roi = cv2.medianBlur(roi, kernel_size)
  61.     # 将处理后的 ROI 放回原图
  62.     image[y:y+h, x:x+w] = roi
  63.     # 显示处理后的图像
  64.     cv2.imshow('Result Image', image)
  65.     cv2.waitKey(0)
  66.    
  67. remote_water_mark_5('image/4_water.jpg')
复制代码
测试效果如下图所示:


下面这个图,去除了噪点处理处罚的代码。

4.4 练习模子(未完成)

作者实验过举行练习模子处理处罚,但在练习数据时,电脑CPU咔咔100%,因此放弃。这里就不附代码供各人参考,由于没有练习出模子,不知道效果怎样,也不知道对不对。
5. 本文总结

本文写了几种去水印的方案,详细怎样选择,小同伴们可以根据现实环境去选择,本文也是我使用python去水印一起研究过来的总结。
由于刚刚打仗python不多,如有错误之处,各人可以帮助指出来,感谢!
渴望有资助的朋侪帮助点个赞赞,作者后续会连续学习分享Java和Python干系知识,有爱好的朋侪可以添加挚友一起研究学习。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表