ef13a40c4ef2a1f6d978fa9ee80fbe14.png

2018走到了年尾,这一年经历如何、收获几多?

很感激这一年来遇到的各路贵人、朋友,以及一直默默支持我的家人。

今天,我想用Python来表达:有你们在的样子真好~

4edffc468e559e10735b1dd2ebc66c38.png

以上是效果图,通过获取微信好友头像图片组成背景,与个人头像融合,生成新的头像图片

思路

利用开源的微信接口itchat,扫码登录个人微信,读取好友信息中的头像存到本地,对头像图片进行裁剪、拼接和融合,最后将生成的图片再发送至微信到文件传输助手~

其实获取头像图片的步骤并不复杂,按照itchat官方文档的指引代码量很小。自己要做的集中在对图片文件的处理,需要些耐心。

itchat

“itchat是一个开源的微信个人号接口,使用python调用微信从未如此简单。”

“使用不到三十行的代码,你就可以完成一个能够处理所有信息的微信机器人。”

首先是安装 pip install itchat,在代码中import itchat,之后直接调用方法即可。

#扫码登录
itchat.auto_login()

#获取好友列表
friendlist = itchat.get_friends(update=True)

# 发给文件助手
itchat.send_image('result.jpg', 'filehelper')

#退出登录
itchat.logout()

获取头像图片

通过好友列表中的信息,读取头像图片内容,存储到本地,这样就完成了头像素材的获取。

好友如果很多,这个阶段耗时会较长。此外这个过程中发现有的好友可能没有设置头像、或者头像格式比较特殊,会导致读取失败,这里要利用try except语法进行控制

def get_wx_profiles():
    #扫码登录
    itchat.auto_login()

    #获取好友列表
    friendlist = itchat.get_friends(update=True)

    #列表首位是你自己
    if friendlist[0]["PYQuanPin"]:
        user = friendlist[0]["PYQuanPin"]
    else:
        user = friendlist[0]["NickName"]

    #创建用你微信名字命名的文件夹,存储好友头像
    if not os.path.exists(user):
        os.mkdir(user)

    #先读取你的微信头像,存储为 你的名字.jpg
    self_head = "{}/{}.jpg".format(os.getcwd(),user)
    with open(self_head,'wb') as f:
        head = itchat.get_head_img(friendlist[0]['UserName'])
        f.write(head)

    print("读取本人头像完毕")

    #进入文件夹
    os.chdir(user)
    print("开始读取好友头像...")
    for i in friendlist[1:]:
        try:
            i['head_img'] = itchat.get_head_img(userName=i['UserName'])
            i['head_img_name'] = "%s.jpg" % i['UserName']
        except ConnectionError:
            print('Fail to get %s' % i['UserName'])
        try:
            with open(i['head_img_name'],'wb') as f:
                f.write(i['head_img'])
        except:
            print(i['head_img_name'],"图片下载失败")
    print("读取好友头像完毕")
    return os.getcwd(),self_head

裁剪拼接

由于每个头像图片大小不一,需要统一标准裁剪。根据头像数量,计算略大些的平方数来设置拼接后的方图尺寸。

例如,你的好友数600,略大些的平方数是25的平方625,最终拼接图大小会定为25*25头像尺寸。剩余空白位置会填充用过的头像。此外好友头像如果获取失败,在这里我会读取到的本人头像来替换,数目小先忽略。

def combine(folder,self_head):
    os.chdir(folder)
    imgList = os.listdir(folder)
    numImages = len(imgList)
    eachLine = int(math.sqrt(numImages)) + 1
    eachSize = 100
    print("好友头像设定为", eachSize, "像素,每行", eachLine, "个好友,合成图为", eachSize * eachLine,"像素的方形图")
    toImage = Image.new('RGB', (eachSize * eachLine, eachSize * eachLine), "#FFFFFF")  # 新建一块画布
    x = 0
    y = 0
    for i in range(eachLine*eachLine):
        try:
            img = Image.open(imgList[i%numImages])  # 打开图片
        except IOError:
            print("第%d位朋友头像可能没有设置头像,稍后用本人头像替代" % i)  # 有些人没设置头像,就会有异常
            img = Image.open(self_head)
        finally:
            img = img.resize((eachSize, eachSize), Image.ANTIALIAS)  # 缩小图片
            toImage.paste(img, (x * eachSize, y * eachSize))  # 拼接图片
            x += 1
        if x == eachLine:
            x = 0
            y += 1

    print("图像拼接完成")

    os.chdir(os.path.pardir)
    os.getcwd()
    print('保存拼接的图片到目录:', os.getcwd())
    toImage.save('all.jpg', quality=100)
    return eachSize * eachLine

图像融合

图像融合是在图像加法的基础上增加了系数和亮度调节量。主要调用的函数是addWeighted,链接,方法:

dst = cv2.addWeighter(scr1, alpha, src2, beta, gamma)

其中,alpha 为 src1 透明度,beta 为 src2 透明度.

目标图像 = 图像1 * 系数1 + 图像2 * 系数2 + 亮度调节量

这里我采用了原个人头像0.7系数、背景头像集合图0.3系数:

src1 = cv2.imread("resize.jpg")
src2 = cv2.imread("all.jpg")

result = cv2.addWeighted(src1,0.7,src2,0.3,0)

cv2.imwrite("result.jpg",result)

最终生成融合图,通过itchat发送到文件传输助手方便使用~

效果图

最后再附一张生成的测试图

2a5c677c67d5fbdad80db2ccdf8bd8ad.png

回顾

最初的想法是用好友头像图片来实现“千图成像”的效果,实践过程中发现要么使用头像不全、要么复杂不够美观,所以暂时采用了融合图这种简单直接的模式来做个样本。

当然,相关的千图成像算法会继续研究。

此外关于itchat的应用真的很值得一看,之后我也要多挖掘些相关的应用。

代码下载

GitHub下载链接

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐