热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

千图成像_Python实现千图成像,祝小可爱们圣诞快乐

❝微信公众号:「Python干货铺子」关注即可开启快乐学习Python和Matlab的大门,您还在犹豫什么~❞前言当走上街头时能隐约察觉到多了些许“红白

微信公众号:「Python干货铺子」关注即可开启快乐学习Python和Matlab的大门,您还在犹豫什么~

前言

当走上街头时能隐约察觉到多了些许“红白绿”的色彩,那是:圣诞老人?、雪花❄️、圣诞树?。霓虹灯闪烁,各类促销活动海报琳琅满目。没有错,圣诞节快来了~

从写文章开始,一路上得到了不少小伙伴的支持和鼓励,而这周CSDN上的总排名不偏不倚,恰好100名整。我想,这大概是某种巧合,更确切来说应该是一种激励。近些日,严酷寒冬似乎柔情了许多,有了那么几日的柔柔暖阳,而我希望可以把这份温暖也带给大家。

我将用粉丝的头像拼接出一幅圣诞树,正所谓,“「千图成像,集万千之美」”。

一、?圣诞树?

6fb4c08eb62d5614b611476ac42ea22f.png

该图的像素为6200x10250,将其局部放大后的效果为:f44fc28b2467c810c4d278888aaf8aa9.png今天所用到的代码是比较「通用」的,只需要替换背景图和图片库即可打造属于你自己的专属图片。详情分析,客观您往下瞅瞅~

帅小伙!圣诞来袭,还不赶快用来表白一波,还在犹豫啥呢?

二、代码分析

1.头像爬取

通过爬虫将粉丝的头像下载到本地,具体分析大家可以参考我之前的博客【前方高能!看小伙是怎么表白粉丝的】,完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sat Oct 17 12:27:33 2020
@author: kimol_love
"""

import requests

def get_fansInfo():
    '''
    获取粉丝相关信息
    '''
    url = 'https://me.csdn.net/api/relation/index?pageno=%d&pagesize=%d&relation_type=fans' # 接口地址
    COOKIEs = {} # CSDN登陆后的COOKIEs
    headers = {  # 请求头
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Referer': 'https://i.csdn.net/',
        'Origin': 'https://i.csdn.net',
        'Connection': 'keep-alive',
        'TE': 'Trailers',
    }
    # 获取粉丝总数
    res = requests.get(url%(1,10),headers=headers,COOKIEs=COOKIEs)
    res_json = res.json()
    N_fans = res_json['data']['data_all']
    print('一共有%d个粉丝'%N_fans)
    # 获取全部粉丝数据
    res = requests.get(url%(1,N_fans),headers=headers,COOKIEs=COOKIEs)
    res_json = res.json()
    return res_json

def download_avatar(username,url):
    '''
    下载用户头像
    '''
    savePath = './avatars' # 头像存储目录
    res = requests.get(url)
    with open('%s/%s.jpg'%(savePath,username),'wb') as f:
        f.write(res.content)
     

if __name__ == '__main__':
    fans = get_fansInfo()
    for f in fans['data']['list']:
        username = f['fans'] # 用户名
        url = f['avatar']    # 头像地址
        download_avatar(username,url)
        print('用户"%s"头像下载完成!'%username)

将头像下载完毕并去重,结果如下:cc70f72f8deab3d20d77ab95e229b0be.png一共有2796张非重复图片,有了它们,我们便可以开始——搞事情!

2.千图成像

所谓「千图成像」就是用很多张图片拼接成一张完整的图片,它需要两个部分:「一张背景图」,「一个图片库」。根据背景图的结构用图片库中的图片来进行拼接,最终形成新的图片。

一种最简单直观的思路便是:遍历背景图中的每个像素点,并用图库中与之颜色最相近的图片粘贴在这个位置。

因此,我们首先需要计算每个图片的“平均颜色”,即图片像素点(R,G,B)的平均值,代码如下:

def compute_mean(imgPath):
    '''
    计算平均(R,G,B)
    '''
    img = Image.open(imgPath)
    img = img.convert('RGB')
    imgArray = np.array(img)
    R = np.mean(imgArray[:,:,0])
    G = np.mean(imgArray[:,:,1])
    B = np.mean(imgArray[:,:,2])
    return (R,G,B)

遍历图片库中的每张图片,并得到它们的平均距离,生成一个图片列表,以便后续的使用:

def get_imgList(imgDir):
    '''
    获取图片列表(图片目录及平均颜色)
    '''
    imgList = []
    for imgName in os.listdir(imgDir):
        path = imgDir+imgName
        color = compute_mean(path)
        imgList.append({'path':path,'RGB':color})
    return imgList

该列表的每个元素是一个字典,包括了「path」「RGB」,分别表示图片的路径以及图片的平均颜色,如下:4f86a24511c73e157cf43762ba42bda9.png在得到了图片的“平均颜色”后,便是比较背景图的像素点与它的相似性,这里采用了欧式距离:

def compute_distance(color1, color2):
    '''
    计算两张图的颜色差
    '''
    dis = 0
    for i in range(len(color1)):
        dis += (color1[i]-color2[i])**2
    dis = dis**0.5
    return dis

剩下的便是遍历背景图,并进行比较填充,代码如下:

def create_image(bgImg,imgDir,N=10,M=50):
    '''
    根据背景图,用头像填充出新图
    bgImg:背景图地址
    imgDir:头像目录
    N:背景图缩放的倍率
    M:头像的大小(MxM)
    '''
    # 获取图片列表
    imgList = get_imgList(imgDir)
    
    # 读取背景图
    bg = Image.open(bgImg)
    bg = bg.resize((bg.size[0]//N,bg.size[1]//N)) # 缩放
    bgArray = np.array(bg)
    width = bg.size[0]*M  # 新生成图片的宽度
    height = bg.size[1]*M # 新生成图片的高度
    
    # 创建空白的新图
    newImg = Image.new('RGB',(width,height))
    
    # 循环填充图
    for x in range(bgArray.shape[0]):
        for y in range(bgArray.shape[1]):
            ## 找到距离最小的图片
            minDis = 10000
            index = 0
            for img in imgList:
                dis = compute_distance(img['RGB'],bgArray[x][y])
                if dis                     index = img['path']
                    minDis = dis
            ## 填充
            tempImg = Image.open(index)
            tempImg = tempImg.resize((M,M))
            newImg.paste(tempImg,(y*M,x*M))
            print('(%d, %d)'%(x,y))
            
    # 保存图片
    newImg.save('千图成像.jpg')

调用它:

create_image('bg.jpg','./avatars(dr)/',5,50)

函数的输入有「bgImg」「imgDir」「N」「M」,它们分别表示:

参数含义
bgImg背景图的地址
imgDir图片库的目录
N背景图的压缩比率
M填充的图片大小

注:imgDir最后需要有目录连接符/,否则会报错;N是为了将背景图的尺寸进行调整压缩,否则容易因为像素点太多而执行缓慢。

最后,代码一Run,小图在手,简单的快乐,美滋滋~

写在最后

客观来说,该代码的执行效率并不高,特别是当N设置得较小(即背景图片像素点很多)或者图片库中的图片很多时。针对这个问题,也有很多优化方法,例如采用图片向量的方式对图片进行编码,进而比较等等。感兴趣的小伙伴可以参考这篇文章。如果需要完整代码,请在后台回复「千图成像」即可领取~

最后,祝愿最可爱的小伙伴们圣诞快乐?,愿我们聚于一图,焕尽万丈芒!另祝即将奔赴考研战场的小伙伴「考的都会,会的都考」!

我是kimol君,咋们下次再会~3876059238ef38088759842836cd0d3d.png创作不易,大侠请留步… 动起可爱的双手,来波点赞关注再走呗 (๑◕ܫ←๑)




推荐阅读
  • 使用 ModelAttribute 实现页面数据自动填充
    本文介绍了如何利用 Spring MVC 中的 ModelAttribute 注解,在页面跳转后自动填充表单数据。主要探讨了两种实现方法及其背后的原理。 ... [详细]
  • Python网络编程:深入探讨TCP粘包问题及解决方案
    本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ... [详细]
  • selenium通过JS语法操作页面元素
    做过web测试的小伙伴们都知道,web元素现在很多是JS写的,那么既然是JS写的,可以通过JS语言去操作页面,来帮助我们操作一些selenium不能覆盖的功能。问题来了我们能否通过 ... [详细]
  • egg实现登录鉴权(七):权限管理
    权限管理包含三部分:访问页面的权限,操作功能的权限和获取数据权限。页面权限:登录用户所属角色的可访问页面的权限功能权限:登录用户所属角色的可访问页面的操作权限数据权限:登录用户所属 ... [详细]
  • 本文介绍了使用Python和C语言编写程序来计算一个给定数值的平方根的方法。通过迭代算法,我们能够精确地得到所需的结果。 ... [详细]
  • 基于SSM框架的在线考试系统:随机组卷功能详解
    本文深入探讨了基于SSM(Spring, Spring MVC, MyBatis)框架构建的在线考试系统中,随机组卷功能的设计与实现方法。 ... [详细]
  • Python3爬虫入门:pyspider的基本使用[python爬虫入门]
    Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 探讨多种方法来确定Java对象的实际类型,包括使用instanceof关键字、getClass()方法等。 ... [详细]
  • 本文探讨为何Request对象的外观设计被认为是精妙的,重点在于其如何利用门面模式确保数据安全,同时保持系统的高效交互。 ... [详细]
  • 本文介绍了如何使用 Python 的 Pyglet 库加载并显示图像。Pyglet 是一个用于开发图形用户界面应用的强大工具,特别适用于游戏和多媒体项目。 ... [详细]
  • 本文探讨了Python中的enchant模块及其提供的dict_exists()函数,该函数用于检测特定语言词典的可用性。 ... [详细]
  • 在使用 PyInstaller 将 Python 应用程序打包成独立的可执行文件时,若项目中包含动态加载的库或插件,需要正确配置 --hidden-import 和 --add-binary 参数,以确保所有依赖项均能被正确识别和打包。 ... [详细]
  • 笔记说明重学前端是程劭非(winter)【前手机淘宝前端负责人】在极客时间开的一个专栏,每天10分钟,重构你的前端知识体系& ... [详细]
  • 在测试软件或进行系统维护时,有时会遇到电脑蓝屏的情况,即便使用了沙盒环境也无法完全避免。本文将详细介绍常见的蓝屏错误代码及其解决方案,帮助用户快速定位并解决问题。 ... [详细]
author-avatar
最佳永恒的六二
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有