图像处理库Pillow安装与使用

PIL:Python Imaging Library,是Python平台事实上的图像处理标准库了。但是PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x。
下面来介绍如何安装及使用Pillow库。

安装

pip install pillow

在安装后通过在python控制台中输入"import PIL"命令可以验证是否成功安装

使用Pillow

1、读取图像

pillow的Image模块读取图像文件后得到的是PIL类型的image文件

import requests
from io import BytesIO
from PIL import Image
import matplotlib.pyplot as plt
#========================================================
#  加载图片
#========================================================
def read_image(path, mode='RGB'):
    '''
    加载本地单张图片
    INPUT  -> 单张图片路径, 特殊模式
    OUTPUT -> 单张图文件
    '''
    pil_im = Image.open(path)
    if mode == '1':
        # 非黑即白模式: 0表示黑, 255表示白
        return pil_im.convert('1')  
    elif mode == 'L':
        # 灰色模式: 0表示黑,255表示白,其他数字表示不同的灰度。转换算法 L = R * 299/1000 + G * 587/1000+ B * 114/1000
        return pil_im.convert('L')
    elif mode == 'RGB':
        return pil_im.convert('RGB')

def read_net_image(url, mode='RGB'):
    '''
    加载网络单张图片
    INPUT  -> 单张图片网址, 特殊模式
    OUTPUT -> 单张图文件
    '''
    pil_im = Image.open(BytesIO(requests.get(url).content))
    if mode == '1':
        return pil_im.convert('1')
    elif mode == 'L':
        return pil_im.convert('L')
    elif mode == 'RGB':
        return pil_im

img=read_image('test.png', 'RGB')
plt.axis('off') # 不显示坐标轴
plt.imshow(img)
plt.show()

查看PIL类型的image文件的信息

print(pil_im.size)  #图片的尺寸
print(type(img)) 
print(pil_im.mode)  #图片的模式
print(pil_im.format)  #图片的格式

获得某点像素用getpixel((w, h))可以直接返回这个点三个通道的像素值(Pillow采取左上角为(0,0)的坐标系统)

#得到像素:
print(pil_im.getpixel((100,200)))

2、保存图像

img.save('test.jpg')

这行代码不仅能保存图片,还是转换格式,如本例中,就由原来的png图片保存为了jpg图片。

3、像素访问

from PIL import Image
from PIL import ImageColor
'''200×200的透明正方形'''
img = Image.new('RGBA', (200, 200))

'''遍历上半部份的所有像素'''
for x in range(200):
    for y in range(100):
        '''设置每个像素的颜色'''
        img.putpixel((x, y), (255,255,255))

for x in range(200):
    for y in range(100,200):
        '''假定不知道RGB元组,必须使用ImageColor.getcolor()'''
        img.putpixel((x, y), ImageColor.getcolor('darkgray', 'RGBA'))

img.save('putpixel.png')

4、通道分离与合并

r,g,b=img.split()   #分离三通道
pic=Image.merge('RGB',(r,g,b))   #合并三通道

5、裁剪图片

def image_clip(pil_im, x, y, width, height):
    '''
    从一张图片中截取某个区域
    INPUT  -> 单张图文件, 坐标点x, 坐标点y, 目标宽度, 目标高度
    OUTPUT -> 截取后的图片
    '''
    im_w, im_h = pil_im.size
    x2 = x + width
    y2 = y + height
    if x + width > im_w:
        x2 = im_w
    if y + height > im_h:
        y2 = im_h
    box = (x, y, x2, y2)
    region = pil_im.crop(box)
    return region

6、刚体几何变换

图像的放缩

def image_resize1(pil_im, dst_w, dst_h):
    '''
    使一张图片变换尺寸(非等比例)(指定宽高)
    INPUT  -> 单张图文件, 目标宽度, 目标高度
    OUTPUT -> 处理后的图片
    '''
    return pil_im.resize((dst_w, dst_h))

def image_resize_proportionally1(pil_im, c):
    '''
    使一张图片变换尺寸(等比例)(倍数缩放)
    INPUT  -> 单张图文件, 目标宽度, 目标高度
    OUTPUT -> 处理后的图片
    '''
    height, width = pil_im.size
    dst_w = height*c
    dst_h = width*c
    return pil_im.resize((dst_w, dst_h))

def image_resize_proportionally2(pil_im, dst_w, dst_h):
    '''
    使一张图片变换尺寸(等比例)
    INPUT  -> 单张图文件, 目标宽度, 目标高度
    OUTPUT -> 处理后的图片
    '''
    ori_w, ori_h = pil_im.size
    widthRatio = heightRatio = None
    ratio = 1
    if (ori_w and ori_w > dst_w) or (ori_w and ori_h > dst_h):
        if (ori_w > dst_w):
            widthRatio = float(dst_w) / ori_w # 获取宽度缩放比例
        if (ori_h > dst_h):
            heightRatio = float(dst_h) / ori_h # 获取高度缩放比例
        if widthRatio and heightRatio:
            if widthRatio < heightRatio:
                ratio = widthRatio
            else:
                ratio = heightRatio
        if widthRatio and not heightRatio:
            ratio = widthRatio
        if heightRatio and not widthRatio:
            ratio = heightRatio
        newWidth = int(ori_w * ratio)
        newHeight = int(ori_h * ratio)
    else:
        newWidth = ori_w
        newHeight = ori_h
    return pil_im.resize((newWidth,newHeight), Image.ANTIALIAS)

图像的旋转

def image_rotate(pil_im, angle, clockwise=False):
    '''
    使一张图片旋转
    INPUT  -> 单张图文件, 旋转角度, 旋转方向(默认逆时针)
    OUTPUT -> 旋转后的图文件
    '''
    if clockwise:
        angle = 360 - int(angle)
        pil_im = pil_im.rotate(angle, expand=True)  # expand参数如果设为True,就会放大图像的尺寸,以适应整个旋转后的新图像
    else: 
        pil_im = pil_im.rotate(angle, expand=True)
    return pil_im

7、图像加水印

from PIL import ImageDraw, ImageFont, ImageEnhance

def image_watermark_logo(ori_im, mark_im):
    '''
    给一张图片加上图片水印
    INPUT  -> 原始图片, 水印图片, 透明度
    OUTPUT -> 处理后的图片
    '''
    ori_w, ori_h = ori_im.size
    mark_w, mark_h = mark_im.size
    # 图层
    dst_im = Image.new('RGBA', ori_im.size, (255,255,255,0))  # 设置图片尺寸和透明度
    dst_im.paste(mark_im, (ori_w-mark_w, ori_h-mark_h))
    # 覆盖
    dst_im = Image.composite(dst_im, ori_im, dst_im)
    return dst_im

def image_watermark_text(ori_im, fontpath, text=''):
    '''
    给一张图片加上文字水印
    INPUT  -> 原始图片, 字体路径, 文本
    OUTPUT -> 处理后的图片
    '''
    ori_im = ori_im.convert('RGBA')
    ori_w, ori_h = ori_im.size
    # 文本遮罩层
    text_overlay = Image.new('RGBA', ori_im.size, (255,255,255,0))
    image_draw = ImageDraw.Draw(text_overlay)
    # 获取文本大小
    fnt = ImageFont.truetype(fontpath, 20)
    text_size_x, text_size_y = image_draw.textsize(text, font=fnt)
    # 设置文本位置
    text_xy = (ori_w-text_size_x, ori_h-text_size_y)
    # 设置文本颜色和透明度
    image_draw.text(text_xy, text, font=fnt, fill=(255,255,255,50))
    # 覆盖
    dst_im = Image.alpha_composite(ori_im, text_overlay)
    return dst_im

8、图像标识框

def image_tag(pil_im, x1, y1, x2, y2):
    '''
    在图片上标记矩形框
    INPUT  -> 单张图文件, 对角点坐标(PIL使用笛卡尔像素坐标系统,坐标(0,0)位于左上角)
    OUTPUT -> 绘制后的图文件
    '''
    canvas = ImageDraw.Draw(pil_im)
    canvas.line([(x1, y1), (x2, y1), (x2, y2), (x1, y2), (x1, y1)], fill='red')
    return canvas

9、使用图像滤镜

ImageFilter是PIL的滤镜模块,通过这些预定义的滤镜,可以方便的对图片进行一些过滤操作,从而去掉图片中的噪音(部分的消除),这样可以降低将来处理的复杂度(如模式识别等)。

ImageFilter.BLUR           模糊滤镜
ImageFilter.CONTOUR           轮廓
ImageFilter.EDGE_ENHANCE       边界加强
ImageFilter.EDGE_ENHANCE_MORE     边界加强(阀值更大)
ImageFilter.EMBOSS                 浮雕滤镜
ImageFilter.FIND_EDGES         边界滤镜
ImageFilter.SMOOTH           平滑滤镜
ImageFilter.SMOOTH_MORE        平滑滤镜(阀值更大)
ImageFilter.SHARPEN              锐化滤镜

要使用PIL的滤镜功能,需要引入ImageFilter模块

from import ImageFilter 
def filterDemo():  
    img = Image.open("sandstone_half.jpg")  
    imgfilted = img.filter(ImageFilter.SHARPEN)  
    imgfilted.save("sandstone_sharpen.jpg")

10、PIL Image图像与numpy数组互转

前面的一些例子中,我们都是利用Image.open()来打开一幅图像,然后直接对这个PIL对象进行操作。如果只是简单的操作还可以,但是如果操作稍微复杂一些,就比较吃力了。因此,通常我们加载完图片后,都是把图片转换成矩阵来进行更加复杂的操作。

#========================================================
#  图像数组化与还原
#========================================================

def image_to_array(pil_im):
    '''
    图片转化为数组
    INPUT  -> 单张图文件
    OUTPUT -> 数组
    '''
    return np.array(pil_im, 'f')

def array_to_image(image_arr):
    '''
    数组还原为图片
    INPUT  -> 数组
    OUTPUT -> 单张图文件
    '''
    if len(image_arr.shape) == 3:  # 格式为(height(rows), weight(colums), 3)
        r = Image.fromarray(np.uint8(image_arr[:,:,0]))
        g = Image.fromarray(np.uint8(image_arr[:,:,1]))
        b = Image.fromarray(np.uint8(image_arr[:,:,2]))
        image = Image.merge("RGB", (r, g, b))
        return image        
    elif len(image_arr.shape) == 2:  # 格式为(height(rows), weight(colums))
        return Image.fromarray(np.uint8(image_arr))

你可能感兴趣的:(图像处理库Pillow安装与使用)