当前位置: 首页 > backend >正文

【教学类-34-12】20250509(通义万相)4*3蝴蝶拼图(圆形、三角、正方、半圆的凹凸小块+数字提示+参考图灰色)

背景介绍

制作了四款异形角拼图,初步实现效果

【教学类-34-10】20250503(通义万相)4*3蝴蝶拼图(圆形、三角、正方、半圆的凹凸小块+参考图灰色)-CSDN博客文章浏览阅读1.4k次,点赞46次,收藏15次。【教学类-34-10】20250503(通义万相)4*3蝴蝶拼图(圆形、三角、正方、半圆的凹凸小块+参考图灰色) https://blog.csdn.net/reasonsummer/article/details/147654458?sharetype=blogdetail&sharerId=147654458&sharerefer=PC&sharesource=reasonsummer&spm=1011.2480.3001.8118

存在问题

拼图多了,切开来,搞不清楚是那个蝴蝶的拼图的图片。

所以我需要在拼图块后面画上数字。

WORD模版

代码展示

1、圆形凹凸拼图3:4+数字编号+灰色参考图
 

'''
目的:3*4彩色拼图(圆形凹凸),+背面数字编号,有灰色参考图,插入WORD,
作者:deepseek,阿夏
时间:20250503
'''import os
import time
import random
from PIL import Image, ImageDraw, ImageEnhance
from docx import Document
from docx.shared import Cm, Pt
from docx.shared import RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from docx2pdf import convert# sj=int(input('1:顺序插入、2:乱序\n'))
# 配置参数
yangshi = 0.56
wide = 3
high = 4
Number = wide * high
border_width = 5  # 5磅黑色实线# 路径设置
path = r'D:\20250506彩色蝴蝶无白色'
prz = os.path.join(path, "01图片")
pathz = [os.path.join(prz, f) for f in os.listdir(prz) if f.endswith(".png")]
print(f"找到{len(pathz)}张原始图片")# 画布尺寸配置
canvas_width = 2830  # 画布宽度
canvas_height = 1950  # 画布高度
cell_width = canvas_width // high
cell_height = canvas_height // widedef convert_to_light_gray(image):"""将图像转为浅灰色(保留透明度)"""# 转为灰度图gray = image.convert('L')# 提高亮度enhancer = ImageEnhance.Brightness(gray)light_gray = enhancer.enhance(1.9)# 合并回RGBA图像return Image.merge('RGBA', (light_gray, light_gray, light_gray, image.split()[3]))def draw_border_on_edge(img, border_width=5):"""在透明与非透明交界处绘制黑色实线"""img = img.convert("RGBA")width, height = img.sizedraw = ImageDraw.Draw(img)pixels = img.load()edge_map = set()# 找出所有边缘像素for x in range(width):for y in range(height):if pixels[x, y][3] > 0:  # 如果当前像素不透明for dx in [-1, 0, 1]:for dy in [-1, 0, 1]:if dx == 0 and dy == 0:continuenx, ny = x + dx, y + dyif 0 <= nx < width and 0 <= ny < height:if pixels[nx, ny][3] == 0:  # 相邻像素透明edge_map.add((x, y))break# 在边缘像素处绘制黑线for x, y in edge_map:for i in range(max(0, x-border_width//2), min(width, x+border_width//2+1)):for j in range(max(0, y-border_width//2), min(height, y+border_width//2+1)):if (i - x)**2 + (j - y)**2 <= (border_width//2)**2:draw.point((i, j), fill=(0, 0, 0, 255))return imgdef SplitImages(img_path, row, col):"""分割原始图片为row×col的小图"""img = Image.open(img_path).convert("RGBA")imgSize = img.sizesplitW = int(imgSize[0]/col)splitL = int(imgSize[1]/row)pimg = img.load()imbList = []for i in range(row):rowList = []for j in range(col):imb = Image.new('RGBA', (splitW, splitL), (255,255,255,0))pimb = imb.load()for k in range(j * splitW, (j + 1) * splitW):for z in range(i * splitL, (i + 1) * splitL):pimb[k - j * splitW, z - i * splitL] = pimg[k,z]rowList.append(imb)imbList.append(rowList)return imbListdef Resize(img, rizeW, rizel, pastePoint=None): """调整图像大小"""if pastePoint is None:pastePoint = [0, 0]new_im = Image.new('RGBA', [rizeW, rizel], (255,255,255,0))new_im.paste(img, pastePoint)return new_imdef SplitCircle(imbList, imgPath, output_folder):"""生成凹凸拼图效果并直接保存到目标文件夹"""img = Image.open(imgPath).convert("RGBA")imgSize = img.sizecol = len(imbList[0])row = len(imbList)splitW = int(imgSize[0]/col)splitL = int(imgSize[1]/row)minV = min(splitW, splitL)r_d = int(minV / 4)r_offset = int(minV / 8)pSplitW = splitW + (r_d + r_offset) * 2pSplitL = splitL + (r_d + r_offset) * 2pimg = img.load()pointList = []for i in range(row):colPointList = []for j in range(col):colPoint = []rowPoint = []if j != col - 1:colPoint = [splitW * (j + 1), int(splitL/2) + i * splitL]if i != row - 1:rowPoint = [int(splitW / 2) + j * splitW, splitL * (i + 1)]colPointList.append({'colPoint': colPoint, 'rowPoint': rowPoint})imbList[i][j] = Resize(imbList[i][j], pSplitW, pSplitL, [r_d + r_offset, r_d + r_offset])pointList.append(colPointList)small_images = []for i in range(row):for j in range(col):imbImg = imbList[i][j]new_img = imbImglrRight = random.choice([True, False])drRight = random.choice([True, False])new_img_imb = new_img.load()if j != col - 1:new_next_img = imbList[i][j + 1]new_next_img_imb = new_next_img.load()for k in range((j + 1) * splitW - (0 if lrRight else r_d + r_offset), (j + 1) * splitW + (r_d + r_offset if lrRight else 0)):for z in range(i * splitL, (i + 1) * splitL):r_w = pointList[i][j]['colPoint'][0] + (r_offset if lrRight else -r_offset)r_l = pointList[i][j]['colPoint'][1]r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** yangshiif r < r_d:if lrRight:new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]new_next_img_imb[k - (j + 1) * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)else:new_next_img_imb[k - (j + 1) * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)imbList[i][j + 1] = new_next_img   if i != row - 1:new_down_img = imbList[i + 1][j]new_down_img_imb = new_down_img.load()for k in range(j * splitW, (j + 1) * splitW):for z in range((i + 1) * splitL - (r_d + r_offset if not drRight else 0), (i + 1) * splitL + (0 if not drRight else r_d + r_offset)):r_w = pointList[i][j]['rowPoint'][0]r_l = pointList[i][j]['rowPoint'][1] + (r_offset if drRight else -r_offset)r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** yangshiif r < r_d:if drRight:new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]new_down_img_imb[k - j * splitW + r_d + r_offset, z - (i + 1) * splitL + r_d + r_offset] = (255,255,255,0)else:new_down_img_imb[k - j * splitW + r_d + r_offset, z - (i + 1) * splitL + r_d + r_offset] = pimg[k, z]new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)imbList[i + 1][j] = new_down_img# 直接保存小图到目标文件夹idx = i * high + jfile_path = os.path.join(output_folder, f"{idx:02d}.png")new_img.save(file_path)img_with_border = draw_border_on_edge(Image.open(file_path), border_width)img_with_border.save(file_path)small_images.append(Image.open(file_path).convert('RGBA'))return small_imagesdef generate_combined_image(small_images, output_path):"""生成组合图"""canvas = Image.new('RGBA', (canvas_width, canvas_height), (255, 255, 255, 0))for row in range(wide):for col in range(high):index = row * high + colsmall_img = small_images[index]cell_center_x = col * cell_width + cell_width // 2cell_center_y = row * cell_height + cell_height // 2paste_x = cell_center_x - small_img.width // 2paste_y = cell_center_y - small_img.height // 2canvas.alpha_composite(small_img, (paste_x, paste_y))gray_canvas = convert_to_light_gray(canvas)gray_canvas.save(output_path)return output_pathimport os
from docx import Document
from docx.shared import Cm, Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
import randomdef generate_word_doc(small_images, combined_path, output_docx_path, img_index, sj=1):'''生成Word文档参数:small_images: 小图路径列表combined_path: 组合图路径output_docx_path: 输出的Word文档路径img_index: 当前处理的原图序号sj: 1表示按默认顺序插入,2表示随机打乱插入顺序'''# 假设path、wide、high、Number是全局变量# 加载模板文档template_path = os.path.join(path, f'02长方形模板{wide}乘{high}.docx')doc = Document(template_path)# 确保文档中有至少三个表格# if len(doc.tables) < 3:#     raise ValueError("模板文档必须包含至少三个表格")# 创建索引列表indices = list(range(Number))  # Number = wide * high = 12if sj == 2:  # 随机打乱顺序random.shuffle(indices)else:pass# 第一个表格: 插入12张小图 (3行4列)table1 = doc.tables[0]for row in range(wide):for col in range(high):# 获取索引(随机或顺序)idx = indices[row * high + col] if sj == 2 else (row * high + col)cell = table1.cell(row, col)# 清除单元格原有内容for paragraph in cell.paragraphs:for run in paragraph.runs:run.clear()# 添加新图片paragraph = cell.paragraphs[0]run = paragraph.add_run()# 图片名称img_path = os.path.join(os.path.dirname(combined_path), f"{idx:02d}.png")run.add_picture(img_path, width=Cm(6.71), height=Cm(6.4))  # 宽度6.71cm, 高度6.4cmparagraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER# 第二个表格: 插入序号 (3行4列)table2 
http://www.xdnf.cn/news/4964.html

相关文章:

  • 什么是AIOps
  • python小区物业管理系统-小区物业报修系统
  • 操作系统的初步了解
  • 重构 cluster-db 选择器,新增限制字段 showDb 不影响原功能前提实现查询功能增量拓展
  • ABP vNext + EF Core 实战性能调优指南
  • 捌拾叁- 量子傅里叶变换
  • 【25软考网工】第六章 网络安全(1)网络安全基础
  • Rust 中的 `String`、`str` 和 `str`:深入解析与使用指南
  • Java大师成长计划之第16天:高级并发工具类
  • 自动驾驶的“眼睛”:用Python构建智能障碍物检测系统
  • U9C对接飞书审批流完整过程
  • 【Pandas】pandas DataFrame clip
  • js原型污染 + xss劫持base -- no-code b01lersctf 2025
  • PostgreSQL 18 Beta 1发布,有哪些功能亮点?
  • P2572 [SCOI2010] 序列操作 Solution
  • Shell 脚本编程详细指南:第五章 - 函数与参数传递
  • ROS1 和 ROS2 在同一个系统中使用
  • 分布式ID设计 数据库主键自增
  • 第423题-有效的括号序列
  • 大模型——Trae IDE 指南:轻松配置自定义 AI 规则 (Trae Rules)
  • 阅文集团C++面试题及参考答案
  • 服务器配置错误导致SSL/TLS出现安全漏洞,如何进行排查?
  • 汽车制造行业的数字化转型
  • 华为云Flexus+DeepSeek征文|从开通到应用:华为云DeepSeek-V3/R1商用服务深度体验
  • 【软件设计师:存储】16.计算机存储系统
  • gitlab相关面试题及答案
  • 深入了解 Stable Diffusion:AI 图像生成的奥秘
  • 【论文阅读】——Articulate AnyMesh: Open-Vocabulary 3D Articulated Objects Modeling
  • 聚焦车辆模式管理:概念阐释、测试方案设计与实施
  • 代码随想录第40天:图论1