Python之PIL【持续更新填补】

在这里插入图片描述

PIL

Image

  • 坐标值:整型int或浮点型float

  • size:Image是(宽,高),np.shape是(高, 宽)

    • Image.open(img).size=(宽, 高)

    • cv2.imread(img).shape=(高, 宽, 通道数)

    • imageio.v3.imread(uri=img).shape=(高, 宽, 通道数)

  • Image转Array

    from PIL import Image
    import cv2
    import numpy as np
    
    # 打开PIL图像
    img_pil = Image.open('image.jpg')
    
    # 将PIL图像转换为NumPy数组
    imgread = np.array(img_pil)
    
    # 如果PIL图像是RGBA模式(包含透明通道),需要将其转换为RGB模式
    if imgread.shape[2] == 4:
        imgread = cv2.cvtColor(imgread, cv2.COLOR_RGBA2BGR)
    
    cv2.imwrite('new_image.jpg', imgread)
    
from PIL import Image

# 打开图像
img_pil = Image.open(image_file)  # 或 请求url -> 获取`图片二进制字节流` -> BytesIO将二进制字节流转为io流 = Image.open(BytesIO(requests.get(url).content))

# 创建图像 Image.new(mode, size, color=0)
# w=100,h=100的黑色三通道的图片
img_new = Image.new(mode="RGB", size=(100, 100), color=0)

# 显示图像
img_pil.show()

# 保存图像
img_pil.save(image_file)
  • Image.open(fp, mode="r", formats=None):读取图片。打开并标识给定的映像文件。

    • fp:路径对象或文件对象。
    • mode:模式。必须是“r”。
  • img_pil.convert(mode=None, matrix=None, dither=None, palette=Palette.WEB, colors=256)

    • mode:请求的模式。PIL有九种不同模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。

      • img_pil.convert('1'):二值图像,非黑即白。每个像素用8个bit表示,0表示黑,255表示白。

      • img_pil.convert('L'):灰度图像,每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。

        模式RGB到L的转换公式:L = R * 0.299 + G * 0.587 + B * 0.114。  
        
      • img_pil.convert('P'):8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。

      • img_pil.convert("RGBA"):32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道

      • img_pil.convert("CMYK"):32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。四种标准颜色是:C:Cyan = 青色,又称为天蓝色或湛蓝;M:Magenta = 品红色,又称为洋红色;Y:Yellow = 黄色;K:Key Plate(blacK) = 定位套版色(黑色)。

      • img_pil.convert("YCbCr"):为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。

        模式RGB到YCbCr的转换公式:\\ 
        Y = 0.257R+0.504G+0.098B+16 \\ Cb = -0.148R-0.291G+0.439B+128 \\ Cr = 0.439R-0.368G-0.071*B+128 ```
        
      • img_pil.convert("I"):32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。

        模式RGB到I的转换公式:I = R * 0.299 + G * 0.587 + B * 0.114  
        
      • img_pil.convert("F"):32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。

        模式RGB到F的转换公式:F = R * 0.299 + G * 0.587 + B * 0.114  
        
    • matrix:可选的转换矩阵。如果给定,则应为包含浮点值的4元组或12元组。

    • dither:抖动方法,在模式“RGB”转换为“P”“ RGB”或“ L”转换为“1”时使用。可用的方法有:data:NONE或data:FLOYDSTEINBERG(默认)。请注意,在提供matrix参数时不使用此选项

    • palette:从模式“RGB”转换为“P”时使用的调色板。可用的调色板是WEB或ADAPTIVE。

    • colors:用于“ ADAPTIVE”调色板的颜色数。 默认值为256。

  • img_pil.size:获取图片尺寸(x, y),即(w, h)

  • img_pil.width:获取图片宽度

  • img_pil.height:获取图片高度

  • img_pil.getbands():获取通道。len(img_pil.getbands())获取通道数。

    # 获取通道数len(img_pil.getbands()) -> len(('R', 'G', 'B')) / len(('L'))
    print(len(img_pil.getbands()))  
    
  • img_pil.rotate(angle, resample=Resampling.NEAREST, expand=0, center=None, translate=None, fillcolor=None):旋转图片。angle表示要旋转的角度,角度制。

  • img_pil.resize(size, resample=None, box=None, reducing_gap=None):调整图像大小。

  • img_pil.paste(im, box=None, mask=None):将paste方法中,传入的图像粘贴在原图像上。

    obj.paste(im, box=None, mask=None)
    
    # 将一张图img2粘贴到另一张图像img1上, box=(左上x, 左上y, 右下x, 右下y)
    img1 = Image.new("RGB",(100, 100))
    img2 = Image.new("RGB",(20, 20, 40, 40),"red")
    img1.paste(img2,(20, 20, 40, 40))
    
    # 将图像img中的box改成color色
    img = Image.new("RGB", (100,100)).paste(color="red", box=(10,10,30,30))
    
    # 不是很清楚mask的使用:利用mask,首先将被paste图像先与mask图像“相乘”,规定0为黑色,1为白色,再将“乘积”paste到目标图像
    
  • img_pil.show():显示图片。

  • img_pil.save(fp, format=None, **params):保存图片。

    • fp:路径对象或文件对象。
    img_pil.save("to.jpg")
    

ImageFont

load()

ImageFont.load(file)
  • 从指定的文件中加载一种字体,该函数返回对应的字体对象。如果该函数失败,将产生IOError异常。

load_path()

ImageFont.load_path(file)
  • 和函数load()一样,但是如果没有指定当前路径的话,会从sys.path开始查找指定的字体文件。

truetype()

ImageFont.truetype(file,size, encoding=value)
  • 加载一个TrueType或者OpenType字体文件,并且创建一个字体对象。

    • file:字体路径

    • size:字号

    • encoding:指定编码方式创建一个字体对象。通常的编码方式有“unic”(Unicode),“symb”(Microsoft Symbol),“ADOB”(Adobe Standard),“ADBE”(Adobe Expert)和“armn”(Apple Roman)

font = ImageFont.truetype("symbol.ttf", 16, encoding="symb")
draw.text((0, 0), unichr(0xF000 + 0xAA))

ImageFont对象的方法

obj.getsize()
font.getsize(text)
  • 返回给定文本的宽度和高度(width, height),返回值为2元组。
obj.getmask()
font.getmask(text,mode="")
  • 为给定的文本返回一个位图(Image object)。这个位图是PIL内部存储内存的实例(为Image.core接口模块定义);
  • 如果字体使用了抗锯齿,位图的模式为“L”,且其最大值为255。否则,它的模式为“1”;
  • 可选参数mode用于一些显卡驱动指定自己喜欢的模式;如果为空,渲染器可能会返回任意模式。注意:该模式总是一个字符串。

ImageDraw

from PIL import ImageDraw

# 绘制图片
draw = ImageDraw.Draw(img_pil)  # 或 draw = ImageDraw.ImageDraw(img_pil)
  • 参数

    • fill:线条或中间区域填充颜色,‘red’、(255,0,0)、‘#FF0000’、125等。ImageColor 中的颜色表达方式。方法可设置outline参数时,fill为内部区域填充颜色,否则为线条颜色。

    • outline:轮廓线条颜色。

    • width:线条宽度,单位pixels。

● 圆/圆弧

draw.arc(xy, start, end, fill=None, width=1)
# todo 在给定的边界(左,上,右,下)内绘制圆弧。圆弧使用 fill颜色 和 width宽度的线条从start角度开始到end角度结束
# xy:定义边界(圆弧满圆外接矩形框左上xy右下xy)的坐标[(x0, y0), (x1, y1)] or [x0, y0, x1, y1]
# start:起始角度,单位度。 角度从水平位置右方开始,顺时针方向为正。
# end:结束角度。

# (0, 0, 100, 100)矩形框的内切圆,圆心(50, 50),半径为50,起始角度即起始点为(100, 50)顺时针旋转360度
draw.arc((0, 0, 100, 100), start=0, end=360, fill='red', width=3)

● 位图

draw.bitmap(xy, bitmap, fill=None)
# todo 根据bitmap为蒙版从(x,y)位置开始填充fill颜色。与Image.paste(im, box, mask) 方法类似,paste 填充图像,bitmap 填充颜色。
# xy:起始坐标,( x , y )
# bitmap:作为蒙版的图像。必须是含透明图 mode=1 或能做遮罩的 mode (L or RGBA)

● 弦

draw.chord(xy, start, end, fill=None, outline=None, width=1)

# 类似draw.arc(),但会将绘制的弧两个端点链接起来,outline是线的颜色,fill是内部填充颜色
draw.chord(xy=(0, 0, 100, 100), start=0, end=90, fill=None, outline="#FF0000")

● 椭圆

draw.ellipse(xy, fill=None, outline=None, width=1)
# xy:椭圆外接矩形框的左上xy右下xy,**画圆形(外接矩形w==h)**

# 画椭圆
draw.ellipse(xy=(x1, y1, x2, y2), fill="yellow", outline="red", width=1)

# 画圆
draw.ellipse(xy=(x1, y1, x1+3, y1+3), fill=(255, 255, 0), outline=(255, 0, 0), width=1)

● 线/折线

draw.line(xy, fill=None, width=0, joint=None)
# todo 在xy列表中的坐标之间绘制一条线。
# xy:点与点之间坐标,[(x0, y0), (x1, y1),...] or [x0, y0, x1, y1,....]
# joint:线之间的联合类型,如:curve圆角。


# 画一个以差值为10的白色网格
diff_value = 10
for next_diff_value in range(diff_value, img_pil.width, diff_value):  # 竖线
    fill = "black" if next_diff_value / 100 == next_diff_value // 100 else "white"  # 每满100线条改为黑色
    draw.line(xy=[(next_diff_value, 0), (next_diff_value, img_pil.height)], fill=fill, width=0, joint=None)
for next_diff_value in range(diff_value, img_pil.height, diff_value):  # 横线
    fill = "black" if next_diff_value / 100 == next_diff_value // 100 else "white"
    draw.line(xy=[(0, next_diff_value), (img_pil.width, next_diff_value)], fill=fill, width=0, joint=None)

# 画折线
draw.line(xy=[(10, 10), (20, 20), (30, 30), (20, 40)], fill="red", width=3, joint="curve")

● 形状

draw.shape(shape, fill=None, outline=None)

● 扇形图

draw.pieslice(xy, start, end, fill=None, outline=None, width=1)
# xy:定义边界的坐标[(x0, y0), (x1, y1)] or [x0, y0, x1, y1],
# start:起始角度,单位度。 角度从水平位置右方开始,顺时针方向为正。
# end:结束角度

draw.pieslice((0, 0) + obj.size , start=0, end=300, outline="#FF0000",fill='#FFFFFF',width=1)

● 点

draw.point(xy, fill=None)

draw.point(xy=(x1, y1), fill="red")

● 多边形/正多边形

# 多边形
draw.polygon(xy, fill=None, outline=None, width=1)

# 正多边形
draw.regular_polygon(bounding_circle, n_sides, rotation=0, fill=None, outline=None)

● 矩形/圆角矩形

# 矩形
draw.rectangle(xy, fill=None, outline=None, width=1)

# 圆角矩形
draw.rounded_rectangle(xy, radius=0, fill=None, outline=None, width=1)

● 文本

draw.text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False, *args, **kwargs)
# xy:文字的左上角位置
# text:文本. 如果包含换行符需将文本传递给 multiline_text()
# fill:文字颜色
# font:字体,需要时 ImageFont 实例。
# spacing:如果文本传递给multiline_text(),则为行之间的像素数。
# align:对齐方式,如果文本传递给multiline_text(), 值有"left","center","right"。
# direction:文字方向。'rtl'(从右到左),'ltr'(从左到右)或'ttb'(从上到下)
# features:在文本布局期间使用的OpenType字体功能列表。通常用于打开默认情况下未启用的可选字体功能,如'dlig'或'ss01';也可用于关闭默认字体功能,例如'-liga'以禁用连字或'-kern'禁用字距调整。参阅:https://learn.microsoft.com/en-us/typography/opentype/spec/featurelist
# 设置字体,将字体库复制到当前目录
font = ImageFont.truetype('font_path', 32)  # 字体路径,字号
# 填充文字
draw.text(xy=(10,10), text="text", font=font, fill="#FFFFFF")


draw.multiline_text(xy, text, fill=None, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False)
# 绘制带换行的文字
draw.multiline_text((10,10), "Hello,nwoodman", font=font, fill="#FFFFFF")

draw.textsize(text, font=None, spacing=4, direction=None, features=None, language=None, stroke_width=0)
# 获取文字的大小,(width, height)
# text:文本. 如果包含换行符需将文本传递给 multiline_textsize()
# font:字体,需要时 ImageFont 实例。
# spacing:如果文本传递给multiline_textsize(),则为行之间的像素数。
# direction:文字方向。'rtl'(从右到左),'ltr'(从左到右)或'ttb'(从上到下)
# features:在文本布局期间使用的OpenType字体功能列表。通常用于打开默认情况下未启用的可选字体功能,如'dlig'或'ss01';也可用于关闭默认字体功能,例如'-liga'以禁用连字或'-kern'禁用字距调整。

draw.multiline_textsize(text, font=None, spacing=4, direction=None, features=None, language=None, stroke_width=0)


draw.textlength(text, font=None, direction=None, features=None, language=None, embedded_color=False)


draw.textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False)

draw.multiline_textbbox(xy, text, font=None, anchor=None, spacing=4, align="left", direction=None, features=None, language=None, stroke_width=0, embedded_color=False)

ImageStat

def get_image_light_mean(dst_src):
    # 转换图像到灰度,返回平均像素亮度
    im = Image.open(dst_src).convert('L')
    stat = ImageStat.Stat(im)
    return stat.mean[0]


def get_image_light_rms(dst_src):
    # 转换图像到灰度,返回RMS像素亮度
    im = Image.open(dst_src).convert('L')
    stat = ImageStat.Stat(im)
    return stat.rms[0]


def get_image_light_mean_sqrt(dst_src):
    # 平均像素,然后转换为“可感知的亮度”
    im = Image.open(dst_src)
    stat = ImageStat.Stat(im)
    r, g, b = stat.mean
    return math.sqrt(0.241 * (r ** 2) + 0.691 * (g ** 2) + 0.068 * (b ** 2))


def get_image_light_rms_sqrt(dst_src):
    # 像素的均方根,然后转换为“感知亮度”
    im = Image.open(dst_src)
    stat = ImageStat.Stat(im)
    r, g, b = stat.rms
    return math.sqrt(0.241 * (r ** 2) + 0.691 * (g ** 2) + 0.068 * (b ** 2))


def get_image_light_gs(dst_src):
    # 计算像素的“感知亮度”,然后返回平均值
    im = Image.open(dst_src)
    stat = ImageStat.Stat(im)
    gs = (math.sqrt(0.241 * (r ** 2) + 0.691 * (g ** 2) + 0.068 * (b ** 2))
          for r, g, b in im.getdata())
    return sum(gs) / stat.count[0]
  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值