PIL基础操作
PIL基础操作
新建图片
1 2 3 4 5 6 7 8 9 10 11 | 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" ) |
打开图片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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)<br> # 存储图片 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指定核的大小
裁切图片
在这个副本上的任何操作不会影响到原图像
1 2 3 | # 接收元组(X,Y,X,Y) cp_img = img.crop(( 0 , 100 , 30 , 300 )) cp_img.save( "cp.jpg" , "JPEG" ) |
复制图片
1 2 3 4 5 6 7 8 9 10 11 | # 剪切 # 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不是等比例缩放的
1 2 3 4 | w,d = img. size # 只接受整数 new_img = img.resize(( 500 , 350 )) new_img.save( "1.jpg" , "JPEG" ) |
旋转图片
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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)
导入包
1 2 | from PIL import ImageDraw from PIL import Image |
直线
1 2 3 4 5 6 7 8 9 10 | # 新建画板 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" ) |
效果:
圆
1 2 3 4 5 6 7 8 9 10 | # 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) |
效果:
弦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # 用法与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" ) |
效果:
扇区
1 2 3 4 5 6 7 8 9 10 11 | # 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" ) |
效果:
多边形
1 2 3 4 5 6 7 | # 根据第一个参量中的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" ) |
效果:
矩形
1 2 3 4 5 | # (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 ) |
效果:
添加文字
1 2 3 4 5 6 | # Position是一个二元元组,指定字符串左上角坐标,string是要写入的字符串 # options选项可以为fill或者font(只能选择其中之一作为第三参量. # 不能两个同同时存在,要改变字体颜色,见ImageFont模块 # text = u"人生苦短,我用派生" text = u "I Love You" drawObject.text([ 100 , 200 ], text, "red" ) |
效果:
字
在图片中写字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 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) |
生成验证码(借鉴):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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是更好的选择
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性