马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1. 前言
本文为作者学习记录,使用Python联合OpenCV,总结了几种常见的水印去除方式,简单图片去水印效果良好,但是复杂图片有点一言难尽,本文部分代码仅供参考,并不能针对全部水印通用,须要根据详细水印颜色、位置等环境举行分析调解代码。
2. 颜色先容
本文统共使用了两种格式的颜色,一种是BGR,另一种是HSV。
关于怎样获取BGR的颜色,可以直接使用截图大概罗致颜色的工具罗致即可。如下图:
有一点须要注意:Python内里用的是BGR,截图工具给的是RGB,这个使用的使用须要调解下次序
HSV是由色调(H),饱和度(S),亮度(V)构成,怎样获取HSV的值,这里提供一段Python的代码获取。此中'image/3_water.jpg'更换成你的图片路径。详细如下:- import cv2
- import numpy as np
- from matplotlib import pyplot as plt
-
- image=cv2.imread('image/3_water.jpg')
- HSV=cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
- def getpos(event,x,y,flags,param):
- if event==cv2.EVENT_LBUTTONDOWN: #定义一个鼠标左键按下去的事件
- print(HSV[y,x])
-
- cv2.imshow("imageHSV",HSV)
- cv2.imshow('image',image)
- cv2.setMouseCallback("imageHSV",getpos)
- cv2.waitKey(0)
复制代码 效果图如下,左边的为原图,右边的为转为HSV的图片,点击你须要获取颜色的位置,会在控制台打印对应的颜色值。
3. 添加水印
先准备几张测试图片,给这些图片打上水印。这里以下面的图片经行演示。
添加水印代码如下:- import cv2
- import numpy as np
-
- def create_watermark(image_path):
- # 读取图像
- image = cv2.imread(image_path)
-
- # 设置水印文本
- watermark_text = 'www.xiaoxiaofeng.com'
-
- # 设置字体
- font = cv2.FONT_HERSHEY_SIMPLEX
- # 设置字体大小
- font_scale = 0.5
- # 注意,这里是BGR 蓝色(B)、绿色(G)和红色(R)
- font_color = (62, 62, 187)
- # 设置字体粗细
- thickness = 1
-
- # 获取图像的高度和宽度
- height, width = image.shape[:2]
- # 设置文本位置(右下角)
- text_position = ( width - 200, height - 20 ) # 例如,在右下角
-
- # 添加水印文本
- cv2.putText(image, watermark_text, text_position, font, font_scale, font_color, thickness, cv2.LINE_AA)
-
- # 显示图像
- cv2.imshow('Watermarked Image', image)
- cv2.waitKey(0)
- cv2.destroyAllWindows()
-
- # 保存图像
- cv2.imwrite('image/2_water.jpg', image)
- create_watermark('image/2.jpg')
复制代码 添加完水印的效果如下图:
4. 去除水印
关于去除水印,效果最好的应该还是练习模子,用模子去除效果肯定比力好,但是对于简单的水印,也没须要去练习模子,而且练习模子的门槛比力高,自己的"超配00年代"的电脑就别想了。
这里针对几种常见的水印,简单的形貌下去水印的头脑,以及实今世码。
4.1 文档类图片去水印
关于图片准备,这里直接用word创建了一个带水印的文档,然后截图,图片如下:
实现目的:去除中央配景的中的【笑小枫】的水印。
实现头脑:配景为白色,字体颜色为玄色,水印颜色为灰色,因此可以将水印的灰色更换为白色即可
方案一:
通过观测,水印的颜色大多为(214, 214, 214),但是边沿的锯齿处有部分颜色为214-245之间,这里界说3个色彩相加之和位于 640-740之间的,全部更换为白色,固然如许大概会误伤一部分颜色,详细须要针对多种方案比力选用。- import numpy as np
- import cv2
- def remote_water_mark_1(image):
- # 读取图像
- image = cv2.imread(image)
- # 显示原始图像
- cv2.imshow('Original Image', image)
- # 设置替换颜色为白色
- replace_color = (255, 255, 255)
- # 获取图片大小
- height, width = image.shape[:2]
- for i in range(height):
- for j in range(width):
- # 获取当前像素点的颜色值
- varP = image[i, j]
- # 如果当前像素点的颜色值总和在640到760之间,则替换为白色
- if sum(varP) > 640 and sum(varP) < 740:
- image[i, j] = replace_color
- # 显示处理后的图像
- cv2.imshow('Result Image', image)
- cv2.waitKey(0)
-
- remote_water_mark_1('image/3.jpg')
复制代码 去水印后的效果图如下:
可以看到,图片底部的水印去掉了,细致看图片中的笔墨颜色有点眇小变革,这就是由于部分像素颜色被误伤了导致的。下面看下方案二,可以办理这个标题。
方案二:
和方案一的头脑同等,但是不再使用BGR的颜色处理处罚图片,而是使用HSV对图片举行处理处罚。通过创建颜色范围的掩码,更换掉对应像素的颜色,详细代码如下:- import numpy as np
- import cv2
- def remote_water_mark_2(image):
- # 读取图像
- image = cv2.imread(image)
- # 显示原始图像
- cv2.imshow('Original Image', image)
- # 将图像从BGR颜色空间转换为HSV颜色空间
- hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
- # 定义要替换的颜色范围(在 HSV 空间中)
- lower_blue = np.array([0, 0, 214])
- upper_blue = np.array([0, 0, 245])
- # 在HSV图像中,根据定义的颜色范围创建掩码
- mask = cv2.inRange(hsv_image, lower_blue, upper_blue)
-
- # 显示掩码图像
- cv2.imshow('mask Image', mask)
- # 将掩码中对应位置的颜色替换为红色(在 HSV 空间中),白底在HSV空间就是红色。
- hsv_image[mask > 0] = [0, 0, 255]
- # 如果需要,将图片转换回 BGR 颜色空间
- result_image = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)
- # 显示结果图像
- cv2.imshow('Result Image', result_image)
- cv2.waitKey(0)
-
- remote_water_mark_2('image/3.jpg')
复制代码 去水印后的效果图如下,可以通过mask掩码图像(玄色配景,白色水印图)清楚的看到水印的形状。这里可以根据mask掩码调解颜色区间的参数。可以看到右边图片乐成去除水印,而且笔墨颜色同等。
4.2 固定位置水印去除方式
上文提到了,水印配景颜色如果和图片颜色范例,大概会误伤,出现意向不到标题。全部针对可以确认固定位置的水印,我们只管处理处罚固定位置,淘汰对图片的损伤。
如下图:水印固定在右下角,颜色和字体颜色根本同等,如许如果全图处理处罚,整张图片就面目一新了。以是我们可以针对右下角固定的位置,特殊处理处罚。
代码如下:- import numpy as np
- import cv2
- def remote_water_mark_3(image):
- # 读取图像
- image = cv2.imread(image)
- # 显示原始图像
- cv2.imshow('Original Image', image)
- # 获取图像的高度和宽度
- height, width = image.shape[:2]
- # 定义 ROI 的坐标和大小
- x, y, w, h = width-280, height-40, 280, 40
- roi = image[y:y+h, x:x+w]
- # 将 ROI 从 BGR 颜色空间转换为 HSV 颜色空间
- hsv_image = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
- # 定义要替换的颜色范围,范围尽量越小越好(在 HSV 空间中)
- lower_blue = np.array([0, 0, 0])
- upper_blue = np.array([0, 0, 240])
- # 创建掩码
- mask = cv2.inRange(hsv_image, lower_blue, upper_blue)
- # 替换颜色
- hsv_image[mask > 0] = [0, 0, 255] # 将匹配的颜色替换为红色(在 HSV 空间中)
- # 如果需要,将图片转换回 BGR 颜色空间
- roi = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)
- # 将处理后的 ROI 放回原图
- image[y:y+h, x:x+w] = roi
- # 显示处理后的图像
- cv2.imshow('Result Image', image)
- cv2.waitKey(0)
-
- remote_water_mark_2('image/1_water.jpg')
复制代码 处理处罚后的效果如下图所示
可以瞥见水印已经去掉了。由于这里配景是白色,以是很长处理处罚,但如果配景不是白色,而是一些其他颜色改怎么处理处罚呢?接下来看下面
4.3 复杂配景致的水印处理处罚
针对复杂配景致的图片,处理处罚时肯定会肯定水平的损伤图片了,如果须要相对精准,可以练习模子处理处罚,单纯使用代码,还是有肯定步调限定。如果水印位置不固定,数量不固定,巨细不固定等等,代码范围性就很大了,纯openCV代码暂还没找到方案,这里还是以简单的示例。
先看下面这张相对简单的图片
方案一:
使用inpaint函数修复图片,代码如下:- import numpy as np
- import cv2
- def remote_water_mark_6(image):
- # 读取图像
- image = cv2.imread(image)
- # 显示原始图像
- cv2.imshow('Original Image', image)
- height, width = image.shape[:2]
- # 创建一个掩码,标记水印区域
- mask = np.zeros(image.shape[:2], np.uint8)
- height, width = image.shape[:2]
- # 假设水印在这个区域,绘制矩形掩码
- cv2.rectangle(mask, (width-220, height-50), (width, height), 255, -1)
- # 使用inpaint函数修复图像
- denoised_image = cv2.inpaint(image, mask, 1, cv2.INPAINT_TELEA)
- # 显示结果图像
- cv2.imshow('Result Image', denoised_image)
- cv2.waitKey(0)
-
- remote_water_mark_6('image/2_water.jpg')
复制代码 处理处罚后的效果图如下,可以看到水印处理处罚掉了,但是图片水印处有略微变形。
针对下面这张图片举行测试:
可以看到水印固然去掉了,但是水印出糊的很锋利
方案二:
此方案为自己写的,暂未经大量图片测试,但测试了部分图片,效果还可,因此放在这里做个比力
实现头脑:实现步调根本于上面同等,针对水印颜色区间像素举行颜色更换,更换的颜色值,这里取周边像素颜色出现次数最多的颜色做更换。然后对地区图片举行噪点处理处罚,只管中和处理处罚部分于原图像的匹配度,如果水印下方是笔墨范例,不可以举行噪点处理处罚。
详细代码如下:
详细使用时须要根据水印位置和颜色调解对应的参数- import numpy as np
- import cv2
- from collections import Counter
- def find_most_frequent_color(color_list):
- """
- 找到颜色列表中出现频率最高的颜色。
- Args:
- color_list (list): 颜色列表,每个颜色可以是一个包含三个整数的列表,分别表示RGB值。
- Returns:
- tuple: 出现频率最高的颜色,以元组形式返回,包含三个整数,分别表示RGB值。
- """
- # 将颜色列表中的每个颜色转换为元组形式
- color_list = [tuple(color) for color in color_list]
- # 使用 Counter 统计每种颜色出现的次数
- color_counts = Counter(color_list)
- # 获取出现次数最多的颜色,并返回该颜色
- return color_counts.most_common(1)[0][0]
- def remote_water_mark_5(image):
- # 读取图像
- image = cv2.imread(image)
- # 显示原始图像
- cv2.imshow('Original Image', image)
- height, width = image.shape[:2]
- # 定义 ROI(水印的位置,需要根据实际情况调整)
- x, y, w, h = width-200, height-35, 200, 35 # ROI 的坐标和大小
- roi = image[y:y+h, x:x+w]
- for yy in range(25, -1, -1):
- for xx in range(195):
- # 获取当前像素的颜色
- pixel_color = roi[yy, xx]
- pixel_color_sum = sum(pixel_color[:3])
- # 检查当前像素的颜色是否与要替换的颜色匹配,需要根据实际情况调整
- if (pixel_color_sum > 300 and pixel_color_sum < 650):
- if sum(roi[yy, xx]) == sum(roi[yy, xx-1]) and sum(roi[yy, xx]) == sum(roi[yy+1, xx]):
- continue
- is_fix = False
- color_set = [roi[yy, xx]]
- for i in range(5, -1, -1):
- if is_fix:
- break
- temp = roi[yy + i, xx + i]
- temp1 = roi[yy - i, xx - i]
- color_set.append(temp)
- color_set.append(temp1)
- color_set.append( roi[yy + i, xx + 2])
- color_set.append( roi[yy + 2, xx + i])
- color_set.append( roi[yy - i, xx - 2])
- color_set.append( roi[yy - 2, xx - i])
- color_set.append( roi[yy + i, xx - i])
- color_set.append( roi[yy - i, xx + i])
- if sum(temp) == sum(temp1):
- roi[yy, xx] = temp
- is_fix = True
- elif i == 1:
- most_frequent_color = find_most_frequent_color(color_set)
- roi[yy, xx] = most_frequent_color
- # 滤波窗口大小,如果背景处是文字,不可以进行噪点处理,不然会糊掉
- kernel_size = 3
- # 对 ROI 进行中值滤波
- roi = cv2.medianBlur(roi, kernel_size)
- # 将处理后的 ROI 放回原图
- image[y:y+h, x:x+w] = roi
- # 显示处理后的图像
- cv2.imshow('Result Image', image)
- cv2.waitKey(0)
-
- remote_water_mark_5('image/4_water.jpg')
复制代码 测试效果如下图所示:


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

4.4 练习模子(未完成)
作者实验过举行练习模子处理处罚,但在练习数据时,电脑CPU咔咔100%,因此放弃。这里就不附代码供各人参考,由于没有练习出模子,不知道效果怎样,也不知道对不对。
5. 本文总结
本文写了几种去水印的方案,详细怎样选择,小同伴们可以根据现实环境去选择,本文也是我使用python去水印一起研究过来的总结。
由于刚刚打仗python不多,如有错误之处,各人可以帮助指出来,感谢!
渴望有资助的朋侪帮助点个赞赞,作者后续会连续学习分享Java和Python干系知识,有爱好的朋侪可以添加挚友一起研究学习。
|