O penCV轻松搞定,不信看内容

640?wx_fmt=jpeg

公众号【OpenCV学堂】,致力于计算机视觉开发技术传播,原创技术文章200+的,涉及OpenCV开发、tensorflow开发、模型解析与训练、传统图像处理算法解析,对图像与视觉感兴趣的强烈推荐关注!


相信最近两天大家都被微信头像的国庆版新装刷爆了朋友圈了,不少人都@微信官方,要求换装为国庆版头像,朋友圈也是各种生成链接满天飞。其实这个事情在小编看来没有那么复杂,这么简单的事情怎么好意思随便@,直接自己100行代码搞定。


好了,废话少说,下面就给大家看看程序运行的效果,是不是辨识度很高,想知道怎么做的吗,继续往下看!
640?wx_fmt=png


思路分析

01

完整的程序实现分为三个部分完成,第一部分首先需要准备一个模板图像,我准备的模板图像,是从腾讯官方截取的,算是借用吧,显示如下:
640?wx_fmt=png
然后根据这个 模板图像,生成遮罩图层mask图像,这里主要是通过inRange来实现mask生成,通过imagewatch我观察到模板图中的空白区域的像素值为(216、216、216)所以上下浮点5,最终得到遮罩层mask图像如下:
640?wx_fmt=png
注意:因为得到mask图像还有一些小的瑕疵,这个时候通过简单的形态学闭操作处理就会的比较好的轮廓外形。


有了mask之后,就可以对输入的模板图像与头像图像,进行融合,生成一张国庆版头像了,这个时候直接的像素相加效果会比较生硬。所以先通过高斯模糊生成边缘的融合权重,这样边缘看上去比较自然。
640?wx_fmt=png
最后对选择的任意图像,都可以先通过 人脸检测,自动定位到人脸区域,然后截取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, ( 300300), ( 104.0177.0123.0),  FalseFalse);
    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, ( 015), cv.FONT_HERSHEY_SIMPLEX,  0.5, ( 02550))

     # 绘制检测矩形
    count =  0
     for detection  in cvOut[ 00, :, :]:
        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, ( 210210210), ( 225225225))
    se = cv.getStructuringElement(cv.MORPH_RECT, ( 33))
    mask = cv.morphologyEx(mask, cv.MORPH_CLOSE, se)
     # mask with gaussian
    mask = cv.GaussianBlur(mask, ( 55),  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()


运行测试
640?wx_fmt=png
传送门->代码下载地址:
https://github.com/gloomyfish1998/opencv_tutorial/tree/master/python
Logo

为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。

更多推荐