[code] Dust3r

FSA·2024년 8월 8일
0

vision

목록 보기
24/25

1. 설치

  • DUSt3R를 클론하세요.
git clone --recursive https://github.com/naver/dust3r
cd dust3r
# 이미 dust3r를 클론한 경우:
# git submodule update --init --recursive
  • conda를 사용하여 환경을 만드세요.
conda create -n dust3r python=3.11 cmake=3.14.0
conda activate dust3r
conda install pytorch torchvision pytorch-cuda=12.1 -c pytorch -c nvidia  # 시스템에 맞는 cuda 버전을 사용하세요.
pip install -r requirements.txt
# 선택사항: 추가 패키지를 설치하여:
# - HEIC 이미지 지원 추가
# - 일부 데이터셋 전처리에서 깊이 맵을 렌더링하는 데 사용되는 pyrender 추가
# - visloc.py에 필요한 패키지 추가
pip install -r requirements_optional.txt
  • 옵션으로, RoPE의 CUDA 커널을 컴파일하세요 (CroCo v2에서와 같이).
# DUST3R는 RoPE 위치 임베딩을 사용하며, 이를 위해 CUDA 커널을 컴파일하여 실행 시간을 단축할 수 있습니다.
cd croco/models/curope/
python setup.py build_ext --inplace
cd ../../../

2. 체크포인트

  • 체크포인트는 두 가지 방법으로 얻을 수 있습니다:
      1. huggingface_hub 통합 기능을 사용하여, 모델을 자동으로 다운로드
      1. 또는 여러 사전 학습된 모델을 제공
모델명훈련 해상도헤드인코더디코더
DUSt3R_ViTLarge_BaseDecoder_224_linear.pth224x224LinearViT-LViT-B
DUSt3R_ViTLarge_BaseDecoder_512_linear.pth512x384, 512x336, 512x288, 512x256, 512x160LinearViT-LViT-B
DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth512x384, 512x336, 512x288, 512x256, 512x160DPTViT-LViT-B
  • 이 모델들을 훈련할 때 사용한 하이퍼파라미터는 'Our Hyperparameters' 섹션에서 확인할 수 있습니다.

  • 특정 모델을 다운로드하려면, 예를 들어 DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth:

mkdir -p checkpoints/
wget https://download.europe.naverlabs.com/ComputerVision/DUSt3R/DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth -P checkpoints/
  • 체크포인트에 대해서는, 사용된 모든 공개 훈련 데이터셋 및 기본 체크포인트의 라이선스와 CC-BY-NC-SA 4.0을 준수해야 합니다.
  • 자세한 내용은 'Our Hyperparameters' 섹션을 참조하세요.

3. 인터랙티브 데모

  • 이 데모에서는 DUSt3R를 사용하여 장면을 재구성할 수 있습니다. 먼저 동일한 장면을 나타내는 이미지를 선택하세요.
  • 글로벌 정렬 스케줄 및 반복 횟수를 조정할 수 있습니다.

참고:

  • 이미지 하나 또는 두 개를 선택한 경우, 글로벌 정렬 절차는 건너뜁니다.(mode=GlobalAlignerMode.PairViewer).
  • "Run"을 클릭하고 기다리세요. 글로벌 정렬이 끝나면 재구성이 나타납니다.
  • 슬라이더 "min_conf_thr"을 사용하여 낮은 신뢰도의 영역을 표시하거나 제거할 수 있습니다.
python3 demo.py --model_name DUSt3R_ViTLarge_BaseDecoder_512_dpt

# --weights를 사용하여 로컬 파일에서 체크포인트를 로드하세요, 예: --weights checkpoints/DUSt3R_ViTLarge_BaseDecoder_512_dpt.pth
# --image_size를 사용하여 선택한 체크포인트에 맞는 해상도를 선택하세요. 512 (기본값) 또는 224
# --local_network를 사용하여 로컬 네트워크에서 접근 가능하게 만들거나, --server_name을 사용하여 URL을 수동으로 지정하세요.
# --server_port를 사용하여 포트를 변경하세요, 기본적으로 7860부터 사용 가능한 포트를 검색합니다.
# --device를 사용하여 다른 장치를 사용하세요, 기본값은 "cuda"입니다.

4. Docker를 이용한 인터랙티브 데모

  • NVIDIA CUDA 지원을 포함하여 Docker를 사용하여 DUSt3R를 실행하려면 다음 지침을 따르세요:
      1. Docker 설치: 이미 설치하지 않았다면, Docker와 Docker Compose를 Docker 웹사이트에서 다운로드하고 설치하세요.
      1. NVIDIA Docker Toolkit 설치: GPU 지원을 위해 Nvidia 웹사이트에서 NVIDIA Docker Toolkit을 설치하세요.
      1. Docker 이미지를 빌드하고 실행하세요: ./docker 디렉토리로 이동하여 다음 명령을 실행하세요:
cd docker
bash run.sh --with-cuda --model_name="DUSt3R_ViTLarge_BaseDecoder_512_dpt"
  • CUDA 지원 없이 데모를 실행하려면 다음 명령을 실행하세요:
cd docker
bash run.sh --model_name="DUSt3R_ViTLarge_BaseDecoder_512_dpt"
  • 기본적으로 demo.py--local_network 옵션과 함께 실행됩니다.

  • 웹 UI에 접근하려면 http://localhost:7860/로 이동하세요 (또는 네트워크에서 접근하려면 localhost를 머신 이름으로 변경하세요).

  • run.shdocker-compose-cuda.yml 또는 docker-compose-cpu.yml 설정 파일을 사용하여 docker-compose를 실행한 다음, entrypoint.sh를 사용하여 데모를 시작합니다.

5. 사용법

from dust3r.inference import inference
from dust3r.model import AsymmetricCroCo3DStereo
from dust3r.utils.image import load_images
from dust3r.image_pairs import make_pairs
from dust3r.cloud_opt import global_aligner, GlobalAlignerMode

if __name__ == '__main__':
    device = 'cuda'
    batch_size = 1
    schedule = 'cosine'
    lr = 0.01
    niter = 300

    model_name = "naver/DUSt3R_ViTLarge_BaseDecoder_512_dpt"
    # 필요한 경우 로컬 체크포인트 경로를 model_name에 지정할 수 있습니다.
    model = AsymmetricCroCo3DStereo.from_pretrained(model_name).to(device)
    # load_images는 이미지 목록 또는 디렉토리를 받을 수 있습니다.
    images = load_images(['croco/assets/Chateau1.png', 'croco/assets/Chateau2.png'], size=512)
    pairs = make_pairs(images, scene_graph='complete', prefilter=None, symmetrize=True)
    output = inference(pairs, model, device, batch_size=batch_size)

    # 이 단계에서, raw dust3r 예측을 가지고 있습니다.
    view1, pred1 = output['view1'], output['pred1']
    view2, pred2 = output['view2'], output['pred2']
    # 여기서 view1, pred1, view2, pred2는 길이가 2인 리스트의 딕셔너리입니다.
    #  -> 대칭화를 하기 때문에 (im1, im2)와 (im2, im1) 쌍을 가지고 있습니다.
    # 각 view에는 다음이 포함됩니다:
    # 정수 이미지 식별자: view1['idx']와 view2['idx']
    # 이미지: view1['img']와 view2['img']
    # 이미지 크기: view1['true_shape']와 view2['true_shape']
    # 데이터 로더에 의해 출력된 인스턴스 문자열: view1['instance']와 view2['instance']
    # pred1과 pred2는 신뢰도 값을 포함합니다: pred1['conf']와 pred2['conf']
    # pred1은 view1['img'] 공간에서 view1['img']의 3D 포인트를 포함합니다: pred1['pts3d']
    # pred2는 view2['img'] 공간에서 view1['img']의 3D 포인트를 포함합니다: pred2['pts3d_in_other_view']

    # 다음으로 global_aligner를 사용하여 예측을 정렬합니다.
    # 작업에 따라 raw 출력을 그대로 사용해도 될 수 있습니다.
    # 입력 이미지가 두 개뿐인 경우, GlobalAlignerMode.PairViewer를 사용할 수 있습니다: 출력만 변환됩니다.
    # GlobalAlignerMode.PairViewer를 사용하는 경우, compute_global_alignment를 실행할 필요가 없습니다.
    scene = global_aligner(output, device=device, mode=GlobalAlignerMode.PointCloudOptimizer)
    loss = scene.compute_global_alignment(init="mst", niter=niter, schedule=schedule, lr=lr)

    # scene에서 유용한 값을 가져옵니다:
    imgs = scene.imgs
    focals = scene.get_focals()
    poses = scene.get_im_poses()
    pts3d = scene.get_pts3d()
    confidence_masks

 = scene.get_masks()

    # 재구성 시각화
    scene.show()

    # 두 이미지 간의 2D-2D 매칭 찾기
    from dust3r.utils.geometry import find_reciprocal_matches, xy_grid
    pts2d_list, pts3d_list = [], []
    for i in range(2):
        conf_i = confidence_masks[i].cpu().numpy()
        pts2d_list.append(xy_grid(*imgs[i].shape[:2][::-1])[conf_i])  # imgs[i].shape[:2] = (H, W)
        pts3d_list.append(pts3d[i].detach().cpu().numpy()[conf_i])
    reciprocal_in_P2, nn2_in_P1, num_matches = find_reciprocal_matches(*pts3d_list)
    print(f'found {num_matches} matches')
    matches_im1 = pts2d_list[1][reciprocal_in_P2]
    matches_im0 = pts2d_list[0][nn2_in_P1][reciprocal_in_P2]

    # 몇 가지 매칭을 시각화합니다.
    import numpy as np
    from matplotlib import pyplot as pl
    n_viz = 10
    match_idx_to_viz = np.round(np.linspace(0, num_matches-1, n_viz)).astype(int)
    viz_matches_im0, viz_matches_im1 = matches_im0[match_idx_to_viz], matches_im1[match_idx_to_viz]

    H0, W0, H1, W1 = *imgs[0].shape[:2], *imgs[1].shape[:2]
    img0 = np.pad(imgs[0], ((0, max(H1 - H0, 0)), (0, 0), (0, 0)), 'constant', constant_values=0)
    img1 = np.pad(imgs[1], ((0, max(H0 - H1, 0)), (0, 0), (0, 0)), 'constant', constant_values=0)
    img = np.concatenate((img0, img1), axis=1)
    pl.figure()
    pl.imshow(img)
    cmap = pl.get_cmap('jet')
    for i in range(n_viz):
        (x0, y0), (x1, y1) = viz_matches_im0[i].T, viz_matches_im1[i].T
        pl.plot([x0, x1 + W0], [y0, y1], '-+', color=cmap(i / (n_viz - 1)), scalex=False, scaley=False)
    pl.show(block=True)
  • 위 코드는 DUSt3R 모델을 사용하여 두 이미지 간의 3D 재구성 및 특징 매칭을 수행하는 데모 프로그램
  • 이 프로그램은 이미지를 입력으로 받아 모델을 통해 3D 포인트를 추출하고, 이를 정렬하여 장면을 재구성하며, 두 이미지 간의 매칭 결과를 시각화합니다.
  • 각 단계의 목적과 역할을 설명하면 다음과 같습니다:

5.1. 주요 단계와 역할

  1. 모델 로드 및 준비
    • 사전 학습된 DUSt3R 모델을 불러오고 device에 맞게 설정합니다.
    • 예제 이미지를 로드하고 이미지 쌍을 생성합니다.
  2. 모델 추론
    • DUSt3R 모델을 사용하여 이미지 쌍에서 특징을 추출
    • 추론 결과로부터 두 이미지의 특징 벡터를 가져옴
  3. 글로벌 정렬 (중요!!)
    • global_aligner를 사용하여 예측 결과를 정렬
    • 두 이미지 간의 3D 포인트를 정렬하여 전체 장면을 재구성
    • GlobalAlignerMode.PairViewer 모드를 사용하면 두 이미지 간의 매칭 결과만 변환하고, 정렬을 건너뜁니다.
  4. 재구성 시각화
    • 재구성된 장면을 시각화
    • scene.show()를 통해 3D 포인트와 이미지를 확인할 수 있음
  5. 특징 매칭
    • find_reciprocal_matches 함수를 사용하여 두 이미지 간의 2D-2D 특징 매칭을 수행
    • 신뢰도 마스크를 사용하여 유효한 매칭을 필터링
  6. 매칭 결과 시각화
    • 몇 가지 매칭 결과를 시각화하여 결과를 확인
    • Matplotlib을 사용하여 두 이미지와 매칭된 특징들을 한 화면에 보여줍니다.
    • 색상 맵을 사용하여 매칭된 특징을 연결하는 선의 색상을 지정합니다.

5.2. 코드의 목적

  • 이 코드는 DUSt3R 모델을 사용하여 두 이미지 간의 3D 재구성과 특징 매칭을 수행하고 이를 시각화하는 데모 프로그램
  • 이를 통해 사용자는 DUSt3R 모델의 기능과 성능을 직관적으로 이해할 수 있습니다.
  • 주요 목적은 다음과 같습니다:
    1. DUSt3R 모델의 3D 재구성 능력 시연
    • DUSt3R 모델이 이미지에서 어떻게 3D 포인트를 추출하고, 이를 통해 장면을 재구성하는지 보여줍니다.
    1. 특징 매칭의 정확성 및 효율성 평가
    • 추출된 특징을 기반으로 두 이미지 간의 매칭을 수행하는 과정을 시연합니다.
    1. 시각화를 통한 이해도 증진
    • 재구성과 매칭 결과를 시각적으로 표현하여 모델의 결과를 쉽게 이해할 수 있도록 합니다.

5.3. dataset

5.3.1. 7-scenes

  • 여기에서는 7-scenes 데이터셋을 kapture 포맷으로 가져오는 방법을 설명
    • 가져오는 과정에서는 이미지와 포즈를 사용하며, 다른 데이터(예: 깊이 맵)는 무시
  • 가져오는 동안 하나의 장면이 매핑과 쿼리로 나뉩니다.
    • 모든 7-scenes에 대해 변환을 적용할 수 있습니다.
  • 완전한 데이터셋 정보는 여기에서 확인할 수 있습니다.

5.3.2. 원본 데이터셋에서 변환

  • 하나의 장면을 다운로드하면,
    • kapture_import_7scenes.py 스크립트를 사용하여 각 시퀀스를 kapture 모델로 변환할 수 있습니다.

1) Microsoft 웹사이트에서 7-scenes를 다운로드하세요.

cd /<mydatasets>/7-scenes
curl http://download.microsoft.com/download/2/8/5/28564B23-0828-408F-8631-23B1EFF1DAC8/heads.zip -o heads.zip

2) 모든 파일을 압축 해제하세요.

  • Ubuntu에서는 다음 명령어를 사용하세요:
unzip heads.zip
cd heads
# 모든 내부 zip 파일을 압축 해제
find . -iname "*.zip" -print0 | xargs -n1 -0 -I {} unzip {}
rm *.zip ../heads.zip # 모든 zip 파일을 삭제 (선택 사항)

장면의 디렉토리 구조는 다음과 같습니다:

<scene>
├── <scene>.png
├── <seq-##>
│   ├── frame-000000.color.png
│   ├── frame-000000.depth.png
│   ├── frame-000000.pose.txt
│   ├── frame-000001.color.png
│   ├── frame-000001.depth.png
│   ├── frame-000001.pose.txt
│   ├── frame-000002.color.png
..
├── TestSplit.txt
└── TrainSplit.txt
  • TestSplit.txtTrainSplit.txt 파일에는 각각 쿼리 또는 매핑에 사용할 시퀀스가 포함되어 있습니다.

3) kapture로 가져오기

  • 이 섹션에서는 매핑/쿼리 분할을 사용하여 모든 장면을 가져오는 방법을 설명
  • 각 장면에 대해 (예: stairs), 매핑과 쿼리를 다음과 같이 가져옵니다:
kapture_import_7scenes.py -i /<mydatasets>/7-scenes/stairs -o /<mykaptures>/7-scenes/stairs/mapping -p mapping

참고:

  • 매핑과 쿼리를 분할하지 않고 가져올 수도 있습니다.

  • 이 경우 모든 데이터가 단일 데이터셋으로 병합됩니다.

  • 또한 단일 시퀀스를 직접 경로를 지정하여 가져올 수도 있습니다 (예: /<mydatasets>/7-scenes/stairs/seq-01).

  • 모든 장면/분할을 한 번에 처리하려면, GNU parallel을 사용하세요:

parallel \
kapture_import_7scenes.py -v info -i /<mydatasets>/7-scenes/{1} /<mykaptures>/7-scenes/{1}/{2} -p {2} \
::: chess fire heads office pumpkin redkitchen stairs ::: query mapping

데이터셋 준비

7-scenes 데이터를 kapture 포맷으로 변환한 후, 이미지 쌍을 생성하는 방법을 설명합니다. 아래에 제시된 두 가지 툴을 사용합니다.

  1. deep-image-retrieval
  2. kapture-localization

이 두 스크립트를 사용하여 데이터셋을 변환하고 이미지 쌍을 생성할 수 있습니다.

  1. 데이터셋 변환:
    extract_kapture.py 스크립트를 사용하여 7-scenes 데이터를 kapture 포맷으로 변환합니다.

    python extract_kapture.py --input_dir /<mydatasets>/7-scenes/ --output_dir /<mykaptures>/7-scenes/
  2. 이미지 쌍 생성:
    변환된 데이터셋에서 이미지 쌍을 생성하려면, kapture_compute_image_pairs.py 스크립트를 사용합니다.

    python kapture_compute_image_pairs.py -i /<mykaptures>/7-scenes/ -o /<mykaptures>/7-scenes/pairsfile.txt

이 과정을 통해 7-scenes 데이터를 kapture 포맷으로 변환하고, 이미지 쌍을 생성할 수 있습니다.



6. 결과

  • demo.py로 돌렸을 떄 / test.py로 돌렸을때
  • 둘 다 망함
[2024-08-15 15:19:06] T: [[ 0.3197652 ]
 [ 0.00537205]
 [-0.03373383]]
T: [[ 0.3197652 ]
 [ 0.00537205]
 [-0.03373383]]
profile
모든 의사 결정 과정을 지나칠 정도로 모두 기록하고, 나중에 스스로 피드백 하는 것

0개의 댓글