对于图像识别,大量的工作在于图像的处理,处理效果好,那么才能很好地识别,因此,良好的图像处理是识别的基础。在Python中,有一个优秀的图像处理框架,就是PIL库。感觉就是装逼利器啊…

Pillow是PIL(Python Imaging Library,Python图像库)的一个分支,提供了对于开发者许多比较友好和直观的功能。

安装 Pillow:

#python3
pip3 install pillow

#python2
pip install pillow

通道
一个图片可以包含一到多个数据通道,如果这些通道具有相同的维数和深度,Pil允许将这些通道进行叠加

模式
1             1位像素,黑和白,存成8位的像素
L             8位像素,黑白
P             8位像素,使用调色板映射到任何其他模式
RGB           3×8位像素,真彩
RGBA          4×8位像素,真彩+透明通道
CMYK          4×8位像素,颜色隔离
YCbCr         3×8位像素,彩色视频格式
I             32位整型像素
F             32位浮点型像素

获取图片的基本信息

如获取图片的大小、通道、模式等信息

# coding=utf-8

from PIL import Image

im = Image.open("png/im1.png")
print im.size

# getbands() - 显示该图像的所有通道,返回一个tuple
bands = im.getbands()
# getbbox() - 返回一个像素坐标,4个元素的tuple
bboxs = im.getbbox()
# getcolors() - 返回像素信息
colors = im.getcolors()
# getextrema() - 获取图像中每个通道的像素最小和最大值,是一个tuple类型
extremas = im.getextrema()

print "bans:{0} bboxs:{1} colors:{2}  extremas:{3}".format(bands,bboxs,colors,extremas)

# getpixel() - 获取该坐标
pixels = im.getpixel((10,10))
print "pixels:{0}".format(pixels)

通道分离与合并

  • 变灰处理
  • 提出RGB通道
# coding=utf-8

from PIL import Image
import matplotlib.pyplot as plt
img=Image.open('png/im1.jpg')  #打开图像
gray=img.convert('L')   #转换成灰度
gray.show()
r,g,b=img.split()   #分离三通道
pic=Image.merge('RGB',(r,g,b)) #合并三通道
pic.show()

使用PIL 做图片混合

注意事项:

  • 两张图片必须尺寸相等,如果不相等,请先强制改变一张图的尺寸

  • 将im2合成到im1中,如果其一是透明的, 才能看到结果,不然最终结果只会显示出im2

# coding=utf-8

from PIL import Image
import os
import logging

logging.basicConfig(level=logging.INFO)

destdir="post"

def init():
	if not os.path.exists(destdir):
		os.makedirs(destdir)

def resize(_im1,_im2):
	if _im1.size != _im2.size:
		_im2 = _im2.resize(_im1.size)
		logging.info("im1 im2 size not equal, force resize im2 as im1 size")
	return _im2

def composite(_im1,_im2,_dest,_show=False):
	# 将im2合成到im1中,如果其一是透明的,
	# 才能看到结果,不然最终结果只会显示出im2
	try:
		_im2=resize(_im1,_im2)
		print _im1.size,_im2.size,_show
		newim = Image.alpha_composite(_im1,_im2)
		newim.save(destdir+"/"+_dest+".png")
		if _show :
			newim.show()
	except Exception as e:
		logging.INFO("composite err:{0}".format(e.massge))


def blend(_im1,_im2,_dest,_show=False):
	# image.blend(im1,im2,alpha) alpha为透明度
	try:
	 	_im2=resize(_im1,_im2)
		newim = Image.blend(_im1,_im2,0.1)
		newim.save(destdir+"/"+_dest+".png")
		if _show:
			newim.show()
	except Exception as e:
		logging.error("blend err,with arg:{0}".format(e.message))

def mask(_im1,_im2,_mask,_dest,_show=False):
	"""
	composite可以使用另外一个图片作为蒙板(mask),所有的这三张图片必须具备相同的尺寸,mask图片的模式可以为“1”,“L”,“RGBA”
	"""
	try:
		_im2 = resize(im1,im2)
		_mask = resize(im1,_mask)
		newim = Image.composite(_im2,_im1,_mask)
		if _show:
			newim.show()
		newim.save(destdir+"/"+_dest+".png")
		logging.info("mask {0} finish ".format(_dest))
	except Exception as e:
		logging.warning("mask err:{0}".format(e.message))


if __name__ == "__main__":
	init();
	im1 = Image.open("png/im1.png")
	im2 = Image.open("png/im2.png")
	im3 = Image.open("png/im3.png")
	composite(im1,im2,"composite",True)
	blend(im1,im2,"blend",False)
	mask(im1,im2,im3,"mask",True)

使用 PIL 做一些美术效果

所有的效果:
引入ImageFilter, 他有如下选项:

  • BLUR - 模糊处理
  • CONTOUR - 轮廓处理
  • DETAIL - 增强
  • EDGE_ENHANCE - 将图像的边缘描绘得更清楚
  • EDGE_ENHANCE_NORE - 程度比EDGE_ENHANCE更强
  • EMBOSS - 产生浮雕效果
  • SMOOTH - 效果与EDGE_ENHANCE相反,将轮廓柔和
  • SMOOTH_MORE - 更柔和
  • SHARPEN - 效果有点像DETAIL
# coding=utf-8

from PIL import Image
from PIL import ImageFilter

im = Image.open("png/im1.png")
filterimg = im.filter(ImageFilter.BLUR)
filterimg.show()

批量生成水印图

分为字体水印和图片 logo 水印

注意:

使用字体水印时,图片保存的时候一定要是 png 格式的。

# coding=utf-8

from PIL import Image, ImageDraw, ImageFont
import glob,os

size = 128,128
outdir = "jp_mark/"


# 制作字体水印
def mark_by_font(im,name,fnt):
	im = im.convert('RGBA')
	txt=Image.new('RGBA', im.size, (0,0,0,0))
	d=ImageDraw.Draw(txt)
	d.text((txt.size[0]-80,txt.size[1]-30), "cnBlogs",font=fnt, fill=(255,255,255,255))
	out=Image.alpha_composite(im, txt)
	# out.show()
	out.save(outdir+name+".png")
	print "mark_by_font:"+name

# 制作图片水印
def mark_by_img(im,name,mark):
	im = im.transpose(Image.ROTATE_270)  #顺时针旋转
	layer=Image.new('RGBA', im.size, (0,0,0,0))
	layer.paste(mark, (im.size[0]-140,im.size[1]-140))
	out = Image.composite(layer,im,layer)
	out.save(outdir+name+".jpg")
	print "mark_by_img:"+name

if __name__=="__main__":
	mark = Image.open("png/logo.gif")
	font = ImageFont.truetype("/Library/Fonts/Arial Bold.ttf", 20)
	if not os.path.exists(outdir):
			os.makedirs(outdir)

	for infile in glob.glob("jp/*.jpg"):
		im = Image.open(infile)
		file,ext = os.path.splitext(infile)
		name = file.split('/')[1]
		mark_by_font(im,name,font)
		mark_by_img(im,name,mark)

负责的像素计算

负责变黑、变亮、灰度处理等

# coding=utf-8

from PIL import Image
import os
import numpy as np
import matplotlib.pyplot as plt


destdir="post"
size=(56,56)
im = Image.open("png/im1.png")

c=Image.eval(im,lambda i:i*2)
c.show()

# 也可以用 np.asarray(im) 区别是 np.array() 是深拷贝,np.asarray() 是浅拷贝
img=np.array(im.convert('L'))

rows,cols=img.shape
# for i in range(rows):
#     for j in range(cols):
#         if (img[i,j]<=128):
#             img[i,j]=0
#         else:
#             img[i,j]=1

plt.figure("lena")
plt.imshow(img,cmap='gray')
plt.axis('off')
plt.show()

结语:有了上面强大的图像功能,我们就能很方便的批量处理大量的图片了,再也不需要美术慢慢的倒腾了。