获取某个文件夹下自己想要的文件格式(包括子文件夹下的)
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)