定制的乐高马赛克像素画生成器-微信小程序版本-AI 风格优化-一键完成所有工作

Liang Brick Mosaic Generator - Liangdabiao定制的乐高马赛克像素画生成器

English | 中文

项目简介

这是一个100%客户端运行 的开源网络应用,可以将你自己的图片转换成乐高(LEGO)积木马赛克拼贴图,并生成可下载的PDF拼搭说明书或长图说明书。你可以使用现有的乐高Art系列套装来拼搭出完全自定义的马赛克作品。

本应用参考了Christoph Fritzsch开源项目 custombrickmosaic.github.io 进行大量深度定制开发,目前已经达到适应大部分图片生成像素画,还带有功能完全一致的微信小程序版本。用户可以在手机上完成从图片上传到下载说明书的全部流程,所有计算均在客户端完成,图片不会上传到任何服务器。

核心特点:

  • 从任意图片生成乐高积木马赛克
  • 整个项目所有都是免费,0成本部署一个AI乐高马赛克像素画生成器
  • 小程序也是开源免费,功能是一致,用户体验很棒
  • 隐私保护:所有计算都在你的浏览器中完成,图片不会上传到任何服务器
  • 自动生成带分区指导的PDF拼搭说明书长图说明书
  • 支持组合多个乐高Art系列套装来获得更大尺寸的马赛克
  • 支持自定义裁剪:可自由框选图片区域,自动保持马赛克宽高比
  • 支持AI 风格优化:对接火山引擎即梦 AI,一键将图片转为多边形艺术风格,提升马赛克效果
  • 支持图片裁切、色彩调整等预处理(色相、饱和度、明度、对比度、暗部、亮部)
  • 完全免费开源

在线使用:https://lego.348349.xyz/

特别感谢佬友支持: linux.do

AI一键优化:

小程序:


目录


工作原理

整体流程

复制代码
用户上传图片 → 图片预处理(裁剪/缩放/调色)→ 算法分配积木 → 生成预览 → 生成PDF/长图说明书

核心算法

整个马赛克生成分为两个阶段:

第一阶段:初始分配
  1. 调整尺寸:将输入图片重新缩放至马赛克目标尺寸(宽 × 高 颗粒度)
  2. 添加噪声:在原始颜色值中加入微小随机噪声,以打破颜色相等的情况,避免算法卡住
  3. 颜色匹配 :将每个像素的颜色与你选择的乐高套装中所有可用颜色进行比较,计算颜色距离(RGB空间中的平方欧氏距离)
  4. 贪心分配:按像素逐个分配最匹配的可用颜色,每分配一个颗粒,对应颜色的可用数量减1。如果最佳颜色已用完,则选择下一个最佳匹配颜色

作者测试过多种颜色空间(如CIE LAB),发现RGB空间已经能获得很好的效果。CIE LAB版本代码目前保留但被注释掉了。

第二阶段:优化交换

初始分配完成后,算法进入优化阶段:

  • 迭代尝试交换两个不同像素之间的积木颗粒
  • 如果交换后总体颜色匹配度变好(总色差更小),则保留交换
  • 重复这个过程,直到无法再通过交换改善结果
  • 这个"暴力"交换过程能显著提升最终效果,但对于大尺寸马赛克需要较长计算时间

颜色匹配原理

颜色距离计算公式(RGB空间):

复制代码
distance = (r1 - r2)² + (g1 - g2)² + (b1 - b2)²

distance越小,颜色越接近。


详细操作步骤

步骤1:选择源图片

  1. 点击"1. 选择源图片"下的文件选择框
  2. 从你的电脑或手机中选择一张图片
  3. 图片加载后会显示预览缩略图
  4. 选择裁切方式:
    • 裁切中心:保持原图宽高比,只裁切中心区域
    • 缩放适应:将整张图拉伸/缩放到目标尺寸
    • 自定义裁切:打开裁剪工具,自由框选所需区域(自动保持马赛克宽高比)
  5. (可选)勾选"忽略图片中的黑色区域"
  6. (可选)使用颜色调整滑块微调图片效果

步骤2:选择马赛克尺寸

  1. 通过加减按钮调整马赛克的宽度和高度(单位:乐高颗粒/studs)
  2. 查看下方显示的所需颗粒数量
  3. 一个标准乐高Art套装是48×48=2304颗粒

步骤3:选择你拥有的乐高Art套装

  1. 在列表中找到你拥有的套装,通过加减按钮设置你要使用的数量
  2. 每个套装包含不同的颜色和颗粒数量,程序会自动计算总可用颗粒
  3. 查看下方显示的总可用颗粒数
  4. 注意:必须保证可用颗粒数 ≥ 所需颗粒数,才能进行计算

步骤4:计算马赛克

  1. 点击"计算马赛克"按钮开始计算
  2. 进度条会显示计算进度
  3. 等待计算完成,右侧会显示马赛克预览图

步骤5:下载说明书

计算完成后,提供两种下载格式:

  • PDF格式:点击"下载拼搭说明书 (PDF)",生成标准PDF文件
  • 长图格式:点击"下载说明书长图 (PNG)",生成一张包含全部说明内容的长图,适合手机查看或社交分享

界面功能详解

左侧控制面板

第一部分:选择源图片(Step 1)

裁切/缩放按钮组

复制代码
[裁切中心] [缩放适应] [自定义裁切]
  • 裁切中心:保持原图宽高比,只裁切中心区域适应目标尺寸
  • 缩放适应:将整张图拉伸/缩放到目标尺寸,可能会改变宽高比
  • 自定义裁切 :打开交互式裁剪弹窗,自由拖动选择裁剪区域
    • 裁剪框自动保持马赛克的宽高比(宽度:高度)
    • 支持拖动移动选区、缩放图片、调整裁剪框大小
    • 裁剪完成后自动更新预览并重新计算

忽略黑色区域复选框

  • 勾选后:RGB值为(0,0,0)的纯黑色区域不会被分配积木,在说明书中用"?"标记
  • 默认:勾选

AI 风格优化按钮

  • 点击"AI 风格优化"按钮,将当前图片发送到后端 AI 服务进行风格化处理
  • 使用火山引擎即梦 AI,将图片转换为多边形艺术风格(锐利线条、现代图形感)
  • 处理时间约 10-30 秒,完成后自动替换图片并刷新预览
  • 可多次点击"重新AI优化"进行迭代优化
  • 注意:此功能需要部署到 Cloudflare Pages 才能使用(依赖后端 API)

颜色调整滑块

滑块 范围 功能
暗部 (Shadows) -100 ~ +100 调整暗部亮度曲线
亮部 (Highlights) -100 ~ +100 调整亮部亮度曲线
色相 (Hue) -180 ~ +180 整体颜色偏移
饱和度 (Saturation) -100 ~ +100 色彩饱和度调整
明度 (Value) -100 ~ +100 整体亮度调整
对比度 (Contrast) -100 ~ +100 明暗对比度调整
第二部分:选择马赛克尺寸(Step 2)
  • 通过加减按钮或直接输入调整宽度和高度(16~200)
  • 下方实时显示所需颗粒数量
第三部分:选择拥有的乐高Art套装(Step 3)

每个套装可输入小数(如0.5),用于限制颜色数量以获得更具艺术感的效果。详见颗粒限制技巧

第四部分:运行计算(Step 4)

点击"计算马赛克"按钮,进度条分为初始分配和优化交换两个阶段。

第五步:下载说明书(Step 5)

两种下载格式:

  • 下载拼搭说明书 (PDF):标准PDF文件,每页一个16×16分区
  • 下载说明书长图 (PNG):所有页面纵向拼接的长图(2倍清晰度),适合手机查看和分享

右侧预览区

  • 马赛克预览:计算完成后显示生成的马赛克预览图
  • 颜色调整:提供6个滑块实时调整图片颜色参数

支持的乐高Art套装

程序内置了以下11款乐高Art系列套装的颜色和颗粒数据:

序号 套装名称 产品编号 标准尺寸 颗粒总数
1 The Beatles 31198 48×48 2304
2 Marilyn Monroe 31197 48×48 2304
3 Iron Man 31199 48×48 2304
4 The Sith 31200 48×48 2304
5 Hogwarts 31201 48×48 2304
6 Mickey Mouse 31202 48×48 2304
7 Personalized Portrait 41958 48×48 2304
8 World Map 31203 48×192 约9216
9 Art Project 21226 48×48 2304
10 Elvis Presley 31204 48×48 2304
11 Batman 31205 48×48 2304

组合示例:

  • 1个套装:48×48
  • 2个套装:64×64(需要 4096颗粒)
  • 4个套装:96×96(需要 9216颗粒)
  • 世界地图套装:可以做48×192的长条横幅马赛克

使用技巧

输入图片选择

  • 好的对比度是获得好结果的关键
  • 选择颜色分布与你拥有的套装相近的图片
  • 尝试不同的裁切方式,多试几张
  • 均匀纯色背景效果更好,可以先用图像处理软件将背景换成纯色

自定义裁剪技巧

  • 使用自定义裁剪可以精确选择图片中你想要的区域
  • 裁剪框会自动保持与马赛克相同的宽高比
  • 建议先调整好马赛克的目标宽高比,再进行裁剪,这样裁剪框比例与最终结果一致

颜色调整技巧

  • 多试不同滑块组合,看看调整后对结果的影响
  • 使用色相滑块让整体颜色更接近乐高现有颜色
  • 有时降低饱和度能获得更好效果
  • 利用暗部/亮部滑块可以精细控制图片的明暗分布
  • 如果图片背景占很大空间,先用外部软件将背景设为纯黑,然后勾选"忽略黑色区域"

颗粒限制的艺术效果

  • 刻意限制颗粒数量能获得更有艺术感的结果
  • 限制颗粒数量会迫使算法使用次优颜色,反而增加了马赛克的色彩空间
  • 技巧:输入小数如0.9来进一步限制每种颜色可用数量

AI 风格优化

AI 风格优化功能通过对接火山引擎即梦 AI,将用户上传的图片一键转换为更适合乐高马赛克的艺术风格。

风格效果

  • 纯黑色背景
  • 戏剧性低光
  • 多边形艺术风格,锐利的线条和刻面,现代图形感
  • 动态构图,融合写实与抽象

工作原理

复制代码
用户点击"AI 风格优化"
    ↓
前端将 canvas 图片转为 JPEG base64
    ↓
POST 到 /api/ai-optimize(Cloudflare Pages Function)
    ↓
后端调用火山引擎即梦 AI API(签名认证 + 异步任务)
    ↓
轮询等待 AI 处理完成(最长约3分钟)
    ↓
返回优化后的图片 URL/base64
    ↓
前端替换图片、刷新预览,如已生成马赛克则自动重新计算

后端 API

  • 路径:/api/ai-optimize
  • 方法:POST
  • 请求体:{ "imageBase64": "data:image/jpeg;base64,...", "prompt": "风格描述" }
  • 返回:{ "success": true, "imageUrl": "..." }

环境变量

后端 API 需要配置以下环境变量(在 Cloudflare Pages Settings → Environment variables 中设置):

变量名 说明
VOLC_ACCESS_KEY_ID 火山引擎 Access Key ID
VOLC_SECRET_ACCESS_KEY 火山引擎 Secret Access Key

本地运行

本项目是纯静态HTML+JavaScript应用,无需构建过程,无需任何依赖。

方法一:直接打开

用浏览器直接打开 index.html 即可使用。

方法二:使用本地HTTP服务器

bash 复制代码
python -m http.server 8000
# 然后访问 http://localhost:8000
bash 复制代码
npx serve .

依赖项

所有依赖都通过CDN加载:

  • Bootstrap 5.0.0-beta2(CSS + JS)
  • jsPDF 1.5.3(PDF生成)
  • Cropper.js 1.6.2(图片裁剪)

无需npm install,无需任何构建工具。


部署到 Cloudflare Pages

本项目包含 Cloudflare Pages Function(functions/api/),因此不能使用 Cloudflare 后台的直接拖拽上传(拖拽上传不支持 Functions),必须使用 wrangler CLI 部署。

前提条件

  1. 安装 Node.js(18+)
  2. Cloudflare Dashboard 创建 Pages 项目
  3. 准备好火山引擎的 Access Key(用于 AI 风格优化功能)

部署步骤

1. 安装 wrangler 并登录

bash 复制代码
npm install -g wrangler
wrangler login

登录后会自动打开浏览器进行授权。

2. 配置环境变量

在 Cloudflare 后台 Pages → 你的项目 → Settings → Environment variables 中添加:

变量名
VOLC_ACCESS_KEY_ID 你的火山引擎 AK
VOLC_SECRET_ACCESS_KEY 你的火山引擎 SK

3. 部署

bash 复制代码
# 部署到已有项目
npx wrangler pages deploy . --project-name=你的项目名

# 或部署到新项目
npx wrangler pages deploy .

部署完成后会输出访问 URL。

项目文件结构(含 Cloudflare)

复制代码
/
├── index.html              # 主页面
├── brickMosaic.js          # 前端逻辑
├── cf_about.png            # 头像
├── favicon.ico             # 图标
├── LICENSE                 # MIT 许可证
├── package.json            # wrangler 部署脚本
├── wrangler.toml           # Cloudflare 配置
└── functions/
    └── api/
        └── ai-optimize.js  # AI 优化 API(Pages Function)

注意事项

  • 不要使用 Cloudflare 后台的拖拽上传 ,它不会处理 functions/ 目录,会导致 API 返回 405
  • 可以通过 Git 集成部署(Cloudflare Pages 关联 GitHub 仓库),推送代码后自动部署,这也支持 Functions
  • 本地开发测试可用 npx wrangler pages dev .,会自动启动本地服务器并支持 Functions 调用

项目文件结构

复制代码
/
├── index.html           # 主HTML页面,包含UI布局
├── brickMosaic.js       # 全部应用逻辑
├── cf_about.png         # About页面作者头像
├── favicon.ico          # 网站图标
└── LICENSE              # MIT许可证

技术架构

  • 语言:原生JavaScript (ES6+)
  • 图像处理:HTML5 Canvas API
  • 样式框架:Bootstrap 5(CDN)
  • PDF生成:jsPDF 1.5.3(CDN)
  • 图片裁剪:Cropper.js 1.6.2(CDN)
  • 长图生成:Canvas API + toDataURL()
  • 部署:GitHub Pages 静态托管
  • 计算:马赛克生成在浏览器客户端完成;AI 优化通过 Cloudflare Pages Function 调用火山引擎 API

主要函数说明

函数 功能
init() 初始化UI状态和事件处理器
rgb2hsv() / hsv2rgb() RGB转HSV色彩空间互相转换
adjustImageHSV() 应用色相、饱和度、明度调整
adjustImageContrast() 应用对比度调整
adjustImageCurves() 应用暗部/亮部曲线调整
rgb2lab() / lab2rgb() / deltaE() RGB转CIE LAB,计算DeltaE色差(已注释)
getPartListOfOneSet() 获取指定套装的所有颜色和数量数据
updatePartList() 根据用户选择更新总可用零件列表
drawPreviewImage() 绘制预览缩略图(支持自定义裁剪)
generateValidColoring() 核心两阶段生成算法
drawMosaic() 在画布上绘制马赛克预览
openCustomCropModal() 打开自定义裁剪弹窗
confirmCustomCrop() 确认裁剪并应用
generateInstructions() 生成PDF说明书
generatePDFTitlePage() 生成PDF标题页(马赛克预览+色块图例)
generatePDFSectionPage() 生成PDF分区指导页(16×16网格)
generateInstructionsImage() 生成长图说明书(PNG)
generateImageTitlePage() 生成长图标题页(Canvas渲染)
generateImageSectionPage() 生成长图分区页(Canvas渲染)

小程序像素画说明书原理

复制代码
● 说明书长图生成原理

  整体架构

  用户点击"下载说明书"
      ↓
  generateImage()
      ↓
  创建一张超高的离屏Canvas(宽度固定,高度 = 页数 × 单页高度)
      ↓
  逐页绘制:
    ├─ 第1页:标题页(总览)
    ├─ 第2页:分区1(左上角16×16)
    ├─ 第3页:分区2(第2列16×16)
    ├─ ...
    └─ 第N页:最后一个分区
      ↓
  wx.canvasToTempFilePath() 导出为一张PNG长图
      ↓
  wx.previewImage() 预览 / wx.saveImageToPhotosAlbum() 保存到相册

  关键参数

  SCALE = 4        // 1mm = 4px(手机屏幕适配)
  PAGE_W = 210×4 = 840px    // A4纸宽度
  PAGE_H = 297×4 = 1188px   // A4纸高度
  SECTION_SIZE = 16          // 每个分区16×16颗粒

  以 48×48 马赛克为例:
  - 分区数 = ceil(48/16) × ceil(48/16) = 3×3 = 9个分区
  - 总页数 = 1(标题页)+ 9(分区页)= 10页
  - 长图总高度 = 1188 × 10 = 11880px


  第1页:标题页 (renderTitlePage)

  ┌─────────────────────────────────┐
  │  Custom Brick Mosaic            │
  │  Source: mosaic                 │
  │  Resolution: 48 x 48 (3x3)     │
  │                                  │
  │  ┌─────────────────────────┐    │
  │  │                         │    │
  │  │   整个马赛克缩略预览     │    │  每个颗粒画一个彩色小方块
  │  │   带分区网格线           │    │  网格线将图分成16×16的区域
  │  │   每个区域标序号          │    │  每个区域中心写编号 1-9
  │  │                         │    │
  │  └─────────────────────────┘    │
  │                                  │
  │  ┌─────────┐                    │
  │  │ 颜色图例 │                    │  每种实际用到的颜色:
  │  │ ●1 150x │                    │    圆形/方形(取决于积木类型)
  │  │ ●2 230x │                    │    内圈编号
  │  │ ■3 180x │                    │    数量统计
  │  │ ...     │                    │
  │  └─────────┘                    │
  │                                  │
  │  github.com/liangdabiao     │
  │  Page 1 / 10                     │
  └─────────────────────────────────┘

  标题页做了这些事:
  1. 绘制马赛克总览 --- 遍历 finalMosaicIm[x][y],每个颗粒画一个 brickW × brickH 的彩色方块
  2. 绘制分区网格 --- 白色半透明线将图分成 16×16 的区域,每个区域中心写编号
  3. 统计颜色用量 --- 遍历所有颗粒,按 im[x][y][3](颜色索引)统计每种颜色出现次数
  4. 绘制颜色图例 --- 为每种颜色画圆形(圆钉)或方形(板),内圈写编号,旁边写数量×
  5. 颗粒类型区分 --- im[x][y][4] 决定形状:3024=方形板,6141=圆钉,其他=普通圆形

  第2~N页:分区页 (renderSectionPage)

  ┌─────────────────────────────────┐
  │  Section 3                       │
  │                                  │
  │  ┌─────────────────────────┐    │
  │  │ ■ ■ ● ■ ■ ● ■ ■ ● ■ ■  │    │
  │  │ ■ ● ■ ■ ● ■ ● ■ ● ■ ■  │    │  16×16网格
  │  │ ● ■ ■ ● ■ ● ■ ● ■ ■ ■  │    │  每个位置画一个积木颗粒
  │  │ ■ ■ ● ■ ■ ● ■ ● ■ ● ■  │    │  黑色背景+彩色圆形/方形
  │  │ ...                     │    │  颗粒中心写颜色编号
  │  │ ■ ● ■ ■ ● ■ ● ■ ● ■ ■  │    │
  │  └─────────────────────────┘    │
  │                                  │
  │  github.com/liangdabiao     │
  │  Page 4 / 10                     │
  └─────────────────────────────────┘

  分区页做了这些事:
  1. 计算当前分区对应的马赛克区域 --- 例如 Section 3(编号从0开始是2),对应第1列第0行的16×16区域
  xOffset = sectionNumber % numSectionsX * 16  // 水平偏移
  yOffset = floor(sectionNumber / numSectionsX) * 16  // 垂直偏移
  2. 在黑色背景上画网格 --- 每个格子中心画积木颗粒
  3. 颗粒大小 --- gridSize / 16 / 2 作为半径,尽量占满页面
  4. 颗粒上写编号 --- 与标题页图例中的编号对应,方便用户找颗粒

  数据来源

  所有数据来自 _finalMosaicIm,这是算法 generateValidColoring() 的输出:

  im[x][y] = [R, G, B, colorIndex, partType, elementId]
  //  R, G, B:    匹配到的乐高颜色RGB值
  //  colorIndex: 在fullPartList中的索引
  //  partType:   积木类型(6141=圆钉, 3024=方形板, 3=忽略)
  //  elementId:  乐高官方零件编号

  对比网页版的差异

  ┌──────────┬───────────────┬─────────────────────┐
  │   维度   │    网页版     │      小程序版       │
  ├──────────┼───────────────┼─────────────────────┤
  │ 输出格式 │ PDF (jsPDF)   │ PNG长图             │
  ├──────────┼───────────────┼─────────────────────┤
  │ 渲染方式 │ jsPDF绘图命令 │ Canvas 2D绑定       │
  ├──────────┼───────────────┼─────────────────────┤
  │ 分辨率   │ 1mm=6px       │ 1mm=4px(手机适配) │
  ├──────────┼───────────────┼─────────────────────┤
  │ 保存方式 │ 浏览器下载    │ 预览+保存到相册     │
  ├──────────┼───────────────┼─────────────────────┤
  │ 历史记录 │ 无            │ 本地存储最近20条    │
  └──────────┴───────────────┴─────────────────────┘

  核心渲染逻辑(标题页布局、分区页网格、颜色图例)与网页版完全一致,只是从 jsPDF API 翻译成了 Canvas 2D API。

数据隐私

算法完全在你的浏览器中运行,所有计算都在你的本地机器上完成。不需要将数据上传到任何服务器,数据隐私得到保证。

你可以断网使用,图片永远不会离开你的设备。


更新日志

AI 风格优化

  • 新增"AI 风格优化"按钮,对接火山引擎即梦 AI API
  • 一键将图片转换为多边形艺术风格(纯黑背景、戏剧性低光、锐利刻面线条)
  • 通过 Cloudflare Pages Function 实现后端 API(/api/ai-optimize
  • 支持火山引擎 HMAC-SHA256 签名认证
  • 异步任务提交 + 轮询机制,最长等待约3分钟
  • 优化完成后自动刷新预览,如已生成马赛克则自动重新计算
  • 图片安全检测失败时给出友好提示

自定义裁剪功能

  • 集成 Cropper.js 1.6.2,新增"自定义裁切"按钮
  • 裁剪弹窗自动保持马赛克宽高比
  • 等待弹窗完全展开后再初始化裁剪器,避免容器尺寸为0的问题
  • 裁剪结果正确传递到马赛克生成和"忽略黑色区域"检测

说明书长图下载

  • 新增"下载说明书长图 (PNG)"按钮
  • 内容与PDF完全一致:标题页(马赛克预览+色块图例)+ 分区指导页(16×16编号网格)
  • 使用Canvas API渲染,1mm = 6px(2倍清晰度)
  • 所有页面纵向拼接为一张长图,适合手机查看和社交分享
  • PDF和长图共享进度条和状态管理

颜色调整增强

  • 新增"暗部"和"亮部"曲线调整滑块
  • 支持对图片暗部和亮部分别进行精细控制

Bug 修复

  • 修复自定义裁剪 + "忽略黑色区域"组合使用时,黑色检测使用了原图而非裁剪后的图像,导致马赛克出现大量空白区域的问题
  • 修复裁剪弹窗在 Bootstrap 5.0.0-beta2 中的兼容性问题(getOrCreateInstance 不存在,改用 getInstance + new

其他类似项目


许可证

MIT License - 详见 <LICENSE> 文件。


源代码

https://github.com/liangdabiao

欢迎提交Issue和Pull Request。

相关推荐
中电金信2 小时前
中电金信:赋能精准决策,两大场景解锁金融营销新范式
大数据·人工智能
醉卧考场君莫笑2 小时前
NLP(jieba库实现分词以及代码实现)
人工智能·自然语言处理
虹科网络安全2 小时前
艾体宝洞察|生成式 AI 安全:趋势、风险与最佳实践
人工智能·安全
weixin_6682 小时前
云计算与大模型私有化部署详解
人工智能·云计算
CelestialYuxin2 小时前
第13章课时48 GAN-2
人工智能·神经网络·生成对抗网络
xiaotao1312 小时前
03-深度学习基础:Agent与工具调用
人工智能·深度学习·大模型·agent
AI自动化工坊2 小时前
T3 Code:专为AI编程代理设计的Web IDE技术实践指南
前端·ide·人工智能·ai编程·t3
只说证事2 小时前
2026产品岗,怎么转型产品数据分析/商业分析岗?能优化产品决策效率吗?
大数据·人工智能·数据分析
heimeiyingwang2 小时前
【架构实战】边缘计算架构设计与应用场景
人工智能·架构·边缘计算