soarli

边缘像素点透明度自动化处理方案
今天下午,CaprYang(温春阳学长)解决了一个layui官方都没能解决的问题:png边缘像素点透明化处理(如果...
扫描右侧二维码阅读全文
21
2021/09

边缘像素点透明度自动化处理方案

今天下午,CaprYang(温春阳学长)解决了一个layui官方都没能解决的问题:png边缘像素点透明化处理(如果用ps生硬的选出则因边缘像素点偏向于白色而无法巧妙地适配深色模式)。于是官方索性对图形上半部分不做任何处理给了个白色背景,仅对下半部分做了透明化处理。

图片位置“layui/dist/css/modules/layer/default/icon.png

接下来就是图形处理过程了。

原始图片

icon.png

处理代码

1.0

import cv2 as cv

base = [255, 255, 255] # BGR

def area(x, y): # 输入像素位置 返回纯色BGR
    if x < 30:
        if y < 30:
            return [18, 155, 243]
        if y < 60:
            return [155, 186, 0]
        if y < 90:
            return [69, 84, 232]
        if y < 120:
            return [0, 197, 244]
        if y < 150:
            return [120, 120, 120]
        if y < 180:
            return [59, 75, 231]
        if y < 210:
            return [109, 205, 17]
    return None # 不在区域

def alpha(color, dot, base): # 传入纯色 当前像素颜色 底色 计算透明度
    dis, sum = [], 0
    for i in range(3): # 三通道
        dis.append(abs(color[i] - base[i]))
        sum += abs(color[i] - base[i])
    a = 0
    for i in range(3):
        w = dis[i] / sum
        aa = (dot[i] - base[i]) / (color[i] - base[i])
        a += aa * w
    return min(int(a * 255 + 0.5), 255)

img = cv.imread("icon.png", cv.IMREAD_UNCHANGED) # 读取带透明度
b, g, r, a = cv.split(img)
print(img.shape)

for x in range(img.shape[0]):
    for y in range(img.shape[1]):
        color = area(x, y)
        if color == None:
            continue
        print(img[x, y])
        a = alpha(color, img[x, y][:-1], base)
        img[x, y][2] = a

cv.imwrite("icon.out.png", img)

经过了一番处理:

这实在是够细节的!

于是有了2.0

import cv2 as cv

base = [255, 255, 255] # 背景色 BGR

def area(x, y): # 输入像素位置 返回纯色BGR
    if x < 30:
        if y < 30:
            return [18, 155, 243]
        if y < 60:
            return [155, 186, 0]
        if y < 90:
            return [69, 84, 232]
        if y < 120:
            return [0, 197, 244]
        if y < 150:
            return [120, 120, 120]
        if y < 180:
            return [59, 75, 231]
        if y < 210:
            return [109, 205, 17]
    return None # 不在区域

def alpha(color, dot, base): # 传入纯色 当前像素颜色 底色 计算透明度
    dis, sum = [], 0
    for i in range(3): # 三通道
        dis.append(abs(color[i] - base[i]))
        sum += abs(color[i] - base[i])
    a = 0
    for i in range(3):
        w = dis[i] / sum
        aa = (dot[i] - base[i]) / (color[i] - base[i])
        a += aa * w
    return int(a * 255 + 0.5)

img = cv.imread("icon.png", cv.IMREAD_UNCHANGED) # 读取带透明度
print(img.shape)

for x in range(img.shape[0]):
    for y in range(img.shape[1]):
        color = area(x, y)
        if color == None:
            continue
        print(img[x, y])
        a = alpha(color, img[x, y][:-1], base)
        img[x, y] = color + [a] # 纯色+透明度

cv.imwrite("icon.out.png", img)

代码说明

最终成果

处理后的图片

icon.out.png

打包下载

icon.zip

没有一点白边了!

补充:三原色图片
1024px-AdditiveColorMixing.svg.png

最后修改:2021 年 09 月 22 日 01 : 22 AM

发表评论