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

【教学类-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 

相关文章:

  • 打造专属AI好友:小智AI聊天机器人详解
  • 解决Win11下MySQL服务无法开机自启动问题
  • 车载以太网转USB接口工具选型指南(2025版)
  • vison transformer vit 论文阅读
  • 计算机系统结构-第九章-互联网络 第十章
  • 独立自主的网络浏览器——Ladybird
  • 一种海杂波背景下前视海面目标角超分辨成像方法——论文阅读
  • 机器学习 期末考试题
  • 学习黑客认识Security Operations Center
  • 高效对接:金蝶采购申请单集成钉钉案例解析
  • STM32F103RCT6 + MFC实现网口设备搜索、修改IP、固件升级等功能
  • 【SQL系列】多表关联更新
  • WHAT - 简单服务发现
  • Java中的控制流语句:if、switch、for、foreach、while、do-while
  • Java+Selenium+快代理实现高效爬虫
  • qiankun微前端任意位置子应用
  • 工业与协议融合篇:如何将多个协议集成进一个系统?
  • 从韦斯利・卡普洛看北斗星咨询公司的技术咨询引领之路
  • 分布式ID设计 数据库主键自增
  • 智慧校园安全可视化指挥调度系统解决方案
  • 拿出压箱底作品,北京交响乐团让上海观众享受音乐盛宴
  • 央行:货币与物价的关系受多重因素影响,提振物价的关键在于扩大有效需求
  • “浦东时刻”在京展出:沉浸式体验海派风情
  • 明明睡够了,怎么还有黑眼圈?可能是身体在求救
  • 苹果Safari浏览器上的搜索量首次下降
  • 两部上戏学生作品亮相俄罗斯“国际大学生戏剧节”