环境与效果python3。9。6pycharm2021 库环境:dlibopencvpython 视频图片效果如下: 基本原理 使用dlib的shapepredictor68facelandmarks。dat模型获取一张有正脸的图片(1。png)和摄像头的自己的68个人脸特征点。 根据人脸特征点获取分别获取人脸掩模 对第一个图片仿射变换使其脸部对准摄像头图片中的脸部得到新的图片 对人脸掩模执行相同的操作仿射 将两个性的得到图取并集(不能让别的地方空了) 用opencv对两上面操作,对仿射变换后的a图片和摄像头图片进行泊松融合完整源码coding:utf8importcv2importdlibimportnumpyasnpdetectordlib。getfrontalfacedetector()dlib的正向人脸检测器predictordlib。shapepredictor(rshapepredictor68facelandmarks。dat)dlib的人脸形状检测器defgetimagesize(image):获取图片大小(高度,宽度):paramimage:image:return:(高度,宽度)imagesize(image。shape〔0〕,image。shape〔1〕)returnimagesizedefgetfacelandmarks(image,facedetector,shapepredictor):获取人脸标志,68个特征点:paramimage:image:paramfacedetector:dlib。getfrontalfacedetector:paramshapepredictor:dlib。shapepredictor:return:np。array(〔〔〕,〔〕〕),68个特征点detsfacedetector(image,1)shapeshapepredictor(image,dets〔0〕)facelandmarksnp。array(〔〔p。x,p。y〕forpinshape。parts()〕)returnfacelandmarksdefgetfacemask(imagesize,facelandmarks):获取人脸掩模:paramimagesize:图片大小:paramfacelandmarks:68个特征点:return:imagemask,掩模图片masknp。zeros(imagesize,dtypenp。uint8)pointsnp。concatenate(〔facelandmarks〔0:16〕,facelandmarks〔26:17:1〕〕)cv2。fillPoly(imgmask,pts〔points〕,color255)returnmaskdefgetaffineimage(image1,image2,facelandmarks1,facelandmarks2):获取图片1仿射变换后的图片:paramimage1:图片1,要进行仿射变换的图片:paramimage2:图片2,只要用来获取图片大小,生成与之大小相同的仿射变换图片:paramfacelandmarks1:图片1的人脸特征点:paramfacelandmarks2:图片2的人脸特征点:return:仿射变换后的图片threepointsindex〔18,8,25〕Mcv2。getAffineTransform(facelandmarks1〔threepointsindex〕。astype(np。float32),facelandmarks2〔threepointsindex〕。astype(np。float32))dsize(image2。shape〔1〕,image2。shape〔0〕)affineimagecv2。warpAffine(image1,M,dsize)returnaffineimage。astype(np。uint8)defgetmaskcenterpoint(imagemask):获取掩模的中心点坐标:paramimagemask:掩模图片:return:掩模中心imagemaskindexnp。argwhere(imagemask0)miny,minxnp。min(imagemaskindex,axis0)maxy,maxxnp。max(imagemaskindex,axis0)centerpoint((maxxminx)2,(maxyminy)2)returncenterpointdefgetmaskunion(mask1,mask2):获取两个掩模掩盖部分的并集:parammask1:maskimage,掩模1:parammask2:maskimage,掩模2:return:两个掩模掩盖部分的并集masknp。min(〔mask1,mask2〕,axis0)掩盖部分并集mask((cv2。blur(mask,(5,5))255)255)。astype(np。uint8)缩小掩模大小maskcv2。blur(mask,(3,3))。astype(np。uint8)模糊掩模returnmaskdefskincoloradjustment(im1,im2,maskNone):肤色调整:paramim1:图片1:paramim2:图片2:parammask:人脸mask。如果存在,使用人脸部分均值来求肤色变换系数;否则,使用高斯模糊来求肤色变换系数:return:根据图片2的颜色调整的图片1ifmaskisNone:im1ksize55im2ksize55im1factorcv2。GaussianBlur(im1,(im1ksize,im1ksize),0)。astype(np。float)im2factorcv2。GaussianBlur(im2,(im2ksize,im2ksize),0)。astype(np。float)else:im1faceimagecv2。bitwiseand(im1,im1,maskmask)im2faceimagecv2。bitwiseand(im2,im2,maskmask)im1factornp。mean(im1faceimage,axis(0,1))im2factornp。mean(im2faceimage,axis(0,1))im1np。clip((im1。astype(np。float)im2factornp。clip(im1factor,1e6,None)),0,255)。astype(np。uint8)returnim1defmain():im1cv2。imread(1。png)faceimageim1cv2。resize(im1,(600,im1。shape〔0〕600im1。shape〔1〕))landmarks1getfacelandmarks(im1,detector,predictor)68facelandmarksiflandmarks1isNone:print({}:检测不到人脸。format(imagefacepath))exit(1)im1sizegetimagesize(im1)脸图大小im1maskgetfacemask(im1size,landmarks1)脸图人脸掩模camcv2。VideoCapture(0)whileTrue:retval,im2cam。read()cameraimagelandmarks2getfacelandmarks(im2,detector,predictor)68facelandmarksiflandmarks2isnotNone:im2sizegetimagesize(im2)摄像头图片大小im2maskgetfacemask(im2size,landmarks2)摄像头图片人脸掩模affineim1getaffineimage(im1,im2,landmarks1,landmarks2)im1(脸图)仿射变换后的图片affineim1maskgetaffineimage(im1mask,im2,landmarks1,landmarks2)im1(脸图)仿射变换后的图片的人脸掩模unionmaskgetmaskunion(im2mask,affineim1mask)掩模合并affineim1skincoloradjustment(affineim1,im2,maskunionmask)肤色调整pointgetmaskcenterpoint(affineim1mask)im1(脸图)仿射变换后的图片的人脸掩模的中心点seamlessimcv2。seamlessClone(affineim1,im2,maskunionmask,ppoint,flagscv2。NORMALCLONE)进行泊松融合cv2。imshow(seamlessim,seamlessim)else:cv2。imshow(seamlessim,im2)ifcv2。waitKey(1)27:按Esc退出breakcv2。destroyAllWindows()ifnamemain:main() 完整项目文件私信回复333,可直接分享