热门标签 | 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创作不易,大侠请留步… 动起可爱的双手,来波点赞关注再走呗 (๑◕ܫ←๑)




推荐阅读
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 本文介绍如何在 Android 中自定义加载对话框 CustomProgressDialog,包括自定义 View 类和 XML 布局文件的详细步骤。 ... [详细]
  • WinMain 函数详解及示例
    本文详细介绍了 WinMain 函数的参数及其用途,并提供了一个具体的示例代码来解析 WinMain 函数的实现。 ... [详细]
  • 利用python爬取豆瓣电影Top250的相关信息,包括电影详情链接,图片链接,影片中文名,影片外国名,评分,评价数,概况,导演,主演,年份,地区,类别这12项内容,然后将爬取的信息写入Exce ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • MySQL 5.7 学习指南:SQLyog 中的主键、列属性和数据类型
    本文介绍了 MySQL 5.7 中主键(Primary Key)和自增(Auto-Increment)的概念,以及如何在 SQLyog 中设置这些属性。同时,还探讨了数据类型的分类和选择,以及列属性的设置方法。 ... [详细]
  • 本文详细介绍了如何使用Python中的smtplib库来发送带有附件的邮件,并提供了完整的代码示例。作者:多测师_王sir,时间:2020年5月20日 17:24,微信:15367499889,公司:上海多测师信息有限公司。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • MySQL Decimal 类型的最大值解析及其在数据处理中的应用艺术
    在关系型数据库中,表的设计与SQL语句的编写对性能的影响至关重要,甚至可占到90%以上。本文将重点探讨MySQL中Decimal类型的最大值及其在数据处理中的应用技巧,通过实例分析和优化建议,帮助读者深入理解并掌握这一重要知识点。 ... [详细]
  • 开发日志:高效图片压缩与上传技术解析 ... [详细]
  • 本文介绍了如何使用 Node.js 和 Express(4.x 及以上版本)构建高效的文件上传功能。通过引入 `multer` 中间件,可以轻松实现文件上传。首先,需要通过 `npm install multer` 安装该中间件。接着,在 Express 应用中配置 `multer`,以处理多部分表单数据。本文详细讲解了 `multer` 的基本用法和高级配置,帮助开发者快速搭建稳定可靠的文件上传服务。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
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社区 版权所有