圣誕節:讓Serverless送你一頂圣誕帽

圣誕節到了,我偷偷瞄了一眼,身邊人的頭像很和諧,我覺得這不正常:圣誕老人沒給你們發帽子么?

好吧,既然圣誕老人沒給大家發帽子,那Serverless架構給大家發一頂帽子吧。

先來預覽一下樣子,百度隨便找了一個圖:

image

加上圣誕帽:

image

看完效果,來測試一下功能(如果就是想玩一玩,可以直接使用我的這個接口):

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)
        }

使用方法:

下載我打包好的文件:https://serverless-framework-1256773370.cos.ap-chengdu.myqcloud.com/demo/Add-Christmas-Hat/Add-Christmas-Hat.zip

解壓出來:

image

打開命令行工具,進入到項目目錄:

image

執行serverless --debug:

image

可能會喚起二維碼登錄,手機掃碼登錄就好:

image

部署成功:

image

此時,你的接口地址就是,返回給你的地址+/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送給大家的圣誕帽了。


image
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容