基于Python实现网页版之复杂图片去水印

基于Python实现网页版去复杂图片水印

Python可以用OpenCV去除图片水印,但只针对简单图片,对于复杂图片水印,目前采用最多的是固定位置去除,但是这种方式不能针对所有照片,还有就是采用AI训练的方式,就这种方式而言,效果不错,但是很耗费时间,追求完美的话,至少需要20h,从经济上讲很不划算,所以本文一种特殊的方式,通过图像转化为HSV图,提取水印照片,参考PS的方式,与原图对比稀释掉水印,这种方式有两大缺点:

(1)针对图像色彩丰富,尤其深色系效果明显;

(2)目前大部分水印为灰色较多,这种方式只针对灰色水印。

本文参考了麦拂沙博主的文章,同时转用了该文章的图片,非常感谢。

基于Flask框架实现网页上传图片 

打开网页输入以下网址:127.0.0.1:5000,这是来源于后面代码app.run(host='0.0.0.0', port=5000, debug=True)。

基于Python实现网页版之复杂图片去水印

基于Python实现网页版之复杂图片去水印

                                                                                                                                         水印原图

代码解析:

(1)Flask框架搭建

新建qushuiyin.py文件,在该文件下输入以下代码。

from flask import Flask, render_template, request, redirect, url_for, make_response, jsonify
from werkzeug.utils import secure_filename
import os
import cv2
import time
import numpy as np
from PIL import Image

from datetime import timedelta

# 设置允许的文件格式
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS


app = Flask(__name__)
# 设置静态文件缓存过期时间
app.send_file_max_age_default = timedelta(seconds=1)


# @app.route('/upload', methods=['POST', 'GET'])
@app.route('/', methods=['POST', 'GET'])  # 添加路由
def upload():
    if request.method == 'POST':
        f = request.files['file']

        if not (f and allowed_file(f.filename)):
            return jsonify({"error": 1001, "msg": "请检查上传的图片类型,仅限于png、PNG、jpg、JPG、bmp"})

        user_input = request.form.get("name")

        basepath = os.path.dirname(__file__)  # 当前文件所在路径

        upload_path = os.path.join(basepath, './static/photo', secure_filename(f.filename))  # 注意:没有的文件夹一定要先创建,不然会提示没有该路径
        f.save(upload_path)

        return render_template('REpicture_ok.html', val1=time.time())

    return render_template('REpicture.html')


if __name__ == '__main__':
    # app.debug = True
    app.run(host='0.0.0.0', port=5000, debug=True)

(2)REpicture_ok.html和Repicture.html搭建

在当前目录下新建Repicture_ok.html和Repicture.html空白文件,输入以下代码。

#REpicture.html
<head>
    <meta charset="UTF-8">
    <title>图片右下角去水印</title>
</head>
<body>
    <h1>请上传图片文件</h1>
    <form action="" enctype='multipart/form-data' method='POST'>
        <input type="file" name="file" style="margin-top:20px;"/>
        <br>
        <input type="submit" value="去水印" class="button-new" style="margin-top:15px;"/>
    </form>
</body>
</html>
#REpicture_ok.html
<head>
    <meta charset="UTF-8">
    <title>图片右下角去水印</title>
</head>
<body>
    <h1>请上传图片文件</h1>
    <form action="" enctype='multipart/form-data' method='POST'>
        <input type="file" name="file" style="margin-top:20px;"/>
        <br>
        <input type="submit" value="去水印" class="button-new" style="margin-top:15px;"/>
    </form>
    <img src="{{ url_for('static', filename= './photo/result.jpg',_t=val1) }}" width="400" height="400" alt="你的图片被外星人劫持了~~"/>
</body>
</html>

注意:filename= './photo/result.jpg',路径要描述准确,否则会报错。

(3)得到反色水印图

原理是借鉴PS软件去水印方式,通过HSV提取出反色水印图,代码及执行结果如下:

在qushuiyin.py里f.save(upload_path)代码后接着输入以下代码:

        src = cv2.imread(upload_path)
        rows, cols, channels = src.shape
        hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
        low_hsv = np.array([0, 0, 46])
        high_hsv = np.array([20, 70, 200])
        mask = cv2.inRange(hsv, low_hsv, high_hsv)
        erode = cv2.erode(mask, None, iterations=1)
        dilate = cv2.dilate(erode, None, iterations=1)
        for i in range(rows):
            for j in range(cols):
                if dilate[i, j] != 255:  # 像素点255表示白色
                    src[i, j] = (255, 255, 255)  # 此处替换颜色,为BGR通道,不是RGB通道

        img = cv2.imwrite("new.png", src)

基于Python实现网页版之复杂图片去水印

说明:

如何获取 low_hsv, high_hsv两个数组的值:

第一种方式:可以参考一下下表

基于Python实现网页版之复杂图片去水印

第二种方式:新建一个PicNum.py的文件,输入以下代码运行(注意修改图片路径),会得到一个HSV图,鼠标左键点击你需要的地方,软件上会显示出HSV值,可以参考。

import numpy as np
import cv2

src = cv2.imread("./static/3.jpg")  # 用PIL中的Image.open打开图像
rows,cols,channels = src.shape
hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
def getpos(event,x,y,flags,param):
    if event==cv2.EVENT_LBUTTONDOWN: #定义一个鼠标左键按下去的事件
       print(hsv[y,x])
cv2.imshow('imageHSV',hsv)
cv2.setMouseCallback("imageHSV",getpos)
cv2.waitKey(0)
cv2.destroyAllWindows()

(4)实现复杂图片去水印

在上面代码的后面接着输入:

        src = cv2.imread(upload_path)
        newImg = cv2.imread("new.png")
        save = np.zeros(src.shape, np.uint8)  # 创建一张空图像用于保存
        for row in range(src.shape[0]):
            for col in range(src.shape[1]):
                for channel in range(src.shape[2]):
                    if newImg[row, col, channel] == 0:
                        val = 0
                    else:
                        reverse_val = 255 - src[row, col, channel]
                        val = 255 - reverse_val * 256 / newImg[row, col, channel]
                        if val < 0: val = 0

                    save[row, col, channel] = val

        dst = cv2.inpaint(save, mask, 3, cv2.INPAINT_TELEA)
        cv2.imwrite(os.path.join(basepath, './static/photo', 'result.jpg'), dst)
        #os.remove(os.path.join(basepath, './static/photo', 'new.png'))

给大家看看执行效果:

基于Python实现网页版之复杂图片去水印

总结:

本文讲述的去复杂图片的水印,我觉得效果还可以,相比于通过PS软件获得反色水印图要简便快捷一些,虽然效果称不上完美,但是相比于AI训练方式也要简便快捷好多,同时还可以应用于服务器上。

最后我想留下一个问题,如果能点击获得原图的HSV值,是否可以实现橡皮擦工具,也就是可以实现点击就能去掉水印,这个问题留待以后有时间研究一下。

上一篇:读取yuv分量|matlab


下一篇:[opencv完整项目详解] 传统图像算法解决路标的检测和识别