Kinect pour Windows v2 profondeur pour le désalignement de l'image couleur
actuellement, je suis en train d'élaborer un outil pour le Kinect pour Windows v2 (similaire à celle de la XBOX ONE). J'ai essayé de suivre quelques exemples, et disposer d'un exemple qui montre l'image de la caméra, la profondeur de l'image, et une image que les cartes de la profondeur à l'rvb à l'aide d'opencv. Mais je vois qu'il reprend ma main lors de la cartographie, et je pense que c'est dû à une erreur dans les coordonnées du mappeur de la partie.
ici est un exemple:
Et voici l'extrait de code qui crée l'image (rgbd image dans l'exemple)
void KinectViewer::create_rgbd(cv::Mat& depth_im, cv::Mat& rgb_im, cv::Mat& rgbd_im){
HRESULT hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(cDepthWidth * cDepthHeight, (UINT16*)depth_im.data, cDepthWidth * cDepthHeight, m_pColorCoordinates);
rgbd_im = cv::Mat::zeros(depth_im.rows, depth_im.cols, CV_8UC3);
double minVal, maxVal;
cv::minMaxLoc(depth_im, &minVal, &maxVal);
for (int i=0; i < cDepthHeight; i++){
for (int j=0; j < cDepthWidth; j++){
if (depth_im.at<UINT16>(i, j) > 0 && depth_im.at<UINT16>(i, j) < maxVal * (max_z / 100) && depth_im.at<UINT16>(i, j) > maxVal * min_z /100){
double a = i * cDepthWidth + j;
ColorSpacePoint colorPoint = m_pColorCoordinates[i*cDepthWidth+j];
int colorX = (int)(floor(colorPoint.X + 0.5));
int colorY = (int)(floor(colorPoint.Y + 0.5));
if ((colorX >= 0) && (colorX < cColorWidth) && (colorY >= 0) && (colorY < cColorHeight))
{
rgbd_im.at<cv::Vec3b>(i, j) = rgb_im.at<cv::Vec3b>(colorY, colorX);
}
}
}
}
}
Quelqu'un a une idée de comment résoudre ce problème? Comment éviter cette duplication?
Merci d'avance
Mise à JOUR:
Si je fais une simple image de profondeur seuillage je obtenir l'image suivante:
C'est ce plus ou moins, je m'attendais à arriver, et ne pas avoir un double de la main en arrière-plan. Est-il un moyen pour éviter cette double main dans le fond?
source d'informationauteur api55
Vous devez vous connecter pour publier un commentaire.
Je vous suggérons d'utiliser le BodyIndexFrame pour déterminer si une valeur appartient à un joueur ou pas. De cette façon, vous pouvez rejeter toute RVB des pixels qui n'appartient pas à un joueur et de garder le reste d'entre eux. Je ne pense pas que CoordinateMapper est couché.
Quelques remarques:
Voici ma démarche lorsqu'une trame arrive (c'est en C#):
Ici est l'initialisation des tableaux:
Avis que le _depthPoints tableau a une 1920x1080 taille.
Encore une fois, la chose la plus importante est l'utilisation de la BodyIndexFrame source.
Enfin j'ai un peu de temps pour écrire la longue réponse tant attendue.
Permet de commencer avec un peu de théorie pour comprendre ce qui se passe vraiment et puis une réponse possible.
Il faut commencer par connaître la façon de passer d'un point 3D nuage qui a la profondeur de la caméra que l'origine du système de coordonnées d'une image dans le plan image de la caméra RVB. Pour cela, il suffit d'utiliser la caméra sténopé modèle:
Ici,
u
etv
sont les coordonnées dans le plan image de la caméra RVB. la première matrice dans le côté droit de l'équation est l'appareil photo de la matrice, AKA intrinsèques de la Caméra RVB. La matrice suivante est la rotation et la translation de la extrinsics, ou pour mieux dire, la transformation nécessaire pour aller de la Profondeur de la caméra du système de coordonnées de la caméra RVB système de coordonnées. La dernière partie est le point 3D.En gros, quelque chose comme ça, est ce que le SDK de Kinect. Donc, ce qui pourrait aller mal que fait la main est dupliqué? eh bien, en fait plus d'un point de projets pour le même pixel....
En d'autres mots, et dans le contexte du problème en question.
La profondeur de l'image, est une représentation d'ordre de nuage de points, et je suis l'interrogation de la
u v
les valeurs de chacun de ses pixels que dans la réalité peuvent être facilement converties en points 3D. Le kit de développement vous donne la projection, mais il peut pointer vers le même pixel (généralement, plus la distance à l'axe z entre deux points voisins peut donner à ce problème assez facilement.Maintenant, la grande question, comment pouvez-vous éviter cela.... eh bien, je ne suis pas sûr en utilisant le SDK de Kinect, puisque vous ne savez pas la valeur Z de la points à l'issue de la extrinsics sont appliquées, de sorte qu'il n'est pas possible d'utiliser une technique comme la Z mise en mémoire tampon.... Cependant, on peut supposer que la valeur de Z sera assez similaire et d'utiliser ceux de l'original pointcloud (à vos risques et périls).
Si vous faisiez manuellement, et pas avec le SDK, vous pouvez appliquer la Extrinsics pour les points, et l'utilisation du projet dans le plan de l'image, de marquage dans une autre matrice qui point est mappé à laquelle pixel et si il y a un point existant déjà mappé, vérifiez les valeurs z et comparés entre eux et laissez toujours le point le plus proche de la caméra. Ensuite, vous aurez un valide cartographie sans aucun problème. De cette façon, est une sorte de naïf, probablement que vous pouvez obtenir mieux, car le problème est maintenant clair 🙂
J'espère que c'est assez clair.
P. S.:
Je n'ai pas Kinect 2 pour le moment donc je ne peux PAS essayer de voir si il y a une mise à jour par rapport à ce problème ou s'il se passe la même chose. J'ai utilisé la première version (pas avant la libération) du SDK... Donc, beaucoup de changements peuvent s'était passé... Si quelqu'un sait si c'était le résoudre il suffit de laisser un commentaire 🙂