消除图片中的浅色水印
在z-library上下载了一本何逊集校注,这书的扫描质量非常高,可惜的是每页都有一个颜色较浅的水印,而且书页背面的字迹有渗透,阅读时显得页面较脏,而且会干扰页面的文字识别。原始页面参见下图:
对于一个强迫症患者,自然不能忍受这种状况。好在这个水印和渗透痕迹与正文文本相比,明显颜色轻很多,可以利用python轻松消除。首先将pdf文件导出为图片,放置于某个文件夹中,然后可利用下面的python程序完成去水印:
import os
import cv2
def background_to_white(filename, image_path, thresh=600):
"""
通过计算图像的每一像素点的rgb值,将大于阈值的像素点调整为白色,从而消除浅色背景(水印)
:param filename: 要调整背景的图片文件名
:param image_path: 图像文件的路径
:param thresh: 阈值,像素rgb之和大于此值将变更为白色
:return: 成功则返回处理后的图片,numpy.ndarray类型,否则返回None
"""
if not (isinstance(thresh, int) or isinstance(filename, str) or isinstance(image_path, str)):
print('无法识别的参数类型。')
return None
img = None
if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.tiff')):
img = cv2.imread(os.path.join(image_path, filename))
if img is None:
print('读取图像文件失败。')
return None
# 利用广播机制计算每个像素的RGB通道和
rgb_sum_per_pixel = img.sum(axis=2)
# 利用广播机制设置满足条件的像素为白色(RGB值为255, 255, 255)
img[rgb_sum_per_pixel > thresh] = [255, 255, 255]
return img
if __name__ == '__main__':
# 读取图像(将此处的图像路径替换为你实际的图像路径)
image_path = 'H:\\Download\\huanmie\\orig'
# 输出图像路径(将此处的图像路径替换为你实际使用的路径)
out_path = 'H:\\Download\\huanmie\\output'
# 阈值,可先处理一页进行试验,调整出合理值
thresh = 630
for filename in os.listdir(image_path):
if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.tiff')):
img = background_to_white(filename, image_path, thresh)
cv2.imwrite(os.path.join(out_path, filename), img)
print(f'{filename}已经处理完毕。')
最初处理时,本想直接使用OpenCV
的threshold
函数,结果产生了笔画粘黏。用上面的程序处理的效果不错,如下:
对于扫描效果不太好的图片,可以参考消除对比度增强后的图片中产生的噪点一文中的自适应对比度增强函数及消除噪点的方法,先进行自适应对比度增强再消除噪点(本文处理的示例书籍无需如此),改造如下:
import cv2
import os
from convert_pdf_to_thres import adapt_contrast_enhancement
def background_to_white(filename, image_path, thresh=600, need_ace=False):
"""
通过计算图像的每一像素点的rgb值,将大于阈值的像素点调整为白色,从而消除浅色背景(水印)
:param filename: 要调整背景的图片文件名
:param image_path: 图像文件的路径
:param thresh: 阈值,像素rgb之和大于此值将变更为白色
:param need_ace: 是否进行自适应对比度增强处理
:return: 成功则返回处理后的图片,numpy.ndarray类型,否则返回None
"""
if not (isinstance(thresh, int) or isinstance(filename, str) or isinstance(image_path, str)):
print('无法识别的参数类型。')
return None
img = None
if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.tiff')):
img = cv2.imread(os.path.join(image_path, filename))
if img is None:
print('读取图像文件失败。')
return None
else:
# 必要时进行自适应对比度增强
if need_ace:
img = adapt_contrast_enhancement(img)
# 利用广播机制计算每个像素的RGB通道和
rgb_sum_per_pixel = img.sum(axis=2)
# 利用广播机制设置满足条件的像素为白色(RGB值为255, 255, 255)
img[rgb_sum_per_pixel > thresh] = [255, 255, 255]
return img
if __name__ == '__main__':
# 读取图像(将此处的图像路径替换为你实际的图像路径)
image_path = 'H:\\Download\\huanmie\\orig'
out_path = 'H:\\Download\\huanmie\\output'
thresh = 630
for filename in os.listdir(image_path):
if filename.endswith(('.jpg', '.jpeg', '.png', '.bmp', '.tiff')):
img = background_to_white(filename, image_path, thresh, need_ace=True)
# 读取原始图片
orig_img = cv2.imread(os.path.join(image_path, filename))
# 转换为二值图片,作为除噪点的掩码图片。thresh参数应取较大值
_, mask_img = cv2.threshold(orig_img, 230, 255, cv2.THRESH_BINARY)
# 准备一张与原图形状一致的黑色图片
result = np.zeros_like(img)
# 将消除了浅色水印的图片转换为灰度图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 在纯白色像素点处做上标记(True)
white_mask = (gray == 255)
# 在黑色图片上进行蚀刻,标记为True的像素点蚀刻成白色
result[white_mask] = [255, 255, 255]
# 消除蚀刻出的图片中的噪点
img = cv2.bitwise_or(result, mask_img)
# 保存处理后的图片
cv2.imwrite(os.path.join(out_path, filename), img)
print(f'{filename}已经处理完毕。')
上面的from convert_pdf_to_thres import adapt_contrast_enhancement
,系从自己编写的包含了adapt_contrast_enhancement
函数的同一项目目录下的convert_pdf_to_thres.py
文件中引入该函数,该函数的具体内容参见消除对比度增强后的图片中产生的噪点。