1. 程式人生 > >python opencv加水印 去水印

python opencv加水印 去水印

opencv python 圖像處理

收到的需求是在一個圖上匹配到水印 然後將原來的水印換成一個新水印

先要安裝一個庫 庫文件代碼如下:

# coding=utf-8

import cv2
import numpy as np

# 膨脹算法 Kernel
_DILATE_KERNEL = np.array([[0, 0, 1, 0, 0],
                           [0, 0, 1, 0, 0],
                           [1, 1, 1, 1, 1],
                           [0, 0, 1, 0, 0],
                           [0, 0, 1, 0, 0]], dtype=np.uint8)

class WatermarkRemover(object):
    """"
    去除圖片中的水印(Remove Watermark)
    """

    def __init__(self, verbose=True):
        self.verbose = verbose
        self.watermark_template_gray_img = None
        self.watermark_template_mask_img = None
        self.watermark_template_h = 0
        self.watermark_template_w = 0
        self.watermark_start_x = 0
        self.watermark_start_y = 0

    def load_watermark_template(self, watermark_template_filename):
        """
        加載水印模板,以便後面批量處理去除水印
        :param watermark_template_filename:
        :return:
        """
        self.generate_template_gray_and_mask(watermark_template_filename)

    def dilate(self, img):
        """
        對圖片進行膨脹計算
        :param img:
        :return:
        """
        dilated = cv2.dilate(img, _DILATE_KERNEL)
        return dilated

    def generate_template_gray_and_mask(self, watermark_template_filename):
        """
        處理水印模板,生成對應的檢索位圖和掩碼位圖
        檢索位圖
            即處理後的灰度圖,去除了非文字部分

        :param watermark_template_filename: 水印模板圖片文件名稱
        :return: x1, y1, x2, y2
        """

        # 水印模板原圖
        img = cv2.imread(watermark_template_filename)

        # 灰度圖、掩碼圖
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        _, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_TOZERO + cv2.THRESH_OTSU)
        _, mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)

        mask = self.dilate(mask)  # 使得掩碼膨脹一圈,以免留下邊緣沒有被修復
        #mask = self.dilate(mask)  # 使得掩碼膨脹一圈,以免留下邊緣沒有被修復

        # 水印模板原圖去除非文字部分
        img = cv2.bitwise_and(img, img, mask=mask)

        # 後面修圖時需要用到三個通道
        mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

        self.watermark_template_gray_img = gray
        self.watermark_template_mask_img = mask

        self.watermark_template_h = img.shape[0]
        self.watermark_template_w = img.shape[1]

        # cv2.imwrite(‘watermark-template-gray.jpg‘, gray)
        # cv2.imwrite(‘watermark-template-mask.jpg‘, mask)

        return gray, mask

    def find_watermark(self, filename):
        """
        從原圖中尋找水印位置
        :param filename:
        :return: x1, y1, x2, y2
        """
        # Load the images in gray scale
        gray_img = cv2.imread(filename, 0)
        return self.find_watermark_from_gray(gray_img, self.watermark_template_gray_img)

    def find_watermark_from_gray(self, gray_img, watermark_template_gray_img):
        """
        從原圖的灰度圖中尋找水印位置
        :param gray_img: 原圖的灰度圖
        :param watermark_template_gray_img: 水印模板的灰度圖
        :return: x1, y1, x2, y2
        """
        # Load the images in gray scale

        method = cv2.TM_CCOEFF
        # Apply template Matching
        res = cv2.matchTemplate(gray_img, watermark_template_gray_img, method)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            x, y = min_loc
        else:
            x, y = max_loc

        return x, y, x + self.watermark_template_w, y + self.watermark_template_h

    def remove_watermark_raw(self, img, watermark_template_gray_img, watermark_template_mask_img):
        """
        去除圖片中的水印
        :param img: 待去除水印圖片位圖
        :param watermark_template_gray_img: 水印模板的灰度圖片位圖,用於確定水印位置
        :param watermark_template_mask_img: 水印模板的掩碼圖片位圖,用於修復原始圖片
        :return: 去除水印後的圖片位圖
        """
        # 尋找水印位置
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        x1, y1, x2, y2 = self.find_watermark_from_gray(img_gray, watermark_template_gray_img)
        self.watermark_start_x = x1
        self.watermark_start_y = y1
        # 制作原圖的水印位置遮板
        mask = np.zeros(img.shape, np.uint8)
        # watermark_template_mask_img = cv2.cvtColor(watermark_template_gray_img, cv2.COLOR_GRAY2BGR)
        # mask[y1:y1 + self.watermark_template_h, x1:x1 + self.watermark_template_w] = watermark_template_mask_img
        mask[y1:y2, x1:x2] = watermark_template_mask_img
        mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)

        # 用遮板進行圖片修復,使用 TELEA 算法
        dst = cv2.inpaint(img, mask, 4, cv2.INPAINT_TELEA)
        # cv2.imwrite(‘dst.jpg‘, dst)

        return dst

    def remove_watermark(self, filename, output_filename=None):
        """
        去除圖片中的水印
        :param filename: 待去除水印圖片文件名稱
        :param output_filename: 去除水印圖片後的輸出文件名稱
        :return: 去除水印後的圖片位圖
        """

        # 讀取原圖
        img = cv2.imread(filename)

        dst = self.remove_watermark_raw(img,
                                        self.watermark_template_gray_img,
                                        self.watermark_template_mask_img
                                        )

        if output_filename is not None:
            cv2.imwrite(output_filename, dst)

        return dst

註意 上面的代碼要加上這兩句 才能顯示 原來水印的位置
技術分享圖片
去水印代碼如下:

from nowatermark import WatermarkRemover

path = ‘E:/sample/‘

watermark_template_filename = path + ‘watermark.png‘
remover = WatermarkRemover()
remover.load_watermark_template(watermark_template_filename)

remover.remove_watermark(path + ‘20180516144931.png‘, path + ‘20180516144932.png‘)
print(remover.watermark_start_x)
print(remover.watermark_start_y)

這裏輸出的兩個值 是指的水印在原圖中的位置

加水印代碼如下:

import cv2
import numpy as np
path = ‘E:/sample/‘
matimage = cv2.imread(path + ‘20180516144932.png‘)

#matimagenew = np.zeros((matimage.shape[0],matimage.shape[1],3))
matimagenew = matimage-matimage
watermark_template_filename = path + ‘watermark.png‘
matlogo = cv2.imread(watermark_template_filename)

matimagenew[359:359+matlogo.shape[0],453:453+matlogo.shape[1]] = matlogo
imagenew = cv2.addWeighted(matimage,1,matimagenew,1,1)
savepath = path + ‘20180516144933.png‘
cv2.imwrite(savepath,imagenew)

其中的359為水印在原圖中的位置的縱坐標 453為橫坐標

python opencv加水印 去水印