3D FingerPrint - нужно извлекать гряды и долины ?? Visual Studio 2010 и C ++ - PullRequest
0 голосов
/ 20 июня 2011

Мне нужно извлечь гребни и впадины из 3D отпечатка пальца.Выходными данными должен быть файл сгиба, который точно показывает, где находятся гребни и впадины на трехмерном отпечатке пальца, используя разные цвета.

Входной файл - файл сгиба только с положениями x, y, z.Я получил это от 3D-сканера.Вот как выглядят первые несколько строк файла -

ply
format ascii 1.0
comment VCGLIB generated
element vertex 6183
property float x
property float y
property float z
end_header
-32.3271 -43.9859 11.5124
-32.0631 -43.983 11.4945
12.9266 -44.4913 28.2031
13.1701 -44.4918 28.2568
13.4138 -44.4892 28.2531
13.6581 -44.4834 28.1941
13.9012 -44.4851 28.2684
...     ...      ...       

Если вам нужны данные - напишите мне на nisha.m234@gmail.com.

Алгоритм: Я пытаюсь найти основные изгибы для извлечения гребней и впадин.

Следующие шаги я:

  1. Взять точку x
  2. Найдите своих ближайших соседей.Я использовал k от 3 до 20.
  3. среднее k ближайших соседей => дает (_x, _y, _z)
  4. вычислить ковариационную матрицу
  5. Теперь я беру собственные значения исобственные векторы этой ковариационной матрицы
  6. Я получаю u, v и n здесь из собственных векторов.u является вектором, соответствующим наибольшему собственному значению v, соответствующему 2-му наибольшему n, являющемуся 3-м наименьшим вектором, соответствующим наименьшему собственному значению
  7. Затем для преобразования точки (x, y, z) я вычисляю матрицу T
    T = 
      | ui |     |u |     |x - _x| 
      | vi |  =  |v |  x  |y - _y|
      | ni |     |n |     |z - _z|
  8. для каждого i из k ближайших соседей:
      | n1 |   |u1*u1  u1*v1  v1*v1| | a |<br>
      | n2 | = |u2*u2  u2*v2  v2*v2| | b | <br>
      |... |   | ...    ...    ... | | c | <br>
      | nk |   |uk*uk  uk*vk  vk*vk|<br>
    Решите это для a, b и c с наименьшими квадратами
  9. это уравнение даст мне a, b, c
  10. теперь я вычисляю собственные значения матрицы
    | a b |
    | b a |
  11. Это даст мне 2 собственных значения.один - это Kmin, а другой - Kmax.

Моя проблема: Вывод не так близок к поиску правильных хребтов и долин.Я полностью застрял и разочарован.Я не уверен, где именно я понимаю это неправильно.Я думаю, что нормальные не рассчитаны правильно.Но я не уверен.Я очень новичок в графическом программировании, и поэтому математика, нормали, шейдеры идут выше моей головы.Любая помощь будет оценена. ПОЖАЛУЙСТА, ПОЖАЛУЙСТА, ПОМОГИТЕ !!

Ресурсы: Я использую Visual Studio 2010 + Eigen Library + ANN Library.

Другие используемые параметры Я пытался использовать MeshLab.В MeshLab я использовал шарообразные треугольники, а затем применил шейдер polkadot3d.Если правильно определить хребты и долины.Но я не могу его кодировать.

Моя функция: // функция выводит в файл ply

void getEigen()
{

int nPts; // actual number of data points
ANNpointArray dataPts; // data points
ANNpoint queryPt; // query point 
ANNidxArray nnIdx;// near neighbor indices 
ANNdistArray dists; // near neighbor distances 
ANNkd_tree* kdTree; // search structure

//for k = 25 and esp = 2, seems to got few ridges
queryPt = annAllocPt(dim);                  // allocate query point
dataPts = annAllocPts(maxPts, dim);         // allocate data points
nnIdx = new ANNidx[k];                      // allocate near neigh indices
dists = new ANNdist[k];                     // allocate near neighbor dists
nPts = 0;                                   // read data points

ifstream dataStream;
dataStream.open(inputFile, ios::in);// open data file
dataIn = &dataStream;

ifstream queryStream;
queryStream.open("input/query.pts", ios::in);// open data file
queryIn = &queryStream; 

while (nPts < maxPts && readPt(*dataIn, dataPts[nPts])) nPts++;

kdTree = new ANNkd_tree(                    // build search structure
                dataPts,                    // the data points
                nPts,                       // number of points
                dim);                       // dimension of space

while (readPt(*queryIn, queryPt))           // read query points
{   
    kdTree->annkSearch(                     // search
            queryPt,                        // query point
            k,                              // number of near neighbors
            nnIdx,                          // nearest neighbors (returned)
            dists,                          // distance (returned)
            eps);                           // error bound

    double x = queryPt[0];
    double y = queryPt[1];
    double z = queryPt[2];
    double _x = 0.0;
    double _y = 0.0;
    double _z = 0.0;

    #pragma region Compute covariance matrix

    for (int i = 0; i < k; i++) 
    {
        _x += dataPts[nnIdx[i]][0];
        _y += dataPts[nnIdx[i]][1];
        _z += dataPts[nnIdx[i]][2];
    }       

    _x = _x/k; _y = _y/k; _z = _z/k;

    double A[3][3] = {0,0,0,0,0,0,0,0,0};

    for (int i = 0; i < k; i++) 
    {
        double X = dataPts[nnIdx[i]][0];
        double Y = dataPts[nnIdx[i]][1];
        double Z = dataPts[nnIdx[i]][2];

        A[0][0] += (X-_x) * (X-_x);
        A[0][1] += (X-_x) * (Y-_y);
        A[0][2] += (X-_x) * (Z-_z);

        A[1][0] += (Y-_y) * (X-_x);
        A[1][1] += (Y-_y) * (Y-_y);
        A[1][2] += (Y-_y) * (Z-_z);

        A[2][0] += (Z-_z) * (X-_x);
        A[2][1] += (Z-_z) * (Y-_y);
        A[2][2] += (Z-_z) * (Z-_z);
    }

    MatrixXd C(3,3);
    C <<A[0][0]/k, A[0][1]/k, A[0][2]/k,
        A[1][0]/k, A[1][1]/k, A[1][2]/k,
        A[2][0]/k, A[2][1]/k, A[2][2]/k;

    #pragma endregion

    EigenSolver<MatrixXd> es(C);
    MatrixXd Eval = es.eigenvalues().real().asDiagonal();
    MatrixXd Evec = es.eigenvectors().real();

    MatrixXd u,v,n;
    double a = Eval.row(0).col(0).value();
    double b = Eval.row(1).col(1).value();
    double c = Eval.row(2).col(2).value();

    #pragma region SET U V N

    if(a>b && a>c)
    {
        u = Evec.row(0);
        if(b>c) 
        { v = Eval.row(1); n = Eval.row(2);}
        else
        { v = Eval.row(2); n = Eval.row(1);}
    }
    else
    if(b>a && b>c)
    {
        u = Evec.row(1);
        if(a>c) 
        { v = Eval.row(0); n = Eval.row(2);}
        else
        { v = Eval.row(2); n = Eval.row(0);}
    }
    else
    {
        u = Eval.row(2);
        if(a>b) 
        { v = Eval.row(0); n = Eval.row(1);}
        else
        { v = Eval.row(1); n = Eval.row(0);}        
    }

    #pragma endregion

    MatrixXd O(3,3); 
    O <<u, 
        v, 
        n;

    MatrixXd UV(k,3);
    VectorXd N(k,1);

    for( int i=0; i<k; i++)
    {
        double x = dataPts[nnIdx[i]][0];;
        double y = dataPts[nnIdx[i]][1];;
        double z = dataPts[nnIdx[i]][2];;

        MatrixXd X(3,1);
        X << x-_x,
             y-_y,
             z-_z;

        MatrixXd T = O * X;

        double ui = T.row(0).col(0).value();
        double vi = T.row(1).col(0).value();
        double ni = T.row(2).col(0).value();

        UV.row(i) << ui * ui, ui * vi, vi * vi;
        N.row(i) << ni;
    }

    Vector3d S = UV.colPivHouseholderQr().solve(N);

    MatrixXd II(2,2);

    II << S.row(0).value(), S.row(1).value(),
          S.row(1).value(), S.row(2).value();

    EigenSolver<MatrixXd> es2(II);

    MatrixXd Eval2 = es2.eigenvalues().real().asDiagonal();
    MatrixXd Evec2 = es2.eigenvectors().real();

    double kmin, kmax;
    if(Eval2.row(0).col(0).value() < Eval2.row(1).col(1).value())
    {
        kmin = Eval2.row(0).col(0).value();
        kmax = Eval2.row(1).col(1).value();
    }
    else
    {
        kmax = Eval2.row(0).col(0).value();
        kmin = Eval2.row(1).col(1).value();         
    }

    double thresh = 0.0020078;

    if (kmin < thresh && kmax > thresh )
        cout    << x << " " << y << " " << z << " "
                << 255 << " " << 0 << " " << 0 
                << endl;
    else 
        cout    << x << " " << y << " " << z << " "
                << 255 << " " << 255 << " " << 255 
                << endl;                    
}

delete [] nnIdx;
delete [] dists;
delete kdTree;
annClose();
}

Это часть моего дипломного проекта.Мне нужно сделать это, используя данные облака трехмерных точек.У меня нет сканера со мной.Это сторонняя компания, и они просто предоставляют мне 3D очки.Я должен работать только над этими 3D точками.

Спасибо,
NISHA

@ Том - Спасибо.Шейдер polkadot3d в MeshLab не был точным, но он дал мне приблизительное представление о том, где находятся гребни и долины.Я думаю, что библиотека ANN не дает мне правильных соседей для начала, что приводит к неправильным нормам.Но я не уверен, как это исправить.Поскольку это часть диссертации, я и мой профессор придумали этот алгоритм для извлечения гребней и долин.Согласно моим исследованиям и другим статьям, я читал, что этот метод действительно работает для извлечения риджей и долин.Я просто не получаю его правильно в коде :( Я совершенно уверен, что предложенный вами метод также будет работать, но мне, возможно, придется придерживаться моего текущего алгоритма и, если он вообще не работает, должен быть в состоянии сказать, почему онне работает! Но в настоящее время проблема, похоже, заключается в моем коде, чем в методе, который я использую, или я пропускаю какой-то шаг здесь.

1 Ответ

2 голосов
/ 20 июня 2011

Рассматривали ли вы превращение проблемы в проблему анализа изображений? Если данные сканируются нажатием пальца на плоскую поверхность, вы можете превратить сканирование в изображение, где уровень серого определяется глубиной z каждой точки (расстояние между поверхностью и точкой). Затем вы можете просто нарисовать треугольники с помощью Gourad Shading. Вероятно, вы можете сделать нечто подобное, создав 3D выпуклый корпус, а затем измерить z-расстояния от него.

Если у вас есть изображение, вы можете легко найти гряды и долины.

...