Toriyung

导航

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为融合后增加的颜色数值(越大越趋近白色)

 

 

posted on 2022-03-13 22:41  Toriyung  阅读(31)  评论(0编辑  收藏  举报