콘텐츠로 이동
Search

Pointcept:SmallObjectAnalysis

PointGroup 작은 객체 미검출 원인 분석 절차

배경

  • Pointcept의 PointGroup(PG-v1m1, SpUNet backbone)으로 instance segmentation 진행 중
  • 최초 100장에서 품질이 낮아 약 600장의 PointCloud를 추가하여 훈련
  • 데이터를 늘렸음에도 작은 객체가 여전히 잡히지 않음

결론 요약

데이터를 늘려도 작은 객체가 안 잡히는 경우, 원인은 대개 "데이터 양"이 아니라 아래 셋 중 하나이다.

  1. 파이프라인에 박힌 크기 필터
  2. semantic 브랜치의 누락
  3. offset 회귀의 대형 객체 편향

이 셋을 분리해서 확인하는 순서로 진행한다.

구조적 원인: 코드에 박힌 크기 필터

기준 파일:

  • configs/scannet/insseg-pointgroup-v1m1-0-spunet-base.py
  • pointcept/models/point_group/point_group_v1m1_base.py
  • pointcept/engines/hooks/evaluator.py

PointGroup 코드에는 작은 객체를 걸러내는 지점이 최소 네 곳 있다. 전부 grid_size=0.02 복셀 단위이다.

지점

기본값

효과

GridSample grid_size

0.02

2cm 복셀화. 작은 객체는 점 수가 급감

cluster_min_points (bfs_cluster)

50

50점 미만 클러스터는 생성되지 않음

cluster_propose_points

100

100점 이하 proposal 폐기 (point_group_v1m1_base.py:154)

evaluator min_region_sizes

100

100점 미만 예측은 평가에서 제외 (evaluator.py:339)

즉 복셀화 후 100점 이하가 되는 객체는 모델이 맞춰도 출력되지 않고, 출력돼도 평가되지 않는다. 데이터를 6배 늘려도 이 벽은 그대로이다.

그 외 구조적 요인

  • 클러스터링은 segment_pred가 같은 점끼리만 묶는다. semantic 브랜치가 작은 클래스를 벽/바닥으로 분류하면 instance 단계로 아예 진입하지 못한다.
  • offset loss는 점 단위 평균이라 큰 객체가 gradient를 지배한다. 작은 객체의 중심 예측은 노이즈가 커서 cluster_thresh=1.5(3cm) 안에서 이웃 객체와 병합되거나 쪼개지기 쉽다.

진행 순서

1. 데이터 통계

  • 클래스별 인스턴스 수, 인스턴스당 점 수 분포를 GridSample 0.02 적용 후 기준으로 산출
  • 100점 미만 인스턴스 비율 = 구조적으로 검출 불가능한 비율
  • 추가한 600장의 라벨 품질 확인
    • 작은 객체가 일관되게 라벨링되었는지
    • instance id가 scene 내에서 유일한지
    • 원본 100장과 센서/점 밀도가 같은지

2. Semantic 상한 확인

  • 검증 셋에서 클래스별 semantic IoU 확인
  • 작은 클래스의 IoU가 낮으면 instance 문제가 아니라 semantic 문제
  • 처방: class-weighted CE, 작은 객체 포함 scene 오버샘플링, grid_size 축소

3. 오라클 실험으로 브랜치 분리

실험

AP가 크게 오르면

GT semantic + 예측 offset으로 클러스터링

semantic 브랜치 문제

예측 semantic + GT centroid로 클러스터링

offset 브랜치 문제

둘 다 오르지 않으면 필터 또는 라벨 문제이다.

4. 필터 완화 실험

재훈련 없이 test만 다시 실행하면 된다.

파라미터

기본값

완화값

cluster_min_points

50

10

cluster_propose_points

100

20

evaluator min_region_sizes

100

20

AP25가 회복되면 모델은 이미 잡고 있는데 필터가 버리고 있었다는 뜻이다.

5. 실패 유형 분류

작은 객체 GT 각각에 대해 예측을 대조하여 네 가지로 태깅한다.

  1. semantic 누락
  2. 이웃 객체에 병합
  3. 여러 조각으로 분리
  4. 크기 필터로 폐기

이 분포가 최종 처방을 결정한다.

6. 훈련 상태 점검

  • 100장 → 700장이면 같은 800 epoch라도 iteration이 7배
  • 학습 곡선과 train 셋 AP를 함께 확인
    • train에서도 작은 클래스가 안 잡히면 underfit 또는 라벨 문제
    • train에서는 잡히는데 val에서 안 잡히면 일반화 문제

처방 후보

  • grid_size 0.02 → 0.01 (메모리 2~4배 증가, 작은 객체에 가장 직접적)
  • offset loss를 인스턴스 단위로 정규화하거나 작은 인스턴스에 가중치 부여
  • semantic CE에 class weight, 작은 객체 포함 scene 반복 샘플링
  • SphereCrop sample_rate=0.8이 작은 객체를 잘라내는지 확인
  • PointGroup 자체의 한계라면 query 기반인 SGIFormer 검토
    • configs/scannetpp/insseg-sgiformer-v1m1-0-ptv3-base.py

See also

lastmod 2026-09-14created 2026-09-14author Zer0 sitemap