图像九宫格切分1x3、3x3 Python

文章目录

  • 1、需求
  • 2、实现
    • 2-1 贴图、切分
    • 2-2 GUI
  • 3、运行效果
  • 4、代码


1、需求

  • 把一个图像切分成 1x3 或者 3x3
  • 切分出来的图像比例希望都是 1:1 正方形
  • 如果图像尺寸满足 切分条件,自动填充一些“白边”然后继续切分
  • 如果填充了白边的话,希望能够调整原图像在画布上的位置(居中、对齐左边等)
  • 都到这了,或许可以给原图像再加一个边距,这样如果刚好够切分图像整体也会多一层“白边”

2、实现

2-1 贴图、切分

秉持着怎么方便怎么来的原则,就用一下 Pillow 库。

1、打开图像获取尺寸,计算画布大小
Image.open Image.size
2、创建新画布,并将目标贴进去
Image.new Image.paste
3、对贴好图的画布进行切分
Image.crop Image.save

2-2 GUI

界面不是很复杂,也不需要很复杂,那就用 tkinter

1、图片路径、输出路径
tkinter.filedialog tkinter.Label tkinter.Entry tkinter.Button
2、切分模式、对齐模式
tkinter.Label tkinter.Button
3、背景颜色
tkinter.Label tkinter.colorchooser.askcolor tkinter.Button
4、内边距
tkinter.Label tkinter.Scale

3、运行效果

分析结束,走你
在这里插入图片描述
3x3切分
1x3切分

4、代码

from typing import Union
from PIL import Image
from os.path import exists, split as path_split
from os import makedirs


class ImgAlign:
    START = 0
    CENTER = 1
    END = 2

    MIDDLE = (CENTER, CENTER)
    LEFT_CENTER = (START, CENTER)
    RIGHT_CENTER = (END, CENTER)

    LEFT_TOP = (START, START)
    CENTER_TOP = (CENTER, START)
    RIGHT_TOP = (END, START)

    LEFT_BOTTOM = (START, END)
    CENTER_BOTTOM = (CENTER, END)
    RIGHT_BOTTOM = (END, END)

    ALIGNS = [
            LEFT_TOP, CENTER_TOP, RIGHT_TOP,
            LEFT_CENTER, MIDDLE, RIGHT_CENTER,
            LEFT_BOTTOM, CENTER_BOTTOM, RIGHT_BOTTOM
        ]

    def __getitem__(self, item: int):
        return self.ALIGNS[item]


class ImgSpliter:
    ONELINE_MODE = 1
    THREELINE_MODE = 0
    WHITE = '#FFF'
    BLACK = '#000'
    PADDING = Union[int,
                    list[int, int], tuple[int, int],
                    list[int, int, int, int], tuple[int, int, int, int]]

    def __init__(self):
        self.id = 0

    @classmethod
    def split_it(cls, img_path: str, out_dir='./', save_origin=False, mode=ONELINE_MODE,
                 bg=WHITE, padding: PADDING = (0, 0), align=ImgAlign.MIDDLE):
        """
        切分图像
        :param img_path: 图像路径
        :param out_dir: 切分后图像保存文件夹
        :param mode: 切分模式:一行还是三行
        :param bg: 画布背景颜色。Image.new 里的color配置
        :param padding: 画布内边距(相当于原图像外边距)。可以是 n(上下左右都是n);(上下,左右) ;(上,下,下,左,右)
        :param align: 对齐方式。 ImgAlign 里的”枚举“
        :return:
        """
        _padding = (0, 0, 0, 0)
        if isinstance(padding, int):
            _padding = (padding, padding, padding, padding)
        elif isinstance(padding, (tuple, list)):
            if len(padding) == 2:
                _padding = (padding[0], padding[0], padding[1], padding[1])
            elif len(padding) == 4:
                _padding = padding
                pass
            else:
                raise ValueError("padding 数组长度应为2或者4")
        else:
            raise ValueError("padding 数组长度应为2或者4")
        im = Image.open(img_path)
        img_name = '.'.join(path_split(img_path)[-1].split('.')[:-1])
        _out_dir = out_dir + f'/{img_name}'
        img_format = im.format
        width, height = im.size
        width += _padding[2] + _padding[3]
        height += _padding[0] + _padding[1]
        if not exists(_out_dir):
            makedirs(_out_dir)
        if mode == cls.ONELINE_MODE:
            # 1、宽小于等于三倍高。总长三倍高
            if width <= height*3:
                bk_size = (height*3, height)
            # 2、宽大于三倍高。总长等于宽,总高等于三分之一长。
            else:
                fix_width = width % 3
                _width = width + (3-fix_width if fix_width else 0)
                bk_size = (_width, _width // 3)
            paste_start_x = 0  # START
            if align[0] == ImgAlign.CENTER:
                paste_start_x = (bk_size[0]-width)//2
            elif align[0] == ImgAlign.END:
                paste_start_x = bk_size[0]-width
            paste_start_y = 0  # START
            if align[1] == ImgAlign.CENTER:
                paste_start_y = (bk_size[1]-height)//2
            elif align[1] == ImgAlign.END:
                paste_start_y = bk_size[1] - height
            bk = Image.new('RGB', bk_size, bg)
            bk.paste(im, (paste_start_x+_padding[2], paste_start_y+_padding[0]))
            if save_origin:
                tail = 1
                origin_out_path = f'{_out_dir}/{img_name}_wrap.{img_format}'
                while exists(origin_out_path):
                    origin_out_path = f'{_out_dir}/{img_name}_wrap-{tail}.{img_format}'
                    tail += 1
                bk.save(origin_out_path)
            im.close()
            for i in range(3):
                curr_img = bk.crop((
                    i*bk_size[1],
                    0,
                    (i+1) * bk_size[1],
                    bk_size[1]
                ))
                tail = 1
                out_path = f'{_out_dir}/{img_name}_{i+1}.{img_format}'
                while exists(out_path):
                    out_path = f'{_out_dir}/{img_name}_{i+1}-{tail}.{img_format}'
                    tail += 1
                curr_img.save(out_path)
                curr_img.close()
                yield i+1, out_path
            bk.close()
        elif mode == cls.THREELINE_MODE:
            _canvas_size = max(width, height)
            fix_size = 3 - _canvas_size % 3 if _canvas_size % 3 else 0
            canvas_size = _canvas_size + fix_size
            per_size = canvas_size // 3

            paste_start_x = 0  # START
            if align[0] == ImgAlign.CENTER:
                paste_start_x = (canvas_size-width)//2
            elif align[0] == ImgAlign.END:
                paste_start_x = canvas_size-width
            paste_start_y = 0  # START
            if align[1] == ImgAlign.CENTER:
                paste_start_y = (canvas_size-height)//2
            elif align[1] == ImgAlign.END:
                paste_start_y = canvas_size - height

            bk = Image.new('RGB', (canvas_size, canvas_size), bg)
            bk.paste(im, (paste_start_x+_padding[2], paste_start_y+_padding[0]))
            if save_origin:
                tail = 1
                origin_out_path = f'{_out_dir}/{img_name}_wrap.{img_format}'
                while exists(origin_out_path):
                    origin_out_path = f'{_out_dir}/{img_name}_wrap-{tail}.{img_format}'
                    tail += 1
                bk.save(origin_out_path)
            im.close()
            for row in range(3):
                for col in range(3):
                    x_start = col * per_size
                    y_start = row * per_size
                    curr_img = bk.crop((
                        x_start, y_start,
                        x_start + per_size, y_start + per_size
                    ))
                    tail = 1
                    out_path = f'{_out_dir}/{img_name}_{row + 1}{col + 1}.{img_format}'
                    while exists(out_path):
                        out_path = f'{_out_dir}/{img_name}_{row + 1}{col + 1}-{tail}.{img_format}'
                        tail += 1
                    curr_img.save(out_path)
                    curr_img.close()
                    yield row*3+col+1, out_path
            bk.close()

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

挖到宝了,大数据分析工具做分析真的太快了

随着企业越做越大&#xff0c;累积数据的速度越来越快&#xff0c;但分析的效率却不升反降&#xff0c;不利于数字化运营决策。但大数据分析工具的出现让这一现象成为过去&#xff0c;无他&#xff0c;就是大数据分析工具做分析的真的太快了&#xff0c;可在任意终端上随时按需…

网络编程--socket编程

这里写目录标题 套接字概念通信原理总结 预备知识网络字节序简介字节转换函数 IP地址转换函数为什么单独列出函数原型sockaddr结构体 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录二级目录 套接字 概念 Socket本身有插座的意思&#xff0c;但他是进程之间网络通…

《LIO-SAM阅读笔记》1.IMU预积分模块

前言&#xff1a; LIO-SAM是一个多传感器融合的紧耦合SLAM框架&#xff0c;融合的传感器类型有雷达、IMU和GPS&#xff0c;其中雷达和IMU在LIO-SAM框架中必须使用的。LIO-SAM的优化策略采用了GTSAM库&#xff0c;GTSAM库采用了因子图的优化方法&#xff0c;其提供了一些列C的外…

K8S理论

kubernetes&#xff1a;8个字母省略&#xff0c;就是k8s 自动部署自动扩展和管理容器化部署的应用程序的一个开源系统 k8s是负责自动化运维管理多个容器化程序的集群&#xff0c;是一个功能强大的容器编排工具 分布式和集群化的方式进行容器化管理 版本有1.15 .1.18 .1.20 …

力扣-收集足够苹果的最小花园周长[思维+组合数]

题目链接 题意&#xff1a; 给你一个用无限二维网格表示的花园&#xff0c;每一个 整数坐标处都有一棵苹果树。整数坐标 (i, j) 处的苹果树有 |i| |j| 个苹果。 你将会买下正中心坐标是 (0, 0) 的一块 正方形土地 &#xff0c;且每条边都与两条坐标轴之一平行。 给你一个整…

【flink番外篇】7、flink的State(Keyed State和operator state)介绍及示例 - 完整版

Flink 系列文章 一、Flink 专栏 Flink 专栏系统介绍某一知识点&#xff0c;并辅以具体的示例进行说明。 1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。 2、Flink基础系列 本部分介绍Flink 的基础部分&#xff0c;比如术语、架构、编程模型、编程指南、基本的…

dpdk原理概述及核心源码剖析

dpdk原理 1、操作系统、计算机网络诞生已经几十年了&#xff0c;部分功能不再能满足现在的业务需求。如果对操作系统做更改&#xff0c;成本非常高&#xff0c;所以部分问题是在应用层想办法解决的&#xff0c;比如前面介绍的协程、quic等&#xff0c;都是在应用层重新开发的框…

docker 私有仓库

Docker 私有仓库 一、私有仓库搭建 # 1、拉取私有仓库镜像 docker pull registry # 2、启动私有仓库容器 docker run -id --nameregistry -p 5000:5000 registry # 3、打开浏览器 输入地址http://私有仓库服务器ip:5000/v2/_catalog&#xff0c;看到{"repositories&quo…

Linux操作系统——进程(三) 进程优先级

进程优先级 首先呢&#xff0c;我们知道一个进程呢&#xff08;或者也可以叫做一个任务&#xff09;&#xff0c;它呢有时候要在CPU的运行队列中排队&#xff0c;要么有时候阻塞的时候呢又要在设备的等待队列中排队&#xff0c;其实我们排队的本质就是&#xff1a;确认优先级。…

【数据结构】什么是二叉树?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;二叉树的定义 &#x1f4cc;二叉树的特点 &#x1f4cc;特殊二叉树 &#x1f4cc;二叉树的性质 &#x1f4cc;二叉树的存储结构 &#x1f4cc;二叉树…

大语言模型说明书

在浩瀚的信息宇宙中&#xff0c;大语言模型如同一颗璀璨的星星正在熠熠生辉。21世纪以来&#xff0c;人工智能可谓是飞速发展&#xff0c;从简单的神经网络到大语言模型、生成式AI&#xff0c;这并非仅仅是一种技术的进步&#xff0c;更是人类智慧的飞跃。大语言模型不仅仅是语…

opencv入门到精通——形态学转换

目录 目标 理论 1. 侵蚀 2. 扩张 3. 开运算 4. 闭运算 5. 形态学梯度 6. 顶帽 7. 黑帽 结构元素 目标 在这一章当中&#xff0c; 我们将学习不同的形态学操作&#xff0c;例如侵蚀&#xff0c;膨胀&#xff0c;开运算&#xff0c;闭运算等。我们将看到不同的功能&…

期末复习【计算机图像处理】

期末复习【计算机图像处理】 前言版权推荐期末复习期末考点内容期末考试题型一、填空 2分*10 概念二、简答 5分*2三、计算 10分*6四、绘图 10分*1 测验二测验三最后 前言 2023-12-25 15:09:07 昨天没有睡好 0点~3点看B站 Google模拟面试 3点~5点没睡着 5~6点睡了一会 6~12点终…

isp代理/双isp代理/数据中心代理的区别?如何选择?

本文我们来详细科普一下几种不同的代理类型&#xff1a;isp代理/双isp代理/数据中心代理&#xff0c;了解他们的区别&#xff0c;选择更适合自己的代理类型。 在讲述这几种代理类型之前&#xff0c;我们先复习一下代理大类有哪几种。 一、机房代理和非机房代理 在做代理ip选…

《试题与研究》期刊发表投稿方式

《试题与研究》杂志是面向全国公开发行的国家CN级权威教育期刊。创刊以来一直以服务教育服务学生为办刊宗旨&#xff0c;以优秀的内容质量和编校质量深受广大读者好评&#xff0c;其权威性、导向性、针对性、实用性在全国教育期刊中独树一帜。为推动教育科研事业的发展&#xf…

20231225使用亿佰特的蓝牙模块dongle协议分析仪E104-2G4U04A抓取BLE广播数据

20231225使用亿佰特的蓝牙模块dongle协议分析仪E104-2G4U04A抓取BLE广播数据 结论&#xff1a;硬件蓝牙分析仪 不一定比 手机端的APK的效果好&#xff01; 亿佰特E104-2G4U04A需要3片【单通道】&#xff0c;电脑端的UI为全英文的。 BLE-AnalyzerPro WCH升级版BLE-PRO蓝牙分析仪…

DRF视图组件

【1】两个视图基类 APIView APIView是 Django REST Framework 提供的一个基类&#xff0c;用于创建基于函数或基于类的视图。使用 APIView 可以根据需求自定义请求处理逻辑&#xff0c;对于简单的接口逻辑&#xff0c;可以直接继承APIView类。 GenericAPIView GenericAPIVi…

如何使用 YOLOv8 做对象检测

介绍 对象检测是一项计算机视觉任务&#xff0c;涉及识别和定位图像或视频中的对象。它是许多应用的重要组成部分&#xff0c;例如自动驾驶汽车、机器人和视频监控。 多年来&#xff0c;已经开发了许多方法和算法来查找图像中的对象及其位置。卷积神经网络对于此类任务有着非…

Dbeaver如何连接Oceanbase?

Dbeaver & Oceanbase 一、新增驱动二、连接数据库 一、新增驱动 1、新建驱动 点击数据库 -> 驱动管理器 -> 新建 2、设置驱动 驱动名称可随意填写注意驱动类型要是Generichost:port填写实际的host和port 库中新增下载的oceanbase驱动jar包 二、连接数据库 1、找…

linux 系统重启 Redis 服务

先 打开服务器 执行 sudo systemctl stop redis暂停Redis服务 然后 执行 sudo systemctl start redis启动 redis 服务 然后可以执行 sudo systemctl status redis查看 redis 状态