iconfinder 图标去水印
目标
去除 iconfinder 上 icon 的水印
原理
利用水印像素点和原图像素点颜色合并的原理,如果拥有加过水印的图片和水印图片,就可以反向推出原图原像素点的颜色;前提是你得拥有他的水印图片
1、制作水印图片
我们先从iconfinder上找两张图片(保证纯水印的区域互补,可以合成一个完整的水印图),用这两张图片的两个部分,合成一张完整的水印图片,最终 256x256的水印是长这个样子的
2、减去水印
2.1、水印是怎么加上去的
两个透明色的合并,颜色我们使用 rgba 来表示,看一下透明度的推导过程
第一块玻璃透明度是0.2,第二块玻璃透明度是0.5, 一束光通过两块玻璃后通过的光是多少
\$(1 - 0.2) \times (1 - 0.5)\$
按照上面的推理,可以得到下面的公式
两个透明色的合并
\$\alpha_t = 1 - (1 - \alpha_o)(1 - \alpha_w)
\alpha_t = \alpha_o + \alpha_w - \alpha_o\alpha_w\$
反推一下,已知α_t和α_w的情况下求α_o
\$\alpha_o = \frac{\alpha_t - \alpha_w}{1 - \alpha_w}\$
从公式能看出来,如果水印是完全不透明的,那原来的透明度是求不出来的
rbg 3个通道的颜色计算方式,用上面求出的α_o 值代入,求得R_o
\$R_t\alpha_t = R_o\alpha_o(1 - \alpha_w) + R_w\alpha_w\$
\$R_o = \frac{R_t\alpha_t - R_w\alpha_w}{\alpha_o(1 - \alpha_w)}\$
\$R_o = \frac{R_t\alpha_t - R_w\alpha_w}{\alpha_o(1 - \alpha_w)}\$
从公式能看出来,如果水印是完全不透明的,那原来的颜色是求不出来的
把加过水印的图和水印对应位置的像素进行逐个对比,如果水印位置是全透明的,则像素点的颜色不变,否则根据上面的公式反向计算出原来图片该像素点的颜色;
3、代码实现
# 安装依赖包
pip install pillow
from PIL import Image
import argparse
import os
def calc_pixel(input_rgba, watermark_rgba):
watermark_red, watermark_green, watermark_blue, watermark_alpha = watermark_rgba
if watermark_alpha == 255:
return watermark_rgba
input_red, input_green, input_blue, input_alpha = input_rgba
output_alpha = 255 * (input_alpha - watermark_alpha) / (255 - watermark_alpha)
if output_alpha == 0:
return 0, 0, 0, 0
output_red = 255 * (input_red * input_alpha - watermark_red * watermark_alpha) / \
((255 - watermark_alpha) * output_alpha)
output_green = 255 * (input_green * input_alpha - watermark_green * watermark_alpha) / \
((255 - watermark_alpha) * output_alpha)
output_blue = 255 * (input_blue * input_alpha - watermark_blue * watermark_alpha) / \
((255 - watermark_alpha) * output_alpha)
return round(output_red), round(output_green), round(output_blue), round(output_alpha)
def remove_watermark(input_name, watermark_name, output_name):
if not os.path.exists(input_name):
print("图片不存在")
return
input_image = Image.open(input_name)
watermark_image = Image.open(watermark_name)
output_image = Image.new(input_image.mode, input_image.size)
w, h = input_image.size
for x in range(w):
for y in range(h):
watermark_rgba = watermark_image.getpixel((x, y))
input_rgba = input_image.getpixel((x, y))
output_rgba = calc_pixel(input_rgba, watermark_rgba)
output_image.putpixel((x, y), output_rgba)
output_image.save(output_name)
def output_path_or_default(input_path, output_path):
if output_path:
return output_path
root, ext = os.path.splitext(input_path)
return root + ".unmark" + ext
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = "watermark remover for iconfiner")
parser.add_argument("--output", dest = "output", help = "output image")
parser.add_argument("input", help = "input image")
args = parser.parse_args()
output = output_path_or_default(args.input, args.output)
remove_watermark(args.input, "watermark.png", output)
4、引用
浏览 30566 次
禁止转载