官方Demo的效果是這樣的:
雖然基本上還算準確改化,但是對精度要求比較高的使用場景來說還是差一點。
查閱代碼
FaceStreamDetectorViewController.m
//Line 91
self.captureManager.previewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;
攝像頭預覽圖像的縮放方式為:AVLayerVideoGravityResizeAspectFill
查閱文檔
AVLayerVideoGravityResize
Specifies that the video should be stretched to fill the layer’s bounds.
AVLayerVideoGravityResizeAspect
Specifies that the player should preserve the video’s aspect ratio and fit the video within the layer’s bounds.
AVLayerVideoGravityResizeAspectFill
Specifies that the player should preserve the video’s aspect ratio and fill the layer’s bounds.
Demo中繪制關(guān)鍵點的邏輯分析如下:
1. 攝像頭捕獲到的圖像數(shù)據(jù)回調(diào):
-(void)onOutputFaceImage:(IFlyFaceImage*)faceImg;
2. 然后會調(diào)用下面這個方法對檢測到的坐標信息按照preview的大小進行縮放:
-(void)praseTrackResult:(NSString*)result OrignImage:(IFlyFaceImage*)faceImg
3.其中對關(guān)鍵點進行縮放的方法如下
-(NSMutableArray*)praseAlign:(NSDictionary* )landmarkDic OrignImage:(IFlyFaceImage*)faceImg
4. 具體執(zhí)行縮放的代碼
CGPoint pScale(CGPoint p ,CGFloat wScale, CGFloat hScale){
p.x*=wScale;
p.y*=hScale;
return p;
}
// scale coordinates so they fit in the preview box, which may be scaled
CGFloat widthScaleBy = self.previewLayer.frame.size.width / faceImg.height;
CGFloat heightScaleBy = self.previewLayer.frame.size.height / faceImg.width;
//省略中間計算屏幕旋轉(zhuǎn)的部分以及其他運算過程
p=pScale(p, widthScaleBy, heightScaleBy);
結(jié)論:繪制關(guān)鍵點的縮放方式對應的攝像頭preview的縮放方式應該是
AVLayerVideoGravityResize岩臣,而官方Demo中給的是AVLayerVideoGravityResizeAspectFill怯伊,如此導致了繪制的關(guān)鍵點偏差炫狱。
最終效果如下圖