随机布局真实风格文档图像集的布局生成算法及Python3实现咨询
随机单栏文档布局生成实现方案
核心实现逻辑
- 采用递归二分空间切分法生成布局,严格规避整页左右双栏结构:从扣除全局页边距的20001500有效内容区出发,每次随机选择切分方向,切分后保证两个子块都满足最小宽300、最小高500*的尺寸要求,直到块体无法再做合规切分,即标记为最终布局单元。
- 切分方向做概率倾斜:80%概率选择上下方向切分(保证整体阅读流是从上到下的单栏逻辑),20%概率在块体内部做小范围左右切分(比如段落旁搭配窄幅配图),从规则层面杜绝生成从页顶贯通到页底的双栏布局。
- 每个最终布局单元随机匹配真实PDF常见的元素类型:正文段落、内嵌配图、代码块,通过细节渲染(如正文行长随机浮动、配图带边框、代码块带浅灰底)模拟真实纸质文档的观感,避免人工生成的违和感。
可运行Python3实现代码
import random from PIL import Image, ImageDraw # 严格匹配需求的固定参数 CANVAS_SIZE = (2000, 1500) # 目标纸张尺寸 宽*高 MIN_BLOCK_SIZE = (300, 500) # 布局单元最小尺寸要求 PAGE_MARGIN = 100 # 模拟真实文档的全局页边距留白 def split_block(block): """递归切分布局块,严格校验最小尺寸,避免不合规的细碎块""" x, y, w, h = block min_w, min_h = MIN_BLOCK_SIZE # 判断可切分方向:切分后的子块不能小于最小尺寸 can_split_vertical = (h - min_h) >= min_h # 上下切分可行性 can_split_horizontal = (w - min_w) >= min_w # 块内左右切分可行性 if not can_split_vertical and not can_split_horizontal: return [block] # 切分方向选择:优先上下切分(80%权重),避免整页双栏 choice_pool = [] if can_split_vertical: choice_pool.extend(["vertical"] * 4) if can_split_horizontal: choice_pool.append("horizontal") split_dir = random.choice(choice_pool) if split_dir == "vertical": # 上下随机切分 split_pos = random.randint(y + min_h, y + h - min_h) upper_block = (x, y, w, split_pos - y) lower_block = (x, split_pos, w, (y + h) - split_pos) return split_block(upper_block) + split_block(lower_block) else: # 块内左右随机切分 split_pos = random.randint(x + min_w, x + w - min_w) left_block = (x, y, split_pos - x, h) right_block = (split_pos, y, (x + w) - split_pos, h) return split_block(left_block) + split_block(right_block) def render_single_block(draw, block): """渲染单个布局单元,模拟真实文档视觉效果""" x, y, w, h = block block_type = random.choice(["paragraph", "embedded_image", "code_snippet"]) if block_type == "paragraph": # 模拟正文:等距排列的随机长度浅灰横线 line_interval = 32 for line_top in range(y + 30, y + h - 30, line_interval): line_width = random.randint(int(w*0.7), int(w*0.95)) draw.line([(x+30, line_top), (x+30 + line_width, line_top)], fill=(80,80,80), width=4) elif block_type == "embedded_image": # 模拟内嵌配图:柔和色块加细边框 img_color = (random.randint(180,220), random.randint(180,220), random.randint(180,220)) draw.rectangle( [(x+20, y+20), (x + w - 20, y + h - 20)], fill=img_color, outline=(0,0,0), width=2 ) elif block_type == "code_snippet": # 模拟代码块:浅灰背景加彩色等距行 draw.rectangle( [(x+20, y+20), (x + w - 20, y + h - 20)], fill=(240,240,240), outline=(0,0,0), width=2 ) line_interval = 30 color_pool = [(0,100,200), (0,120,0), (180,50,50)] for line_top in range(y + 40, y + h - 40, line_interval): line_width = random.randint(int(w*0.3), int(w*0.8)) line_color = random.choice(color_pool) draw.line([(x+40, line_top), (x+40 + line_width, line_top)], fill=line_color, width=3) if __name__ == "__main__": # 初始化白色纸张画布 doc_img = Image.new("RGB", CANVAS_SIZE, (255,255,255)) draw_handle = ImageDraw.Draw(doc_img) # 扣除全局页边距得到有效内容根块 margin = PAGE_MARGIN root_layout_block = ( margin, margin, CANVAS_SIZE[0] - 2*margin, CANVAS_SIZE[1] - 2*margin ) # 生成全页随机布局 final_blocks = split_block(root_layout_block) # 逐块渲染内容 for block in final_blocks: render_single_block(draw_handle, block) # 导出生成的文档图像 doc_img.save("random_generated_doc.png")
使用说明
- 运行前安装依赖:执行
pip install pillow即可,无其他复杂环境要求 - 生成的图像严格匹配所有参数要求:纸张尺寸固定为20001500,所有布局单元宽高都不低于300500,无贯通式双栏结构
- 可根据实际需求调整随机概率(比如上下切分的权重、元素类型的占比),进一步贴近目标文档的观感
内容的提问来源于stack exchange,提问作者KwangHo Bae
相关产品推荐
相关产品推荐

