相似變換
相似變換:等距變換+均勻尺度縮放;
等距變換:平移+旋轉,所謂平移旋轉其實就是 wx+b,w 和 b 組成變換矩陣
在等距變換中,角度、平行性、垂直性 不發生變換
SimilarityTransform 用法
這是一個類
class SimilarityTransform(EuclideanTransform): def __init__(self, matrix=None, scale=None, rotation=None, translation=None):
參數解釋:
matrix:可選,(3,3)齊次變換矩陣,即 相似變換矩陣
Has the following form:: X = a0 * x - b0 * y + a1 = = s * x * cos(rotation) - s * y * sin(rotation) + a1 Y = b0 * x + a0 * y + b1 = = s * x * sin(rotation) + s * y * cos(rotation) + b1 where ``s`` is a scale factor and the homogeneous transformation matrix is:: [[a0 b0 a1] [b0 a0 b1] [0 0 1]]
scale:縮放因子
rotation:旋轉角度,逆時針,以弧度表示角度
translation: 平移參數(tx, ty)
相關方法
def estimate(self, src, dst): """ Parameters ---------- src : (N, 2) array Source coordinates. dst : (N, 2) array Destination coordinates. Returns ------- success : bool True, if model estimation succeeds. """
從一組對應點(源點、目標點)估計變換矩陣
示例代碼1
from skimage import transform as trans import numpy as np src = np.array([ [38.2946, 51.6963], [73.5318, 51.5014], [56.0252, 71.7366], [41.5493, 92.3655], [70.7299, 92.2041] ], dtype=np.float32) dst = np.array([ [38.2946, 51.6963], [73.5318, 51.5014], [56.0252, 71.7366], [41.5493, 92.3655], [70.7299, 92.2041] ], dtype=np.float32) tform = trans.SimilarityTransform() res =tform.estimate(dst, src) M = tform.params print(res) print(M)
獲取變換矩陣用 params
[[ 1.00000004e+00 0.00000000e+00 -2.47753889e-06] [ 0.00000000e+00 1.00000004e+00 -3.17953211e-06] [ 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
示例代碼2
from skimage import io,data from skimage import transform as tf import matplotlib.pylab as plt ### 原圖 img = data.camera() io.imshow(img) plt.show() ### 相似變換 tform = tf.SimilarityTransform(scale=1.5,rotation=np.deg2rad(10),translation=(10,12)) img1 = tf.warp(img,tform) io.imshow(img1) plt.show()
人臉對齊
在人臉識別時,有時候 檢測到的人臉是 傾斜的,此時需要把臉扶正,這就叫人臉對齊;
人臉對齊有很多方法,相似變換只是最簡單的一種;
大體思路
人臉檢測時會識別到 人臉關鍵點,這是 相似變換的源點;
假設我們最后要截取一張(112,96)大小的正臉,那么人臉的五個關鍵點分別在什么位置才算是正臉呢?所以我們需要五個參考點,作為 目標點;
根據 N 組 源點、目標點得到變換矩陣;
把整張臉 乘以 變換矩陣 得到 變換后的 正臉;
import numpy as np import cv2 import matplotlib.pylab as plt from skimage import transform ################### 人臉關鍵點標注 ################### landmark = np.array([[153, 244, 215, 214, 292, 252, 196, 292, 346, 300]]) landmark = np.reshape(landmark, (2, 5)).T print(landmark) img = cv2.imread('wt.jpg') for point in landmark: cv2.circle(img, tuple(point), 2, (0, 0, 255)) cv2.imshow('img', img) cv2.waitKey(10000) ################### 標准臉的關鍵點 ################### REFERENCE_FACIAL_POINTS = np.array([ [30.29459953, 51.69630051], [65.53179932, 51.50139999], [48.02519989, 71.73660278], [33.54930115, 92.3655014], [62.72990036, 92.20410156] ], np.float32) # Lets create a empty image| empty_img = np.zeros((112,96,3), np.uint8) for point in REFERENCE_FACIAL_POINTS: cv2.circle(empty_img, tuple(point), 2, (0, 0, 255)) plt.figure(figsize=(5, 5)) plt.imshow(empty_img) plt.show() ################### 把人臉1和標准臉對齊 ################### #### 變換矩陣 trans = transform.SimilarityTransform() res = trans.estimate(landmark, REFERENCE_FACIAL_POINTS) M = trans.params print(res) # True print(M) # 變換矩陣 # [[ 0.29581306 -0.16732268 28.26420688] # [ 0.16732268 0.29581306 -47.51195016] # [ 0. 0. 1. ]] #### 人臉對齊 print(M[:2, :]) new_img = cv2.warpAffine(img, M[:2, :], dsize=(120, 120)) cv2.imshow('new_img', new_img) cv2.waitKey(1000000)
最后一張就是 對齊后 的人臉
參考資料:
https://blog.csdn.net/C_chuxin/article/details/100546657 skimage庫的transform.SimilarityTransform()用法
https://www.jianshu.com/p/57c440af5760 人臉對齊
https://zhuanlan.zhihu.com/p/61343643 從零開始搭建人臉識別系統(二):人臉對齊