【问题标题】:Create UV Texture map from DensePose Output从 DensePose 输出创建 UV 纹理贴图
【发布时间】:2021-08-31 13:40:48
【问题描述】:

我正在尝试以 SURREAL 数据集的格式生成单个 UV 纹理贴图。原始 DensePose 存储库中有一个笔记本讨论如何使用来自 SMPL 的图像应用纹理传输:github.com/facebookresearch/DensePose/blob/master/notebooks/DensePose-RCNN-Texture-Transfer.ipynb

但是,在这种情况下,我尝试直接使用从 DensePose 获得的输出:

在转储模式下,我在 data[0]['pred_densepose'][0].uv 中获取 uv 坐标,尺寸为:torch.Size([2, 1098, 529])

我用黑色背景上的 dp_u,dp_v 可视化将运行推理的输出叠加在图像上。这是图片的链接:https://densepose.s3.amazonaws.com/test1uv.0001.png

这是我用来推断的命令:python3 apply_net.py show configs/densepose_rcnn_R_101_FPN_DL_WC2M_s1x.yaml model_final_de6e7a.pkl input.jpg dp_u,dp_v -v --output output.png 这是原图的链接:https://densepose.s3.amazonaws.com/02_1_front.jpg

使用这些组件,我尝试生成与 SMPL 格式相同的 24 部分 uv 纹理贴图: https://densepose.s3.amazonaws.com/extracted_smpl_texture_apprearance.png https://densepose.s3.amazonaws.com/texture_from_SURREAL.png

如果有人能分享如何解决这个问题,那将非常有帮助。如果需要更多信息,请告诉我。

【问题讨论】:

    标签: computer-vision pytorch uv-mapping


    【解决方案1】:

    我不知道问题是否仍然存在,或者您是否能够找到解决方案。如果其他人会挑战同样的问题,这是我的解决方案。我将来自官方 github 问题页面的几个不同的代码和想法放在了 densepose (https://github.com/facebookresearch/DensePose/issues/68)。

    我假设我们已经从 github denspose 存储库中获得了 apply_net.py 实用程序的输出。从您的帖子来看,它是一个数据输出(您可以从中获得data[0]['pred_densepose'][0].uv)。

    让我们做一些编码:

    import copy
    import cv2  
    import matplotlib
    import numpy as np
    
    from matplotlib import pyplot as plt
    
    matplotlib.use('TkAgg')
    
    # I assume the data are stored in pickle, and you are able to read them 
    results = data[0]
    IMAGE_FILE = 'path/to/image.png'
    
    
    def parse_iuv(result):
        i = result['pred_densepose'][0].labels.cpu().numpy().astype(float)
        uv = (result['pred_densepose'][0].uv.cpu().numpy() * 255.0).astype(float)
        iuv = np.stack((uv[1, :, :], uv[0, :, :], i))
        iuv = np.transpose(iuv, (1, 2, 0))
        return iuv
    
    
    def parse_bbox(result):
        return result["pred_boxes_XYXY"][0].cpu().numpy()
    
    
    def concat_textures(array):
        texture = []
        for i in range(4):
            tmp = array[6 * i]
            for j in range(6 * i + 1, 6 * i + 6):
                tmp = np.concatenate((tmp, array[j]), axis=1)
            texture = tmp if len(texture) == 0 else np.concatenate((texture, tmp), axis=0)
        return texture
    
    
    def interpolate_tex(tex):
        # code is adopted from https://github.com/facebookresearch/DensePose/issues/68
        valid_mask = np.array((tex.sum(0) != 0) * 1, dtype='uint8')
        radius_increase = 10
        kernel = np.ones((radius_increase, radius_increase), np.uint8)
        dilated_mask = cv2.dilate(valid_mask, kernel, iterations=1)
        region_to_fill = dilated_mask - valid_mask
        invalid_region = 1 - valid_mask
        actual_part_max = tex.max()
        actual_part_min = tex.min()
        actual_part_uint = np.array((tex - actual_part_min) / (actual_part_max - actual_part_min) * 255, dtype='uint8')
        actual_part_uint = cv2.inpaint(actual_part_uint.transpose((1, 2, 0)), invalid_region, 1,
                                   cv2.INPAINT_TELEA).transpose((2, 0, 1))
        actual_part = (actual_part_uint / 255.0) * (actual_part_max - actual_part_min) + actual_part_min
        # only use dilated part
        actual_part = actual_part * dilated_mask
    
        return actual_part
    
    
    def get_texture(im, iuv, bbox, tex_part_size=200):
        # this part of code creates iuv image which corresponds
        # to the size of original image (iuv from densepose is placed
        # within pose bounding box).
        im = im.transpose(2, 1, 0) / 255
        image_w, image_h = im.shape[1], im.shape[2]
        bbox[2] = bbox[2] - bbox[0]
        bbox[3] = bbox[3] - bbox[1]
        x, y, w, h = [int(v) for v in bbox]
        bg = np.zeros((image_h, image_w, 3))
        bg[y:y + h, x:x + w, :] = iuv
        iuv = bg
        iuv = iuv.transpose((2, 1, 0))
        i, u, v = iuv[2], iuv[1], iuv[0]
    
        # following part of code iterate over parts and creates textures
        # of size `tex_part_size x tex_part_size`
        n_parts = 24
        texture = np.zeros((n_parts, 3, tex_part_size, tex_part_size))
        
        for part_id in range(1, n_parts + 1):
            generated = np.zeros((3, tex_part_size, tex_part_size))
    
            x, y = u[i == part_id], v[i == part_id]
            # transform uv coodrinates to current UV texture coordinates:
            tex_u_coo = (x * (tex_part_size - 1) / 255).astype(int)
            tex_v_coo = (y * (tex_part_size - 1) / 255).astype(int)
            
            # clipping due to issues encountered in denspose output;
            # for unknown reason, some `uv` coos are out of bound [0, 1]
            tex_u_coo = np.clip(tex_u_coo, 0, tex_part_size - 1)
            tex_v_coo = np.clip(tex_v_coo, 0, tex_part_size - 1)
            
            # write corresponding pixels from original image to UV texture
            # iterate in range(3) due to 3 chanels
            for channel in range(3):
                generated[channel][tex_v_coo, tex_u_coo] = im[channel][i == part_id]
            
            # this part is not crucial, but gives you better results 
            # (texture comes out more smooth)
            if np.sum(generated) > 0:
                generated = interpolate_tex(generated)
    
            # assign part to final texture carrier
            texture[part_id - 1] = generated[:, ::-1, :]
        
        # concatenate textures and create 2D plane (UV)
        tex_concat = np.zeros((24, tex_part_size, tex_part_size, 3))
        for i in range(texture.shape[0]):
            tex_concat[i] = texture[i].transpose(2, 1, 0)
        tex = concat_textures(tex_concat)
    
        return tex
    
    
    iuv = parse_iuv(results)
    bbox = parse_bbox(results)
    image = cv2.imread(IMAGE_FILE)[:, :, ::-1]
    uv_texture = get_texture(image, iuv, bbox)
    
    # plot texture or do whatever you like
    plt.imshow(uv_texture)
    plt.show()
    

    享受

    【讨论】:

      猜你喜欢
      • 2019-08-12
      • 2014-12-15
      • 2013-02-14
      • 1970-01-01
      • 1970-01-01
      • 2015-01-11
      • 2013-08-20
      • 2017-03-29
      • 2018-07-29
      相关资源
      最近更新 更多