- 解决去水印封装问题
- 去半透明水印(颜色中和)
- 去不规则水印(sift)
- pdf图片去水印
pip install opencv-python
import cv2
import numpy as np
import os
import glob
from matplotlib import pyplot as plt
class WaterMark:
def __init__(self):
pass
def remove(self, src_url, mask_url=None):
result_url = src_url.replace('.jpg', '_out.jpg')
src_url_arr = str(src_url).split('/')
mask_url_arr = []
if mask_url:
mask_url_arr.append(mask_url)
else:
src_platform = src_url_arr[-1].split('_')[0]
mask_dir = f"{'/'.join(src_url_arr[:-1])}/mask/"
for file in glob.glob(f'{mask_dir}/{src_platform}*_mask*'):
mask_url_arr.append(file)
print('src_url', src_url)
src_img = cv2.imread(src_url)
for _, v in enumerate(mask_url_arr):
print('mask_url', v)
mask_img = cv2.imread(v)
rect = self.find_water_sift(src_img=src_img, mask_img=mask_img)
if len(rect[0]) > 0:
result = self.inpaint(src_img=src_img, rect=rect, enlarge=4)
else:
rect = self.find_water_template(src_img=src_img, mask_img=mask_img)
if len(rect[0]) > 0:
result = self.inpaint(src_img=src_img, rect=rect, enlarge=10)
if len(result) > 0:
cv2.imwrite(result_url, result)
cv2.imshow('result.jpg', result)
else:
print('没有找到水印')
cv2.waitKey(0)
def remove_base(self, src_img, mask_img):
result = np.zeros(src_img.shape, np.uint8)
result[mask_img != 0] = np.clip(255 - (255 - src_img[mask_img != 0]) / mask_img[mask_img != 0] * 256, 0, 255)
return result
def inpaint(self, src_img, rect, enlarge=10):
rect_min, rect_max = rect[0], rect[1]
thresh_img = np.zeros(src_img.shape, np.uint8)
rect_min -= enlarge
rect_max += enlarge
thresh_img[rect_min[1]:rect_max[1], rect_min[0]:rect_max[0]] = \
src_img[rect_min[1]:rect_max[1], rect_min[0]:rect_max[0]]
kernel = np.ones((3, 3), np.uint8)
thresh = cv2.inRange(thresh_img, np.array([1, 1, 1]), np.array([255, 255, 255]))
hi_mask = cv2.dilate(thresh, kernel, iterations=1)
result = cv2.inpaint(src_img, hi_mask, 5, flags=cv2.INPAINT_TELEA)
return result
def remove_threshold(self, src_img):
hight, width, depth = src_img.shape[0:3]
thresh = cv2.inRange(src_img, np.array([180, 180, 180]), np.array([255, 255, 255]))
kernel = np.ones((3, 3), np.uint8)
hi_mask = cv2.dilate(thresh, kernel, iterations=1)
specular = cv2.inpaint(src_img, hi_mask, 5, flags=cv2.INPAINT_TELEA)
cv2.namedWindow("Image", 0)
cv2.resizeWindow("Image", int(width / 2), int(hight / 2))
cv2.imshow("Image", src_img)
cv2.namedWindow("newImage", 0)
cv2.resizeWindow("newImage", int(width / 2), int(hight / 2))
cv2.imshow("newImage", specular)
cv2.waitKey(0)
cv2.destroyAllWindows()
def remove_pdf(self, src_img):
new = np.clip(2.0 * src_img - 160, 0, 255).astype(np.uint8)
cv2.imshow('cleaned.jpg', new)
cv2.waitKey(0)
def find_water_template(self, src_img, mask_img):
theight, twidth = mask_img.shape[:2]
result = cv2.matchTemplate(src_img, mask_img, cv2.TM_SQDIFF_NORMED)
cv2.normalize(result, result, 0, 1, cv2.NORM_MINMAX, -1)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
strmin_val = str(min_val)
return [np.array(min_loc), np.array([min_loc[0] + twidth, min_loc[1] + theight])]
def find_waters_template(self, src_img, mask_img):
theight, twidth = mask_img.shape[:2]
result = cv2.matchTemplate(src_img, mask_img, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
cv2.rectangle(src_img, min_loc, (min_loc[0] + twidth, min_loc[1] + theight), (0, 0, 225), 2)
strmin_val = str(min_val)
temp_loc = min_loc
other_loc = min_loc
numOfloc = 1
threshold = 0.01
loc = np.where(result < threshold)
for other_loc in zip(*loc[::-1]):
if (temp_loc[0] + 5 < other_loc[0]) or (temp_loc[1] + 5 < other_loc[1]):
numOfloc = numOfloc + 1
temp_loc = other_loc
cv2.rectangle(src_img, other_loc, (other_loc[0] + twidth, other_loc[1] + theight), (0, 0, 225), 2)
str_numOfloc = str(numOfloc)
strText = "MatchResult----MatchingValue=" + strmin_val + "----NumberOfPosition=" + str_numOfloc
cv2.imshow(strText, src_img)
cv2.waitKey()
def find_water_sift(self, src_img, mask_img):
MIN_MATCH_COUNT = 6
template = cv2.cvtColor(mask_img, cv2.COLOR_RGB2GRAY)
target = cv2.cvtColor(src_img, cv2.COLOR_RGB2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(template, None)
kp2, des2 = sift.detectAndCompute(target, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
good = []
for m, n in matches:
if m.distance < 0.8 * n.distance:
good.append(m)
if len(good) >= MIN_MATCH_COUNT:
src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
h, w = template.shape
pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, M)
rect_min = dst.astype(np.int)[0, 0]
rect_max = dst.astype(np.int)[2, 0]
return [rect_min, rect_max]
cv2.polylines(target, [np.int32(dst)], True, 0, 2, cv2.LINE_AA)
else:
print("Not enough matches are found - %d/%d" % (len(good), MIN_MATCH_COUNT))
matchesMask = None
return [], []
draw_params = dict(matchColor=(0, 255, 0),
singlePointColor=None,
matchesMask=matchesMask,
flags=2)
result = cv2.drawMatches(template, kp1, target, kp2, good, None, **draw_params)
plt.imshow(result, 'gray')
plt.show()
if __name__ == '__main__':
src_url = f'../../data/water/QFNAG_.jpg'
mask_url = f'../../data/water/mask/LYJ_mask_L.jpg'
water = WaterMark()
water.remove(src_url=src_url, mask_url=mask_url)