打開國慶的正確方式,教你用OpenCV-Python輕鬆生成微信國慶版頭像

  • 2019 年 10 月 10 日
  • 筆記

文章詳情:OpenCV

相信最近兩天大家都被微信頭像的國慶版新裝刷爆了朋友圈了,不少人都@微信官方,要求換裝為國慶版頭像,朋友圈也是各種生成鏈接滿天飛。其實這個事情在小編看來沒有那麼複雜,這麼簡單的事情怎麼好意思隨便@,直接自己100行程式碼搞定。

好了,廢話少說,下面就給大家看看程式運行的效果,是不是辨識度很高,想知道怎麼做的嗎,繼續往下看!

思路分析

01

完整的程式實現分為三個部分完成,第一部分首先需要準備一個模板影像,我準備的模板影像,是從騰訊官方截取的,算是借用吧,顯示如下:

然後根據這個 模板影像,生成遮罩圖層mask影像,這裡主要是通過inRange來實現mask生成,通過imagewatch我觀察到模板圖中的空白區域的像素值為(216、216、216)所以上下浮點5,最終得到遮罩層mask影像如下:

注意:因為得到mask影像還有一些小的瑕疵,這個時候通過簡單的形態學閉操作處理就會的比較好的輪廓外形。

有了mask之後,就可以對輸入的模板影像與頭像影像,進行融合,生成一張國慶版頭像了,這個時候直接的像素相加效果會比較生硬。所以先通過高斯模糊生成邊緣的融合權重,這樣邊緣看上去比較自然。

最後對選擇的任意影像,都可以先通過人臉檢測,自動定位到人臉區域,然後截取ROI,自動生成,如果無法自動檢測到人臉,則會利用輸入影像自動生成。人臉檢測我這裡採用OpenCV DNN的人臉檢測方法,效果非常好!命中率很高!

程式碼實現

02

完整的程式碼分為三個部分

方法get_face負責輸入影像的人臉檢測與自動ROI提取與返回。程式碼如下:

def get_face(image, detect=True):      if detect is not True:          return image        # 定義人臉ROI      x = 0      y = 0      width = 0      height = 0        # 載入網路      net = cv.dnn.readNetFromTensorflow(model_bin, config=config_text)      h = image.shape[0]      w = image.shape[1]        # 人臉檢測      blobImage = cv.dnn.blobFromImage(image, 1.0, (300, 300), (104.0, 177.0, 123.0), False, False);      net.setInput(blobImage)      cvOut = net.forward()        # Put efficiency information.      t, _ = net.getPerfProfile()      label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency())      cv.putText(image, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))        # 繪製檢測矩形      count = 0      for detection in cvOut[0, 0, :, :]:          score = float(detection[2])          if score > 0.5:              left = detection[3] * w              top = detection[4] * h              right = detection[5] * w              bottom = detection[6] * h              count += 1              x = np.int32(left - 100)              y = np.int32(top - 100)              height = np.int32((bottom - top) + 200)              width = np.int32((right - left) + 200)        if x < 0:          x = 0      if y < 0:          y = 0      if x+width > w:          width = w - x      if y+height > h:          height = h - y        if count == 1:          return image[y:y + height, x:x + width, :]      else:          return image

方法generate_new_profile負責自動生成國慶版頭像,程式碼如下:

def generate_new_profile(flag_icon, avatar):      mask = cv.inRange(icon, (210, 210, 210), (225, 225, 225))      se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))      mask = cv.morphologyEx(mask, cv.MORPH_CLOSE, se)      # mask with gaussian      mask = cv.GaussianBlur(mask, (5, 5), 0)      cv.imshow("mask", mask)        # blend      h, w = mask.shape[:2]      avatar = cv.resize(avatar, (w, h), interpolation=cv.INTER_CUBIC)      cv.imshow("profile", avatar)      result = np.zeros_like(avatar)      for row in range(h):          for col in range(w):              pv = mask[row, col]              w1 = pv / 255.0              w2 = 1.0 - w1              b1, g1, r1 = avatar[row, col]              b2, g2, r2 = icon[row, col]              b1 = b1 * w1 + b2 * w2              g1 = g1 * w1 + g2 * w2              r1 = r1 * w1 + r2 * w2              result[row, col] = [np.int32(b1), np.int32(g1), np.int32(r1)]      return result

讀取本地影像,調用上述兩個方法的程式碼如下:

if __name__ == "__main__":      icon = cv.imread("D:/images/flag.png")      src = cv.imread("D:/images/zhigang.png")      cv.imshow("input", icon)      cv.imshow("profile", src)      avatar = get_face(src, False)      result = generate_new_profile(icon, avatar)      cv.imshow("result", result)      cv.imwrite("D:/result.png", result)      cv.waitKey(0)      cv.destroyAllWindows()

運行測試

傳送門->程式碼下載地址:

https://github.com/gloomyfish1998/opencv_tutorial/tree/master/python

Tags: