Subtitles section Play video Print subtitles [TRAIN WHISTLE] Hello and welcome to another video tutorial about working with Runway and running machine learning models in Runway itself. Now, before you watch this video tutorial, if you've never used Runway before, you might want to go back and look at my Introduction to Runway, how to download and install it. But to be honest, you probably can figure that out if you just go to runwayml.com and click on Download Beta. You're going to want to download and open the runway software. You'll go then to Browse Models. I might go here under Motion, and I'm going to click PoseNet. And you'll find yourself right here. So this is where I am. I've installed Runway. I've downloaded it. And I'm on the page in the Runway software for the PoseNet machine learning model. Now, what is PoseNet? PoseNet is a machine learning model that performs real-time skeletal tracking of one or more people. And guess what? I'm a person, and I've got Runway running here with PoseNet. So I'm going to run it. So let's actually first click Add To Workspace. So I already have a workspace that I've made in the previous video called Coding Train Live Stream. I want to choose an input source, which I want it to be my webcam. So, yep, Runway go right ahead, and there I am. And then I want to choose an output source, which eventually I want to be processing, because I want to get the results of running this machine learning model PoseNet into processing itself. But for right now, I'm just going to click on Preview. So I click on Preview. Oh, and I have to run. But guess what? So this is different than what I've showed in previous videos. I've got an option for Run Locally. And, in fact, this model can only be run locally. It would be silly to run this one in the cloud, because I'd have to spend all this time sending the data over the network. And it's very easy for it to run. This is a very small, fast model. It can be run on most modern computers. So I'm going to click Run Locally. So it requires no GPU credits. Absolutely, can be used for free. And we can see there it goes. It's running right now. It is making guesses as to where the various key points of my skeleton are on my body in the output That's. viewable below. So one of the nice things about working with Runway and its models is a lot of times models have different parameters and values and things that you can tweak and change to try running it in different ways. And these are sort of known as hyper parameters to a machine learning model. And so some of them I would actually have to stop running the model and then I can start to play with it. So, for example, this Architecture one is something I can actually make the models smaller. It might be less accurate, but it will run faster. But so, for example, I'm just going to change this to 0.75 instead. I'm going to run it again. But some of these parameters can actually be tweaked in real time. So, for example, I can change the width and height of the image, which is actually changing the resolution of the image from the webcam itself. And I can make it more grayscale if I want. I could do various things to actually tweak the image before it goes in. But this is not the important piece of what I want to do in this video. What I want to do in this video is we have a moment here where I've got a model running in Runway. And I'm able to play with it, tweak it, get it exactly the way I want it to work. And I want to take that next step from having it run here to be able to see the result of it in my own piece of software. So let's make that happen. This software that I'm going to use to attempt this is something called Processing. So since this size here in Runway of the output is 640 by 362, what I'm going to do in my Processing code is set the size of the canvas to 640 by 362. void draw. background 0. So now, I have a Processing sketch, which I am running right here. How do I see the results, the output of the model in my Processing sketch? So there are a variety of different network protocols that Runway supports. And I can find out about them up here by clicking this Network tab. And the one that I want to use for working with Processing is OSC. So there's a variety of reasons why you might pick one protocol over another. It really depends on what you're doing. In the case of where I just want to get a single image, an HTTP request would make the most sense. And I'll do that in another video when I show you how to work with style again in Runway. But right now, I'm going to click on OSC, which works pretty well with Processing. And it's telling me a lot of information here. So it's saying, hey, this is the server address. So this is the most important thing that I need from Runway. It's what I'm going to tell Processing is the unique IP address, which happens to be the local IP address of this computer and the port number from which it can get the OSC messages. I'm going to click here. And I'm going to create a string called like ip. I'm pretty sure I'm probably going to want the port number in a separate variable. And I'm going to create a port number like this. Now, I could sit here and write all the code for this, which is what I usually do in Coding Train videos. But this is a fairly different circumstance. I really just want to get the example up and running and show you how to do this. And one of the nice things about working with Runway is there are a whole bunch of premade examples for you with different platforms and pieces of software, one of which is Processing. So let me show you how you would actually do this in the real world, how I would be doing this, which is the way to do it right now. So if I go to the Runway ML GitHub-- and I actually should go back one level and go here under Runway ML. You can see here's the GitHub page for the Runway software. And there's a lot of information. There's some sort of like high-level stuff here about how to port your own machine learning model to Runway itself. So if you've trained your own model or you find a model that's not supported by Runway, how you could add it. But that's not what we're really doing here. What I want to look for is here Processing, Runway and Processing. If I click here, this repository has a whole bunch of examples of using Runway with Processing. So you can see there's a StreetView one, attnGAN, face landmarks, im2txt, and, voila, PoseNet. This is the one that I'm working with. So I'm going to look at this example. I should say that this is an open source project. Processing is an open source project that I'm involved with that I've talked about in a lot of other videos. So maybe this is a place where if you find another model in Runway that you've made work and you want to contribute your Processing example here, I would encourage you to do that. And Chris, one of the founders and creators of Runway, and I have been talking about making a Processing library for Runway. And it just so happens that I made two recent video tutorials about how to make a Processing Java library. So I see a project in the future, which is a Processing library for Runway. So if you want to get involved with that, with making that, write in the comments and let me know. And maybe we'll create a GitHub repo for that. OK, so I mean to go here under PoseNet. And I'm just going to click here under posenet.pde. So I could just copy paste the whole thing, but I'm going to kind of go piece by piece. And you can see here already Runway host and Runway port. So I made a mistake in my code. So I got a-- oh, I'm missing the 0.1 here, which I'm sure the Chat is already talking about. And there's an extra 1 here. And this should be an integer. And this would really be Host. So actually let me use the same variable names, runwayHost and runwayPort. OK, so I think I've gotten this right now. Now, in order for the example to work, I need to make sure also I have the Processing OSC library installed. So if I come over here, I can copy paste these import statements. I can copy paste this OSC object that I definitely need. And we'll see very quickly that I have an error, which is the class OscP5 does not exist. This is because I haven't installed the Processing OSC library. You might have already have it installed because you use it with a different project. But I could go here. And I could do Sketch, Import Library, Add Library, OSC to search for it. This is the library I'm looking for oscP5. I'm going to click Install. And now, you'll see that error message goes away. The next thing that I want to do is create an object to receive OSC messages. And I think I can just make this a new OscP5 object. I need to give it a reference to this particular sketch, because it's going to need to trigger events in the sketch when there's data available. And then just give it the port number. This is called runwayPort. So if you look at the runway example, it's actually using this object called OscProperties, which is a bit more sophisticated. It says a remote address, a listening port, a datagram size, and some other stuff. I should probably just copy paste this into my example, but I'm curious if it will work with just the sort of more simplified default OscP5 object, where I just say this and the particular port. But I do need this. I do need a broadcast location, because I'm going to have to send messages to Runway as well, saying I'm connected or I'm disconnected. So there's two things at play here. There's the Processing software. And there's the Runway software. They're both running locally on my computer. Now, it's possible that in other scenarios there could also be a cloud GPU involved that runway sends messages back and forth between. And this is something that I'm going to do in the next example, where I work with something called StyleGAN. I'm going to have Runway also talk to a cloud GPU. But that's not happening here. PoseNet is actually running inside of-- basically wrapped into Runway itself locally. So PoseNets running here in Runway locally. Processing is sending a message like connect. Like, hey, I want to hear information. That's a one-time message. And then Runway will just continuously send data via OSC to Processing about what pose it's detecting with the PoseNet model from the webcam input. So if I wanted, I probably could figure out a way to get the camera input into Processing, send the image to Runway, and then have Runway send the results back. But Runway can connect to the camera directly, so I might as well just do that, because that's pretty easy. So I should also put here that like if I make a little note here, like webcam-- that webcam is talking to Runway. I might also have it talk to Processing if I want to show the results in Processing as well. So this is what's going on in this particular example. So I want to create this broadcast location, which is a net address object. So I need to put that in here. And then the first thing that I want to do is just send the connect message. So I'm going to copy this in and paste it here and say Connect. So what I'm doing when Processing starts up is it calls the function connect, which creates an OSC message. Every single OSC message is comprised of two parts. Those two parts are an address, which is usually denoted as a string, kind of like a path-- and you can see this is server/connect. That's the address. Or you might also think of that almost as like the message name as the way I sometimes think about it-- and then the data. Now, in this case, there actually is no data, because the address itself is the message. So this is a very simplified thing, where this connect message is just, hey, I'm connecting. So the name of the message, the address, is the only thing needs to be there. There's no data. But when Runway sends data back, it's going to have a message name, like a data or key points or poses, something like that. And then that's going to have packaged with it lots of data, like all the xy's of all the positions of everything. All right, so let's run this and see what happens. Yeah, that's pretty good. No errors. Now that I've connected, I want to listen for messages. And the way that that is done is with an event called OSC Event. So this is much like mouse pressed or key pressed or serial event or capture event. This is a function in Processing that has a very special name, called OSC Event. And the oscP5 library knows to call that function when there's data coming in. So I'm going to just copy paste this. And I'm going to put it in here. And what I'm going to-- so let's take a look at this. So there's an OSC Event that has passed through it an OSC message. I'll just change this to message. And if the message has that data-- so this is like its address. Remember that? Its address has data, that's the address we're looking for. Or if it doesn't, get out of here. So I want to ignore any other messages coming in. Then what I want to do is get the data itself. So the data of the message actually comes in as a string. But the string is formatted as JSON, which is JavaScript Object Notation. If you don't know what JSON is I might refer you to a different video of mine that explains what JSON is. JSON works really nicely in JavaScript. It's a little bit awkward to work with it in Processing, because Processing is Java. It doesn't speak JavaScript natively. But we're going to make it work. So the first thing in the message itself is a big string of JSON data, which then is a JSON object that can be parsed with Processing's parseJSONObject function. And then I can just look at it in the console. So let's see if we actually get the data in. I'm not getting anything. And I'm wondering why. And actually I know why, because I had to figure it out. So first of all, there's a clue to me here. It says, could not create datagram socket port 5100, because it's already in use. And I forgot there's a weird thing going on here. If I were using OSC to communicate between two separate computers, I could use the same port number on each separate computer because it's just one port number. But, here, I need to be able to send data to runway at a particular port, as well as receive data into processing at a different port that cannot be the same port, otherwise it will be in conflict. So the port that I am broadcasting to is 57100. That's what's listed in Runway. But the actual port that I want to receive messages at is 57200. And maybe Runway knows just to add 100 to it automatically behind the scenes. But this is the default setup that's in Runway. So I need to have a different port for receiving the data, as the port that I'm sending to. And let me show you what I mean by that in the code. So this is the Runway port right there, 57100. That's the port that I want to broadcast to. And it's part of my broadcast location. That's where I'm broadcasting to. But where I want to receive messages is actually 57200. So now, if I run this, I'm actually receiving messages. But I've got a new error-- ArrayIndexOutOfBoundsException. So this is a rare case, where the data that Runway is sending for all of these poses is actually quite large. And so what it needs is more space. It needs a bigger packet size. And so that's why in the Runway example there was this extra OSC properties object, which allowed setting a larger datagram size. And the listening port is 57200. So just before using OscP5 by default-- you don't need to do this, but I'm going to copy paste this in. I'm going to put this back here and then I am going to change this to properties. And I think I now have all of the pieces, and what I should see is-- there we go, a lot of stuff. And look at this. Now, I've got exactly coming into processing a confidence score-- it clearly cannot see my left ankle, because my left ankle is not viewable to the camera. So that's why that confidence score is so low. Let's scroll up and do like right ear. It's got a very high confidence score and an x and a y for my right ear. So now, I'm at the point, where I can actually use this data. Going back to the Runway example, you can see here that there's a very elaborate loop to parse through the JSON and look at all the different key points and get all the different positions of everything that it detects. I'm going to try to do something much simpler right now. I'm just going to get the right eye and left eye. So let's see if we can figure that out. One way we can approach this is we can make this data variable a global variable. So I'm going to take this JSON object. And I'm going to make this a global variable. I'm going to call it data. And then, in the draw loop, I'm just going to say as long as data is not equal to null-- I forget that I'm in Java. I can just do that-- data will be null until it's received something from Runway. So as soon as it's received something from Runway, all I need to do now is parse this JSON. Something I've done to make this a little bit easier is I've just taken that JSON that prints it to the processing console and I've pasted it into a into a JSON file that I can look at in Visual Studio Code just so I have something to reference to for. So I know that I need to get something called poses. So the first thing that I want is the poses array. So one of the thing that's really weird in Processing with JSON is you have to specify whether the data you're looking at is a JSON object or JSON array. And this poses data is an array, as indicated by this square bracket. So I'm going to say JSONArray poses equals data.getJSONArray string poses. Then, I want to get the key points array. Oh, because there could be more than one pose. But I'm going to assume there's just one pose. So then that's the poses. So then I'm going to say the key points are also an array equal poses.get 0. So that would be the first element of the array. Now, get a new array called key points. Get a JSON array key points. The good news is the Runway example has all of this in there, so if I get it wrong-- key points. I have an error here, because I can't just say get element 0. What is element 0? It's a JSON object. There we go. So now, I have the key points, which are the JSON array called key points in the first JSON object index 0. Then, what do I want to look for? So now, I'm in the key points array. This is element 0. If I knew like left-- oh, this is easy, let's do nose, left eye, and right eye, 0, 1, and 2, perfect. So I want to get JSONObject nose equals keypoints.getJSONObject 0. And we'll do three of these. Left eye-- I'm doing this a little bit different than the Runway example. And then I'll point you runway example after right eye. Certainly, I could use a loop here-- so nose, left eye, right eye. And then I need to get the position-- nosePos equals nos.getJSONObject. I should just do the nose. I'm just going to do the nose just to keep things simpler here. You can extrapolate to figure out how to do the left eye and the right eye-- nose.getJSONObject position. And then x equals-- I'm going to call this nose position. Nose position gets x. Pretty sure this is right. And y equals nosePosition.get y. All right, let's see, what have I gotten wrong here? getFloat. Again, I'm in Java. I've got to specify the type. So if I've done everything correctly, I've gotten all the key points of the first pose. I've gotten the object with all the data for the nose. Then I can get the nose position out of that object, then the x and y out of that object. Phew. Now, I'm gong to say ellipse x,y 2020. And let's make it a red nose. fill 255.0.0. Let's give this a run. And there we go. I am now controlling my nose. From Runway into Processing with OSC messages. Amazing. OK, so this really concludes this particular video tutorial. Certainly, what you might want to do is see the entire skeleton. To use PoseNet effectively, you really want to have the camera probably around 6 feet from you. You want to back up and allow it to see your full form. You can also pass it images and get the pose, the skeleton off from an image. There's lots of different things you can do. And, certainly, I would recommend that you check the example in the Runway GitHub repo itself, which has a nice loop to go through all of the different positions. And actually it also has this little mapping to map what all the connections are between them for the actual skeleton itself. So as a little exercise, see if you can expand what I did to have the right eye and the left eye. But even so, you could just go get the Runway example itself. But this is a guiding principle for how any particular model that you might find in Runway itself-- someone in the chat was just asking about dense pose, for example, that you can communicate from runway via OSC to Processing. But in a lot of other cases, you might want to use web sockets or an HTTP connection to communicate, particularly if you're working in the browser with JavaScript. So what I'm going to do in the next video, if you want to watch, is run StyleGAN to generate a rainbow image and then pass that image into P5 and render it in the browser itself. And breaking news from the chat, Damien writes SRSP stand for Send and Receive on the Same Port. By default, OSC packets are not received and sent by the same port, if you need to send or receive in the same port. Oh, so maybe I could have actually done something with the port numbers. I have no idea. I'm sure people will write about it in the comments. But this code works. The code in the Runway GitHub repository works. So how fun. Use it. Make something with it. Please share it with me. And hope you enjoyed this tutorial about Processing, Runway, and the PoseNet model running locally on your computer. Goodbye. [TRAIN WHISTLE] [MUSIC PLAYING]
B1 runway processing port json posenet data Introduction to Runway: Machine Learning for Creators (Part 2) 1 0 林宜悉 posted on 2020/03/27 More Share Save Report Video vocabulary