[Kinect 2] Utiliser simultanément plusieurs sources
Dans l’article précédent, un exemple était proposé afin de démontrer la base du green screening aussi connu sous le nom de background removal, à l’aide de la source Body Index. Dans ce dernier exemple, de simples pixels verts étaient affichés à la place des pixels du corps des utilisateurs faisant face à la Kinect. Afin de rendre l’exemple plus pertinent encore, cet article expliquera comment activer plusieurs flux simultanément et les combiner, afin, cette fois-ci d’afficher les pixels de la caméra infrarouge à la place des pixels verts.
Principe général
Pour cela, il est nécessaire d’utiliser deux sources de données en même temps. Nous n’allons donc plus utiliser les méthodes OpenReader des sources correspondantes, mais la méthode OpenMultiSourceFrameReader.
Nous obtiendrons ainsi un nouveau type de frame, contenant elle-même des références vers des frames plus spécifiques pour chaque flux ouvert. Il suffira ensuite d’utiliser la frame de la source Body Index pour déterminer les coordonnées de tous les pixels des corps se trouvant devant le capteur et de transposer ces coordonnées sur la frame de caméra infrarouge et de n’afficher que ceux-ci.
Afficher le rendu
En adaptant le modèle précédent, voici comment ouvrir les deux flux qui nous intéressent :
using (var reader = sensor.OpenMultiSourceFrameReader(FrameSourceTypes.BodyIndex | FrameSourceTypes.Infrared))
Pour obtenir les références des frames courantes, il suffit, comme dans le cas des autres sources de données de faire appel à la méthode AcquireLatestFrame, dont nous plaçons le résultat dans une variable frame. Cet objet exposera une propriété pour chaque type de source existante, chacune d’entre elle permettant d’accéder à la frame spécifique voulue :
if (frame != null) { using (var bodyIndexFrame = frame.BodyIndexFrameReference.AcquireFrame()) using (var infraredFrame = frame.InfraredFrameReference.AcquireFrame()) { if (bodyIndexFrame != null && infraredFrame != null) { //...
Nous allons pouvoir utiliser ces deux références pour remplir des tableaux contenant les informations de chaque flux, définis préalablement comme suit :
var bodyIndexBufferSource = new byte[(int)(frameDesc.LengthInPixels)]; var infraredBufferSource = new ushort[(int)(frameDesc.LengthInPixels)];
puis les exploiter ainsi :
infraredFrame.CopyFrameDataToArray(infraredBufferSource); bodyIndexFrame.CopyFrameDataToArray(bodyIndexBufferSource); for (var i = 0; i < bodyIndexBufferSource.Length; i++) { if (bodyIndexBufferSource[i] > bodyCount) { streamConverted.WriteByte(byte.MaxValue); streamConverted.WriteByte(byte.MinValue); streamConverted.WriteByte(byte.MinValue); } else { var tmp = (byte)(infraredBufferSource[i] * byte.MaxValue / ushort.MaxValue); byte intensity = (tmp + 50 > byte.MaxValue) ? tmp : (byte)(tmp + 50); streamConverted.WriteByte(intensity); streamConverted.WriteByte(intensity); streamConverted.WriteByte(intensity); } }
Cet exemple est très simple : le tableau de données de la source Body Index est parcouru, pour chaque pixel ne correspondant pas au corps d’un utilisateur, un pixel de couleur bleue est définis, sinon, le pixel correspondant dans le tableau de la caméra infrarouge est choisis. Ce dernier pixel subit une légère modification car l’intensité enregistrée est parfois trop faible pour l’œil humain lorsque l’affichage est fait avec un niveau de gris : nous augmentons donc artificiellement cet intensité afin de produire des pixels plus clairs.
Pour rappel, l’objet streamConverted est défini ainsi dans les exemples précédents :
var streamConverted = new MemoryStream(((int)(frameDesc.LengthInPixels)) * 3);
Notre exemple de green screening est presque opérationnel. En effet, pour être vraiment complet, il reste à remplacer les pixels de la caméra infrarouge par ceux de la caméra couleur. Néanmoins, nous verrons que cela n’est pas si simple de prime abords. En effet, l’exemple de cet article est très simple car les frames utilisées ont une structure similaire : ce sont des tableaux de numérique de 512 par 424. La transposition est donc simple entre ces deux sources puisque chaque pixels correspondant à les mêmes coordonnées dans l’un ou l’autre tableau. Dans le cas suivant, nous verrons les techniques qu’il faut mettre en place lorsque la structure des frames n’est plus la même. Nous verrons aussi comment tenir compte de l’alignement des objectifs sur le capteur.
Commentaires