uehtml 网站源码,易企cms网站模板,深圳做电商平台网站建设,建设厅网站打不开目录
一、仿射变换
1、什么是仿射变换
2、原理
3、图像的仿射变换
1#xff09;图像的几何变换主要包括
2#xff09;图像的几何变换主要分为
1、刚性变换#xff1a;
2、仿射变换
3、透视变换
3#xff09;常见仿射变换
二、案例实现
1、定义关键点索引
2、定…目录
一、仿射变换
1、什么是仿射变换
2、原理
3、图像的仿射变换
1图像的几何变换主要包括
2图像的几何变换主要分为
1、刚性变换
2、仿射变换
3、透视变换
3常见仿射变换
二、案例实现
1、定义关键点索引
2、定义函数用于获取脸部掩膜
3、定义函数求变换矩阵
4、定义求68关键点函数
5、定义函数修改图片颜色
6、主函数
运行结果 一、仿射变换
1、什么是仿射变换 仿射变换Affine Transformation是指在向量空间中进行一次线性变换(乘以一个矩阵)和一次平移(加上一个向量)变换到另一个向量空间的过程即对图像进行形状、大小和方位的变换。 2、原理 仿射变换代表的是两幅图之间的映射关系仿射变换矩阵为2x3的矩阵如下图中的矩阵M其中的B起着平移的作用而A中的对角线决定缩放反对角线决定旋转或错切。 原像素点坐标(x,y)则矩阵仿射变换基本算法原理 所以仿射变换是一种二维坐标x,y到二维坐标u,v之间的线性变换其数学表达式如下 这个矩阵是2×3的但是这会改变原始图像的维度为此增加一个维度构造齐次变换矩阵3×3 这就保持了图像的‘平直性’和‘平行性’。 平直性直线、圆弧不变。平行性平行关系不变直线相对位置不变但是夹角可能会改变。 3、图像的仿射变换 1图像的几何变换主要包括 平移、旋转、缩放、剪切、仿射、透视等。 2图像的几何变换主要分为 刚性变换、仿射变换和透视变换投影变换 1、刚性变换 平移旋转 相似变换缩放剪切 2、仿射变换 从一个二维坐标系变换到另一个二维坐标系属于线性变换。通过已知3对坐标点可以求得变换矩阵 3、透视变换 从一个二维坐标系变换到一个三维坐标系属于非线性变换。通过已知4对坐标点可以求得变换矩阵。 3常见仿射变换 常见的仿射变换包括平移Translation、缩放Scaling、旋转Rotation、错切Shearing和镜像Flipping等 平移沿着x和y轴的平移使图像的位置发生改变。 缩放沿着x和y轴的缩放使图像的大小发生改变。 旋转绕图像中心点进行旋转使图像按某个角度进行旋转。 错切使图像在某个方向上产生倾斜。 镜像沿着x或y轴进行镜像翻转使图像左右或上下对称。 二、案例实现 1、定义关键点索引
# 定义关键点索引
JAW_POINTS list(range(0,17)) # 脸部轮廓关键点
RIGHT_BROW_POINTS list(range(17,22)) # 左眉毛
LEFT_BROW_POINTS list(range(22,27)) # 右眉毛
NOSE_POINTS list(range(27,35)) # 鼻子
RIGHT_EYE_POINTS list(range(36,42)) # 左眼
LEFT_EYE_POINTS list(range(42,48)) # 右眼
MOUTH_POINTS list(range(48,61)) # 上嘴唇
FACE_POINTS list(range(17,68)) # 除了脸颊的其余部位# 关键点集
POINTS [LEFT_BROW_POINTS RIGHT_EYE_POINTS LEFT_EYE_POINTS RIGHT_BROW_POINTS NOSE_POINTS MOUTH_POINTS]# 处理为元组后续使用方便
POINTStuple tuple(POINTS) # 元组内存放关键点集的列表 2、定义函数用于获取脸部掩膜
def getFaceMask(im,keyPoints): # 传入图像和关键点矩阵根据关键点获取脸部掩膜im np.zeros(im.shape[:2],dtypenp.float64) # 生成一个和图像大小一致的0矩阵类型为浮点型for p in POINTS: # 遍历每一个关键点的索引号points cv2.convexHull(keyPoints[p]) # 调用凸包函数获取凸包即最小凸多边形,返回凸包边界信息cv2.fillConvexPoly(im,points,color1) # 在掩膜im上填充凸包pointscolor1表示填充蓝色# 单通道im构成3通道im(3行列)改变形状(行、列、3)适应0penCVim np.array([im,im,im]).transpose((1,2,0)) # 将掩膜升高一个维度然后转换第一个维度和第三个维度的位置表示为宽、高、3通道im cv2.GaussianBlur(im,ksize(25,25),sigmaX0) # 使用高斯模糊对im掩膜进行处理高斯核大小为25*25,0表示指定高斯核在x方向的标准差设置为0表示自动计算一个合适的值return im # 返回处理完的掩膜图像 3、定义函数求变换矩阵
def getM(points1, points2):points1 points1.astype(np.float64) # int8转换为浮点数类型points2 points2.astype(np.float64) # 转换为浮点数类型c1 np.mean(points1,axis0) # 计算均值axis0表示计算行方向或垂直方向c2 np.mean(points2,axis0) # 用于归一化:(数值-均值)/标准差均值不同主要是脸五官位置大小不同points1 - c1 # 减去均值points2 - c2 # 减去均值s1 np.std(points1) # 方差计算标准差s2 np.std(points2)points1 / s1 # 除标准差,计算出归一化的结果points2 / s2 # 除标准差,计算出归一化的结果# 奇异值分解Singular Value DecompositionU, S, Vt np.linalg.svd(points1.T * points2) # points1.T * points2计算协方差矩阵使用np.linalg.svd对协方差矩阵进行奇异值分解返回三个矩阵R (U * Vt).T # 通过U和Vt计算旋转矩阵RU * Vt将points1对其到points2T为转置return np.hstack(((s2 / s1) * R,c2.T-(s2 / s1) * R * c1.T)) # 返回a仿射到b的变换矩阵# 计算一个刚体变换矩阵该矩阵可以将一个点集points1经过旋转和平移后对齐到另一个点集points2同时考虑了可能的尺度差异。4、定义求68关键点函数
def getKeyPoints(im): # 接收到一张图片获取图片中人脸的关键点rects detector(im,1) # 调用人脸检测器获取人脸方框位置返回数组类型其中存放方框左上角坐标和右下角坐标shape predictor(im,rects[0]) # 调用预训练模型,获取人脸的68个关键点s np.matrix([[p.x,p.y] for p in shape.parts()]) # shape.parts()获取关键点的迭代器遍历出来每一个关键点将遍历出来的关键点存入列表然后使用np.matrix创建一个二维矩阵return s # 返回68个关键点的坐标矩阵5、定义函数修改图片颜色
def normalColor(a, b):ksize (111,111) # 非常大的核用于进行高斯模糊的核去噪等运算时为11就比较大了aGauss cv2.GaussianBlur(a,ksize,0) # 对a进行高斯滤波bGauss cv2.GaussianBlur(b,ksize,0) # 对b进行高斯滤波weight aGauss/bGauss # 计算目标图像调整颜色的权重值,存在0除警告可忽略。where_are_inf np.isinf(weight) # 检查weight中是否有无穷大的值weight[where_are_inf] 0 # 如果有将其更改为0return b * weight # 将权重应用于图像b以调整其颜色6、主函数
a cv2.imread(pyy1.png) # 待换脸的A图片
b cv2.imread(zly1.png)detector dlib.get_frontal_face_detector() # 构造脸部位置检测器
predictor dlib.shape_predictor(shape_predictor_68_face_landmarks.dat) # 读取人脸68关键点检测器的预处理模型aKeyPoints getKeyPoints(a) # 将图片传入函数获取A图片的68个关键点坐标矩阵
bKeyPoints getKeyPoints(b)bOriginal b.copy() # 不对原来的图片b进行破坏和修改aMask getFaceMask(a,aKeyPoints) # 获取图片A的人脸掩膜
cv2.imshow(aMask,aMask) # 展示掩膜
cv2.waitKey()bMask getFaceMask(b,bKeyPoints) # 获取图片B的人脸掩膜
cv2.imshow(bMask, bMask)
cv2.waitKey()求出b脸仿射变换到a脸的变换矩阵M
M getM(aKeyPoints[POINTStuple],bKeyPoints[POINTStuple]) # 传入a脸关键点坐标和b脸关键点坐标获取a仿射到b的变换矩阵将b的脸部(bmask)根据M仿射变换到a上
dsize a.shape[:2][::-1] # 获取原图高宽然后倒序
# 目标输出与图像a大小一致
# 需要注意shape是(行、列),warpAffine参数dsize是(列、行)
# 使用a.shape[:2][::-1]获取a的(列、行)# 函数warpAffine(src,M,dsize,dstNone, flagsNone, borderModeNone, borderValueNone)
# src:输入图像
# M:运算矩阵2行3列的
# dsize:运算后矩阵的大小也就是输出图片的尺寸
# dst:输出图像
# flags:插值方法的组合与resize函数中的插值一样可以查看cv2.resize
# borderMode:边界模式BORDER_TRANSPARENT表示边界透明
# borderValue:在恒定边框的情况下使用的borderValue值;默认情况下它是0
bMaskWarp cv2.warpAffine(bMask,M,dsize,borderModecv2.BORDER_TRANSPARENT,flagscv2.WARP_INVERSE_MAP)
# 返回变换后的掩膜图像包含了根据变换矩阵M和指定大小dsize对bMask进行仿射变换的结果。cv2.imshow(bMaskWarp,bMaskWarp)
cv2.waitKey()获取脸部最大值(两个脸模板叠加)
mask np.max([aMask,bMaskWarp],axis0) # a将掩膜图像与b变换后的掩膜图像数值转变为数组类型然后沿行方向求最大值
cv2.imshow(mask,mask)
cv2.waitKey()使用仿射矩阵M将b映射到a
# 计算b图片经过变换矩阵进行仿射变换处理后的图像
bWrap cv2.warpAffine(b,M, dsize,borderModecv2.BORDER_TRANSPARENT,flagscv2.WARP_INVERSE_MAP)
cv2.imshow(bWrap,bWrap)
cv2.waitKey()# 求b图片仿射到图片a的颜色值b的颜色值改为a的颜色
bcolor normalColor(a,bWrap)
cv2.imshow(bcolor,bcolor)
cv2.waitKey()# 换脸(mask区域用bcolor非mask区城用a)
out a*(1.0-mask) bcolor * mask# 输出原始人脸、换脸结果
cv2.imshow(a,a)
cv2.imshow(b ,bOriginal)
cv2.imshow(out, out/255)
cv2.waitKey()
cv2.destroyAllWindows() 运行结果