“网格生成”案例源码详解 (Python)
testmesh.py用于生成网格
- 打开testmesh网格生成案例
- 预处理图像
- 绘制人脸关键点和左右眉毛,眼睛,嘴巴的轮廓
- 指定模型路径和输入形状
- 设置相机并开始读图
- 启动模型
打开testmesh网格生成案例
在VScode中进入代码编辑状态。
导入相关库
引用模块介绍
- math模块提供了许多对浮点数的数学运算函数。
- cv2模块是OpenCV 2.0的简写,在计算机视觉项目的开发中,OpenCV作为较大众的开源库,拥有了丰富的常用图
像处理函数库,采用C/C++语言编写,可以运行在Linux/Windows/Mac等操作系统上,能够快速的实现一些图像处理和识别的任务。 - sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互。
- NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。在机器学习算法中大部分都是调用Numpy库来完成基础数值计算的。
- blazeface:来自谷歌的研究人员通过改造mobileNet提出更为紧凑的轻量级特征提取方法、结合适用于移动端GPU高效运行的新型锚框机制,以及代替非极大值抑制的加权方法保证检测结果的稳定性,在移动端上实现了超高速的高性能人脸检测BlazeFace,最快不到一毫秒的检测速度为众多人脸相关的应用提供了更广阔的发展空间。
- cvs图形控件模块
- tflite_gpu,GPU加速代码由AID提供,TensorFlow Lite 支持多种硬件加速器。GPU 是设计用来完成高吞吐量的大规模并行工作的。因此,它们非常适合用在包含大量运算符的神经网络上,一些输入张量可以容易的被划分为更小的工作负载且可以同时执行,通常这会导致更低的延迟。在最佳情况下,用 GPU 在实时应用程序上做推理运算已经可以运行的足够快,而这在以前是不可能的。
预处理图像
#预处理图像为float32格式,float的高精度
def preprocess_image_for_tflite32(image, model_image_size=192):
#cv2.cvtColor(p1,p2) 是颜色空间转换函数,p1是需要转换的图片,p2是转换成何种格式。
#cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
#cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
#cv2.resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None) —— 将原始图像调整为指定大小。
#src是原始图像,dsize输出图像的尺寸(元组方式),这里默认参数是192*192,和模型保持一致。
image = cv2.resize(image, (model_image_size, model_image_size))
#设置axis为0,矩阵从192*192的二维矩阵变成了1*192*192的三维矩阵
image = np.expand_dims(image, axis=0)
#把image0——255的像素变到-1——1范围
image = (2.0 / 255.0) * image - 1.0
#将image转换为float32类型
image = image.astype('float32')
return image
#preprocess_img_pad,预处理图像外边缘,以免丢失边缘和角落的信息。
def preprocess_img_pad(img,image_size=128):
# fit the image into a 128x128 square
# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等。
#img.shape 参数不写的话默认读入三通道图片,例如(640,640,3)
#这里相当于把元组(640,640,3)转换为一维数组[640,640,3]
shape = np.r_[img.shape]
#shape [640 480 3]
#uint32型为无符号32位整数,占4个字节,取值范围在0~4,294,967,295之间
#shape.max()最大值为640, shape[:2]的结果为[640,480],所以pad_all的值为[0,160]
pad_all = (shape.max() - shape[:2]).astype('uint32')
#执行除法并向下取整
#pad指图像边缘需要补的长度和宽度,pad的值为[0,80]
pad = pad_all // 2
# print ('pad_all',pad_all)
#pad(array, pad_width, mode, **kwargs)
#返回值:数组
#在卷积神经网络中,为了避免因为卷积运算导致输出图像缩小和图像边缘信息丢失,常常采用图像边缘填充技术,
# 即在图像四周边缘填充0,使得卷积运算后图像大小不会缩小,同时也不会丢失边缘和角落的信息。在Python的numpy库中,常常采用numpy.pad()进行填充操作
#在卷积神经网络中,通常采用constant填充方式
#‘constant’——表示连续填充相同的值,每个轴可以分别指定填充值,constant_values=(x, y)时前面用x填充,后面用y填充,缺省值填充0,
#img_pad_ori保存填充后的图,填充原始彩色图像外边缘
img_pad_ori = np.pad(
img,
((pad[0],pad_all[0]-pad[0]), (pad[1],pad_all[1]-pad[1]), (0,0)),
mode='constant')
#处理完变成黑白图片
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#img_pad填充黑白图外边缘
img_pad = np.pad(
img,
((pad[0],pad_all[0]-pad[0]), (pad[1],pad_all[1]-pad[1]), (0,0)),
mode='constant')
#src是原始图像,dsize输出图像的尺寸(元组方式),这里默认参数是128*128,和模型保持一致。,改变填充后的黑白图像的大小为128*128
img_small = cv2.resize(img_pad, (image_size, image_size))
#np.expand_dims:用于扩展数组的形状,np.expand_dims(a, axis=0)表示在0位置添加数据
#img_small.shape=(128,128,3),3是3通道
img_small = np.expand_dims(img_small, axis=0)
# img_small (1, 128, 128, 3)在0的位置添加数据,也就是最前面
# img_small = np.ascontiguousarray(img_small)
#把img_small 0——255的像素变到-1——1范围
img_small = (2.0 / 255.0) * img_small - 1.0
#将img_small转换为float32类型
img_small = img_small.astype('float32')
# img_norm = self._im_normalize(img_small)
#pad=[ 0 80]
#pad.shape=pad (2,)
#img_pad_ori是保存填充后的图
#img_small是保存填充缩放后的图并转换成float32格式
#pad指图像边缘需要补的长度和宽度
return img_pad_ori, img_small, pad
绘制人脸关键点和左右眉毛,眼睛,嘴巴的轮廓
#绘制人脸关键点和左右眉毛,眼睛,嘴巴的轮廓
def draw_landmarks(image, mesh):
#img.shape 参数不写的话默认读入三通道图片,例如(640,480,3)
#image_size是获得图像的长度
image_size = image.shape[0]
mesh = mesh * image_size
#landmark_point 人脸关键点
landmark_point = []
#cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
#作用:根据给定的圆心和半径等画圆
#参数说明:img:输入的图片data;center:圆心位置;radius:圆的半径;color:圆的颜色;
#thickness:圆形轮廓的粗细(如果为正)。负厚度表示要绘制实心圆。lineType: 圆边界的类型。shift:中心坐标和半径值中的小数位数。
#循环绘制出人脸关键点
for point in mesh:
landmark_point.append((point[0], point[1]))
cv2.circle(image, (point[0], point[1]), 2, (255, 255, 0), -1)
# cv2.line(img, pt1, pt2, color, thickness, lineType) → img 返回img
# 这个函数是opencv中用于在图像中划线的函数
#img,背景图,pt1,直线起点坐标,pt2,直线终点坐标
#color,当前绘画的颜色。如在BGR模式下,传递(255,0,0)表示蓝色画笔。灰度图下,只需要传递亮度值即可。
#thickness,画笔的粗细,线宽。若是-1表示画封闭图像,如填充的圆。默认值是1.
#lineType,线条的类型,
#如8-connected类型、anti-aliased线条(反锯齿),默认情况下是8-connected样式ide,cv2.LINE_AA表示反锯齿线条,在曲线的时候视觉效果更佳。
if len(landmark_point) > 0:
# 参考:https://github.com/tensorflow/tfjs-models/blob/master/facemesh/mesh_map.jpg
# 左眉毛(55:内侧、46:外侧)
cv2.line(image, landmark_point[55], landmark_point[65], (0, 0, 255), 2,-3)
cv2.line(image, landmark_point[65], landmark_point[52], (0, 0, 255), 2,-3)
cv2.line(image, landmark_