En utilisant les pilotes CL NUI Kinect, convertir la couleur de la profondeur à la distance réelle par rapport

StackOverflow https://stackoverflow.com/questions/4763320

  •  16-10-2019
  •  | 
  •  

Question

Je joue avec le pilote Kinect, CL NUI et essayer d'obtenir la profondeur relative des éléments.

La bibliothèque offre un moyen d'obtenir une image représentant la profondeur d'un objet sur l'écran. Voici un exemple:
Kinect Profondeur image

Y at-il un moyen facile de convertir la couleur du pixel à la profondeur des images? Par exemple, la couleur la plus proche pourrait être la profondeur de 0, et pourrait être la profondeur de la couleur le plus éloigné 1.

Quelqu'un sait comment faire?

J'ai trouvé ces cacluations sur la façon de convertir les données en profondeur à la couleur, ce que je veux est l'inverse:

float RawDepthToMeters(int depthValue)
{
    if (depthValue < 2047)
    {
        return float(1.0 / (double(depthValue) * -0.0030711016 + 3.3309495161));
    }
    return 0.0f;
}

Vec3f DepthToWorld(int x, int y, int depthValue)
{
    static const double fx_d = 1.0 / 5.9421434211923247e+02;
    static const double fy_d = 1.0 / 5.9104053696870778e+02;
    static const double cx_d = 3.3930780975300314e+02;
    static const double cy_d = 2.4273913761751615e+02;

    Vec3f result;
    const double depth = RawDepthToMeters(depthValue);
    result.x = float((x - cx_d) * depth * fx_d);
    result.y = float((y - cy_d) * depth * fy_d);
    result.z = float(depth);
    return result;
}

Vec2i WorldToColor(const Vec3f &pt)
{
    static const Matrix4 rotationMatrix(
                            Vec3f(9.9984628826577793e-01f, 1.2635359098409581e-03f, -1.7487233004436643e-02f),
                            Vec3f(-1.4779096108364480e-03f, 9.9992385683542895e-01f, -1.2251380107679535e-02f),
                            Vec3f(1.7470421412464927e-02f, 1.2275341476520762e-02f, 9.9977202419716948e-01f));
    static const Vec3f translation(1.9985242312092553e-02f, -7.4423738761617583e-04f, -1.0916736334336222e-02f);
    static const Matrix4 finalMatrix = rotationMatrix.Transpose() * Matrix4::Translation(-translation);

    static const double fx_rgb = 5.2921508098293293e+02;
    static const double fy_rgb = 5.2556393630057437e+02;
    static const double cx_rgb = 3.2894272028759258e+02;
    static const double cy_rgb = 2.6748068171871557e+02;

    const Vec3f transformedPos = finalMatrix.TransformPoint(pt);
    const float invZ = 1.0f / transformedPos.z;

    Vec2i result;
    result.x = Utility::Bound(Math::Round((transformedPos.x * fx_rgb * invZ) + cx_rgb), 0, 639);
    result.y = Utility::Bound(Math::Round((transformedPos.y * fy_rgb * invZ) + cy_rgb), 0, 479);
    return result;
}

Ma matrice mathématique est faible, et je ne suis pas sûr de savoir comment inverser les calculs.

Était-ce utile?

La solution

Je trouve la solution.

La valeur de profondeur est stockée dans la mémoire image CLNUIDevice.GetCameraDepthFrameRAW. Cette couleur de l'image est créée à partir de la valeur de profondeur onze bits. C'EST À DIRE. vous avez 24 bits pour la couleur RVB (32 si ARVB). Pour obtenir la profondeur, vous devez tronquer les bits inutiles comme ceci:

    private int colorToDepth(Color c) {
        int colorInt = c.ToArgb();

        return (colorInt << 16) >> 16;
    }

Vous utilisez 16, parce que le nombre de 11 bits est 0 rembourré pour le lieu de 16 bits. C'EST À DIRE. vous avez un certain nombre qui ressemble à ceci: 1111 1111 0000 0 ### #### #### où le 1 est le canal alpha, les zéros sont le rembourrage et le « # » est la valeur réelle. Vous le l'opérateurs de bits gauche 16 feuilles avec 0000 0 ### #### #### 0000 0000, que vous voulez repousser mon déplacement à 16 fois à droite: 0000 0000 0000 0 ### ##### ####

Autres conseils

moi si je me trompe, mais d'après ce que je comprends votre code reçoit un tableau de profondeur de la Kinect, le convertit en objets « du monde » (avec x, y, z) en utilisant DepthToWorld, puis convertis que d'une couleur tableau 2D en utilisant WorldToColor. De là, vous essayez de récupérer la distance (en mètres) de chaque pixel par rapport à la Kinect. Droit?

Alors, pourquoi ne pas vous prenez le tableau de profondeur initiale que vous obtenez de la Kinect, et appelez la fonction RawDepthToMeters sur chacun des pixels?

inversing opérations effectuées par votre code juste avant une énorme perte de performance ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top