圣誕節到了,我偷偷瞄了一眼,身邊人的頭像很和諧,我覺得這不正常:圣誕老人沒給你們發帽子么?
好吧,既然圣誕老人沒給大家發帽子,那Serverless架構給大家發一頂帽子吧。
先來預覽一下樣子,百度隨便找了一個圖:
加上圣誕帽:
看完效果,來測試一下功能(如果就是想玩一玩,可以直接使用我的這個接口):
url:
http://service-8d3fi753-1256773370.bj.apigw.tencentcs.com/release/add_christmas_hat
入參:pic,,string類型,原始圖片的base64
出參:picture,string類型,戴帽子的圖片base64
基本測試代碼(Python3):
import base64
import urllib.request
import json
with open("test.png", 'rb') as f:
image = f.read()
image_base64 = str(base64.b64encode(image), encoding='utf-8')
url = "https://service-ly70xmyz-1256773370.sh.apigw.tencentcs.com/test/addChristmasHat"
data = {
"pic": image_base64
}
picture = json.loads(urllib.request.urlopen(urllib.request.Request(url=url, data=json.dumps(data).encode("utf-8"))).read().decode("utf-8"))["picture"]
imgData = base64.b64decode(picture)
with open('output.png', 'wb') as f:
f.write(imgData)
當然,有一些小伙伴可能想要把這個服務部署到自己的云函數上,那么就可以參考下文:
項目核心代碼(Python3的函數,部署在云函數就可以):
import cv2
import dlib
import base64
import json
def addHat(img, hat_img):
print("分離rgba通道,合成rgb三通道帽子圖,a通道后面做mask用")
r, g, b, a = cv2.split(hat_img)
rgbHat = cv2.merge((r, g, b))
print("dlib人臉關鍵點檢測器,正臉檢測")
predictorPath = "shape_predictor_5_face_landmarks.dat"
predictor = dlib.shape_predictor(predictorPath)
detector = dlib.get_frontal_face_detector()
dets = detector(img, 1)
print("如果檢測到人臉")
if len(dets) > 0:
for d in dets:
x, y, w, h = d.left(), d.top(), d.right() - d.left(), d.bottom() - d.top()
print("關鍵點檢測,5個關鍵點")
shape = predictor(img, d)
print("選取左右眼眼角的點")
point1 = shape.part(0)
point2 = shape.part(2)
print("求兩點中心")
eyes_center = ((point1.x + point2.x) // 2, (point1.y + point2.y) // 2)
print("根據人臉大小調整帽子大小")
factor = 1.5
resizedHatH = int(round(rgbHat.shape[0] * w / rgbHat.shape[1] * factor))
resizedHatW = int(round(rgbHat.shape[1] * w / rgbHat.shape[1] * factor))
if resizedHatH > y:
resizedHatH = y - 1
print("根據人臉大小調整帽子大小")
resizedHat = cv2.resize(rgbHat, (resizedHatW, resizedHatH))
print("用alpha通道作為mask")
mask = cv2.resize(a, (resizedHatW, resizedHatH))
maskInv = cv2.bitwise_not(mask)
print("帽子相對與人臉框上線的偏移量")
dh = 0
bgRoi = img[y + dh - resizedHatH:y + dh,
(eyes_center[0] - resizedHatW // 3):(eyes_center[0] + resizedHatW // 3 * 2)]
print("原圖ROI中提取放帽子的區域")
bgRoi = bgRoi.astype(float)
maskInv = cv2.merge((maskInv, maskInv, maskInv))
alpha = maskInv.astype(float) / 255
print("相乘之前保證兩者大小一致(可能會由于四舍五入原因不一致)")
alpha = cv2.resize(alpha, (bgRoi.shape[1], bgRoi.shape[0]))
bg = cv2.multiply(alpha, bgRoi)
bg = bg.astype('uint8')
print("提取帽子區域")
hat = cv2.bitwise_and(resizedHat, cv2.bitwise_not(maskInv))
print("相加之前保證兩者大小一致(可能會由于四舍五入原因不一致)")
hat = cv2.resize(hat, (bgRoi.shape[1], bgRoi.shape[0]))
print("兩個ROI區域相加")
addHat = cv2.add(bg, hat)
print("把添加好帽子的區域放回原圖")
img[y + dh - resizedHatH:y + dh,
(eyes_center[0] - resizedHatW // 3):(eyes_center[0] + resizedHatW // 3 * 2)] = addHat
return img
def main_handler(event, context):
try:
print("將接收到的base64圖像轉為pic")
imgData = base64.b64decode(json.loads(event["body"])["pic"])
with open('/tmp/picture.png', 'wb') as f:
f.write(imgData)
print("讀取帽子素材以及用戶頭像")
hatImg = cv2.imread("hat.png", -1)
userImg = cv2.imread("/tmp/picture.png")
output = addHat(userImg, hatImg)
cv2.imwrite("/tmp/output.jpg", output)
print("讀取頭像進行返回給用戶,以Base64返回")
with open("/tmp/output.jpg", "rb") as f:
base64Data = str(base64.b64encode(f.read()), encoding='utf-8')
return {
"picture": base64Data
}
except Exception as e:
return {
"error": str(e)
}
使用方法:
解壓出來:
打開命令行工具,進入到項目目錄:
執行serverless --debug:
可能會喚起二維碼登錄,手機掃碼登錄就好:
部署成功:
此時,你的接口地址就是,返回給你的地址+/add_christmas_hat,例如我的返回地址是:http://service-n5ahp2w4-1256773370.gz.apigw.tencentcs.com/release
則接口地址就是:
http://service-n5ahp2w4-1256773370.gz.apigw.tencentcs.com/release//add_christmas_hat
大家在自己的項目中,可以直接使用這個接口就好了。例如小程序中上傳一個圖片,發送給這個服務,或者web頁面上傳一個圖片,發送到這個服務,就可以得到Serverless送給大家的圣誕帽了。