专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Python 相关实战

获取某个文件夹下自己想要的文件格式(包括子文件夹下的)

import os

def is_image_file(filename,want_list):
    return (filename.lower().endswith(want) for want in want_list)

"""
功能:获取某个文件夹下的相关的文件格式(包括文件夹里的子文件夹里的文件格式)
file_name : 文件夹地扯,如:E:/images
want_list : 想要输出的文件格式,如:['.png','.jpg']
"""
def get_img_file(file_name,want_list):
    image_list = [] # 用于保存图片地扯

    """
    parent为文件夹路径,相当于file_name,
    dirnames为该文件夹里的文件夹,是一个列表
    filenames为该文件夹下的文件,是一个列表

    os.walk() 方法用于通过在目录树中游走输出在目录中的文件名,向上或者向下。
    os.walk() 方法是一个简单易用的文件、目录遍历器,可以帮助我们高效的处理文件、目录方面的事情。
    """
    for parent, dirnames, filenames in os.walk(file_name):
        # 判断该文件夹下是否还有文件夹
        for dirname in dirnames:
            # 重新拼接好一个新的文件夹路径
            new_file_name = file_name+'/'+dirname
            # 重新调起获取图片地扯
            if get_img_file(new_file_name, want_list) is not None:
                for file in get_img_file(new_file_name, want_list):
                    image_list.append(file)
        # 遍历该文件夹下的图片并保存到imagelist列表中
        for filename in filenames:
            # 判断文件的后缀是否存在,如存在就保存在image_list中
            if is_image_file(file_name,want_list):
                image_list.append(os.path.join(parent, filename))
        return image_list

if __name__ == '__main__':
    file_name = 'E:/download'
    want_list = ['.png', '.jpg', '.jpeg', '.PNG', '.JPG', '.JPEG','.txt']
    arr = get_img_file(file_name,want_list)
    print(arr)

request+open保存网络图片在本地

    import requests,uuid
    link = '网络图片地扯url'
    # 第一步:获取文件
    img_response = requests.get(link)
    # 第二步:设文件名
    filename = str(uuid.uuid4()) + '.jpg'
    # 第三步:保存文件
    with open(filename,'wb') as f:
        f.write(img_response.content)

图片实战操作

本地图片透明背景转白色

from PIL import Image

def transparence2white(img):
    # img=img.convert('RGBA')  # 此步骤是将图像转为灰度(RGBA表示4x8位像素,带透明度掩模的真彩色;CMYK为4x8位像素,分色等),可以省略
    sp = img.size
    width = sp[0]
    height = sp[1]
    print(sp)
    for yh in range(height):
        for xw in range(width):
            dot = (xw, yh)
            color_d = img.getpixel(dot)  # 这里需要用getpixel方法来获取维度数据
            if (color_d[3] == 0):
                color_d = (255, 255, 255, 255)
                img.putpixel(dot, color_d)  # 赋值的方法是通过putpixel
    return img

if __name__ == '__main__':
    img = Image.open('bar.png')
    img = transparence2white(img)
    # img.show()  # 显示图片
    img.save('bar.png')  # 保存图片

或者采用以下的方式:

import cv2

# 修改透明背景为白色
def transparence2white(img):
    sp=img.shape  # 获取图片维度
    width=sp[0]  # 宽度
    height=sp[1]  # 高度
    for yh in range(height):
        for xw in range(width):
            color_d=img[xw,yh]  # 遍历图像每一个点,获取到每个点4通道的颜色数据
            if(color_d[3]==0):  # 最后一个通道为透明度,如果其值为0,即图像是透明
                img[xw,yh]=[255,255,255,255]  # 则将当前点的颜色设置为白色,且图像设置为不透明
    return img

img=cv2.imread('bar.png',-1)  # 读取图片。-1将图片透明度传入,数据由RGB的3通道变成4通道
img=transparence2white(img)  # 将图片传入,改变背景色后,返回
cv2.imwrite('bar.png',img)  # 保存图片,文件名自定义,也可以覆盖件

图片png或jpg格式转换成svg格式

第一种做法:image

这种是在svg里存储base64的图像。

import base64,uuid
from PIL import Image

def img_to_base64(image):
    with open(image, 'rb') as f:
        image = f.read()
        image_base64 = str(base64.b64encode(image), encoding='utf-8')
    return image_base64

def img_to_svg(img_base64, width, height):
    img_str = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' + '\n' + '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
    svg_start = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="{width}px" height="{height}px" viewBox="0 0 {width} {height}" enable-background="new 0 0 {width} {height}" xml:space="preserve">'.format(
        width=width, height=height)
    svg_end = '</svg>'
    image_str = '<image id="image0" width="{width}" height="{height}" x="0" y="0" xlink:href="data:image/png;base64,{base64}" />'.format(
        width=width, height=height, base64=img_base64)
    res_str = img_str + '\n' + svg_start + '\n' + image_str + '\n' + svg_end
    return res_str

def write_svg(content):
    svg_filename = str(uuid.uuid1()) + '.svg'
    with open(svg_filename, 'w') as f:
        f.write(content)

if __name__ == '__main__':
    image = 'deee.png'
    img = Image.open(image)
    width, height = img.size
    image_base64 = img_to_base64(image)
    res = img_to_svg(image_base64, width, height)
    write_svg(res)

上面的源码,我是参照

通过上传png的图片到上面的两个链接中,然后分别下载转化后的svg图片,通过查看svg的源码可以发现里面是把png或jpg的图片进行base64转化后,然后保存到svg中的。

第二种做法

import sys
import os
from PIL import Image

def convertPixel(r, g, b, a=1):
    color = "#%02X%02X%02X" % (r, g, b)
    opacity = a
    return (color, opacity)

for r in sys.argv[1:]:
    root, ext = os.path.splitext(r)

    image = Image.open(r)
    mode = image.mode
    pixels = image.load()
    width, height = image.size
    print(height)
    print(mode)

    if "RGB" in mode:
        output = "<svg width='%d' height='%d' viewBox='0 0 %d %d' xmlns='http://www.w3.org/2000/svg'>" % (
        width, height, width, height)

        for r in range(height):
            for c in range(width):
                color, opacity = convertPixel(*pixels[c, r])
                output += "<rect x='%d' y='%d' width='1' height='1' fill='%s' fill-opacity='%s' />" % (
                c, r, color, opacity)
        output += "</svg>"
        # 写入文件svg
        with open(root + '.svg', 'w') as f:
            f.write(output)

这种做法有一个缺点:转化出来的svg文件有点大。

第三种:路径的svg

import turtle as te
from bs4 import BeautifulSoup
import argparse
import sys
import numpy as np
import cv2
import os

WriteStep = 15  # 贝塞尔函数的取样次数
Speed = 1000
Width = 600  # 界面宽度
Height = 600  # 界面高度
Xh = 0  # 记录前一个贝塞尔函数的手柄
Yh = 0
scale = (1, 1)
first = True
K = 32

def Bezier(p1, p2, t):  # 一阶贝塞尔函数
    return p1 * (1 - t) + p2 * t

def Bezier_2(x1, y1, x2, y2, x3, y3):  # 二阶贝塞尔函数
    te.goto(x1, y1)
    te.pendown()
    for t in range(0, WriteStep + 1):
        x = Bezier(Bezier(x1, x2, t / WriteStep),
                   Bezier(x2, x3, t / WriteStep), t / WriteStep)
        y = Bezier(Bezier(y1, y2, t / WriteStep),
                   Bezier(y2, y3, t / WriteStep), t / WriteStep)
        te.goto(x, y)
    te.penup()

def Bezier_3(x1, y1, x2, y2, x3, y3, x4, y4):  # 三阶贝塞尔函数
    x1 = -Width / 2 + x1
    y1 = Height / 2 - y1
    x2 = -Width / 2 + x2
    y2 = Height / 2 - y2
    x3 = -Width / 2 + x3
    y3 = Height / 2 - y3
    x4 = -Width / 2 + x4
    y4 = Height / 2 - y4  # 坐标变换
    te.goto(x1, y1)
    te.pendown()
    for t in range(0, WriteStep + 1):
        x = Bezier(Bezier(Bezier(x1, x2, t / WriteStep), Bezier(x2, x3, t / WriteStep), t / WriteStep),
                   Bezier(Bezier(x2, x3, t / WriteStep), Bezier(x3, x4, t / WriteStep), t / WriteStep), t / WriteStep)
        y = Bezier(Bezier(Bezier(y1, y2, t / WriteStep), Bezier(y2, y3, t / WriteStep), t / WriteStep),
                   Bezier(Bezier(y2, y3, t / WriteStep), Bezier(y3, y4, t / WriteStep), t / WriteStep), t / WriteStep)
        te.goto(x, y)
    te.penup()

def Moveto(x, y):  # 移动到svg坐标下(x,y)
    te.penup()
    te.goto(-Width / 2 + x, Height / 2 - y)
    te.pendown()

def Moveto_r(dx, dy):
    te.penup()
    te.goto(te.xcor() + dx, te.ycor() - dy)
    te.pendown()

def line(x1, y1, x2, y2):  # 连接svg坐标下两点
    te.penup()
    te.goto(-Width / 2 + x1, Height / 2 - y1)
    te.pendown()
    te.goto(-Width / 2 + x2, Height / 2 - y2)
    te.penup()

def Lineto_r(dx, dy):  # 连接当前点和相对坐标(dx,dy)的点
    te.pendown()
    te.goto(te.xcor() + dx, te.ycor() - dy)
    te.penup()

def Lineto(x, y):  # 连接当前点和svg坐标下(x,y)
    te.pendown()
    te.goto(-Width / 2 + x, Height / 2 - y)
    te.penup()

def Curveto(x1, y1, x2, y2, x, y):  # 三阶贝塞尔曲线到(x,y)
    te.penup()
    X_now = te.xcor() + Width / 2
    Y_now = Height / 2 - te.ycor()
    Bezier_3(X_now, Y_now, x1, y1, x2, y2, x, y)
    global Xh
    global Yh
    Xh = x - x2
    Yh = y - y2

def Curveto_r(x1, y1, x2, y2, x, y):  # 三阶贝塞尔曲线到相对坐标(x,y)
    te.penup()
    X_now = te.xcor() + Width / 2
    Y_now = Height / 2 - te.ycor()
    Bezier_3(X_now, Y_now, X_now + x1, Y_now + y1,
             X_now + x2, Y_now + y2, X_now + x, Y_now + y)
    global Xh
    global Yh
    Xh = x - x2
    Yh = y - y2

def transform(w_attr):
    funcs = w_attr.split(' ')
    for func in funcs:
        func_name = func[0: func.find('(')]
        if func_name == 'scale':
            global scale
            scale = (float(func[func.find('(') + 1: -1].split(',')[0]),
                     -float(func[func.find('(') + 1: -1].split(',')[1]))

def readPathAttrD(w_attr):
    ulist = w_attr.split(' ')
    for i in ulist:
        # print("now cmd:", i)
        if i.isdigit() or i.isalpha():
            yield float(i)
        elif i[0].isalpha():
            yield i[0]
            yield float(i[1:])
        elif i[-1].isalpha():
            yield float(i[0: -1])
        elif i[0] == '-':
            yield float(i)

def drawSVG(filename, w_color):
    global first
    SVGFile = open(filename, 'r')
    SVG = BeautifulSoup(SVGFile.read(), 'lxml')
    Height = float(SVG.svg.attrs['height'][0: -2])
    Width = float(SVG.svg.attrs['width'][0: -2])
    transform(SVG.g.attrs['transform'])
    if first:
        te.setup(height=Height, width=Width)
        te.setworldcoordinates(-Width / 2, 300, Width -
                               Width / 2, -Height + 300)
        first = False
    te.tracer(100)
    te.pensize(1)
    te.speed(Speed)
    te.penup()
    te.color(w_color)

    for i in SVG.find_all('path'):
        attr = i.attrs['d'].replace('\n', ' ')
        f = readPathAttrD(attr)
        lastI = ''
        for i in f:
            if i == 'M':
                te.end_fill()
                Moveto(next(f) * scale[0], next(f) * scale[1])
                te.begin_fill()
            elif i == 'm':
                te.end_fill()
                Moveto_r(next(f) * scale[0], next(f) * scale[1])
                te.begin_fill()
            elif i == 'C':
                Curveto(next(f) * scale[0], next(f) * scale[1],
                        next(f) * scale[0], next(f) * scale[1],
                        next(f) * scale[0], next(f) * scale[1])
                lastI = i
            elif i == 'c':
                Curveto_r(next(f) * scale[0], next(f) * scale[1],
                          next(f) * scale[0], next(f) * scale[1],
                          next(f) * scale[0], next(f) * scale[1])
                lastI = i
            elif i == 'L':
                Lineto(next(f) * scale[0], next(f) * scale[1])
            elif i == 'l':
                Lineto_r(next(f) * scale[0], next(f) * scale[1])
                lastI = i
            elif lastI == 'C':
                Curveto(i * scale[0], next(f) * scale[1],
                        next(f) * scale[0], next(f) * scale[1],
                        next(f) * scale[0], next(f) * scale[1])
            elif lastI == 'c':
                Curveto_r(i * scale[0], next(f) * scale[1],
                          next(f) * scale[0], next(f) * scale[1],
                          next(f) * scale[0], next(f) * scale[1])
            elif lastI == 'L':
                Lineto(i * scale[0], next(f) * scale[1])
            elif lastI == 'l':
                Lineto_r(i * scale[0], next(f) * scale[1])
    te.penup()
    te.hideturtle()
    te.update()
    SVGFile.close()

def drawBitmap(w_image):
    print('Reducing the colors...')
    Z = w_image.reshape((-1, 3))

    # convert to np.float32
    Z = np.float32(Z)

    # define criteria, number of clusters(K) and apply kmeans()
    criteria = (cv2.TERM_CRITERIA_EPS, 10, 1.0)
    global K
    ret, label, center = cv2.kmeans(
        Z, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

    # Now convert back into uint8, and make original image
    center = np.uint8(center)
    print(center)
    res = center[label.flatten()]
    res = res.reshape(w_image.shape)
    no = 1
    for i in center:
        sys.stdout.write('\rDrawing: %.2f%% [' % (
                no / K * 100) + '#' * no + ' ' * (K - no) + ']')
        no += 1
        res2 = cv2.inRange(res, i, i)
        res2 = cv2.bitwise_not(res2)
        # print(i)
        res2 = res
        cv2.imwrite('.tmp.bmp', res2)
        # 转成矢量图,保存成.svg格式
        os.system('potrace .tmp.bmp -s --flat')
        print(i)
        drawSVG('.tmp.svg', '#%02x%02x%02x' % (i[2], i[1], i[0]))
    # os.remove('.tmp.bmp')
    # os.remove('.tmp.svg')
    print('\n\rFinished, close the window to exit.')
    te.done()

if __name__ == '__main__':
    paser = argparse.ArgumentParser(
        description="Convert an bitmap to SVG and use turtle libray to draw it.")
    paser.add_argument('filename', type=str,
                       help='The file(*.jpg, *.png, *.bmp) name of the file you want to convert.')
    paser.add_argument(
        "-c", "--color",
        help="How many colors you want to draw.(If the number is too large that the program may be very slow.)",
        type=int, default=32)
    args = paser.parse_args()
    K = args.color
    try:
        bitmapFile = open(args.filename, mode='r')
    except FileNotFoundError:
        print(__file__ + ': error: The file is not exists.')
        quit()
    if os.path.splitext(args.filename)[1].lower() not in ['.jpg', '.bmp', '.png']:
        print(__file__ + ': error: The file is not a bitmap file.')
        quit()
    bitmap = cv2.imread(args.filename)
    # if bitmap.shape[0] > 240:
    #    bitmap = cv2.resize(bitmap,(500,200))
    #    bitmap = cv2.resize(bitmap, (int(bitmap.shape[1] * (
    #        (80 - 50) / bitmap.shape[0])), 80 - 50))
    # print(bitmap.shape[1])
    drawBitmap(bitmap)

使用方式:python demo2.py -c=32 demo.jpg

参考:

注意::该程序转化后的svg是黑白的,没有了色彩。

第二种转化

环境使用ubuntu。

下载potrace

apt install potrace

参考

在线转化为svg工具

图片实际测试

生成透明图

from PIL import Image
image = Image.new(mode='RGBA', size=(410, 615))
image.save('eeeewww.png', 'PNG')  # 保存在当前路径下,格式为PNG
image.close()

合成图片

比如:我有一张透明的人像图片和一张好看的背景,我想要把人像合成到好看的背景中。

from PIL import Image
import numpy as np
import uuid

def blend_images(fore_image, base_image):
    """
    :param fore_image:前景图片,比如:抠出的人物图片
    :param base_image:背景图片,比如:一片好看的花园
    :return: 返回图片路径
    """
    # 读入图片
    base_image = Image.open(base_image).convert('RGB')
    fore_image = Image.open(fore_image).resize(base_image.size)

    # 图片加权合成
    scope_map = np.array(fore_image)[:, :, -1] / 255
    scope_map = scope_map[:, :, np.newaxis]
    scope_map = np.repeat(scope_map, repeats=3, axis=2)
    res_image = np.multiply(scope_map, np.array(fore_image)[:, :, :3]) + np.multiply((1 - scope_map),
                                                                                     np.array(base_image))
    output_path = str(uuid.uuid1()) + '.png'
    # 保存图片
    res_image = Image.fromarray(np.uint8(res_image))
    res_image.save(output_path)
    return output_path

if __name__ == '__main__':
    file_path = blend_images('./images/ddd.png', 'demo.jpg')
    print(file_path)

文章永久链接:https://tech.souyunku.com/46908

未经允许不得转载:搜云库技术团队 » Python 相关实战

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们