Hello!今天我们来学习一下这个神奇的图片处理的第三方函数库——PIL库
(本blog部分图片及代码来自网络)
这是一个支持图像存储、显示和处理的函数库,它能够处理几乎所有图像格式,可以完成对图像的缩放、裁剪、叠加以及图像添加条纹,文字等信息等的操作。
首先是利用pip下载一个:
它有许多子库,例如:Image、ImageChops、ImageDraw等等,他们各有神通,发挥着自己的作用,
首先我们当然学习的是经典的Image子库;
方法 | 描述 |
Image.open(filename) | 根据参数加载图像文件 |
Image.new(mode,size,color) | 根据给定参数创建一个新的图像 |
Image.open(StringIO.StringIO(buffer)) | 从字符串中获取图像 |
Image.frombytes(mode,size,data) | 根据像素点data创建图像 |
Image.verify() | 对图像文件完整性进行检查,返回异常 |
常用函数
读取一张图片:
im=Image.open(‘test.jpg’)
显示一张图片:
im.show()
保存图片:
im.save(“save.gif”,“GIF”) #保存图像为gif格式
查看图像信息
im.format, im.size, im.mode
图片裁剪:
box=(100,100,500,500)
#设置要裁剪的区域
region=im.crop(box) #此时,region是一个新的图像对象。
改变图像的大小
out=img.resize((128,128))#resize成128*128像素大小
旋转图像
out=img.rotate(45) #逆时针旋转45度
图像类型转换
im=im.convert(“RGBA”)
(2)缩略图的学习,我们有时候为了节约储存空间,会将原来的图片进行压缩,通过等比例压缩之后会变成缩略图,那么如何用Image库来实现呢??
代码如下:
from PIL import Image
im=Image.open("test1.png")
im.thumbnail((128,128))
im.save("nest","png")
im.show("nest")
原图与缩略图如下:
from PIL import Image
im=Image.open("test1.png")
r,g,b=im.split()
newr=g.point(lambda i:i*0.9)
newg=g.point(lambda i:i<100)
om=Image.merge(im.mode,(newr,newg,b))
om.save("nest.png")
om.show("nest")
原图:
简单的来说,浮雕就是把所要呈现的图像突起于石头表面,根据凹凸的程度不同从而形成三维的立体感。
用Python画一张浮雕画,那就进行类似的原理,通过勾画图像的轮廓,并且降低周围的像素值,那就可以产生一张具有立体感的浮雕效果图片。我们可以采用相邻像素相减的方法来得到轮廓与平面的差,类似边缘的特征,从而获得这种立体感,为了增强图片的主观感受,我们还可以给这个差加上一个固定值。
那具体怎么实现呢?首先先把图片读入内存,转化为灰度图像,使用当前像素值 = 相邻像素值之差来得到图像的边缘特征,在加上固定数值150就可以得到浮雕效果了。
import cv2
import numpy as np
img = cv2.imread('E:\pythonee\LearnOpenCV\\test222.jpg',1) imgInfo = img.shape height = imgInfo[0] width = imgInfo[1] gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) dstImg = np.zeros((height,width,1),np.uint8) # 算法:newPixel = grayCurrentPixel - grayNextPixel + 150 for i in range(0,height): for j in range(0,width-1): grayCurrentPixel = int(gray[i,j]) grayNextPixel = int(gray[i,j+1]) newPixel = grayCurrentPixel - grayNextPixel + 150 if newPixel > 255: newPixel = 255 if newPixel < 0: newPixel = 0 dstImg[i,j] = newPixel cv2.imshow('dstImg',dstImg) cv2.waitKey(0)
注意在这里图像像素是用0-255的范围表示的,所以当像素值大于255时,需要将他变为255
(5)提取图片的轮廓的代码如下:
from PIL import Image
from PIL import ImageFilter
im=Image.open("test1.png")
om=im.filter(ImageFilter.CONTOUR)
om.show("nest")
原图与提取轮廓图的对比如下
(6)美白磨皮实现原理
大神提供的算法:Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100 ;
大神本神传送门,该算法其实是对 PS 的一种磨皮方案的脚本实现。
Python + OpenCV 实现
网上看到的一个基于上述公式的 python 实现方案beauty_face
,但是他再线性光叠加时出错,修正后如beauty_face2
(由于对Python矩阵运算不熟悉使用了比较笨的方法实现), 具体见代码:
#!/bin/python
# 祛痘美白
import numpy as np import cv2 def beauty_face(img): ''' Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100 ; https://my.oschina.net/wujux/blog/1563461 ''' dst = np.zeros_like(img) #int value1 = 3, value2 = 1; 磨皮程度与细节程度的确定 v1 = 3 v2 = 1 dx = v1 * 5 # 双边滤波参数之一 fc = v1 * 12.5 # 双边滤波参数之一 p = 0.1 temp4 = np.zeros_like(img) temp1 = cv2.bilateralFilter(img,dx,fc,fc) temp2 = cv2.subtract(temp1,img) temp2 = cv2.add(temp2,(10,10,10,128)) temp3 = cv2.GaussianBlur(temp2,(2*v2 - 1,2*v2-1),0) temp4 = cv2.add(img,temp3) dst = cv2.addWeighted(img,p,temp4,1-p,0.0) dst = cv2.add(dst,(10, 10, 10,255)) return dst def beauty_face2(src): ''' Dest =(Src * (100 - Opacity) + (Src + 2 * GuassBlur(EPFFilter(Src) - Src + 128) - 256) * Opacity) /100 ; ''' dst = np.zeros_like(src) #int value1 = 3, value2 = 1; 磨皮程度与细节程度的确定 v1 = 3 v2 = 1 dx = v1 * 5 # 双边滤波参数之一 fc = v1 * 12.5 # 双边滤波参数之一 p = 0.1 temp4 = np.zeros_like(src) temp1 = cv2.bilateralFilter(src,dx,fc,fc) temp2 = cv2.subtract(temp1,src) temp2 = cv2.add(temp2, (10,10,10,128)) temp3 = cv2.GaussianBlur(temp2,(2*v2 - 1,2*v2-1),0) temp4 = cv2.subtract(cv2.add(cv2.add(temp3, temp3), src), (10, 10, 10, 255)) dst = cv2.addWeighted(src,p,temp4,1-p,0.0) dst = cv2.add(dst, (10, 10, 10,255)) return dst def init(): img = cv2.imread('testimg.jpg') # blur1 = cv2.GaussianBlur(img, (5,5),0) # blur2 = cv2.bilateralFilter(img, 9 , 75, 75) blur3 = beauty_face(img) blur4 = beauty_face2(img) cv2.imshow('image0', img) # cv2.imshow('image1', blur1) # cv2.imshow('image2', blur2) cv2.imshow('image3', blur3) cv2.imshow('image4', blur4) #cv2.namedWindow('image', cv2.WINDOW_NORMAL) #cv2.resizeWindow('image', 1000, 1000) #定义frame的大小 cv2.waitKey(0) cv2.imwrite('result1.png', blur3) cv2.imwrite('result2.png', blur4) cv2.destroyAllWindows() if __name__ == "__main__": init()
实验效果图
原图:beauty_face
与 beauty_face2
对比如下:
总结
直接使用 PS 双曲线、中性灰、高低频等磨皮方案,能比自动化处理取得不错的效果,但自动化胜在傻瓜化。目前的方案是对全图做了平滑处理,并不只是对脸部,更高级方案可参考图像算法---磨皮算法研究汇总。
。