如何用Python实现图像拼接画(把一堆小图拼成大图)

news2024/12/26 10:50:36

诸神缄默不语-个人CSDN博文目录

在这里的图像拼接画指的是一张大图由很多小图组成,效果就像这样:
在这里插入图片描述

原理:将大图拆成很多小块,每一块计算平均颜色,用平均颜色最相近的小图来替代,就可以。
直接遍历就可以,也就跑几个小时。如果想要加速的话可以考虑研究一下用多线程或者多进程来实现。

注意本博文中涉及的实验都是在Windows平台上实现的,如果要转成其他系统需要尤其注意文件路径格式。

文章目录

  • 1. 预处理小图:计算每张图的平均颜色,并放到一个新的文件夹中
  • 2. 用小图拼大图

1. 预处理小图:计算每张图的平均颜色,并放到一个新的文件夹中

jupyter notebook格式的代码文件:https://github.com/PolarisRisingWar/all-notes-in-one/blob/main/小图拼大图1-计算小图平均RGB颜色.ipynb

我是直接用CIFAR10的图片来作为小图了。

CIFAR10我是之前做PyTorch 60分钟速成的时候就下载过。这个教程我写过笔记:60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)学习笔记
下载的核心代码是:

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,  download=True, transform=transform)
testset = torchvision.datasets.CIFAR10(root='./data', train=False,  download=True, transform=transform)

代码:
调包→设置参数和工具函数→展示示例图片

import pickle

import numpy as np
import matplotlib.pyplot as plt

def unpickle(file):
    """cifar10数据官方提供的导入代码"""
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='bytes')
    return dict

#设置参数
cifar10_path=r'data\cifar-10-batches-py'
cifar10_file_name=[r'\data_batch_'+str(i) for i in range(1,6)]
cifar10_file_name.append(r'\test_batch')

cifa10_avgcolor_folder=r"data\cifar10-avgcolor"

#展示一张示例图
p='data\cifar-10-batches-py\data_batch_1'
d=unpickle(p)
 
e=d[b'data']
for i in range(100):
    image=e[i]
    red_image=image[:1024].reshape(32,32)
    green_image=image[1024:2048].reshape(32,32)
    blue_image=image[2048:].reshape(32,32)
    result_img=np.ones((32, 32, 3), dtype=np.uint8)
    result_img[:,:,0]=red_image
    result_img[:,:,1]=green_image
    result_img[:,:,2]=blue_image
    plt.imshow(result_img)
    break

在这里插入图片描述

%%time
#遍历所有图片,计算其平均RGB颜色,将其分别存储至对应文件中
for file_name in cifar10_file_name:  #遍历所有batch
    cifar10_batch=cifar10_path+file_name  #该batch对应的路径
    cifar10_batch_unpickle=unpickle(cifar10_batch)
    file_r=open(cifa10_avgcolor_folder+"\\"+file_name+'_r',mode='w')
    file_g=open(cifa10_avgcolor_folder+"\\"+file_name+'_g',mode='w')
    file_b=open(cifa10_avgcolor_folder+"\\"+file_name+'_b',mode='w')
    for picture in cifar10_batch_unpickle[b'data']:
        file_r.write(str(np.mean(picture[:1024]))+'\n')
        file_g.write(str(np.mean(picture[1024:2048]))+'\n')
        file_b.write(str(np.mean(picture[2048:]))+'\n')
    file_r.close()
    file_g.close()
    file_b.close()

2. 用小图拼大图

jupyter notebook格式的代码文件:https://github.com/PolarisRisingWar/all-notes-in-one/blob/main/小图拼大图2.ipynb

大图原始图像是我从网上随便找的一张刘亦菲的写真:
在这里插入图片描述
代码:
调包→设置参数和功能函数→展示大图原图

#导包
import pickle

from PIL import Image

import numpy as np
import matplotlib.pyplot as plt

def unpickle(file):
    """cifar10数据官方提供的导入代码"""
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='bytes')
    return dict

#参数配置
portrait_path=r'liuyifei.jpeg'

block=5  #5*5为一个色块

#小图
cifar10_path=r'data\cifar-10-batches-py'
cifar10_file_names=[r'\data_batch_'+str(i) for i in range(1,6)]
cifar10_file_names.append(r'\test_batch')

cifa10_avgcolor_folder=r"data\cifar10-avgcolor"

#展示原图
portrait_picture=Image.open(portrait_path)
plt.imshow(portrait_picture)

在这里插入图片描述

将图片加载到内存中→设置图像拼接的功能函数

#将图片转换为np.ndarray
portrait_matrix=portrait_picture.convert("RGB")
portrait_ndarray = np.array(portrait_matrix)

#将小图的RGB加载到内存中
little_rgbs={}
for file_name in cifar10_file_names:
    with open(cifa10_avgcolor_folder+"\\"+file_name+'_r') as f:
        little_rgbs[file_name+'_r']=f.readlines()
    with open(cifa10_avgcolor_folder+"\\"+file_name+'_g') as f:
        little_rgbs[file_name+'_g']=f.readlines()
    with open(cifa10_avgcolor_folder+"\\"+file_name+'_b') as f:
        little_rgbs[file_name+'_b']=f.readlines()

#将小图的batch加载到内存中
cifar10_batches=[]
for file_name in cifar10_file_names:  #遍历所有batch
    cifar10_batch=cifar10_path+file_name  #该batch对应的路径
    cifar10_batches.append(unpickle(cifar10_batch)[b'data'])

def convert_smalls_to_big(block_dim:int):
    """
    将一堆小图转换为大图,入参为大图色块的维度,返回新图
    """
    old_shape=portrait_ndarray.shape
    heng_dim=int(old_shape[0]/block_dim)
    zong_dim=int(old_shape[1]/block_dim)
    new_picture=np.ndarray(shape=(heng_dim*32,zong_dim*32,3),dtype=np.int16)
    for i in range(heng_dim):
        for j in range(zong_dim):
            old_matrix=portrait_ndarray[i*block_dim:(i+1)*block_dim,j*block_dim:(j+1)*block_dim,:]
            r=np.mean(old_matrix[:,:,0])
            g=np.mean(old_matrix[:,:,1])
            b=np.mean(old_matrix[:,:,2])
            
            least_distance=450  #理论最大值应该是np.sqrt(255*255+255*255+255*255)≈442
            least_distance_batch_index=0
            least_distance_picture_index=0
            
            for index in range(6):
                #遍历每一个batch
                for picture_index in range(len(cifar10_batches[index])):
                    #遍历每一张小图,找到平均RGB跟色块RGB最相近的小图,用这个小图来顶替大图的对应色块
                    little_r=float(little_rgbs[cifar10_file_names[index]+'_r'][picture_index])
                    little_g=float(little_rgbs[cifar10_file_names[index]+'_g'][picture_index])
                    little_b=float(little_rgbs[cifar10_file_names[index]+'_b'][picture_index])
                    distance=np.sqrt((little_r-r)**2+(little_g-g)**2+(little_b-b)**2)
                    if distance<least_distance:
                        least_distance=distance
                        least_distance_batch_index=index
                        least_distance_picture_index=picture_index
            little_picture=cifar10_batches[least_distance_batch_index][least_distance_picture_index]
            new_picture[i*32:(i+1)*32,j*32:(j+1)*32,0]=np.reshape(little_picture[:1024],(32,32)).copy()
            new_picture[i*32:(i+1)*32,j*32:(j+1)*32,1]=little_picture[1024:2048].reshape(32,32)
            new_picture[i*32:(i+1)*32,j*32:(j+1)*32,2]=little_picture[2048:].reshape(32,32)
    plt.imshow(new_picture)
    plt.savefig("picture1.png")

拼接图像:

%%time
convert_smalls_to_big(block)

Wall time: 1h 23min 27s
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1205596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

No198.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

雷达波形及MATLAB仿真

文章目录 前言一、雷达波形二、Matlab 仿真1、SFW 的距离分辨率和距离模糊①、MATLAB 源码②、仿真结果 三、资源自取 前言 本文对雷达波形的内容以思维导图的形式呈现&#xff0c;有关仿真部分进行了讲解实现。 一、雷达波形 思维导图如下图所示&#xff0c;如有需求请到文章…

C#中.NET 6.0控制台应用通过EF访问已建数据库

目录 一、新建.NET 6.0控制台应用并建立数据库连接 二、下载并安装EF程序包 三、自动生成EF模型和上下文 1.Blog类模型 2.Post类模型 3.数据库上下文 四、设计自己的应用 VS2022的.NET6.0、.NET7.0框架下默认支持EF7&#xff08;版本号7.0.13&#xff09;&#xff0c;除…

《QT从基础到进阶·二十五》界面假死处理

假如有这样一种情况&#xff0c;我们在主线程写了一个死循环&#xff0c;当程序运行到主线程的死循环代码后界面便卡死点了没有反应&#xff0c;这里提供几种方法处理界面假死的情况&#xff0c;保证比如主线程在执行死循环没有退出的时候点击界面不会卡死能继续执行其他功能。…

【c++】——类和对象(中)——实现完整的日期类

作者:chlorine 专栏:c专栏 我的花一定会开。 【学习目标】 拷贝复制——赋值运算符重载 目录 &#x1f393;运算符重载(-><...) &#x1f393;日期&天数 &#x1f393;前置和后置重载 我们完成了赋值运算符重载章节的学习&#xff0c;对operator关键字的使用有…

wpf devexpress项目中添加GridControl绑定数据

本教程讲解了如何添加GridControl到wpf项目中并且绑定数据 原文地址Lesson 1 - Add a GridControl to a Project and Bind it to Data | WPF Controls | DevExpress Documentation 1、使用 DevExpress Template Gallery创建一个新的空白mvvm应用程序&#xff0c;这个项目包括了…

算法笔记-第七章-队列

算法笔记-第七章-队列 队列的相关知识点c中队列queue用法队列的操作序列求和队列约瑟夫环-队列匹配队列 队列的相关知识点 大佬的讲解 c中队列queue用法 一&#xff1a;queue是一种容器转换器模板&#xff0c;调用#include< queue>即可使用队列类 二&#xff1a;使用q…

Python--集合----无序,去重,空集合只能用set()方法

集合&#xff08;set&#xff09;是一个无序的不重复元素序列。 特点&#xff1a;天生去重 无序 集合定义&#xff1a;在Python中&#xff0c;我们可以使用一对花括号 {} 或者 set()方法 来定义集合&#xff0c; 但是如果你 定义的集合是一个 空集合&#xf…

SpringCloud Alibaba(上):注册中心-nacos、负载均衡-ribbon、远程调用-feign

Nacos 概念&#xff1a;Nacos是阿里巴巴推出的一款新开源项目&#xff0c;它是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos致力于帮助用户发现、配置和管理微服务&#xff0c;它提供了一组简单易用的特性集&#xff0c;包括动态服务发现、服务配置…

线性代数本质系列(二)矩阵乘法与复合线性变换,行列式,三维空间线性变换

本系列文章将从下面不同角度解析线性代数的本质&#xff0c;本文是本系列第二篇 向量究竟是什么&#xff1f; 向量的线性组合&#xff0c;基与线性相关 矩阵与线性相关 矩阵乘法与复合线性变换 三维空间中的线性变换 行列式 逆矩阵&#xff0c;列空间&#xff0c;秩与零空间 克…

P6入门:项目初始化9-项目详情之资源 Resource

前言 使用项目详细信息查看和编辑有关所选项目的详细信息&#xff0c;在项目创建完成后&#xff0c;初始化项目是一项非常重要的工作&#xff0c;涉及需要设置的内容包括项目名&#xff0c;ID,责任人&#xff0c;日历&#xff0c;预算&#xff0c;资金&#xff0c;分类码等等&…

HTTP服务器——tomcat的安装和使用

文章目录 前言下载tomcattomcat 文件bin 文件夹conf 文件lib 文件log 文件temp 文件webapps 文件work 目录 如何使用 tomcat 前言 前面我们已经学习了应用层协议 HTTP 协议和 HTTP 的改进版——HTTPS&#xff0c;这些协议是我们在写与服务器相关的代码的时候息息相关的&#x…

cocosCreator 之内存管理和释放

版本&#xff1a; 3.4.0 语言&#xff1a; TypeScript 环境&#xff1a; Mac 回顾 前面有两篇博客说明了&#xff1a; cocosCreator 之 resources动态加载、预加载 讲述了静态引用资源&#xff0c;动态加载和预加载相关cocosCreator 之 Bundle 讲述了AssetManager关于对内置…

将随机数设成3407,让你的深度学习模型再涨一个点!文再附3种随机数设定方法

随机数重要性 深度学习已经在计算机视觉领域取得了巨大的成功&#xff0c;但我们是否曾想过为什么同样的模型在不同的训练过程中会有不同的表现&#xff1f;为什么使用同样的代码&#xff0c;就是和别人得到的结果不一样&#xff1f;怎么样才能保证自己每次跑同一个实验得到的…

技术管理责任制度《一》

一、技术管理机构责任制 (1) 按各级技术人员的职责范围&#xff0c;分工负责&#xff0c;做好经常性的技术业务工作。 (2) 组织贯彻执行国家有关技术政策和上级办法的技术标准、规定、规程、和各项技术管理制。 (3) 负责收集和提供技术情报、技术资料、技术建议和技术措施等。 …

什么是状态机?

什么是状态机&#xff1f; 定义 我们先来给出状态机的基本定义。一句话&#xff1a; 状态机是有限状态自动机的简称&#xff0c;是现实事物运行规则抽象而成的一个数学模型。 先来解释什么是“状态”&#xff08; State &#xff09;。现实事物是有不同状态的&#xff0c;例…

Spark3.0中的AOE、DPP和Hint增强

1 Spark3.0 AQE Spark 在 3.0 版本推出了 AQE&#xff08;Adaptive Query Execution&#xff09;&#xff0c;即自适应查询执行。AQE 是 Spark SQL 的一种动态优化机制&#xff0c;在运行时&#xff0c;每当 Shuffle Map 阶段执行完毕&#xff0c;AQE 都会结合这个阶段的统计信…

[工业自动化-19]:西门子S7-15xxx编程 - 软件编程 - PLC程序块、组织块OB与PLC多线程原理、OB、FC、FB、DB

目录 一、PLC的块的种类 1.1 什么是块 1.2 块的种类 1.3 不同块之间的相互调用关系 1.4 OB、FC、FB和DB 二、PLC程序组织块OB 2.1 什么是程序块OB 2.2 为什么需要程序块OB 2.3 PLC有哪些程序块 2.4 如何使用程序块 - OB块的执行顺序和规则 2.5 PLC用户程序主函数&am…

2023.11.12使用flask对图片进行黑白处理(base64编码方式传输)

2023.11.12使用flask对图片进行黑白处理&#xff08;base64编码方式传输&#xff09; 由前端输入图片并预览&#xff0c;在后端处理图片后返回前端显示&#xff0c;可以作为图片处理的模板。 关键点在于对图片进行base64编码的转化。 使用Base64编码可以更方便地将图片数据嵌入…

sass 生成辅助色

背景 一个按钮往往有 4 个状态。 默认状态hover鼠标按下禁用状态 为了表示这 4 个状态&#xff0c;需要设置 4 个颜色来提示用户。 按钮类型一般有 5 个&#xff1a; 以 primary 类型按钮为例&#xff0c;设置它不同状态下的颜色&#xff1a; <button class"btn…