来源丨https://davidsteccieblog.blogspot.com/2017/10/removing-watermarks.html?view=flipcard
翻译整理丨OpenCV与AI深度学习
导读
本文主要给大家分享一个使用OpenCV去除图像水印的实例,代码中的方法很值得借鉴。
背景介绍
作者当时正在准备一篇关于巴林托尔城堡的演讲,在英国皇家建筑师学会(RIBA)的网站上看到了一幅1860年的原画。觉得画作太棒了,但是它有水印。因为作者有图像处理方面的背景,所以决定尝试写一个去除水印的算法应该会很有趣,完成后整体效果还不错!
实现步骤与效果
先来看看原始包含水印的图像:
图像中基本上有3个不同的区域:
- 字母外未触及的区域
- 字母周围的黑线
- 颜色和对比度降低的字母内部区域
初步来看图片中字母(水印)和背景之间对比度较低,尝试后发现在HSV颜色空间的S通道,能够很好的凸显字母:
对S通道做阈值处理,然后标记连通域结果:
代码语言:javascript复制connectivity = 4
ret, thresh_s = cv2.threshold(image_saturation, 42, 255, cv2.THRESH_BINARY_INV) # 50 too high, 25 too low
output = cv2.connectedComponentsWithStats(thresh_s, connectivity, cv2.CV_32S)
blob_image = output[1]
stats = output[2]
pop_thresh = 50
big_blob_colour_map = make_random_colour_map_with_stats(stats, pop_thresh)
all_blob_colour_map = make_random_colour_map_with_stats(stats)
big_blob_coloured_image = big_blob_colour_map[blob_image] # output
all_blob_coloured_image = all_blob_colour_map[blob_image] # output
display_and_output_image("big_blob_coloured_image", big_blob_coloured_image)
display_and_output_image("all_blob_coloured_image", all_blob_coloured_image)
letter_mask = coloured_image_to_edge_mark(big_blob_coloured_image)
连通域筛选,保留字母部分:
通过形态学梯度方法可以获取字母边缘轮廓:
下面的图像看起来可能与带有水印的起始点图像略有不同。但是,黑色边界现在是我创建的“边遮罩”。在这些字母中,我增加了黑白图像的对比度,使其与周围的深褐色图像的对比度完全匹配。这是通过“直方图技术”实现的,使内部图像的强度分布直方图与外部图像的强度分布直方图相匹配。
除了“边缘遮罩”,我还有一个用于字母内部的“字母遮罩”,基本上与早期的色彩相同。
在这些字母中,需要提供缺少的色调和饱和度信息。在边缘遮罩区域,我们需要提供缺少的颜色、饱和度和强度信息。可以使用inpaint图像修复技术用于填充缺失的区域,它是一种用来从照片上去除划痕的技术。
简单来说,色调和饱和度信息在字母遮罩内绘制,强度信息在边缘遮罩内绘制。眼睛对色调和饱和度信息不太敏感,因此在大号字母区域内的大量不准确猜测不成问题。然而,当强度信息在字母掩码内绘制时,这看起来很可怕。眼睛对强度信息非常敏感。因此,有必要在最小可能区域(即仅边缘遮罩)中绘制强度,并使用字母内部的强度信息-这需要复杂的直方图工作(直方图颜色迁移,见源码)。
最终处理结果: