PIL--Pillow学习记录

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont, ImageWin


"""
Python Pillow(PIL)库的用法介绍
Pillow库是一个Python的第三方库。

在Python2中,PIL(Python Imaging Library)是一个非常好用的图像处理库,但PIL不支持Python3,所以有人(Alex Clark和Contributors)提供了Pillow,可以在Python3中使用。

官方文档路径:https://pillow.readthedocs.io/en/latest/

一、安装Pillow

pip install pillow
Pillow库安装成功后,导包时要用PIL来导入,而不能用pillow或Pillow。

import PIL
from PIL import Image
在Pillow库中,除了有二十多个模块,还支持非常多的插件。其中最常用的是Image模块中同名的Image类,其他很多模块都是在Image模块的基础上对图像做进一步的特殊处理,Image模块中会导入部分来使用。本文介绍Image模块的常用方法。

1. PIL库读图,转为numpy:np.array()

2. opencv读入的图像是BGR格式,转为RGB:img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

3. opencv保存时,路径不能是中文!!!否则不报错但是也保存不了!!!

4. 保存图片的路径:'D:/Face Recognition/CASIA-WebFace-aligned',注意是 /,\\也行,但是有个潜在的问题,利用os.path.join()后,路径会自动变成 \ 。这也不报错,但也保存不了图片!!!所以保存时要使用 / ,并且不要使用os.path.join()!!!

5. matpotlib.pyplot保存Image读入的图为jpg格式时会报错:RGBA不能存为RGB!  所以只能存为png格式。但是利用cv2.imwrite可以保存。

6. 读入图片时,要注意有的图像可能是1通道的灰度图。这时如果要训练的话,3通道和1通道无法构成批量来训练。解决方法:使用cv2读入,默认是3通道。如果利用PIL的Image,可以这样写:
img = Image.open(self.root+'/'+img_path).convert('RGB')

或者手动复制三个通道修改成3通道图像:
img = np.stack([img]*3, 2)

1. OpenCV读取图片的格式和PIL不一样,OpenCV是BGR格式,PIL是RGB格式

2. PIL的Image.open()读入图片后并不是numpy数组array格式,这对于后面图像处理以及神经网络读入图片数据会带来麻烦,
    例如用卷积神经网络读入输入图片给placeholder时,往往要将代表图片的矩阵形状进行转换,此时PIL的Image.open()读入的格式是不能用reshape方法的。
    处理方式其实很简单,用np.array()函数直接进行转换就可以。
    示例:
    img = Image.open(path)
    re_img = np.asarray(img)

    将变成array的图片矩阵变回Image对象,使用Image中的fromarray方法
    示例:
    Image.fromarray(re_img)
3. ImageDraw模块提供了图像对象的简单2D绘制。用户可以使用这个模块创建新的图像,注释或润饰已存在图像,为web应用实时产生各种图形。


"""
class Aa(object):

    def draw_font_blend(self):
        """
        含义:创建一个可以在给定图像上绘图的对象。
        注意:图像内容将会被修改。

        首先,通过ImageDraw类创建一个绘制对象draw;

        draw.line():直线的绘制,第一个参数指定的是直线的端点坐标,形式为(x0, y0, x1, y1),第二个参数指定直线的颜色;
        draw.rectangle():矩形绘制,第一个参数指定矩形的对角线顶点(左上和右下),形式为(x0, y0, x1, y1),第二个指定填充颜色,第三个参数指定边界颜色;
        draw.arc():(椭)圆弧的绘制,第一个参数指定弧所在椭圆的外切矩形,第二、三两个参数分别是弧的起始和终止角度, 第四个参数是填充颜色,第五个参数是线条颜色;
        draw.chord():弦的绘制,和弧类似,只是将弧的起始和终止点通过直线连接起来;
        draw.pieslice():圆饼图的绘制,和弧与弦类似,只是分别将起始和终止点与所在(椭)圆中心相连;
        draw.ellipse():椭圆的绘制,第一个参数指定椭圆的外切矩形, 第二、三两个参数分别指定填充颜色和线条颜色,当外切矩形是正方形时,椭圆即为圆;
        draw.polygon():绘制多边形,第一个参数为多边形的端点,形式为(x0, y0, x1, y1, x2, y2,……),第二、三两个参数分别指定填充颜色和线条颜色;
        draw.text():文字的绘制,第一个参数指定绘制的起始点(文本的左上角所在位置),第二个参数指定文本内容,第三个参数指定文本的颜色,第四个参数指定字体(通过ImageFont类来定义)。
        :return:
        """
        img = Image.open("11111.jpg")
        img_copy = img.copy()
        img_draw = ImageDraw.Draw(img_copy)
        # draw.line():直线的绘制,第一个参数指定的是直线的端点坐标,形式为(x0, y0, x1, y1),第二个参数指定直线的颜色;width 线宽度
        img_draw.line((0, 0, 500, 500), (0, 255, 255), width=10)
        # draw.polygon():绘制多边形,第一个参数为多边形的端点,形式为(x0, y0, x1, y1, x2, y2,……),第二、三两个参数分别指定填充颜色和线条颜色;
        img_draw.polygon((100, 100, 500, 150, 600, 450, 110, 550), outline="red", fill="blue")
        img_draw.polygon([(500, 500),(1000, 500),(1200, 1200),(600, 1300)], fill="green")

        # draw.rectangle():矩形绘制,第一个参数指定矩形的对角线顶点(左上和右下),形式为(x0, y0, x1, y1),第二个指定填充颜色,第三个参数指定边界颜色;
        img_draw.rectangle([(800,1800),(2000, 4000)], fill="red")

        # draw.text():文字的绘制,第一个参数指定绘制的起始点(文本的左上角所在位置),第二个参数指定文本内容,第三个参数指定文本的颜色,第四个参数指定字体(通过ImageFont类来定义)。
        font = ImageFont.truetype("consola.ttf", 100, encoding="utf-8") # 设置字体
        img_draw.text((800, 1700), "888", 'fuchsia', font)
        # 使用给定的两张图像及透明度变量alpha,插值出一张新的图像。这两张图像必须有一样的尺寸和模式。
        #   合成公式为:out = image1 (1.0 - alpha) + image2  alpha
        # 若变量alpha为0.0,返回第一张图像的拷贝。若变量alpha为1.0,将返回第二张图像的拷贝。对变量alpha的值无限制。
        new_img = Image.blend(img, img_copy, 0.5)
        new_img.show()


    def open_img(self):
        """
        1. 打开本地图片
        open(fp, mode='r'): 打开一张图片,是Image模块中的函数。如果图片与当前代码在同一目录下,可以只写图片的文件名,其他情况需要拼接图片的路径。mode默认为'r',也必须为'r'。
        show(): 调用图片显示软件打开图片。打开后程序会阻塞,需要手动关闭。
        :return:
        """
        img = Image.open("11111.jpg")
        img.show()

    def creat_img(self):
        """
        2. 创建一张新图片
        new(mode, size, color=0): 创建一张图片(画布),用于绘图,是Image模块中的函数。有3个参数。
        mode, 图片的模式,如“RGB”(red,green,blue三原色的缩写,真彩图像)、“L”(灰度,黑白图像)等。
        size, 图片的尺寸。是一个长度为2的元组(width, height),表示的是像素大小。
        color, 图片的颜色,默认值为0表示黑色。可以传入长度为3的元组表示颜色,也可以传入颜色的十六进制,在版本1.1.4后,还可以直接传入颜色的英文单词,如上面代码中的(0, 0, 255)可以换成‘#0000FF’或‘blue’,都是表示蓝色。
        :return:
        """
        img = Image.new("RGB", (200, 200), "blue")
        img.show()

    def copy_and_paste(self):
        """
        copy(): 拷贝当前的图片,拷贝出来的图片与原图一模一样。如果想在图片上粘贴一些内容,又想保留原图时,可以使用此方法。

        paste(im, box=None, mask=None): 将另一张图片粘贴到当前图片中,如果粘贴的模式不匹配,则将被粘贴图片的模式转换成当前图片的模式。有3个参数。
            im, 被粘贴的图片。传入一张图片,当第二个参数box指定的是一个区域时,im参数也可以是一个整数或颜色值(元组表示,16进制表示和颜色名都可以,如上面代码中的image_new可以换成(0, 0, 255), '#0000FF', 'blue')。
            box, 图片粘贴的位置或区域。传入一个长度为2或4的元组,如果不传值,默认为(0, 0),图片被粘贴在当前图片的左上角。如果传入长度为2的元组(x, y),表示被粘贴图片的左上角坐标位置。如果传入长度为4的元组(x0, y0, x1, y1),
        表示图片粘贴的区域,此时区域的大小必须与被粘贴图片一致,否则会报错,传入的元组长度为其他值也会报错。
            mask, 蒙版。传入一张与被粘贴图片尺寸一样的图片,可以使用模式为'1'、'L'或者'RGBA'的图像。如果mask图像的颜色值为255,则直接按被粘贴图片的颜色粘贴,如果mask图像的颜色值为0,则保留当前图片的颜色(相当于没有粘贴),
        如果mask图像的颜色值为0~255之间的值,则将im与mask进行混合后再粘贴。

        save(fp, format=None, **params): 将当前图片按指定的文件名保存,运行后会将图片按新名字保存在当前路径下(也可以指定路径)。文件名最好带扩展名,方便打开,format表示图片的格式,
        没有指定format则会根据扩展名来解析(如果能解析出来),一般不需要指定format,传入一个带扩展名的文件名即可。
        :return:
        """
        img = Image.open("40.jpg")
        img_copy = img.copy()
        # img_copy.show()
        img_new = Image.new("RGB", (200, 200), (1,1,1))
        img_new2 = Image.new("L", (200, 200), '#646464')
        img_copy.paste(img_new, (100, 100), mask=img_new2)
        img_copy.save("pil.png")

        img_copy2 = Image.open("pil.png")
        print(img_copy2.format, img_copy2.mode)
        img_copy.show()

    def crop(self):
        """
        crop(box=None): 裁剪图片,返回裁剪区域的图片。box表示裁剪的区域,传入长度为4的元组(x0, y0, x1, y1),不传默认为拷贝原图,相当于copy()方法,如果裁剪的区域超过了原图的区域,超出部分用像素格填充。

        resize(size, resample=BICUBIC, box=None, reducing_gap=None): 缩放图片,返回缩放后的图片副本。有4个参数。
            size, 图片缩放后的尺寸,传入一个长度为2的元组(width, height)。
            resample, 重采样,是一个可选的重采样过滤器。可以传入Image.NEAREST, Image.BOX, Image.BILINEAR, Image.HAMMING, Image.BICUBIC, Image.LANCZOS。默认为Image.BICUBIC。如果图像的模式为'1'或'P',则始终设置为Image.NEAREST。
            box, 缩放图片的区域。传入长度为4的元组(x0, y0, x1, y1),这个区域必须在原图的(0, 0, width, height)范围内,如果超出范围会报错,如果不传值则默认将整张原图进行缩放。
            reducing_gap, 减少间隙。传入一个浮点数,用于优化图片缩放效果,默认不进行优化,值大于3.0时优化效果基本已经是公平的重采样。
        Image模块还有很多对图片处理的方法和函数,了解更多可以参考:https://blog.csdn.net/weixin_43790276/article/details/108673454
        :return:
        """
        img = Image.open("888.jpg")
        img_crop = img.crop(box=(200, 200, 400, 400))
        img_crop.show()

        img_resize = img.resize((500, 400), resample=Image.LANCZOS, reducing_gap=5.0)
        img_resize.show()


    def attribute(self):
        """
        width属性表示图片的像素宽度,height属性表示图片的像素高度,width和height组成了size属性,size是一个元组。
        mode属性表示图片的模式,如RGBA,RGB,P,L等。
        format属性表示图片的格式,格式一般与图片的后缀扩展名相关。category属性表示图片的的类别。
        readonly属性表述图片是否为只读,值为1或0,表示的是布尔值。
        info属性表示图片的信息,是一个字典。
        """
        img = Image.open("9999.jpg")
        print("width", img.width)
        print("heigth", img.height)
        print("size", img.size)
        print("format", img.format)



    def mode(self):
        """
        图片有很多模式,支持以下标准模式,参考:https://pillow.readthedocs.io/en/latest/handbook/concepts.html#concept-modes
        mode	描述
        1	1位像素,黑白,每字节存储一个像素
        L	8位像素,黑白
        P 	8位像素,使用调色板映射到任何其他模式
        RGB 	3x8位像素,真彩
        RGBA 	4x8位像素,带透明蒙版的真彩
        CMYK 	4x8位像素,分色
        YCbCr 	3x8位像素,彩色视频格式
        LAB 	3x8位像素,L * a * b颜色空间
        HSV 	3x8位像素,色相,饱和度,值颜色空间
        I 	32位有符号整数像素
        F 	32位浮点像素
        1位像素的范围是0-1,0表示黑1表示白,中间表示灰。8位像素的范围是0-255,如RGB的(0, 0, 0)表示黑,(255, 255, 255)表示白,依此类推。

        2. 图片的模式转换

        :return:
        """
        img = Image.open("666.jpg")
        print(img.mode)
        img1 = img.convert("1")
        print(img1.mode)
        img1.show()
        imgL = img.convert("L")
        print(imgL.mode)
        imgL.show()
        imgP = img.convert("P")
        print(imgP.mode)
        imgP.show()

    def aa(self):
        # cv2读取
        img = cv2.imread("888.jpg")
        # cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 转化为rgb   Image.fromarray() 格式转化为PIL能识别的格式
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        img_new = img.copy()
        # ImageDraw模块提供了图像对象的简单2D绘制。用户可以使用这个模块创建新的图像,注释或润饰已存在图像,为web应用实时产生各种图形。 Draw()创建一个可以在给定图像上绘图的对象。
        draw_img = ImageDraw.Draw(img_new)
        # 根据四个点坐标画框,用颜色填充。
        draw_img.polygon([(200, 200), (800, 200), (800, 800), (200, 800)], fill=(222, 111, 0))
        # 根据四个点,画线框,outline为线框颜色
        # draw_img.polygon([200, 300, 100, 300, 400, 500, 800, 600], outline=(222, 111, 0))
        # 图像合成 两张图片合成,0.5为不透明度,值越大,越不透明
        font = ImageFont.truetype("./doc/simfang.ttf", 10, encoding="utf-8")
        draw_img.text([100, 100], "888", fill=(0, 0, 0), font=font)
        new_img = Image.blend(img, img_new, 0.5)
        # 转化为array格式后,opencv可以读取
        new_img = np.array(new_img)
        # 改变尺寸,按比例缩放
        new_img = cv2.resize(new_img, (0, 0), fx=0.2, fy=0.2, interpolation=cv2.INTER_NEAREST)
        cv2.imshow("aaa",new_img)
        cv2.waitKey(0)



if __name__ == '__main__':
    a = Aa()
    a.draw()


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值