d1ngdongji commited on
Commit
431bc5f
·
verified ·
1 Parent(s): f0c1e20

Upload generate_dataset.py

Browse files
Files changed (1) hide show
  1. generate_dataset.py +242 -0
generate_dataset.py ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import asyncio
3
+ from pathlib import Path
4
+ from PIL import Image
5
+ import random
6
+ from minepi import Skin
7
+ from minepi.skin_render import Render
8
+
9
+ # 创建输出文件夹
10
+ RENDER_OUTPUT_DIR = "rendered_skins"
11
+ TEXTURE_OUTPUT_DIR = "scaled_textures"
12
+ os.makedirs(RENDER_OUTPUT_DIR, exist_ok=True)
13
+ os.makedirs(TEXTURE_OUTPUT_DIR, exist_ok=True)
14
+
15
+ # 获取所有皮肤文件
16
+ TRAIN_DIR = "train"
17
+ skin_files = []
18
+ for file in os.listdir(TRAIN_DIR):
19
+ if file.endswith('.png'):
20
+ skin_files.append(os.path.join(TRAIN_DIR, file))
21
+
22
+ print(f"找到 {len(skin_files)} 个皮肤文件")
23
+
24
+ async def render_skin(skin_path, output_name):
25
+ """渲染单个皮肤为3D全身视图(正面+背面并排)"""
26
+ try:
27
+ # 生成随机深色背景 (RGB值在0-80之间)
28
+ bg_color = (
29
+ random.randint(0, 80),
30
+ random.randint(0, 80),
31
+ random.randint(0, 80)
32
+ )
33
+
34
+ # 读取皮肤文件为PIL Image
35
+ skin_img = Image.open(skin_path)
36
+
37
+ # 创建Skin对象
38
+ skin = Skin(raw_skin=skin_img)
39
+
40
+ # 为腿脚摆动添加±10度的随机偏移
41
+ leg_offset = random.randint(-10, 10)
42
+ arm_offset = random.randint(-10, 10)
43
+ vr_offset = random.randint(-6, 6)
44
+ hr_offset = random.randint(-20,10)
45
+ ratio_offset = random.randint(-2,0)
46
+
47
+ # 计算带随机偏移的角度
48
+ #vrll_front = 15 + leg_offset # 左腿向前
49
+ vrll_front = 15
50
+ #vrrl_front = -15 - leg_offset # 右腿向后
51
+ vrrl_front = -15
52
+ #vrla_front = -15 - arm_offset # 左臂向后
53
+ vrla_front = -15
54
+ #vrra_front = 15 + arm_offset # 右臂向前
55
+ vrra_front = 15
56
+ # vrrl = -15 + vr_offset
57
+ vrrl = -15
58
+ # hrrl = 35 + hr_offset
59
+ hrrl = 35
60
+ # ratiorl = 30 + ratio_offset
61
+ ratiorl = 30
62
+
63
+
64
+ # 渲染正面视图 - 3D行走姿势
65
+ render_front = Render(
66
+ player=skin,
67
+ vr=vrrl, # 垂直旋转,稍微向下看
68
+ hr=hrrl, # 水平旋转35度
69
+ hrh=0, # 头部水平旋转
70
+ vrll=vrll_front, # 左腿向前(带随机偏移)
71
+ vrrl=vrrl_front, # 右腿向后(带随机偏移)
72
+ vrla=vrla_front, # 左臂向后(带随机偏移)
73
+ vrra=vrra_front, # 右臂向前(带随机偏移)
74
+ ratio=ratiorl, # 缩放比例
75
+ aa=True, # 抗锯齿
76
+ display_hair=True,
77
+ display_layers=True
78
+ )
79
+
80
+ # 渲染背面视图 - 旋转180度(使用相反的角度)
81
+ render_back = Render(
82
+ player=skin,
83
+ vr=vrrl, # 垂直旋转,稍微向下看
84
+ hr=hrrl + 180, # 水平旋转215度 (35+180)
85
+ hrh=0, # 头部水平旋转
86
+ vrll=-vrrl_front, # 左腿向后(与正面右腿相反)
87
+ vrrl=-vrll_front, # 右腿向前(与正面左腿相反)
88
+ vrla=-vrra_front, # 左臂向前(与正面右臂相反)
89
+ vrra=-vrla_front, # 右臂向后(与正面左臂相反)
90
+ ratio=ratiorl, # 缩放比例
91
+ aa=True, # 抗锯齿
92
+ display_hair=True,
93
+ display_layers=True
94
+ )
95
+
96
+ # 获取渲染结果
97
+ front_img = await render_front.get_render()
98
+ back_img = await render_back.get_render()
99
+
100
+ # 创建1024x1024的画布,使用随机深色背景
101
+ canvas = Image.new('RGB', (1024, 1024), bg_color)
102
+
103
+ # 计算每个图像的位置(并排放置)
104
+ front_width, front_height = front_img.size
105
+ back_width, back_height = back_img.size
106
+
107
+ # 左侧放置正面视图
108
+ front_x = (512 - front_width) // 2
109
+ front_y = (1024 - front_height) // 2
110
+
111
+ # 右侧放置背面视图
112
+ back_x = 512 + (512 - back_width) // 2
113
+ back_y = (1024 - back_height) // 2
114
+
115
+ # 粘贴正面视图
116
+ if front_img.mode == 'RGBA':
117
+ canvas.paste(front_img, (front_x, front_y), front_img)
118
+ else:
119
+ canvas.paste(front_img, (front_x, front_y))
120
+
121
+ # 粘贴背面视图
122
+ if back_img.mode == 'RGBA':
123
+ canvas.paste(back_img, (back_x, back_y), back_img)
124
+ else:
125
+ canvas.paste(back_img, (back_x, back_y))
126
+
127
+ # 保存渲染图
128
+ render_output_path = os.path.join(RENDER_OUTPUT_DIR, output_name)
129
+ canvas.save(render_output_path)
130
+
131
+ return True
132
+ except Exception as e:
133
+ print(f"渲染失败 {skin_path}: {str(e)}")
134
+ return False
135
+
136
+ def scale_texture(skin_path, output_name):
137
+ """缩放原始材质到1024x1024,灰色背���"""
138
+ try:
139
+ # 打开原始皮肤
140
+ img = Image.open(skin_path)
141
+
142
+ # 处理所有可能有透明度的模式
143
+ # P模式(调色板)、LA模式、RGBA模式都可能有透明度
144
+ if img.mode in ('RGBA', 'LA', 'P'):
145
+ # 先转换为RGBA以保留透明度信息
146
+ if img.mode != 'RGBA':
147
+ img = img.convert('RGBA')
148
+
149
+ # 创建灰色背景
150
+ background = Image.new('RGB', img.size, (128, 128, 128))
151
+ # 使用alpha通道合成
152
+ background.paste(img, (0, 0), img)
153
+ img = background
154
+ elif img.mode == 'RGB' and 'transparency' in img.info:
155
+ # RGB模式但有透明色信息(通常是某个颜色被指定为透明)
156
+ # 需要转换为RGBA来处理透明度
157
+ # 获取透明色
158
+ trans_color = img.info['transparency']
159
+
160
+ # 转换为RGBA
161
+ img = img.convert('RGBA')
162
+
163
+ # 获取图片数据
164
+ datas = img.getdata()
165
+
166
+ # 将透明色替换为完全透明
167
+ newData = []
168
+ for item in datas:
169
+ # 检查是否是透明色(RGB模式的transparency可能是元组或单个值)
170
+ if isinstance(trans_color, tuple):
171
+ if item[:3] == trans_color:
172
+ newData.append((128, 128, 128, 0)) # 完全透明
173
+ else:
174
+ newData.append(item)
175
+ else:
176
+ # 单通道透明度(灰度图)
177
+ if item[0] == trans_color:
178
+ newData.append((128, 128, 128, 0))
179
+ else:
180
+ newData.append(item)
181
+
182
+ img.putdata(newData)
183
+
184
+ # 创建灰色背景并合成
185
+ background = Image.new('RGB', img.size, (128, 128, 128))
186
+ background.paste(img, (0, 0), img)
187
+ img = background
188
+ elif img.mode != 'RGB':
189
+ # 转换其他模式为RGB
190
+ img = img.convert('RGB')
191
+
192
+ # 使用最近邻插值缩放皮肤材质(保持像素风格)
193
+ # 通常Minecraft皮肤是64x64或64x32
194
+ img_resized = img.resize((1024, 1024), Image.NEAREST)
195
+
196
+ # 确保保存为RGB模式(没有透明通道)
197
+ if img_resized.mode != 'RGB':
198
+ img_resized = img_resized.convert('RGB')
199
+
200
+ # 保存缩放后的材质
201
+ texture_output_path = os.path.join(TEXTURE_OUTPUT_DIR, output_name)
202
+ img_resized.save(texture_output_path, 'PNG')
203
+
204
+ return True
205
+ except Exception as e:
206
+ print(f"缩放失败 {skin_path}: {str(e)}")
207
+ return False
208
+
209
+ async def process_all_skins():
210
+ """处理所有皮肤"""
211
+ total = len(skin_files)
212
+ success_render = 0
213
+ success_texture = 0
214
+
215
+ for idx, skin_path in enumerate(skin_files, 1):
216
+ # 获取文件名(不含扩展名)
217
+ filename = os.path.basename(skin_path)
218
+ output_name = filename
219
+
220
+ print(f"处理 [{idx}/{total}]: {filename}")
221
+
222
+ # 渲染皮肤
223
+ if await render_skin(skin_path, output_name):
224
+ success_render += 1
225
+
226
+ # 缩放材质
227
+ if scale_texture(skin_path, output_name):
228
+ success_texture += 1
229
+
230
+ # 每处理10个文件显示进度
231
+ if idx % 10 == 0:
232
+ print(f"进度: {idx}/{total} - 渲染成功: {success_render}, 材质成功: {success_texture}")
233
+
234
+ print(f"\n完成!")
235
+ print(f"总计: {total}")
236
+ print(f"渲染成功: {success_render}")
237
+ print(f"材质缩放成功: {success_texture}")
238
+ print(f"渲染图保存在: {RENDER_OUTPUT_DIR}/")
239
+ print(f"缩放材质保存在: {TEXTURE_OUTPUT_DIR}/")
240
+
241
+ if __name__ == "__main__":
242
+ asyncio.run(process_all_skins())