编程语言
C#编程语言基础
C#面向对象与多线程
C#数据及文件操作
JavaScript基础
JavaScript的数据类型和变量
JavaScript的运算符和表达式
JavaScript的基本流程控制
JavaScript的函数
JavaScript对象编程
JavaScript内置对象和方法
JavaScript的浏览器对象和方法
JavaScript访问HTML DOM对象
JavaScript事件驱动编程
JavaScript与CSS样式表
Ajax与PHP
ECMAScript6的新特性
Vue.js前端开发
PHP的常量与变量
PHP的数据类型与转换
PHP的运算符和优先规则
PHP程序的流程控制语句
PHP的数组操作及函数
PHP的字符串处理与函数
PHP自定义函数
PHP的常用系统函数
PHP的图像处理函数
PHP类编程
PHP的DataTime类
PHP处理XML和JSON
PHP的正则表达式
PHP文件和目录处理
PHP表单处理
PHP处理Cookie和Session
PHP文件上传和下载
PHP加密技术
PHP的Socket编程
PHP国际化编码
MySQL数据库基础
MySQL数据库函数
MySQL数据库账户管理
MySQL数据库基本操作
MySQL数据查询
MySQL存储过程和存储函数
MySQL事务处理和触发器
PHP操作MySQL数据库
数据库抽象层PDO
Smarty模板
ThinkPHP框架
Python语言基础
Python语言结构与控制
Python的函数和模块
Python的复合数据类型
Python面向对象编程
Python的文件操作
Python的异常处理
Python的绘图模块
Python的NumPy模块
Python的SciPy模块
Python的SymPy模块
Python的数据处理
Python操作数据库
Python网络编程
Python图像处理
Python机器学习
TensorFlow深度学习
Tensorflow常用函数
TensorFlow用于卷积网络
生成对抗网络GAN
Python Imaging Library(PIL)是Python的图像处理扩展库,提供了图像处理功能,支持多种图像格式。在PIL中主要提供了Image、ImageChops、ImageColor、ImageDraw、ImagePath、ImageFile、ImageEnhance、PSDraw以及其他一些模块来支持图像的处理,ImageGrab模块还支持对指定区域进行截图。Python 3.x一般使用pillow模块,需要使用pip3进行安装。
1. pillow模块基本用法:
from PIL import Image # 导入pillow库的Image模块
1)打开图像:
im=Image.open('sample.jpg') # 打开图像
2)显示图像:
im.show() # 显示图像
3)查看图像信息:
print(im.format) # 查看图像格式
print(im.size) # 查看图像大小,格式(宽度,高度)
print(im.height) # 查看图像高度
print(im.width) # 看看图像宽度
4)查看图像直方图:
im.histogram() # 查看图像直方图
im.histogram()[:256] # 查看第一个通道的直方图
5)读取像素值:
im.getpixel((150,80)) # 参数是元组,两个元素分别表示x和y坐标
im.putpixel((100,50),(128,30,120)) # 设置像素值,第二个元组参数是RGB颜色值
6)保存图像文件:
im.save('sample1.jpg') # 保存为另一个文件
im.save('sample.bmp') # 保存时同时进行格式转换
def img2jpg(imgFile): # 转换图像文件格式函数
if type(imgFile)==str and imgFile.endswith(('.bmp','.gif','.png')):
with Image.open(imgFile) as im:
im.convert('RGB').save(imgFile[:-3]+'jpg')
# img2jpg('1.gif')
# img2jpg('1.bmp')
# img2jpg('1.png')
7)图像缩放:
im=im.resize((100,100)) # 参数表示图像的新尺寸,分别表示宽和高
8)旋转图像:
im=im.rotate(90) # 逆时针旋转90度
im=im.transpose(Image.ROTATE_180) # 逆时针旋转180度
im=im.transpose(Image.FLIP_LEFT_RIGHT) # 水平翻转
im=im.transpose(Image.FLIP_TOP_BOTTOM) # 垂直翻转
9)图像裁剪与粘贴:
box=(120,194,220,294) # 定义裁剪区域
region=im.crop(box) # 裁剪
region=region.transpose(Image.ROTATE_180)
im.paste(region,box) # 粘贴
10)图像通道分离与合并:
r,g,b=im.split() # 将彩色图像分离为同样大小的三基色分量
imNew=Image.merge(im.mode,(r,g,b))
11)创建缩略图:
im.thumbnail((50,20)) # 参数为缩略图尺寸
im.save('2.jpg') # 保存缩略图
12)屏幕截图:
from PIL import ImageGrab
im=ImageGrab.grab((0,0,800,200)) # 截取屏幕指定区域的图像
im=ImageGrab.grab() # 不带参数表示全屏幕截图
13)图像滤波:
from PIL import ImageFilter
im=im.filter(ImageFilter.DETAIL) # 创建滤波器
im=im.filter(ImageFilter.EDGE_ENHANCE) # 边缘增强
im=im.filter(ImageFilter.EDGE_ENHANCE_MORE)
14)图像模糊:
im=im.filter(ImageFilter.BLUR)
im=im.filter(ImageFilter.GaussianBlur) # 高斯模糊
im.filter(ImageFilter.MedianFilter) # 中值滤波
15)边缘提取:
im=im.filter(ImageFilter.FIND_EDGES)
16)图像点运算:
im=im.point(lambda i:i*1.3) # 整体变亮
im=im.point(lambda i:i*0.7) # 整体变暗
im=im.point(lambda i:i*1.8 if i<100 else i*0.7) # 自定义调整图像敏感度
17)使用图像增强模块:
from PIL import ImageEnhance
enh=ImageEnhance.Brightness(im) # 图像变亮
enh.enhance(1.3).show()
18)图像冷暖色调整:
r,g,b=im.split() # 分离图像
r=r.point(lambda i:i*1.3) # 红分量变为1.3倍
g=g.point(lambda i:i*0.9)
b=b.point(lambda i:0)
im=Image.merge(im.mode,(r,g,b)) # 合并图像
im.show()
19)图像对比度增强:
from PIL import ImageEnhance
im=OmageEnhance.Contrast(im)
im=im.enhance(1.3) # 对比度增强为1.3倍
2. 图像轮廓和直方图:
from PIL import Image
from pylab import *
im=array(Image.open('example.jpg').convert('L'))
imshow(im)
x=ginput(3)
plt.show()
figure()
gray()
contour(im,origin='image')
axis('equal')
axis('off')
show()
figure()
hist(im.flatten(),128)
show()
代码中先将图像转换为灰度图像,然后使用contour()画出轮廓,使用hist()绘制直方图。代码中ginput()方法将鼠标在图像中点击的坐标自动保存在x列表中。
3. 图像灰度变换:
from PIL import Image
from pylab import *
im=array(Image.open('example.jpg').convert('L'))
subplot(221)
imshow(im)
im2=255-im # 反相处理
subplot(222)
imshow(im2)
im3=(100.0/255)*im+400 # 将图像变换到[100,200]区间
subplot(223)
imshow(im3)
im4=255.0*(im/255.0)**2 # 对图像像素值求平方后得到的图像
subplot(224)
imshow(im4)
show()
4. 直方图均衡化:
from PIL import Image
from pylab import *
def histeq(im,nbr_bins=256):
imhist,bins=histogram(im.flatten(),nbr_bins,normed=True)
cdf=imhist.cumsum()
cdf=255*cdf/cdf[-1]
im2=interp(im.flatten(),bins[:-1],cdf)
return im2.reshape(im.shape),cdf
im=array(Image.open('example.jpg').convert('L'))
im2,cdf=histeq(im)
imshow(im2)
show()
5. 动态生成比例分配图:
使用3种颜色填充矩形区域,并在每段中分别居中输出字母A、B、C,要求A、B、C各自所占比例可动态调整。
from PIL import Image,ImageDraw,ImageFont
def redraw(f,v1,v2):
start=int(600*v1)
end=int(600*v2)
im=Image.open(f)
for w in range(start): # 绘制红色区域
for h in range(36,61): # 具体数值需要根据图片大小进行调整
im.putpixel((w,h),(255,0,0))
for w in range(start,end): # 绘制绿色区域
for h in range(36,61):
im.putpixel((w,h),(0,255,0))
for w in range(end,600): # 绘制品红色区域
for h in range(36,61):
im.putpixel((w,h),(255,0,255))
draw=ImageDraw.Draw(im)
font=ImageFont.truetype('simsun.ttc',18)
draw.text((start//2,38),'A',(0,0,0),font=font) # 在各自区域内居中显示字母
draw.text(((end-start)//2+start,38),'B',(0,0,0),font=font)
draw.text(((600-end)//2+end,38),'C',(0,0,0),font=font)
im.save(f) # 保存图片
redraw(r'd:\biaotou1.png',0.1,0.9)
6. 生成验证码图片:
验证码广泛应用于用户注册、登录、留言、购物、网络支付等场合,可以有效阻止用户频繁的非法数据提交。图片验证码是比较传统的验证码方式,图片中除了经过平移、旋转、错切、缩放等基本变换的字母和数字之外,还有一些线条或其他干扰因素。
from PIL import Image,ImageDraw,ImageFont
import random
import string
# 所有可能的字符,英文字母和数字
characters=string.ascii_letters+string.digits
# 获取指定长度的字符串
def selectedCharacters(length):
'''length:the number of characters to show'''
result=''
for i in range(length):
result+=random.choice(characters)
return result
def getColor():
'''get a random color'''
r=random.randint(0,255)
g=random.randint(0,255)
b=random.randint(0,255)
return (r,g,b)
def main(size=(200,100),characterNumber=6,bgcolor=(255,255,255)):
imageTemp=Image.new('RGB', size, bgcolor)
font=ImageFont.truetype('c:\\windows\\fonts\\TIMESBD.TTF',48)
draw=ImageDraw.Draw(imageTemp)
text=selectedCharacters(characterNumber)
width,height=draw.textsize(text,font)
# 设置字体和字号
offset=2
for i in range(characterNumber):
offset+=width//characterNumber
position=(offset,(size[1]-height)//2+random.randint(-10,10))
draw.text(xy=position,text=text[i],font=font,fill=getColor())
# 对验证码图片进行简单变换,采用点运算
imageFinal=Image.new('RGB',size,bgcolor)
pixelsFinal=imageFinal.load()
pixelsTemp=imageTemp.load()
for y in range(0,size[1]):
offset=random.randint(-1,1)
for x in range(0,size[0]):
newx=x+offset
if newx>=size[0]:
newx=size[0]-1
elif newx<0:
newx=0
pixelsFinal[newx,y]=pixelsTemp[x,y]
draw=ImageDraw.Draw(imageFinal)
# 绘制干扰噪声像素
for i in range(int(size[0]*size[1]*0.07)):
draw.point((random.randint(0,size[0]),random.randint(0,size[1])),fill=getColor())
# 绘制干扰线条
for i in range(8):
start=(0,random.randint(0,size[1]-1))
end=(size[0],random.randint(0,size[1]-1))
draw.line([start,end],fill=getColor(),width=1)
# 绘制干扰弧线
for i in range(8):
start=(-50,-50)
end=(size[0]+10,random.randint(0,size[1]+10))
draw.arc(start+end,0,360,fill=getColor())
# 保存验证码图片
imageFinal.save('result.jpg')
imageFinal.show()
if __name__=='__main__':
main((200,100),8,(255,255,255))
7. gif动态图像分离与生成:
GIF(Graphics Interchange Format)是比较常见的一种动态图像,在同一个文件中存储多幅图像,将这些图像依次读出并显示,可以得到简单的动画效果。
1)示例:把GIF动画图片分离得到每帧图片
from PIL import Image,ImageDraw,ImageFont
import os
gifFileName='test.gif'
im=Image.open(gifFileName)
pngDir=gifFileName[:-4]
os.mkdir(pngDir)
try:
while True:
current=im.tell()
im.save(pngDir+'\\'+str(current)+'.png')
im.seek(current+1)
except EOFError:
pass
2)示例:把上面分离GIF文件得到的png图像文件重新合并为一个GIF文件
首先需要使用pip3安装images2gif扩展库,并修改其中426行代码:
palettes.append( getheader(im)[1] )
修改为:palettes.append( im.getheader.getdata()[1] )
然后执行以下程序:
from PIL import Image
import os
import os.path
from images2gif import *
def pngs2gif(gifName,path,duration=0.1,np=0.1):
pngFiles=[f for f in os.listdir(path)]
pngFiles.sort(key=lambda f:int(f[:-4]))
pngFiles=[os.path.join(path,f) for f in pngFiles]
images=[]
for f in pngFiles:
images.append(Image.open(f))
images2gif.writeGif(gifName,images,duration,np)
pngs2gif('abc.gif','test')
8. 材质贴图:
纹理映射中很难保证原始图片恰好和目标物体表面尺寸完全相同,这时需要对原始图片进行必要的缩放和像素采样。
from PIL import Image
from math import floor
def textureMap(srcTextureFile, dstSurfaceFile, dstWidth, dstHeight):
'''srcTextureFile原始图片,dstSurfaceFile模拟目标物体表面
dstWidth目标物体表面宽度,dstHeight目标物体表示高度'''
# 打开原始图片
srcTexture=Image.open(srcTextureFile)
# 创建指定尺寸的目标物体表面
dstSurface=Image.new('RGBA',(dstWidth,dstHeight))
srcWidth,srcHeight=srcTexture.size
# 根据指定物体表面尺寸,计算并获取原始图片中对应位置的像素值
for w in range(dstWidth):
for h in range(dstHeight):
x,y=floor(w/dstWidth*srcWidth), floor(h/dstHeight*srcHeight)
dstSurface.putpixel((w,h),srcTexture.getpixel((x,y)))
dstSurface.save(dstSurfaceFile)
dstSurface.close()
srcTexture.close()
# 也可以使用下面代码:
'''
srcTexture=Image.open(srcTextureFile)
srcTexture=srcTexture.resize((dstWidth,dstHeight))
srcTexture.save(dstSurfaceFile)
srcTexture.cloae()
'''
# 测试
textureMap('sample.jpg',r'new.png',200,250)
9. 图像融合Image Fusion:
图像融合是指将多源通道所采集到的关于同一目标的图像数据综合成高质量的图像。图像融合可以分为像素级融合、特征级融合和决策级融合,而像素级融合又有空域融合算法和变换域融合算法。示例空域融合算法的灰度加权平均法。
from PIL import Image
from random import randint
# 根据原始24位BMP文件生成指定数量含有随机噪点的临时图像
def addNoise(fileName,num):
if not fileName.endswith('.bmp'):
print('Must be bmp image')
return
for i in range(num):
im=Image.open(fileName)
width,height=im.size
n=randint(1,20)
for j in range(n):
w=randint(0,width-1)
h=randint(0,height-1)
im.putpixel((w,h),(0,0,0))
im.save(fileName[:-4]+'_'+str(i+1)+'.bmp')
# 根据多个含有随机噪点的图像,对应位置像素计算平均值,生成结果图像
def mergeOne(fileName,num):
if not fileName.endswith('.bmp'):
print('Must be bmp image')
return
ims=[Image.open(fileName[:-4]+'_'+str(i+1)+'.bmp') for i in range(num)]
im=Image.new('RGB',ims[0].size,(255,255,255))
for w in range(im.size[0]):
for h in range(im.size[1]):
r,g,b=[0]*3
for tempIm in ims:
value=tempIm.getpixel((w,h))
r+=value[0]
g+=value[1]
b+=value[2]
r=r//num
g=g//num
b=b//num
im.putpixel((w,h),(r,g,b))
im.save(fileName[:-4]+'_result.bmp')
# 对比合并后的图像和原始图像之间的相似度
def compare(fileName):
im1=Image.open(fileName)
im2=Image.open(fileName[:-4]+'_result.bmp')
width,height=im1.size
total=width*height
right=0
expectedRatio=0.05
for w in range(width):
for h in range(height):
r1,g1,b1=im1.getpixel((w,h))
r2,g2,b2=im2.getpixel((w,h))
if(abs(r1-r2),abs(g1-g2),abs(b1-b2))<(255*expectedRatio,)*3:
right+=1
return(total,right)
if __name__=='__main__':
#生成32个临时图像,然后进行融合,并对比融合后的图像与原始图像的相似度
addNoise('test.bmp',32)
mergeOne('test.bmp',32)
result=compare('test.bmp')
print('Total number of pixels:{0[0]},right number:{0[0]}'.format(result))
10. 棋盘纹理生成:
国际象棋棋盘由8行8列黑白相间的颜色区域组成,共64个小格。在制作棋盘纹理时,首先生成一个指定大小的白色图像,然后再进行区域颜色填充。
from PIL import Image
def chessgrid(fileName,width,height,color1,color2):
# 生成空白图像
im=Image.new('RGB',(width,height))
for h in range(height):
for w in range(width):
# 填充颜色交叉的图案
if(int(h/height*8)+int(w/width*8))%2==0:
im.putpixel((w,h),color1)
else:
im.putpixel((w,h),color2)
# 保存图像文件
im.save(fileName)
if __name__=='__main__':
fileName='chessgrid.jpg'
chessgrid(fileName,500,500,(128,128,128),(10,10,10))
11. 图像仿射变换:
仿射变换需要配合Scipy工具包中的ndimage模块来完成。命令:
transformed_im=ndimage.affine_transform(im,A,b,size)
其中,通过线性变换矩阵A和平移向量b对图像块进行仿射变换,选项size用来指定输出图像大小,默认输出图像为原始图像大小。示例:
from PIL import Image
from scipy import ndimage
from pylab import *
im=array(Image.open('example.jpg').convert('L'))
H=array([[1.4,0.05,-100],[0.05,1.5,100],[0,0,1]])
im2=ndimage.affine_transform(im,H[:2,:2],(H[0,2],H[1,2]))
figure()
gray()
imshow(im2)
show()