How to store or keep Kinect movement tracking data? - gesture-recognition

Our group is now facing a problem that, we aim to implement a login system using body movements with Kinect device. That is to say, we use body movements as a so call "password". In order to login, user has to enter the "password" by performing certain movements known only by the user. So We simply
Step 1: Detect and track body movements.
Step 2: Analyse it.
Step 3: Compare with the default one like a password. If they match, login successfully.
We are not confused at the second step. The problem is how to store movement data. We know that, Kinect could give us joints of the bodies like head, neck. How do we keep or store these related data to parse them in a certain algorithm to do the comparison so that we know the login is successful or not.
thanks in advance for your suggestions.

You could for example write each joints positional Data in an arbitrary file, like .txt for each frame.
something like this:
void WriteSkeletonToFile(const nite::UserData& user, std::string filename) {
std::ofstream skeletonFile;
skeletonFile.open(filename + ".txt", std::fstream::out | std::fstream::app);
auto writeJointCoordinates = [&skeletonFile](const nite::SkeletonJoint& joint) {
skeletonFile << joint.getPosition().x << ",";
skeletonFile << joint.getPosition().y << ",";
skeletonFile << joint.getPosition().z << ",";
};
//Center body parts
writeJointCoordinates(user.getSkeleton().getJoint(nite::JOINT_HEAD));
writeJointCoordinates(user.getSkeleton().getJoint(nite::JOINT_NECK));
... continue for each joint
skeletonFile << "\n";
skeletonFile.close();
you can afterwards read it in again and use it as you like. But remember to match it with your live skeleton position when comparing it with the stored positions.
You can of course save additional Joint data like rotation (those are calculated with the positions anyway, so not really necessary), ID etc, but i would recommend a slicker File formatting then ;)

Related

Use datastore more efficiently

I am coding my fist a game with lua on the Roblox Stuido ide. The game works -- sort of--, although I know the code is not great. It's a game for small children in which a number shows on a sign and the player has to go to the platform that matches the number. One of the issues that I have is that I want there to be a GUI that displays the points in big numbers as the leader stats on the top corner are not easy to see. What I want is not just for the player to see their own points this would be somewhat easier, just add a textLabel on the starter player gui with a script like so:
while true do
wait(.1)
script.Parent.Text = game.Players.LocalPlayer.leaderstats.Platforms.Value
end
with the following code too:
game.Players.PlayerAdded:connect(function(player)
local playerKey = "Player_" .. player.UserId
local leaderstats = Instance.new("Folder",player)
leaderstats.Name = "leaderstats"
local Platforms = Instance.new("IntValue", leaderstats)
Platforms.Name = "Platforms"
Platforms.Value = 0
platformCount:SetAsync(player.UserId, 0)
StartGui:FireAllClients(player)
end)
Please take note of the last couple of lines of that block, those are what I came up with. I am not sure how to do it better but I sense they are a botch.
My objective is that each player can see not only their scores updated in real time, but also every other player's. This is what is not fully working. My method is as follows. When a player steps on the desired platform I have this code on a local script
allPlats[k].Eliminated = true
player:WaitForChild("leaderstats"):FindFirstChild("Platforms").Value = player:WaitForChild("leaderstats"):FindFirstChild("Platforms").Value + 1 --increase leaderstats
points = points + 1
numIfScored:InvokeServer(column, row, teamColorReady, points, team)
PlatformDeleted.OnClientEvent:Connect(platformTransparency)
Ignore the lines that don't apply to the question. The important part for this question is that I access the intValue created in the leaderstats and increase it's value by one. I also send a call to the server with a remote function that passes where the platform was, the color of the team etc...
The serverside script then uses these values to perform a number of tasks related to setting the next target and updating the way the platforms look and, crucially, sends the data to a datastore:
function numIfScored.OnServerInvoke(plr, col, row, orignalTeamColor, points, team)
game.Workspace.TargetNumber.Value = getAnddisplayTarget(col, row)
PlatformDeleted:FireAllClients(col, row)
for k, v in pairs(allPlats) do
if v.Column == col and v.Row == row then
v.Part.Transparency = 0
v.Part.Material = "Neon"
v.Part.BrickColor = BrickColor.new(orignalTeamColor)
end
end
platformCount:SetAsync(plr.UserId, points)
end
I then run a separate block of code in the same scrip that is constantly updating the gui by grabbing the points from the datastore:
while wait(.1) do
for _, player in pairs(Players:GetPlayers()) do
local points = platformCount:GetAsync(player.UserId)
UpdateGUI:FireAllClients(player.UserId,points, player.Team)
end
end
I have a localscript that is a child of the text label that displays the scores with the following code:
local function UpdateLabel(plrId, points, team)
if team.Name == "Really red Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.Text = points
elseif team.Name == "Really blue Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.Text = points
end
end
StartGui.OnClientEvent:Connect(StartLabel)
This works but is buggy. I play at home with my son an it sort of works, with a bit of lag, but as soon as I try to play with other players, like my friend and his son, the system stops working well. One thing that I know is not good is that if you start playing before another player joins, then that player can't see your progress before they came in. Another problem is that the first player that joins will be seen by players that join later, but as players join that can't see the labels of players that joined before.
Is there a much simpler way to create a gui that updates all the players scores in all the players gui's? Thanks.
I can post full code if needed.
No need for full code. I just needed the sentence "It's in a LocalScript". Even if you're changing the text of the labels in a server script, you're adding the points on a local script which means it'll only change the points for you and not any other player. Instead if you use a RemoteFunction and call on the server to change the points, I'm more than certain it should work.

ruby placeholders NOT populating in external .txt file

Here is what I currently have; the only problem being the external file loads without the placeholder text updated -- instead rather, the placeholder text just says '[NOUN]' instead of actual noun inserted from user in earlier program prompt.
Update; cleaned up with #tadmans suggestions, it is however, still not passing user input to placeholder text in external .txt file.
puts "\n\nOnce upon a time on the internet... \n\n"
puts "Name 1 website:"
print "1. "
loc=gets
puts "\n\Write 5 adjectives: "
print "1. "
adj1=gets
print "\n2. "
adj2=gets
print "\n3. "
adj3=gets
print "\n4. "
adj4=gets
print "\n5. "
adj5=gets
puts "\n\Write 2 nouns: "
print "1. "
noun1=gets
print "\n2. "
noun2=gets
puts "\n\nWrite 1 verb: "
print "1. "
verb=gets
puts "\n\nWrite 1 adverb: "
print "1. "
ptverb=gets
string_story = File.read("dynamicstory.txt")
puts string_story
Currently output is (i.e. placeholders not populated):
\n\nOnce upon a time on the internet...\n\n
One dreary evening while browsing the #{loc} website online, I stumbled accross a #{adj1} Frog creature named Earl. This frog would sit perturbed for hours at a time at the corner of my screen like Malware. One day, the frog appeared with a #{adj2} companion named Waldo that sat on the other corner of my screen. He had a #{adj3} set of ears with sharp #{noun1} inside. As the internet frogs began conversing and becoming close friends in hopes of #{noun2}, they eventually created a generic start-up together. They knew their start-up was #{adj4} but didn't seem to care and pushed through anyway. They would #{verb} on the beach with each other in the evenings after operating with shady ethics by day. They could only dream of a shiny and #{adj5} future full of gold. But then they eventually #{ptverb} and moved to Canada.\n\n
The End\n\n\n
It's important to note that the Ruby string interpolation syntax is only valid within actual Ruby code, and it does not apply in external files. Those are just plain strings.
If you want to do rough interpolation on those you'll need to restructure your program in order to make it easy to do. The last thing you want is to have to eval that string.
When writing code, always think about breaking up your program into methods or functions that have a specific function and can be used in a variety of situations. Ruby generally encourages code-reuse and promoting the "DRY principle", or "Don't Repeat Yourself".
For example, your input method boils down to this generic method:
def input(thing, count = 1)
puts "Name %d %s:" % [ count, thing ]
count.times.map do |i|
print '%d. ' % (i + 1)
gets.chomp
end
end
Where that gets input for a random thing with an arbitrary count. I'm using sprintf-style formatters here with % but you're free to use regular interpolation if that's how you like it. I just find it leads to a less cluttered string, especially when interpolating complicated chunks of code.
Next you need to organize that data into a proper container so you can access it programmatically. Using a bunch of unrelated variables is problematic. Using a Hash here makes it easy:
puts "\n\nOnce upon a time on the internet... \n\n"
words = { }
words[:website] = input('website')
words[:adjective] = input('adjectives', 5)
words[:noun] = input('nouns', 2)
words[:verb] = input('verb')
words[:adverb] = input('adverb')
Notice how you can now alter the order of these things by re-ordering the lines of code, and you can change how many of something you ask for by adjusting a single number, very easy.
The next thing to fix is your interpolation problem. Instead of using Ruby notation #{...}, which is hard to evaluate, go with something simple. In this case %verb1 and %noun2 are used:
def interpolate(string, values)
string.gsub(/\%(website|adjective|noun|verb|adverb)(\d+)/) do
values.dig($1.to_sym, $2.to_i - 1)
end
end
That looks a bit ugly, but the regular expression is used to identify those tags and $1 and $2 pull out the two parts, word and number, separately, based on the capturing done in the regular expression. This might look a bit advanced, but if you take the time to understand this method you can very quickly solve fairly complicated problems with little fuss. It's something you'll use in a lot of situations when parsing or rewriting strings.
Here's a quick way to test it:
string_story = File.read("dynamicstory.txt")
puts interpolate(string_story, words)
Where the content of your file looks like:
One dreary evening while browsing the %website1 website online,
I stumbled accross a %adjective1 Frog creature named Earl.
You could also adjust your interpolate method to pick random words.

Google sheets api adding multiple rows

I'm trying to figure this out and I must be overlooking something basic. (It took me WAAAY longer than it should have just to realize I hadn't added the trigger.)
When forms are submitted, if that page runs out of rows, it automatically expands. I have a reconciliation page where it is pulling the submitted data over line by line and analyzing it for discrepancies (the form collects billable time and tasks.)
So while the Form Responses 1 page will expand, I want to use a trigger on form submit to add a line to the reconciliation page and copy the formulas down. I can't seem to get the line to add though. Looking at the google page for expanding the number of rows, I'm not sure what I am doing wrong there either but I THINK I need to add more java features to my computer.
If I simply copy and paste the example into a new sheet, most of the code is black instead of the standard editor colors. Saving pops up "Missing ; before statement. (line 1, file "Code")"
Line one is simply "import com.google.gdata.client.spreadsheet.*;"
So zerothly: Whats the most basic code I can use to add that blank row?
Then first: Do I need to import a bunch of stuff to get this (adding rows) to work?
Second: If so, and I transfer ownership of the sheet to someone, do they need to do the imports also?
Third: If so, and I want to do edits on another device, will I need to do imports there too?
Fourth: The example uses Update() but I can't seem to find an Update() function in javascript or googlesheets api documentation.
This is the code I am trying and variations commented out which doesn't seem to work:
function onFormSubmit(e) {
Logger.log('form submit triggered')
var sheet = SpreadsheetApp.getActive()
var sss = sheet.getSheetByName('Reconciliation')
var col2 = sss.getRange("B:B");
var col2val = col2.getValues();
var counter = 0;
var sssrange = sss.getDataRange();
// sss.Rows = sss.getLastRow() + 1 //Object does not allow properties to be added or changed if I uncomment - this seems to match the google example line though
Logger.log(sss.getLastRow());//=8
var newsssrange = sssrange.offset(1,0); // didn't actually think this would work (since it also had the .update() part that previously didn't work for me) but came across it and was getting desparate.
// sss.setRowCount(sss.getLastRow() + 1); // TypeError: Cannot find function setRowCount in object Sheet.
Logger.log(sss.getLastRow()); //=8
// sss.Update();//TypeError: Cannot find function Update in object Sheet.
}
Sigh... I am still wondering how to add more rows but I did answer my original need of adding a single line since form submits only add a single line. So I'm going to answer it since I had done so many searches and for some reason this never came up, maybe someone will find this useful if they are having the same issue.
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActive()
var sss = sheet.getSheetByName('Reconciliation')
sss.appendRow(['']);
}
Note that this adds a single blank line. If you run it a second time it won't add a second blank line as appendRow() adds after the last line with data. If you put a string in there or something and run it over and over you will get multiple lines.
I really would like to know about adding multiple lines though also since that will come up and I still seem to be missing something, probably obvious.
Did you know that arrayformula woluld make new lines automatically.? If you paste this formula in Sheet2:
=OFFSET(Sheet1!A1,,,counta(Sheet1!A:A))
and then paste new values in Sheet1 range A:A, then new rows would be added on Sheet2.

pull out r squared from fit model to table in JSL JMP

I'm trying to figure out how to use JSL to write some of the analysis of variance variables values to a table in JMP. My idea is to write a script that runs different types of models with different parameters with R^2 and RSME logging to a table (maybe there is a better way to do this I'm on my second day of JMP). Going through the documentation it seems that different analysis have different ways of doing this and I can't find one for "fit model". I also will need to know how to do this for a neural network which I think I may have found the documentation for.
If you're doing something like screening variables to determine an optimized model, you're in the right place with the fit model platform. However, running the fit model in a loop without human judgment in model selection as you've suggested isn't necessarily expedient.
So at the expense of trying to make JMP/JSL do something it's not really suited for, one way to achieve your generic goal of grabbing text from the fit model platform output is to send your platform to a "report" and then pull from that "report" the data you want, and then send it to a data table. From that data table, you can concatenate it with another data table and you would have your log. That's the idea, here's an example, for some dummy data "Ydata" and "Xdata":
thing = Fit Model(
Y( :Ydata ),
Effects( :Xdata ),
Personality( Standard Least Squares ),
Emphasis( Minimal Report ),
Run(
:Ydata << {Plot Actual by Predicted( 0 ),
Plot Residual by Predicted( 0 ), Plot Effect Leverage( 0 )}
)
);
thing_report = thing<<report;
thing_report_dt_ref = thing_report["Summary of Fit"][1] << make into data table;
//alternatively
//thing_report_dt_ref = thing_report[TableBox(1)] << make into data table;
thing_report_dt_ref << Set Name("Choose_a_name_for_your_new_data_table");
You'd have to handle the looping part, but if you can do it once, you can do it N times.
Because JMP/JSL is stupid, you can alternatively call the "Summary of Fit" directly if your know it's name in the tree structure. In my case, its name was "TableBox(1)". Do:
thing << show tree structure
To see where your data lives in the platform display box.

Import Subtitles in Processing

I am working on this sketch on Processing which gets the videofeed from my webcam/smartphone and shows it when running. I want to import an .srt converted to txt subtitles file from a film to it. I can see that the text file has all these numbers that stand for the start and end subtitle frame before the actual text.
Here's an example:
{9232}{9331}Those swings are dangerous.|Stay off there. I haven't fixed them yet.
{9333}{9374}I think you're gonna live.
What I would like to do is to figure outa code that will
use the numbers and set them as start/end frames to run at the right time as in the film
display the subtitles
figure out how the '|'sign can be used as a symbol to trigger in the script the change of line.
I guess that might already be quite complicated but I just wanted to check whether someone has done anything similar in the past..
I guess what I want to do is save me from doing the whole
if ((current_frame > 9232) && ((current_frame < 9331)) {
text("Those swings are dangerous.", 200, 500/2);
text("Stay off there. I haven't fixed them yet..", 200, (500/2 + 35));
}
thing for each subtitle...
I am quite new to processing so not that familiar with many commands apart from 'for' and 'if', a newbie at importing .txt files and an ignoramus in working with arrays. But I really want to find a nice way in the last two bits..
Any help in any form will be greatly appreciated :)
Cheers,
George
For displaying the appropriate subtitle, you could do something like the following (explanation below, sorry in advance for the wall of text):
String[] subtitles = loadStrings("subtitles.txt");
int currentFrame = 0;
int subtitleIndex = -1;
int startFrame = -1, endFrame = -1;
int fontSize = 10; //change to suit your taste
String[] currentSubtitle;
...
//draw loop start:
//video drawing code goes here
if(currentFrame > endFrame){ //update which subtitle is now/next
subtitleIndex++;
startFrame = int(subtitles[subtitleIndex].split("\\}\\{")[0].substring(1));
endFrame = int(subtitles[subtitleIndex].split("\\}\\{")[1].split("\\}")[0]);
currentSubtitle = subtitles[subtitleIndex].split("\\}")[2].split("\\|");
}
if(currentFrame >= startFrame && currentFrame <= endFrame){
for(int i = 0; i < currentSubtitle.length; i++){
text(currentSubtitle[i], width/2, height - fontSize * (currentSubtitle.length - i));
}
}
currentFrame++;
//draw loop end
Probably that looks pretty intimidating to you, so here's some walk-through commentary. Your program will be a type of state machine. It will either be in the state of displaying a subtitle, or not. We'll keep this in mind later when we're designing the code. First, you need to declare and initialize your variables.
The first line uses the loadStrings() function, which reads through a text file and returns a String array where each element in the array is a line in the file. Of course, you'll need to change the filename to fit your file.
Your code uses a variable called current_frame, which is a very good idea, but I've renamed it to currentFrame to fit the java coding convention. We'll start at zero, and later on our code will increment it on every frame display. This variable will tell us where we are in the subtitle sequence and which message should be displayed (if any).
Because the information for what frame each subtitle starts and ends on is encoded in a string, it's a bit tricky to incorporate it into the code. For now, let's just create some variables that represent when the "current" subtitle-- the subtitle that we're either currently displaying or will be displaying next-- starts and ends. We'll also create an index to keep track of which element in the subtitles array is the "current" subtitle. These variables all start at -1, which may seem a bit odd. Whereas we initialized currentFrame to 0, these don't really have a real "initial" value, at least not for now. If we chose 0, then that's not really true, because the first subtitle may not (probably doesn't) begin and end at frame 0, and any other positive number doesn't make much sense. -1 is often used as a dummy index that will be replaced before the variable actually gets used, so we'll do that here, too.
Now for the final variable: currentSubtitle. The immediate thought would be to have this be a plain String, not a String array. However, because each subtitle may need to be split on the pipe (|) symbols, each subtitle may actually represent several lines of text, so we'll create an array just to be safe. It's possible that some subtitles may be a single-element array, but that's fine.
Now for the hard part!
Presumably, your code will have some sort of loop in it, where on each iteration the pertinent video frame is drawn to the screen and (if the conditions are met), the subtitle is drawn over top of it. I've left out the video portion, as that's not part of your question.
Before we do anything else, we need to remember that some of our variables don't have real values yet-- all those -1s from before need to be set to something. The basic logic of the drawing loop is 1) figure out if a subtitle needs to be drawn, and if so, draw it, and 2) figure out if the "current" subtitle needs to be moved to the next one in the array. Let's do #2 first, because on the first time through the loop, we don't know anything about it yet! The criterion (in general) for moving to the next subtitle is if we're past the end of the current one : currentFrame > endFrame. If that is true, then we need to shift all of our variables to the next subtitle. subtitleIndex is easy, we just add one and done. The rest are... not as easy. I know it looks disgusting, but I'll talk about that at the end so as to not break the flow. Skip ahead to the bottom if you just can't wait :)
After (if necessary) changing all of the variables so that they're relevant to the current subtitle, we need to do some actual displaying. The second if statement checks to see if we're "inside" the frame-boundaries of the current subtitle. Because the currentSubtitle variable can either refer to the subtitle that needs to be displayed RIGHT NOW, or merely just the next one in the sequence, we need to do some checking to determine which one it is for this frame. That's the second if statement-- if we're past the start and before the end, then we should be displaying the subtitle! Recall that our currentSubtitle variable is an array, so we can't just display it directly. We'll need to loop through it and display each element on a separate line. You mentioned the text() command, so I won't go too in depth here. The tricky bit is the y-coordinate of the text, since it's supposed to be on multiple lines. We want the first element to be above the second, which is above the third, etc. To do that, we'll have the y-coordinate depend on which element we're on, marked by i. We can scale the difference between lines by changing the value of fontSize; that'll just be up to your taste. Know that the number you set it to will be equal to the height of a line in pixels.
Now for the messy bit that I didn't want to explain above. This code depends on String's split() method, which is performed on the string that you want split and takes a string as a parameter that instructs it how to split the string-- a regex. To get the startFrame out of a subtitle line in the file, we need to split it along the curly braces, because those are the dividers between the numbers. First, we'll split the string everywhere that "}{" occurs-- right after the first number (and right before the second). Because split() returns an array, we can reference a single string from it using an index between square braces. We know that the first number will be in the first string return by splitting on "}{", so we'll use index 0. This will return (for example) "{1234", because split() removes the thing you're splitting on. Now we need to just take the substring that occurs after the first character, convert it to an int using int(), and we're done!
For the second number, we can take a similar approach. Let's split on "}{" again, only we'll take the second (index 1) element in the returned array this time. Now, we have something like "9331}Those swings are dang...", which we can split again on "}", choose the first string of that array, convert to int, and we're done! In both of these cases, we're using subtitles[subtitleIndex] as the original String, which represents the raw input of the file that we loaded using loadStrings() at the beginning. Note that during all this splitting, the original string in subtitles is never changed-- split(), substring(), etc only return new sequences and don't modify the string you called it on.
I'll leave it to you to figure out how the last line in that sequence works :)
Finally, you'll see that there are a bunch of backslashes cluttering up the split() calls. This is because split() takes in a regex, not a simple string. Regexs use a lot of special notation which I won't get into here, but if you just passed split() something like "}{", it would try to interpret it and it would not behave as expected. You need to escape the characters, telling split() that you don't want them to be interpreted as special and you just want the characters themselves. To do that, you use a backlash before any character that needs to be escaped. However, the backslash itself is yet another special character, so you need to escape it, too! This results in stuff like "\\{" -- the first backslash escapes the second one, which escapes whatever the third character is. Note that the | character also needs to be escaped.
Sorry for the wall of text! It's nice to see questions asked intelligently and politely, so I thought I'd give a good answer in return.

Resources