2011-03-30 4 views
1

3D 개체의 표면에 무작위로 샘플링 된 점 집합이 있습니다. 저는 두 개의 다른 객체들 사이의 유사성을 계산할 수 있기를 원합니다. 이 작업을 수행하기 위해 먼저 비교할 두 오브젝트의 샘플 포인트가 동일한 회전 및 크기를 유지하는지 확인해야합니다. 나는 x/y/z 축을 따라 주요 구성 요소 축을 배향시키고, 가장 긴 주 구성 요소가 단위 길이를 갖도록 배율을 조정하여이 작업을 수행 할 수 있다고 생각했습니다.CGAL을 사용한 주성분 분석을 사용한 점 구름 정렬

내가 먼저 지점 세트의 중심을 계산하고, 기원은 새로운 중심이되도록 모든 지점을 번역합니다.

나는 점을 통해 최적의 피팅 평면을 제공하는 CGAL의 linear_least_squares_fitting_3 기능을 사용하여 주성분 분석을한다. I는 모두 기본 벡터의 외적을 고려하여이 평면의 법선을 계산 :

Plane plane; 
linear_least_squares_fitting_3(points.begin(), points.end(), 
    plane, CGAL::Dimension_tag<0>()); 

auto dir1 = dir2vec(plane.base1().direction()); 
auto dir2 = dir2vec(plane.base2().direction()); 
auto normal = dir1^dir2; // cross product 
normal.normalize(); dir1.normalize(); dir2.normalize(); 

dir2vec 함수 등가 osg::Vec3d 객체 (I는 OpenSceneGraph 그래픽 엔진을 사용하고있다)에 CGAL::Direction_3 오브젝트로 변환한다. 마지막으로, 나는 다음과 같은 코드를 사용하여 장치의 축에 모든 회전 : 여기

Matrixd r1, r2, r3; 
r1.makeRotate(normal, Vec3d(1,0,0)); 
r2.makeRotate(dir1 * r1, Vec3d(0,1,0)); 
r3.makeRotate(dir2 * r1 * r2, Vec3d(0,0,1)); 
auto rotate = [&](Vec3d const &p) { 
    return p * r1 * r2 * r3; 
}; 
transform(osgPoints.begin(), osgPoints.end(), osgPoints.begin(), rotate); 

osgPointsvector<osg::Vec3d>입니다. 테스트 목적으로 회전 된 점의 중심을 원래 위치로 다시 변환하므로 두 점 구름이 겹치지 않습니다.

Vec3d center = point2vec(centroid); 
auto tocentroid = [&](Vec3d const &v) { 
    return v + center; 
}; 
transform(osgPoints.begin(), osgPoints.end(), osgPoints.begin(), tocentroid); 

이를 테스트하기 위해, I는 동일한 지점 세트의 두 복사본을 사용하지만 하나의 변형 (회전) 번역된다. 위의 코드는 회전을 취소해야하지만 결과는 예상 한 것과 다릅니다. this image을 참조하십시오. 빨간색 선은 최상의 피팅 평면과 그 법선의 기본 벡터를 나타냅니다. linear_least_squares_fitting_3에 대한 두 호출의 결과는 비행기 중 하나가 다른 비행기와 관련하여 조금씩 회전하므로 약간 다른 답변을 제공합니다. 두 개체가 원점에 그 중심에 위치하는

Here is another 이미지. 이제는 법선과 기본 벡터가 함께 떨어지는 것을 명확하게 볼 수 있지만 포인트는 그렇지 않습니다.

왜 이런 일이 발생하는지 알 수 있습니까? 어떻게 방지 할 수 있습니까? 점의 집합에 비행기를 피팅

답변

3

구속 하나의 자유도를 떠난다. 비행기는 평상시에 자유롭게 회전 할 수 있으며 적합도는 동일합니다. 나는 CGAL에 대해 아무 것도 모른다. 그러나 나는 적합성을 발견 할 때 편리한 평면을 발견한다는 사실에 놀라지 않을 것이다 (아마도 공간의 원래 축으로부터 가장 가까운 투영 일 것이다). 이 점 구름에 실제 PCA를 한 경우

, 난 당신이 그런 문제가 거라고 생각하지 않습니다. 또는 피팅 알고리즘에 의해 발견 된 표준을 따라 데이터를 재조정 (스트레치) 한 다음 다른 적합도를 찾을 수도 있습니다. 데이터를 충분히 늘리면 발견 된 첫 번째 평면이 직각 평면과 같이 잘 맞지 않아야합니다.

+0

답변 해 주셔서 감사합니다.하지만 불행히도 귀하의 제안이 작동하지 않습니다. 아마도 내가 잘못 이해했기 때문일 수 있습니다. 실제 PCA를 수행하는 C++ 라이브러리에 대해 알고 있습니까? – muksie

0

참으로 JCooper가 제안 CGAL는, 모든 주요 구성 요소를 계산하지 않는 것 같았다. 나는 PCA를하기 위해 ALGLIB 라이브러리로 전환했고 이제는 작동한다.