zoukankan      html  css  js  c++  java
  • PIL基础操作

    PIL基础操作

    新建图片

    from PIL import Image
    
    # 通常使用RGB模式就可以了
    new_img = Image.new('RGB', (100, 100), 'red')
    new_img.save("1.jpg", "JPEG")
    
    new_img = Image.new('RGB', (100, 100), '#B286FF')
    new_img.save("2.jpg", "JPEG")
    
    new_img = Image.new('RGB', (100, 100), (255, 255, 128))
    new_img.save("3.jpg", "JPEG")
    

    打开图片

    BASE_PATH = os.path.dirname(os.path.abspath(__file__))
    
    file_path = os.path.join(BASE_PATH, "fj.jpg")
    
    # 打开图片
    img = Image.open(file_path)
    
    """
    format : 识别图像的源格式,如果该文件不是从文件中读取的,则被置为 None 值。
    size : 返回的一个元组,有两个元素,其值为象素意义上的宽和高。
    mode : 
    · 1 (1-bit pixels, black and white, stored with one pixel per byte)
    · L (8-bit pixels, black and white)
    · P (8-bit pixels, mapped to any other mode using a colour palette)
    · RGB (3x8-bit pixels, true colour)
    · RGBA (4x8-bit pixels, true colour with transparency mask)
    · CMYK (4x8-bit pixels, colour separation)
    · YCbCr (3x8-bit pixels, colour video format)
    · I (32-bit signed integer pixels)
    · F (32-bit floating point pixels)
    """
    
    print img.format, img.size, img.mode, img.height, img.width
    # h,w = img.size    # (X,Y)
    等价于
    # h = img.heigth
    # w = img.width
    
    # 缩略图
    img.thumbnail((w*0.75, h//2))
    img.save("1.jpg", "JPEG")
    
    # 应用模糊滤镜:
    im2 = img.filter(ImageFilter.BLUR)
    # 存储图片 im2.save('blur.jpg', 'JPEG')
    • BLUR:模糊滤波
    • CONTOUR:轮廓滤波
    • DETAIL:细节滤波
    • EDGE_ENHANCE:边界增强滤波
    • EDGE_ENHANCE_MORE:边界增强滤波(程度更深)
    • EMBOSS:浮雕滤波
    • FIND_EDGES:寻找边界滤波
    • SMOOTH:平滑滤波
    • SMOOTH_MORE:平滑滤波(程度更深)
    • SHARPEN:锐化滤波
    • GaussianBlur(radius=2):高斯模糊
    >radius指定平滑半径。
    • UnsharpMask(radius=2, percent=150, threshold=3):反锐化掩码滤波
    >radius指定模糊半径;
    >percent指定反锐化强度(百分比);
    >threshold控制被锐化的最小亮度变化。
    • Kernel(size, kernel, scale=None, offset=0):核滤波
    当前版本只支持核大小为3x3和5x5的核大小,且图像格式为“L”和“RGB”的图像。
    >size指定核大小(width, height);
    >kernel指定核权值的序列;
    >scale指定缩放因子;
    >offset指定偏移量,如果使用,则将该值加到缩放后的结果上。
    • RankFilter(size, rank):排序滤波
    >size指定滤波核的大小;
    >rank指定选取排在第rank位的像素,若大小为0,则为最小值滤波;若大小为size * size / 2则为中值滤波;若大小为size *
    size - 1则为最大值滤波。
    • MedianFilter(size=3):中值滤波
    >size指定核的大小
    • MinFilter(size=3):最小值滤波器
    >size指定核的大小
    • MaxFilter(size=3):最大值滤波器
    >size指定核的大小
    • ModeFilter(size=3):波形滤波器
    选取核内出现频次最高的像素值作为该点像素值,仅出现一次或两次的像素将被忽略,若没有像素出现两次以上,则保留原像素值。
    >size指定核的大小
    ImageFilter类预定义滤波

     裁切图片

    在这个副本上的任何操作不会影响到原图像

    # 接收元组(X,Y,X,Y)
    cp_img = img.crop((0, 100, 30, 300))
    cp_img.save("cp.jpg", "JPEG")
    

     复制图片

    # 剪切
    # cp_img = img.crop((0, 0, 450, 300))
    # 复制
    cp_img = img.copy()
    # 新建图片
    new_img = Image.new("RGB", (500, 300), (255, 255, 255))
    # 在新建的图片上粘贴裁剪的图片
    # new_img.paste(cp_img)
    # 指定起始坐标(左上角)
    new_img.paste(cp_img, (50, 0))
    new_img.save("cp_img.jpg", "JPEG")
    

     调整图片大小

    resize不是等比例缩放的

    w,d = img. size
    # 只接受整数
    new_img = img.resize((500, 350))
    new_img.save("1.jpg", "JPEG")
    

    旋转图片

    # 90度
    img.rotate(90).save("rotate90.jpg", "JPEG")
    # 180度
    img.rotate(180).save("rotate180.jpg", "JPEG")
    # 270度
    img.rotate(270).save("rotate270.jpg", "JPEG")
    # 20度
    img.rotate(20).save("rotate20.jpg", "JPEG")
    # 放大旋转20度,expand放大了图像尺寸,使得边角的图像不被裁剪四个角刚好贴着图像边缘)
    img.rotate(20, expand=True).save("20.jpg", "JPEG")
    # 图像的镜面翻转(必须传入Image.FLIP_LEFT_RIGHT(水平翻转)/Image.FLIP_TOP_BOTTOM(垂直翻转))
    img.transpose(Image.FLIP_LEFT_RIGHT).save("tran_img.jpg", "JPEG")   # 水平翻转
    img.transpose(Image.FLIP_TOP_BOTTOM).save("tran_img_.jpg", "JPEG")   # 垂直翻转
    

    画图(ImageDraw)

    导入包

    from PIL import ImageDraw
    from PIL import Image
    

    直线

    # 新建画板
    im_board = Image.new("RGB", (500, 500), (255, 255, 255))
    # 创建画笔(所有画的动作都是由此对象生成的)
    drawObject = ImageDraw.Draw(im_board)
    
    # 起始xy,结束xy[x,y,x,y]    fill直线颜色    width直线宽度
    drawObject.line([150, 50, 350, 50], fill=10, width=5)
    drawObject.line([(150, 250), 350, 250], fill=128)
    drawObject.line([(150, 50), (150, 250)], "black")
    drawObject.line((350, 50, 350, 250), fill="yellow")
    

     效果:

    # fill颜色为将圆填充色, outline边界颜色
    drawObject.arc((150, 200, 300, 350), 0, 360, fill="black")
    drawObject.arc((150, 220, 300, 350), 180, 360, fill="red")
    drawObject.arc((150, 230, 300, 350), 180, 270, fill="red")
    drawObject.arc((150, 235, 300, 350), 270, 180, fill="red")
    drawObject.arc((150, 240, 300, 350), 180, 270, fill="red")
    drawObject.arc((150, 245, 300, 350), 270, 180, fill="red")
    
    # fill颜色为将圆填充色, outline边界颜色
    # drawObject.ellipse((150, 200, 300, 350), fill="blue", outline=128)
    

     效果:

     

    # 用法与arc相同,用来画圆从startAngle到endAngle的弦
    # Options选项中fill表示将弦与圆弧之间空间用指定颜色填满,outlie表示只规定弦线的颜色
    # drawObject.chord([x1, y1, x2, y2],  startAngle,  endAngle,  options)
    
    # 画圆
    drawObject.ellipse((100, 100, 300, 300), outline=128)
    
    # 画弦并且将弦与弧包围区域涂色
    drawObject.chord((100, 100, 300, 300), 0, 360, fill="yellow")
    
    # 画一条弦
    drawObject.chord((100, 100, 300, 300), 0, 180, outline="blue")
    drawObject.chord((100, 100, 300, 300), 0, 135, outline="blue")
    drawObject.chord((100, 100, 300, 300), 135, 270, outline="blue")
    drawObject.chord((100, 100, 300, 300), 270, 45, outline="blue")
    drawObject.chord((100, 100, 300, 300), 45, 180, outline="blue")
    

     效果:

    扇区

    # options选项中fill选项将扇形区域用指定颜色填满,outline选项只用指定颜色描出区域轮廓
    # drawObject.pieslice([x1,y1,x2,y2],  startAngle,  endAngle,  options)
    # 画一个圆
    drawObject.ellipse((100, 100, 300, 300), outline=128)
    # 画180度到210度的扇形区域轮廓
    drawObject.pieslice((100, 100, 300, 300), 0, 45, outline=128)
    drawObject.pieslice((100, 100, 300, 300), 180, 235, outline=128)
    
    # 画60度到90度的扇形区域
    drawObject.pieslice((100, 100, 300, 300), 0, 90, fill="blue")
    drawObject.pieslice((100, 100, 300, 300), 180, 270, fill="blue")
    

     效果:

    多边形

    # 根据第一个参量中的xy坐标对,连接出整个图形
    # options选项中fill选项将多边形区域用指定颜色填满,outline选项只用指定颜色描出区域轮廓
    # drawObject.polygon(([x1,y1,x2,y2,…],options)
    #                    第一点坐标  第二点坐标    第三点坐标    连接线的颜色
    drawObject.polygon([(50, 300), (200, 300), (50, 100)], outline="red")
    drawObject.polygon([(50, 100), (300, 100), (50, 300), (300, 300)], fill="red", outline="blue")
    drawObject.polygon([(50, 100), (50, 300), (300, 100), (300, 300)], fill="blue", outline="red")
    

     效果:

     

    矩形

    # (x1,y1)表示矩形左上角坐标值,(x2,y2)表示矩形右下角坐标值
    # options选项中fill选项将多边形区域用指定颜色填满,outline选项只用指定颜色描出区域轮廓
    # drawObject.rectangle([x1,y1,x2,y2],options)drawObject
    drawObject.rectangle((100, 100, 300, 300), outline="red")
    drawObject.rectangle((100, 300, 300, 320), fill=128)
    

     效果:

    添加文字

    # Position是一个二元元组,指定字符串左上角坐标,string是要写入的字符串
    # options选项可以为fill或者font(只能选择其中之一作为第三参量.
    # 不能两个同同时存在,要改变字体颜色,见ImageFont模块
    # text = u"人生苦短,我用派生"
    text = u"I Love You"
    drawObject.text([100, 200], text, "red")
    

     效果:

     字

     在图片中写字

    from PIL import ImageDraw, ImageFont
    from PIL import Image
    
    hwxw_path = os.path.join(BASE_PATH, "font", "华文新魏.ttf")
    hwxk_path = os.path.join(BASE_PATH, "font", "华文行楷.ttf")
    hwls_path = os.path.join(BASE_PATH, "font", "华文隶书.ttf")
    # 新建画板
    im_board = Image.new("RGB", (500, 500), (255, 255, 255))
    # 画笔对象
    drawObject = ImageDraw.Draw(im_board)
    # 定义字体  ImageFont.truetype(file,size)
    # 创建一个字体对象.这个函数从指定的文件加载了一个字体对象,并且为指定字体大小
    hwxw_font = ImageFont.truetype(hwxw_path, 18)
    hwxk_font = ImageFont.truetype(hwxk_path, 24)
    hwls_font = ImageFont.truetype(hwls_path, 36)
    """
    注意事项:笔的默认颜色为白色,画笔的颜色可以通过draw的ink属性来改变
    draw.ink = 0(R) + 0(G) * 256 + 0(B) * 256 * 256
    也可以通过fill参数更改字体颜色
    """
    
    drawObject.rectangle([100, 100, 400, 400], outline=128)
    
    text = u"人生苦短"
    text_ = u"我用"
    text__ = u"Python"
    # 利用text函数添加文字
    # drawObject.ink = 0 + 0 * 256 + 0 * 256 * 256
    drawObject.text([180, 170], text, font=hwxw_font, fill="yellow")
    # drawObject.ink = 0 + 128 + 100
    drawObject.text([180, 200], text_, font=hwxk_font, fill="blue")
    # drawObject.ink = 0 + 0 * 256 + 255 * 256 * 256
    drawObject.text([180, 230], text__, font=hwls_font, fill=(255, 222, 111))
    
    
    im_board.save("drawing_board.png", "PNG")
    
    # Font.getsize(text)
    # 返回一个二元素元组,为指定text在指定字体大小之后的size
    print hwxk_font.getsize(text)
    

     生成验证码(借鉴):

    import Image, ImageDraw, ImageFont, ImageFilter
    import random
    
    
    hwxw_path = os.path.join(BASE_PATH, "font", "华文新魏.ttf")
    hwxk_path = os.path.join(BASE_PATH, "font", "华文行楷.ttf")
    hwls_path = os.path.join(BASE_PATH, "font", "华文隶书.ttf")
    font_list = [hwxw_path, hwxk_path, hwls_path]
    
    # 随机字母:
    def rndChar():
        return chr(random.randint(65, 90))
    
    # 随机颜色1:
    def rndColor():
        return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
    
    # 随机颜色2:
    def rndColor2():
        return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
    
    # 240 x 60:
    width = 60 * 4
    height = 60
    image = Image.new('RGB', (width, height), (255, 255, 255))
    # 创建Font对象:
    font = ImageFont.truetype(random.choice(font_list), 36)
    # 创建Draw对象:
    draw = ImageDraw.Draw(image)
    # 填充每个像素:
    for x in range(width):
        for y in range(height):
            draw.point((x, y), fill=rndColor())
    # 输出文字:
    for t in range(4):
        draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
    # 模糊:
    image = image.filter(ImageFilter.BLUR)
    image.save('code.jpg', 'jpeg')
    

    Pillow只是个基础的图像处理库,OpenCV是更好的选择

  • 相关阅读:
    Less学习笔记
    如何在网页启动Windows服务
    让VS2010记住TFS的登陆用户名和密码
    调式WP程序报0x80131500错误的解决办法
    FizzBuzzWhizz是算法题吗?我从设计的角度去解决的。
    基于Roslyn的远程任务平台
    优雅就一个字——设计模式之数据上传接口
    关于反射优化的疑问,单次调用时直接反射要快于委托调用反射?
    用VC++11中编译libthrift项目
    grunt初体验
  • 原文地址:https://www.cnblogs.com/shangpolu/p/8042300.html
Copyright © 2011-2022 走看看