这是一个用来去除水印的小demo。
适合于去除水印颜色较浅,保留元素颜色较深的图片。
比如白底黑字,但带白色或灰色的图片或者其他彩色图片但有白色或灰色水印
该算法对于偏暗的图片去水印的效果不是很好。
基于滑动窗口的图片去水印方法
-
传统去水印方式是统计图片上水印的像素值范围,将RGB值属于某一范围内的像素赋值为[0,0,0]或[255,255,255]已达到去水印效果。
-
但对于受光照影响或本身图片较暗的图片,上述去水印方法效果不理想。
-
针对以上特征的图片,采用局部去水印的方式。
-
具体体现在三个改进点上:
-
1、 利用滑动窗口分割图片
-
2、 针对局部图片采用像素替换的方案A。
像素替换方案A:
图片中需要识别的文字均为黑色,其对应的像素值低。图片中水印位置以及有光照的位置颜色偏白,对应的像素值较高。
将RGB值和高于某个阈值的像素,重置其像素值为[255,255,255]即将颜色置为为白色。达到去除水印的效果。该阈值的设定根据整体像素和的分位数来确定。
滑动窗口的设计让算法关注于局部的颜色差异,分位数的设计让需要改变的像素点根据局部的情况独立确定,避免全局的明暗和其他元素(如国徽)等的影响。
-
3、通过将滑动窗口由小至大的调整,可以进一步增强去水印的效果,使得去除水印后的文字像素损失进一步降低。
我把代码放在了github上。
import cv2
import numpy as np
import os
def move_mark(slices,percentile_ratio):
hight, width, depth = slices.shape[0:3]
sum_ = slices.sum(2)
t = list(set(list(np.array(sum_).flat)))
qual = np.percentile(t,percentile_ratio)
for h in range(hight):
for w in range(width):
if sum_[h][w] > qual:
slices[h][w] = [255,255,255]
return slices
def sliding_window(image, stepSize, windowSize):
# slide a window across the image
for y in range(0, image.shape[0], stepSize[1]):
for x in range(0, image.shape[1], stepSize[0]):
# yield the current window
yield (x, y, image[y:y + windowSize[1], x:x + windowSize[0]])
# 返回滑动窗结果集合,本示例暂时未用到
def get_slice(image, stepSize, windowSize):
slice_sets = []
for (x, y, window) in sliding_window(image, stepSize, windowSize):
# if the window does not meet our desired window size, ignore it
if window.shape[0] != windowSize[1] or window.shape[1] != windowSize[0]:
continue
slice = image[y:y + windowSize[1], x:x + windowSize[0]]
slice_sets.append(slice)
return slice_sets
def do_remove_mark(image,percentile_ratio,size_):
# 自定义滑动窗口的大小
w = image.shape[1]
h = image.shape[0]
# 本代码将图片分为3×3,共九个子区域,winW, winH和stepSize可自行更改
(winW, winH) = (int(w/size_),int(h/size_))
stepSize = (int(w/size_), int(h/size_))
for (x, y, window) in sliding_window(image, stepSize=stepSize, windowSize=(winW, winH)):
# if the window does not meet our desired window size, ignore it
if window.shape[0] != winH or window.shape[1] != winW:
continue
slice = image[y:y+winH,x:x+winW]
image[y:y+winH,x:x+winW] = move_mark(slice,percentile_ratio)
return image
# TODO
# path = "./train/1/"
# for img_ in os.listdir(path):
# if img_[-3:] != "png":continue
# image = cv2.imread(path + img_)
# img = do_remove_mark(image,50,500)
# img = do_remove_mark(img,50,3)
# cv2.imwrite("./trainres/" + img_,img)
-------------------------------------------------
以上方法致力于解决工商图片的水印去除问题。在以上解决方案的基础上,我们可以得到比较可行的结果。但是还有一些遗留问题,请教各位前辈相关解决方案:
去除水印后文字像素有所损失,对于这些损失的像素有什么方案可以补全或者增强?
本身是灰色的图片其像素值与水印接近,做以上处理之后,整个图片的文字细节大部分丢失,如何改进?
欢迎留言赐教,恭候,百拜!