zoukankan      html  css  js  c++  java
  • Python操作图像

    安装Pillow

    pip install Pillow

    打开图像

    from PIL import Image
    img = Image.open("./lena.tiff")

    保存图像

    打开图像之后,可以将其保存,也就是另存为。
    img对象.save(保存路径)

    save方法不仅能够保存图像,还能够转换格式,取决于保存路径的最终文件后缀名。

    img.save("./lena.jpg")
    img.save("./lena.png")

    查看属性

    img = Image.open("./lena.tiff")
    print('图像格式:{}'.format(img.format))
    print('图像尺寸:{}'.format(img.size))
    print('色彩模式:{}'.format(img.mode))

    打印结果:

    图像格式:TIFF
    图像尺寸:(512, 512)
    色彩模式:RGB

    显示图像

    from PIL import Image
    import matplotlib.pyplot as plt
    img = Image.open("./lena.tiff")
    plt.imshow(img)
    plt.show()

    运行结果:

    这是在数字图像处理中 被广泛用来做示例的一张图像  Lena

    imshow函数是对图像进行载入,传入的参数可以是img对象,也可以是Numpy数组,最后由show函数负责将载入的图片进行显示。

    默认是会带上像素坐标轴的,如果不显示坐标轴,可以在plt.show()之前加一句plt.axis("off"),以下会演示效果。

    我们还可以同时显示多张图像,

    from PIL import Image
    import matplotlib.pyplot as plt
    
    #打开三张图片
    img1 = Image.open('./lena.tiff')
    img2 = Image.open('./lena.png')
    img3 = Image.open('./lena.jpg')
    
    #设置画布尺寸
    plt.figure(figsize=(10,5))
    
    plt.subplot(131) #划分子图 本张为1行3列的第一张图
    plt.title(img1.format)  #图片标题
    plt.axis('off') #关闭坐标轴
    plt.imshow(img1) #载入图片
    
    plt.subplot(132)
    plt.title(img2.format)
    plt.axis('off')
    plt.imshow(img2)
    
    plt.subplot(133)
    plt.title(img3.format)
    plt.axis('off')
    plt.imshow(img3)
    
    plt.show() #显示图片

    运行结果:

    色彩模式

    我们可以使用img对象的convert方法将图像转换色彩模式

    img对象.convert(色彩模式)

    色彩模式的取值有如下几种:

    1:二值图像
    L:灰度图像
    P:8位彩色图像
    RGB:24位彩色图像
    RGBA:32位彩色图像
    CMYK:CMYK彩色图像
    YCbCr:YCbCr彩色图像
    I:32位整型灰度图像
    F:32位浮点灰度图像

    用法示例:

    from PIL import Image
    import matplotlib.pyplot as plt
    
    img1 = Image.open('./lena.tiff')
    img_gray = img1.convert("L")
    plt.figure(figsize=(10,10))
    plt.imshow(img_gray,cmap='gray')
    plt.show()

    转成灰度图之后  就是这样子:

    颜色通道

    用img对象的split()方法将图像按照RGB三个通道分离成三个图像。

    也可以用Image库的merge函数将多个通道合并成一个图像。

    from PIL import Image
    import matplotlib.pyplot as plt
    
    plt.rcParams['font.sans-serif']=['SimHei']
    
    img = Image.open('./lena.tiff')
    img_r,img_g,img_b = img.split()
    plt.figure(figsize=(10,10))
    
    plt.subplot(221)
    plt.title('R通道',fontsize=18)
    plt.axis('off')
    plt.imshow(img_r,cmap='gray')
    
    plt.subplot(222)
    plt.title('G通道',fontsize=18)
    plt.axis('off')
    plt.imshow(img_g,cmap='gray')
    
    plt.subplot(223)
    plt.title('B通道',fontsize=18)
    plt.axis('off')
    plt.imshow(img_b,cmap='gray')
    
    img_rgb = Image.merge('RGB',[img_r,img_g,img_b])
    plt.subplot(224)
    plt.title('合并通道',fontsize=18)
    plt.axis('off')
    plt.imshow(img_rgb)
    
    plt.show()

    运行结果:

    按灰度图显示对应通道,比如第一张图中,颜色越亮,表示红色越多,颜色越暗,表示红色越少。

    图像转数组

    在人工智能处理图像的时候,都是先将图像转成数组,数组中的元素对应图像中的各个像素点。

    将图像转为数组需要用到numpy的array函数。

    from PIL import Image
    import numpy as ny
    img = Image.open('./lena.tiff')
    arr = ny.array(img)
    print('形状:{}'.format(arr.shape))
    print(arr)

    打印结果(数组很长,默认中间以省略号代替):

    形状:(512, 512, 3)
    [[[226 137 125]
    [226 137 125]
    [223 137 133]
    ...
    [230 148 122]
    [221 130 110]
    [200 99 90]]

    [[226 137 125]
    [226 137 125]
    [223 137 133]
    ...
    [230 148 122]
    [221 130 110]
    [200 99 90]]]

    图像数组是一个三维数组,前两维对应图像的尺寸,第三维对应图像的三个通道,也就是说前两维是一个512行乘以512列的矩阵,因为整张图像大小就是512像素*512像素,第三维是每个像素点的RGB三个通道的颜色值。 

    接下来我们看一下将一张灰度图转为数组是什么样子的,使用上文转换色彩模式时保存下来的灰度图:

    from PIL import Image
    import numpy as ny
    img = Image.open('./003.jpg')
    arr = ny.array(img)
    print('形状:{}'.format(arr.shape))
    print(arr)

    打印结果:

    形状:(512, 512)
    [[162 161 160 ... 171 154 129]
    [162 162 161 ... 173 158 133]
    [163 162 161 ... 171 155 128]
    ...
    [ 42 45 49 ... 102 103 103]
    [ 41 45 50 ... 105 107 109]
    [ 41 45 51 ... 102 105 107]]

    此时的形状是一个512*512的二维数组,其中每个元素对应一个像素点的灰度值。

    那我们可以将这张灰度图做一个反色处理,将每个像素的颜色值都用255来减一下,也就是黑色变成白色,白色变成黑色。

    import matplotlib.pyplot as plt
    from PIL import Image
    import numpy as ny
    img = Image.open('./003.jpg')
    arr = ny.array(img)
    
    plt.figure(figsize=(10,5))
    
    plt.subplot(121)
    plt.title('old')
    plt.imshow(arr,cmap='gray')
    plt.axis('off')
    
    new_arr = 255 - arr
    plt.subplot(122)
    plt.title('new')
    plt.imshow(new_arr,cmap='gray')
    plt.axis('off')
    
    plt.show()

    运行结果:

    图像缩放

    使用img对象的resize方法可以对图像进行缩放

    import matplotlib.pyplot as plt
    from PIL import Image
    
    img = Image.open('./lena.tiff')
    
    plt.figure(figsize=(10,5))
    
    plt.subplot(121)
    plt.title('old')
    plt.imshow(img)
    
    new_img = img.resize((64,64))
    plt.subplot(122)
    plt.title('new')
    plt.imshow(new_img)
    
    plt.show()

    运行结果:

    通过坐标轴可以看到 原图是512*512尺寸大小,进行缩放成64*64之后,图像的质量下降,出现了类似马赛克的效果,这个操作是一个降采样的过程。

    缩放还可以使用img的thumbnail方法,但不同的是thumbnail方法是对图像的原地操作,不会有返回值,使用示例:

    import matplotlib.pyplot as plt
    from PIL import Image
    
    img = Image.open('./lena.tiff')
    
    plt.figure(figsize=(10,5))
    
    plt.subplot(121)
    plt.title('old')
    plt.imshow(img)
    
    img.thumbnail((64,64))
    plt.subplot(122)
    plt.title('new')
    plt.imshow(img)
    
    plt.show()

    运行结果和之前一模一样。

    图像旋转

    img对象.transpose()方法对图像进行旋转。

    参数中指定旋转方式,有如下几种:

    Image.FLIP_LEFT_RIGHT = 0 水平翻转
    Image.FLIP_TOP_BOTTOM = 1 上下翻转
    Image.ROTATE_90 = 2 逆时针旋转90度
    Image.ROTATE_180 = 3 逆时针旋转180度
    Image.ROTATE_270 = 4 逆时针旋转270度
    Image.TRANSPOSE = 5 将图像转置
    Image.TRANSVERSE = 6 将图像进行转置,再水平翻转

    可以传常量属性,也可以直接传数字,源码中常量是直接映射成数字处理的。

    import matplotlib.pyplot as plt
    from PIL import Image
    
    img = Image.open('./lena.tiff')
    
    plt.rcParams['font.sans-serif']=['SimHei']
    
    plt.figure(figsize=(10,20))
    
    plt.subplot(421)
    plt.axis('off')
    plt.title('原图',fontsize=18)
    plt.imshow(img)
    
    img2 = img.transpose(Image.FLIP_LEFT_RIGHT)
    plt.subplot(422)
    plt.axis('off')
    plt.title('水平翻转',fontsize=18)
    plt.imshow(img2)
    
    img3 = img.transpose(Image.FLIP_TOP_BOTTOM)
    plt.subplot(423)
    plt.axis('off')
    plt.title('上下翻转',fontsize=18)
    plt.imshow(img3)
    
    img4 = img.transpose(Image.ROTATE_90)
    plt.subplot(424)
    plt.axis('off')
    plt.title('逆时针旋转90度',fontsize=18)
    plt.imshow(img4)
    
    img5 = img.transpose(Image.ROTATE_180)
    plt.subplot(425)
    plt.axis('off')
    plt.title('逆时针旋转180度',fontsize=18)
    plt.imshow(img5)
    
    img6 = img.transpose(Image.ROTATE_270)
    plt.subplot(426)
    plt.axis('off')
    plt.title('逆时针旋转270度',fontsize=18)
    plt.imshow(img6)
    
    img7 = img.transpose(Image.TRANSPOSE)
    plt.subplot(427)
    plt.axis('off')
    plt.title('将图像转置',fontsize=18)
    plt.imshow(img7)
    
    img8 = img.transpose(Image.TRANSVERSE)
    plt.subplot(428)
    plt.axis('off')
    plt.title('转置+翻转',fontsize=18)
    plt.imshow(img8)
    
    plt.show()

    运行结果:

    图像裁剪

    img对象.crop((x0,y0,x1,y1))

    参数中的x0,y0代表裁剪内容的左上角坐标,x1,y1代表裁剪内容的右下角坐标,两个坐标即可确定出裁剪的矩形区域。

    import matplotlib.pyplot as plt
    from PIL import Image
    
    img = Image.open('./lena.tiff')
    
    plt.rcParams['font.sans-serif']=['SimHei']
    
    plt.figure(figsize=(10,5))
    
    plt.subplot(121)
    plt.axis('off')
    plt.title('原图',fontsize=18)
    plt.imshow(img)
    
    area = (200,200,400,400)
    img2 = img.crop(area)
    plt.subplot(122)
    plt.axis('off')
    plt.title('裁剪结果',fontsize=18)
    plt.imshow(img2)
    
    plt.show()

    运行结果:

  • 相关阅读:
    紫书 习题 11-15 UVa 1668 (图论构造法)
    紫书 习题 11-16 UVa 1669(树形dp)
    紫书 习题 11-12 UVa 1665 (并查集维护联通分量)
    紫书 习题 11-10 UVa 12264 (二分答案+最大流)
    紫书 习题 11-9 UVa 12549 (二分图最小点覆盖)
    紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
    欧拉回路模板
    架构设计:进程还是线程?是一个问题!(转载)
    JDK个目录,以及与环境变量的关系
    linux cat命令
  • 原文地址:https://www.cnblogs.com/fengyumeng/p/13803223.html
Copyright © 2011-2022 走看看