Skip to content

Max dictionary

Max introduced the dictionary data-type a long time ago. I have had very little experience with it other than setting and recalling custom presets, which was done with the get message. So if we have a dict storing presets with sequences of colour information:

{
    "Sequence" : {
        "one" : [ "G", "B", "G", "C", "B", "M", "C", "G", "Y", "G", "B", "C", "M", "B", "G", "B", "C", "Y", "M", "C", "M", "B", "G", "B", "C", "Z" ],
        "two" : [ "Y", "G", "Y", "B", "G", "C", "B", "Y", "M", "Y", "G", "B", "C", "G", "Y", "G", "B", "M", "C", "B", "C", "G", "Y", "C", "B", "Z" ],
        "three" : [ "M", "Y", "M", "G", "Y", "B", "G", "M", "C", "M", "Y", "G", "B", "Y", "M", "Y", "G", "C", "B", "G", "B", "Y", "M", "Y", "G", "Z" ],
        "four" : [ "C", "M", "C", "Y", "M", "G", "Y", "C", "B", "C", "M", "Y", "G", "M", "C", "M", "Y", "B", "G", "Y", "G", "M", "C", "M", "Y", "Z" ],
        "five" : [ "B", "C", "B", "M", "C", "Y", "M", "B", "G", "B", "C", "M", "Y", "C", "B", "C", "M", "G", "Y", "M", "Y", "C", "B", "C", "M", "Z" ]
    }
}

To retrieve the first entry of “Sequence one” I can send the message: get Sequence::one[1]. For the fourth sequence, colour 6 it would be get Sequence::four[6], etc.

Using the [key] message to access a dictionary

This is easy enough and works perfectly fine. However, I am working on a project right now using PoseNet, which outputs all its data as a dictionary, at frame rate (a low frame rate, but frame rate non-the-less).
I didn’t want to format get messages to extract all the information and was looking for a more elegant solution.

The data is organized like this (truncated):

{
	"score" : 0.299320935792125,
	"keypoints" : [ 		{
			"score" : 0.999612092971802,
			"part" : "nose",
			"position" : 			{
				"x" : 282.762551208749358,
				"y" : 189.991754974048433
			}
		}
, 		{
			"score" : 0.999678492546082,
			"part" : "leftEye",
			"position" : 			{
				"x" : 330.609080207793056,
				"y" : 156.654426548307725
			}
		}
, 		


                   [... reduced ...]

,
                {
			"score" : 0.999244570732117,
			"part" : "rightEye",
			"position" : 			{
				"x" : 245.198799861417285,
				"y" : 149.75491428045251
			}
		}
, 		
, 		{
			"score" : 0.005600165575743,
			"part" : "leftAnkle",
			"position" : 			{
				"x" : 196.871334091756381,
				"y" : 494.033982432012294
			}
		}
, 		{
			"score" : 0.005325738340616,
			"part" : "rightAnkle",
			"position" : 			{
				"x" : 202.849661166242555,
				"y" : 494.650997175064845
			}
		}
 ]
}

We have the key score, which returns the mean score over all tracked points and the key keypoints, which is an array containing all the data.

It was the array of data points that tripped me up for a long time. I missed the [] surrounding the keypoints key. Since PoseNet is able to track multiple people (something I haven’t tried yet), I am assuming that each person gets their own array entry.

I played around a bit getting to know dict.route, dict.unpack, dict.slice, etc.
I think my final solution is quite elegant:


1) dict.unpack the “keypoints”
2) iter through everything in the “keypoints” array
3) dict.unpack the relevant information
4) decide what to keep
5) package it all up again to send over OSC

And here is the final look of it:

Unpacking, parsing, manipulating, and repacking the dictionary data

I am only interested in data were the score is above a certain percentage so I needed to do some easy comparison and repackaging of the data into OSC messages. One thing I might have to do, after confirming that the external application (Unity) receives and can use the data properly, is to create a mechanism that only sends valid messages…

A simple onebang object, controlled by the > object should do the trick…

Become a Patron!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.