解决blender投影歪斜问题

是否会出现blender里面的obj投影到原始视频流上存在偏移的情况,前几次关于blender的博客中也存在这种问题,可以去看看,接下来我们给出一张样图, 如下图所示:

【解决方法】:用重投影方式,投影矩阵去给原始图像增加一定偏移量,这个偏移量的产生是因为blender中obj物体旋转的角度偏移量导致的。

python 复制代码
def process_video_with_objects(camera, video_path, output_dir, output_video_path, obj_dir, fps=30, camera_dict={}):
    os.makedirs(output_dir, exist_ok=True)
    K, R, T = camera_dict['K'], camera_dict['R'], camera_dict['T']
    video = cv2.VideoCapture(video_path)
    if not video.isOpened():
        raise ValueError(f"Could not open video file: {video_path}")
    input_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
    input_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out_video = cv2.VideoWriter(output_video_path, fourcc, fps, (input_width, input_height), True)
    frame_idx = 0
    while True:
        ret, frame = video.read()
        if not ret:
            break
        bpy.context.scene.frame_set(frame_idx)
        scene = bpy.context.scene
        # Load corresponding .obj file for the current frame
        obj_files = sorted([f for f in os.listdir(obj_dir) if f.endswith('_{}.obj'.format(frame_idx + 1))])
        clear_scene(visual_axis, visual_mark, base_keypoints_dict)  # 清空非相机对象并筛选是否可视化坐标轴
        for obj_file in obj_files:
            bpy.ops.import_scene.obj(filepath=os.path.join(obj_dir, obj_file))  # 导入 obj 文件
        # 计算世界坐标原点在相机局部坐标系中的位置
        world_origin = Vector((0, 0, 0))  # 世界坐标原点
        render = bpy.context.scene.render
        # Get the two components to calculate M
        modelview_matrix = camera.matrix_world.inverted()
        # Get the depsgraph for the current scene
        depsgraph = bpy.context.evaluated_depsgraph_get()
        # Get the projection matrix
        projection_matrix = camera.calc_matrix_camera(
                depsgraph,
                x=render.resolution_x,
                y=render.resolution_y,
                scale_x=render.pixel_aspect_x,
                scale_y=render.pixel_aspect_y,
        )
        # Compute P' = M * P
        p1 = np.dot(projection_matrix @ modelview_matrix,  Vector((world_origin.x, world_origin.y, world_origin.z, 1)))
        p2 = Vector(((p1[0] / p1[3]), (p1[1] / p1[3])))
        pixel_x_now, pixel_y_now = (p2.x + 1) * 0.5 * render.resolution_x, (1 - p2.y) * 0.5 * render.resolution_y
        pixel_target = project_points_3d_to_2d(np.array([[0, 0, 0]]), K, R, T)
        shift_x_pixels, shift_y_pixels = (int(pixel_x_now - pixel_target[0][0])), (
            int(pixel_y_now - pixel_target[0][1]))
        frame = shift_image(frame, shift_x_pixels, shift_y_pixels)
     
        scene.render.resolution_x = input_width
        scene.render.resolution_y = input_height
        scene.render.film_transparent = True
        scene.camera = camera

        output_frame_path = os.path.join(output_dir, f'rendered_{frame_idx:04d}.png')
        scene.render.filepath = output_frame_path
        bpy.context.view_layer.update()
        bpy.ops.render.render(write_still=True)
        for obj in bpy.context.selected_objects:
            bpy.data.objects.remove(obj, do_unlink=True)
        rendered_frame = cv2.imread(output_frame_path, cv2.IMREAD_UNCHANGED)
        if rendered_frame is None:
            continue

        if rendered_frame.shape[2] == 3:
            rendered_frame = cv2.cvtColor(rendered_frame, cv2.COLOR_BGR2BGRA)

        alpha = rendered_frame[:, :, 3] / 255.0
        for c in range(0, 3):
            frame[:, :, c] = (1 - alpha) * frame[:, :, c] + alpha * rendered_frame[:, :, c]

        out_video.write(frame)
        frame_idx += 1

    video.release()
    out_video.release()
    print(f"Processed video saved to {output_video_path}")

结果可视化:

blender渲染里面设置透明度

python 复制代码
def createMaterial(color=(0.8, 0.8, 0.8, 0.5), metallic=0, roughness=0., alpha=0.5):
    color_count = [m.name for m in bpy.data.materials].count(str(color))
    if color_count > 0:
        color_index = [m.name for m in bpy.data.materials].index(str(color))
        matg = bpy.data.materials[color_index]
    else:
        matg = bpy.data.materials.new(str(color))
        matg.use_nodes = True
        tree = matg.node_tree
        nodes = tree.nodes
        links = tree.links

        for node in nodes:
            nodes.remove(node)

        # 添加必要的节点
        output = nodes.new(type='ShaderNodeOutputMaterial')
        bsdf = nodes.new(type='ShaderNodeBsdfPrincipled')
        transparent = nodes.new(type='ShaderNodeBsdfTransparent')
        mix_shader = nodes.new(type='ShaderNodeMixShader')
        bsdf.inputs["Base Color"].default_value = color
        bsdf.inputs["Metallic"].default_value = metallic
        bsdf.inputs["Roughness"].default_value = roughness
        mix_shader.inputs[0].default_value = 1 - alpha  # 透明度控制
        links.new(bsdf.outputs[0], mix_shader.inputs[2])      
        links.new(transparent.outputs[0], mix_shader.inputs[1]) 
        links.new(mix_shader.outputs[0], output.inputs[0])    
        matg.blend_method = 'BLEND'
        matg.shadow_method = 'HASHED'
    return matg
相关推荐
在下胡三汉2 天前
3dmax一键烘焙很多张贴图合并成一张贴图插件支持fbx/obj/blender多材质模型合并为一张贴图
blender·材质·贴图
九河_5 天前
【blender】使用bpy对一个obj的不同mesh进行不同的材质贴图(涉及对bmesh的操作)
blender·材质·贴图·bpy
渲染101专业云渲染19 天前
云端算力革命:川翔云电脑如何重新定义创作自由
云计算·电脑·blender·maya·houdini
3D虚拟工厂20 天前
3D虚拟工厂
3d·vue3·blender·数字孪生·three.js
Tipriest_22 天前
介绍常见的图像和视频存储格式以及其优劣势
音视频·blender·视频格式·图像格式
有过~23 天前
Blender 4.4.3三维动画建模和渲染软件Win/Mac双端资源下载
blender
技术小甜甜23 天前
[Blender] 高质量材质推荐第四弹:25-30号精选纹理资源详解
blender·游戏开发·材质·建模·资源
下次见咯!25 天前
Blender基础知识-操作模式、基本操作、渲染、灯光、材质、粒子系统、动画
blender
AllBlue25 天前
fbx导入blender结构错乱,但在threejs中加载正常
blender·threejs
灵境引路人1 个月前
【Blender】Blender 基础:导入&导出
blender