2016-06-21 6 views
2

현재 프로젝트를 위해 Aruco 큐브 감지기를 개발하려고합니다. 목표는 대형 ArUco 보드를 사용하지 않고보다 안정적이고 정확한 자세 추정을하는 것입니다. 그러나 이것이 작동하려면 각 마커의 방향을 알아야합니다. draw3dAxis 메서드를 사용하여 X 축과 Y 축이 동일한 위치에 일관되게 나타나지 않는다는 것을 발견했습니다. 다음은 문제를 보여주는 동영상입니다. https://youtu.be/gS7BWKm2nmgAruco Axis 스왑 중에 3dAxis

Rvec 감지에 문제가있는 것 같습니다. Rvec의 처음 두 값에는 명확한 변화가 있습니다. Rvec는 축이 바뀔 때까지 일정하게 유지됩니다. 이 축 스왑이 발생하면 값은 2 ~ 6의 크기로 변경 될 수 있습니다. 이 메소드를 호출 않습니다

/** 
* Return the id read in the code inside a marker. Each marker is divided into 7x7 regions 
* of which the inner 5x5 contain info, the border should always be black. This function 
* assumes that the code has been extracted previously. 
* @return the id of the marker 
*/ 
protected int calculateMarkerId(){ 
    // check all the rotations of code 
    Code[] rotations = new Code[4]; 
    rotations[0] = code; 
    int[] dists = new int[4]; 
    dists[0] = hammDist(rotations[0]); 
    int[] minDist = {dists[0],0}; 
    for(int i=1;i<4;i++){ 
     // rotate 
     rotations[i] = Code.rotate(rotations[i-1]); 
     dists[i] = hammDist(rotations[i]); 
     if(dists[i] < minDist[0]){ 
      minDist[0] = dists[i]; 
      minDist[1] = i; 
     } 
    } 
    this.rotations = minDist[1]; 
    if(minDist[0] != 0){ 
     return -1; // matching id not found 
    } 
    else{ 
     this.id = mat2id(rotations[minDist[1]]); 
    } 
    return id; 
} 

과 MarkerDetector.detect()와() 메소드 getRotations을 사용합니다 : :이 ARuco 라이브러리는 Marker.calculateMarkerId 같이() 메소드 회전 처리하려고 않습니다

// identify the markers 
    for(int i=0;i<nCandidates;i++){ 
     if(toRemove.get(i) == 0){ 
      Marker marker = candidateMarkers.get(i); 
      Mat canonicalMarker = new Mat(); 
      warp(in, canonicalMarker, new Size(50,50), marker.toList()); 
      marker.setMat(canonicalMarker); 
      marker.extractCode(); 
      if(marker.checkBorder()){ 
       int id = marker.calculateMarkerId(); 
       if(id != -1){ 
        // rotate the points of the marker so they are always in the same order no matter the camera orientation 
        Collections.rotate(marker.toList(), 4-marker.getRotations()); 

        newMarkers.add(marker); 

       } 
      } 
     } 
    } 

ArUco 라이브러리의 전체 소스 코드는 여기에 있습니다 : 사람이 어떤 조언이 있거나 솔루션 https://github.com/sidberg/aruco-android/blob/master/Aruco/src/es/ava/aruco/MarkerDetector.java

경우 나는 매우 자비로운 것. 궁금한 점이 있으면 저에게 연락하십시오.

답변

2

나는이 문제를 발견했다. 마커 클래스에는 마커의 방향에 맞춰 축을 회전하는 데 사용할 수있는 회전 변수가 있습니다. 나는의 Utils 클래스에서 다음과 같은 방법을 썼다 :

protected static void alignToId(Mat rotation, int codeRotation) { 
    //get the matrix corresponding to the rotation vector 
    Mat R = new Mat(3, 3, CvType.CV_64FC1); 
    Calib3d.Rodrigues(rotation, R); 

    codeRotation += 1; 
    //create the matrix to rotate around Z Axis 
    double[] rot = { 
      Math.cos(Math.toRadians(90) * codeRotation), -Math.sin(Math.toRadians(90) * codeRotation), 0, 
      Math.sin(Math.toRadians(90) * codeRotation), Math.cos(Math.toRadians(90) * codeRotation), 0, 
      0, 0, 1 
    }; 

    // multiply both matrix 
    Mat res = new Mat(3, 3, CvType.CV_64FC1); 
    double[] prod = new double[9]; 
    double[] a = new double[9]; 
    R.get(0, 0, a); 
    for (int i = 0; i < 3; i++) 
     for (int j = 0; j < 3; j++) { 
      prod[3 * i + j] = 0; 
      for (int k = 0; k < 3; k++) { 
       prod[3 * i + j] += a[3 * i + k] * rot[3 * k + j]; 
      } 
     } 
    // convert the matrix to a vector with rodrigues back 
    res.put(0, 0, prod); 
    Calib3d.Rodrigues(res, rotation); 
} 

을하고 난 Marker.calculateExtrinsics 방법에서 전화 :

 Utils.alignToId(Rvec, this.getRotations());