Opencv Q&A_7
2022/03/13
基于opencv和dlib库的图像切割landmark和换色
代码
import cv2 as cv import numpy as np import dlib def nothing(x): pass def extractBlock(img,points,mode,bars_,scale=5): ### 裁剪出特定部位并进行颜色改变。 ### poly模式是多边形更精确,rect模式为最小矩阵 if mode == 'poly': mask = np.zeros_like(img) #全黑图片(0,0,0) mask = cv.fillPoly(mask, [points], (bars_[0], bars_[1], bars_[2])) #将图片特定区域填充颜色 mask = cv.GaussianBlur(mask,(17,17),50) #高斯模糊,涂色更加自然 img_poly = cv.addWeighted(img,1,mask,0.4,0) #权重叠加图片 return img_poly if mode == 'rect': bbox = cv.boundingRect(points) #可旋转最小矩阵,返回左上角坐标和宽高 x,y,w,h = bbox img_rect = img[y:y+h,x:x+w] img_rect = cv.resize(img_rect,(0,0),None,scale,scale) return img_rect def getlandmark(faces_): ### 输入所有脸框,解码坐标后找到landmark信息 for face in faces_: landlist_ = [] x1, y1 = face.left(), face.top() #解码方式!! x2, y2 = face.right(), face.bottom() landmarks = predictor(img_gray, face) #输入一维灰色图,脸框,返回68个landmark点 for n in range(68): x = landmarks.part(n).x #解码方式! y = landmarks.part(n).y landlist_.append([x, y]) # cv.circle(img,(x,y),1,(0,255,0),2) # cv.putText(img, str(n),(x+3,y),cv.FONT_HERSHEY_SIMPLEX,0.3,(0,255,0),1) # cv.rectangle(img,(x1,y1),(x2,y2),(0,255,0),2) return landlist_ cv.namedWindow('img') cv.createTrackbar('blue','img',0,255,nothing) cv.createTrackbar('green','img',0,255,nothing) cv.createTrackbar('red','img',0,255,nothing) detector = dlib.get_frontal_face_detector() #正脸检测器 predictor = dlib.shape_predictor('D:\work\\automation\Skill\Python\pythonWORK\cv\\face_land' 'mark\shape_predictor_68_face_landmarks.dat') #landmark检测器 ### 摄像机模式 不需要运行则注释下面的代码 cap = cv.VideoCapture(0) cap.set(3,720) cap.set(4,480) cap.set(10,400) while True: blue_bar = cv.getTrackbarPos('blue', 'img') green_bar = cv.getTrackbarPos('green', 'img') red_bar = cv.getTrackbarPos('red', 'img') flag,img = cap.read() img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) faces = detector(img_gray) if len(faces) != 0: landlist = getlandmark(faces) landlist = np.asarray(landlist[48:]) #嘴唇的landmark序号是48-68 mask = np.zeros_like(img) mask = cv.fillPoly(mask, [landlist], (blue_bar, green_bar, red_bar)) mask = cv.GaussianBlur(mask, (17, 17), 25) img_poly = cv.addWeighted(img, 1, mask, 0.4, 0) cv.imshow('img', img_poly) cv.waitKey(1) ### 图片模式 不需要运行则注释下面的代码 img = cv.imread('D:\work\\automation\Skill\Python\pythonWORK\cv\material\\nanami.jpg') img = cv.resize(img,(0,0),None,1.5,1.5) img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY) faces = detector(img_gray) landlist = getlandmark(faces) landlist = np.asarray(landlist[48:]) while True: blue_bar = cv.getTrackbarPos('blue', 'img') green_bar = cv.getTrackbarPos('green', 'img') red_bar = cv.getTrackbarPos('red', 'img') img_color = extractBlock(img, landlist, mode='poly', bars_=[blue_bar, green_bar, red_bar]) cv.imshow('img', img_color) cv.waitKey(1)
运行效果_1:图片模式
运行效果_2:摄像头模式(手机照片对着摄像头= =|||)
遇到的问题
Q1:detector()和predictor()返回数组的解码方式
Q2:opencv几个函数解释
将图片特定区域填充颜色。输入参数:图片,封闭点集(数组外套一层列表),颜色
2. addweighted():将两张图片融合。输入参数:图片1,图片1的权重,图片2,图片2的权重,gamma为融合后增加的颜色数值(越大越趋近白色)