图片拼接|横向拼接|竖向拼接|正方形拼接|其他模式拼接 python

  • 读取某文件夹下所有子文件夹的图片,进行拼接

文件夹

---文件夹1

|----图片1

|----图片2

---文件夹2

|----图片3

---文件夹3

|----图片4

|----图片5

python 复制代码
import os
import cv2
import numpy as np
import random
from math import ceil, sqrt


# 支持中文路径的图片读取函数
# def cv_imread(file_path):
#     cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
#     cv_img = cv2.cvtColor(cv_img, cv2.COLOR_RGB2BGR)  # 转换为 BGR 格式
#     return cv_img

def cv_imread(file_path):
    """支持中文路径的图片读取,修正反色问题"""
    cv_img = cv2.imdecode(np.fromfile(file_path, dtype=np.uint8), -1)
    return cv_img  # 不再进行颜色转换,直接返回 BGR 图像



def load_images_from_folder(folder):
    """加载指定文件夹及其子文件夹中的所有图片,支持中文路径"""
    images = []
    for root, _, files in os.walk(folder):
        for file in files:
            if file.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tiff')):
                img_path = os.path.join(root, file)
                img = cv_imread(img_path)  # 使用支持中文路径的读取方法
                if img is not None:
                    images.append(img)
    return images


def vertical_stack(images):
    """竖向拼接"""
    return np.vstack(images)


def horizontal_stack(images):
    """横向拼接"""
    return np.hstack(images)


def square_stack(images):
    """拼接成接近正方形的布局"""
    n = len(images)
    cols = ceil(sqrt(n))
    rows = ceil(n / cols)
    max_height = max(img.shape[0] for img in images)
    max_width = max(img.shape[1] for img in images)

    # 创建空白画布
    canvas = np.zeros((rows * max_height, cols * max_width, 3), dtype=np.uint8)

    for idx, img in enumerate(images):
        row = idx // cols
        col = idx % cols
        y_offset = row * max_height
        x_offset = col * max_width
        canvas[y_offset:y_offset + img.shape[0], x_offset:x_offset + img.shape[1]] = img
    return canvas


def chaotic_stack(images):
    """恶搞模式:随机旋转、缩放和排列图片"""
    canvas_size = (1000, 1000, 3)
    canvas = np.zeros(canvas_size, dtype=np.uint8)
    h, w = canvas.shape[:2]

    for img in images:
        # 随机缩放
        scale = random.uniform(0.5, 1.5)
        resized_img = cv2.resize(img, (0, 0), fx=scale, fy=scale)

        # 随机旋转
        angle = random.randint(0, 360)
        center = tuple(np.array(resized_img.shape[1::-1]) // 2)
        rot_mat = cv2.getRotationMatrix2D(center, angle, 1.0)
        rotated_img = cv2.warpAffine(resized_img, rot_mat, resized_img.shape[1::-1], flags=cv2.INTER_LINEAR,
                                     borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0))

        # 随机放置
        x_offset = random.randint(0, w - rotated_img.shape[1])
        y_offset = random.randint(0, h - rotated_img.shape[0])

        try:
            canvas[y_offset:y_offset + rotated_img.shape[0], x_offset:x_offset + rotated_img.shape[1]] = rotated_img
        except ValueError:
            # 如果超出范围,跳过
            continue
    return canvas


def save_image(output_path, image):
    """保存图片,支持中文路径"""
    cv2.imencode('.jpg', image)[1].tofile(output_path)


def main():
    folder = input("请输入图片文件夹路径:")
    output_path = input("请输入拼接后图片保存路径(如 output.jpg):")
    print("选择拼接模式:")
    print("1: 竖向拼接")
    print("2: 横向拼接")
    print("3: 拼成接近正方形")
    print("4: 恶搞模式")
    mode = int(input("请输入模式编号(1/2/3/4):"))

    images = load_images_from_folder(folder)
    if not images:
        print("未找到图片,请检查文件夹路径!")
        return

    if mode == 1:
        result = vertical_stack(images)
    elif mode == 2:
        result = horizontal_stack(images)
    elif mode == 3:
        result = square_stack(images)
    elif mode == 4:
        result = chaotic_stack(images)
    else:
        print("无效的模式编号!")
        return

    save_image(output_path, result)
    print(f"拼接完成,图片已保存至:{output_path}")


if __name__ == "__main__":
    main()
相关推荐
wangchunyu1141 小时前
JAVA CompletableFuture异步编程实战
java·开发语言·python
2501_944521593 小时前
Immer 跨端三方库仓颉适配全流程
python·eclipse·django
信誓旦旦的程序猿3 小时前
【Python量化实战宝典 #26】止损与回撤控制手册:移动止损、最大回撤(Python 可跑)
python·1024程序员节·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
2501_944521593 小时前
Deepmerge 跨端三方库仓颉适配全流程
java·python·eclipse·github
Patrick在香港3 小时前
同一行 strftime,两台机器跑出两种日期
python·datetime·时区·locale·日期处理
2601_967987373 小时前
用Python+OpenCV+YOLO写个游戏脚本:从自动瞄准到自动采集的保姆级教程
python·opencv·yolo·目标检测·游戏自动化
meiying88383 小时前
快递单号批量查询Python脚本:从手动到自动化的完整实现
开发语言·python·自动化
人工智能导论实践课4 小时前
【GUI桌面开发3】PyCharm配置外部工具
ide·python·pycharm
一千柯橘4 小时前
LangChain 的实时输出处理: stream_events 和 Streaming
python·langchain·agent
贾公子4 小时前
图片 AIGC 检测接入实战——URL 与 Base64 的取舍、体积校验与「你送过去的可能不是那张图」
python·aigc