Skip to content

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')
Clone this wiki locally