-
Notifications
You must be signed in to change notification settings - Fork 0
1130630
crodis-strife edited this page Jul 2, 2024
·
6 revisions
輸入圖片的L通道轉換為Blender地形圖
import bpy
import numpy as np
from PIL import Image
# 讀取圖像
image_path = 'D:\\Blender\\113\\0630\\01.jpg' # 替換為你的圖像路徑
image = Image.open(image_path)
# 將圖像轉換為LAB顏色空間
image_lab = image.convert('LAB')
# 提取L通道
L_channel, A_channel, B_channel = image_lab.split()
L_channel = np.array(L_channel)
# 獲取圖像尺寸
height, width = L_channel.shape
# 創建網格
vertices = []
faces = []
# 創建頂點
for y in range(height):
for x in range(width):
z = L_channel[y, x] # 使用L通道值作為高度
vertices.append((x, y, z))
# 創建面
for y in range(height - 1):
for x in range(width - 1):
v1 = y * width + x
v2 = v1 + 1
v3 = v1 + width
v4 = v3 + 1
faces.append((v1, v2, v4, v3))
# 創建網格物體
mesh = bpy.data.meshes.new(name='TerrainMesh')
mesh.from_pydata(vertices, [], faces)
mesh.update()
# 創建物體並將網格分配給它
obj = bpy.data.objects.new('Terrain', mesh)
# 將物體添加到場景中
bpy.context.collection.objects.link(obj)
# 設置場景
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
# 調整視角
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
space.region_3d.view_perspective = 'ORTHO'
#bpy.ops.view3d.view_all(center=True)
Blender地形圖轉回L通道,縮放到原L通道數值範圍後,取代原圖L通道
import bpy
import numpy as np
from PIL import Image
def rescale_image_to_range(image, min_a, max_a):
"""
將圖片的像素值從[image.min(), image.max()]的範圍重新縮放到[min_a, max_a]的範圍
"""
# 將圖片轉換為NumPy數組
image_array = np.array(image)
# 找出圖片的最大值和最小值
max_b = image_array.max()
min_b = image_array.min()
# 計算線性變換的比例和偏移量
scale = (max_a - min_a) / (max_b - min_b)
offset = min_a - min_b * scale
# 應用線性變換
rescaled_image_array = image_array * scale + offset
# 將結果限制在[min_a, max_a]範圍內,並轉換為整數型別
rescaled_image_array = np.clip(rescaled_image_array, min_a, max_a).astype(np.uint8)
# 將數組轉回圖片
rescaled_image = Image.fromarray(rescaled_image_array)
return rescaled_image
# 圖片路徑
ref_image_path = 'D:\\Blender\\113\\0630\\01.jpg'
# 讀取圖片
ref_image = Image.open(ref_image_path)
# 將圖像轉換為LAB顏色空間
image_lab = ref_image.convert('LAB')
# 提取L、A、B通道
l_a, a_a, b_a = image_lab.split()
l_a.save('D://Blender//113//0630//L.jpg')
ref_image_array = np.array(l_a)
max_value = ref_image_array.max()
min_value = ref_image_array.min()
# 選擇地形模型物體
terrain_obj = bpy.data.objects.get('Terrain') # 假設地形模型的名字是'Terrain'
if terrain_obj is None:
raise ValueError("找不到名為 'Terrain' 的物體。")
# 獲取地形模型的頂點數據
vertices = terrain_obj.data.vertices
# 確定圖像的尺寸(這裡假設為1024x1024)
image_width = 1024
image_height = 1024
# 創建一個空白的圖像對象
image = Image.new('L', (image_width, image_height))
# 獲取地形模型的範圍
min_x = min(vertex.co.x for vertex in vertices)
max_x = max(vertex.co.x for vertex in vertices)
min_y = min(vertex.co.y for vertex in vertices)
max_y = max(vertex.co.y for vertex in vertices)
min_z = min(vertex.co.z for vertex in vertices)
max_z = max(vertex.co.z for vertex in vertices)
# 將地形模型的坐標映射到圖像的坐標系中
for vertex in vertices:
# 計算歸一化的高度值(0到1之間)
normalized_height = (vertex.co.z - min_z) / (max_z - min_z)
# 將高度值映射到灰度值(0到255之間)
gray_value = int(normalized_height * 255)
# 計算在圖像中的對應位置
x = int((vertex.co.x - min_x) / (max_x - min_x) * (image_width - 1))
y = int((vertex.co.y - min_y) / (max_y - min_y) * (image_height - 1))
y = image_height - 1 - y # 翻轉y軸
# 確保 x 和 y 在有效範圍內
if 0 <= x < image_width and 0 <= y < image_height:
# 將灰度值設置為圖像中的像素值
image.putpixel((x, y), gray_value)
# 重新縮放圖像的灰度範圍
image = rescale_image_to_range(image, min_value, max_value)
# 保存圖像為JPG文件
image.save('D://Blender//113//0630//terrain_heightmap.jpg')
print("地形高度圖已成功儲存為 terrain_heightmap.jpg。")
# 合併新的L通道和原來的A、B通道
new_image = Image.merge('LAB', (image, a_a, b_a))
# 將結果轉換為RGB模式
result_image = new_image.convert('RGB')
# 保存結果圖片
result_image.save('D://Blender//113//0630//result.jpg')