Passing image from Processing to Javascript and then saving said image back to server using AJAX / PHP? - processing.js

I'm working on a project where I want to load a processing sketch into a canvas, have some things happen to the image when a user mouses over (got that part), and then when they leave the canvas save the image back to the server.
I've looked at these other questions, and can't quite figure this out:
HTML5 CANVAS: How to save and reopen image from server
That's not really working for me.
Uploading 'canvas' image data to the server
I don't exactly understand where to put everything in this.
http://j-query.blogspot.in/2011/02/save-base64-encoded-canvas-image-to-png.html
From outside of Stackoverflow, but I got there from here.
Version 1
This isn't working all the way, I feel like I'm close, the processing sketch is working, and it's kicking out an image, I just can't grab it with JS, and then I don't know what to do with it to get it back to the server.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My Processing Page</title>
<script type="text/javascript" src="../../processingjs/processing.js"></script>
<script type="text/javascript"> //This is for communicating between Processing and Javascript
function showXYCoordinates(x, y) {
document.getElementById('xcoord').value = x;
document.getElementById('ycoord').value = y;
}
var bound = false;
function bindJavascript(instance) {
var pjs = Processing.getInstanceById(instance);
if(pjs != null) {
pjs.bindJavascript(this);
bound = true;
}
if(!bound) {
setTimeout(bindJavascript, 250);
}
}
bindJavascript('B_103');
var processingOutput = Processing.getInstanceByID('B_103');
var img = processingOutput.mouseOut();
</script>
</head>
<body>
<canvas id="B_103" data-processing-sources="B_103/B_103.pde" width="300px" height="300px"></canvas>
<?php
// requires php5
echo $_GET['img'];
define('UPLOAD_DIR', 'B_103/data/');
$img = $_POST['img'];
// $img = str_replace('data:image/png;base64,', '', $img);
// $img = str_replace(' ', '+', $img);
// $data = base64_decode($img);
$file = UPLOAD_DIR . 'image.jpg';
$success = file_put_contents($file, $data);
print $success ? $file : 'Not able to save the file.';
?></body>
</html>
And then there is this:
Version 2
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My Processing Page</title>
<script type="text/javascript" src="../../processingjs/processing.js"></script>
<script type="text/javascript"> //This is for communicating between Processing and Javascript
function showXYCoordinates(x, y) {
document.getElementById('xcoord').value = x;
document.getElementById('ycoord').value = y;
}
var bound = false;
function bindJavascript(instance) {
var pjs = Processing.getInstanceById(instance);
if(pjs != null) {
pjs.bindJavascript(this);
bound = true;
}
if(!bound) {
setTimeout(bindJavascript, 250);
}
}
bindJavascript('B_103');
//var processingOutput = Processing.getInstanceByID('B_103');
//var img = processingOutput.mouseOut();
function save(){ //saves the canvas into a string as a base64 png image. jsvalue is sent to the server by an html form
var b_canvas = document.getElementById("B_103");
var b_context = b_canvas.getContext("2d");
var img = b_canvas.file_put_contents('backpicture.png',base64_decode(substr($str,22)));
}
</script>
</head>
<body>
<canvas id="B_103" data-processing-sources="B_103/B_103.pde" width="300px" height="300px"></canvas>
<?php
echo $_GET['img'];
$str=$_POST['img'];
$file=fopen("B_103/data/image.txt","w");
if(isset($_POST['submit']))
fwrite($file,$str);
fclose($file)
?>
</body>
</html>
So this one is saving a file backwards, but the file has nothing in it. I can deal with Base64 (with the answer to one question about using it in processing) but this file doesn't have it in there.
Any thoughts appreciated, thank you!

Way too much code there =)
Canvas can give you a base64 encoded image with a single function call, so just use canvas.toDataURL("image/png") or canvas.toDataURL("image/jpg") to get that string, and then save it to your server with a normal POST operation.
When it's required again, ask your server for the data using whatever format your GET request takes, and then unpack it as an Image, then draw that image onto your sketch:
var dataURI = /* get the string from your server */
var img = new Image();
img.src = dataURI;
sketch.image(img,0,0);
And we should be good to go.

Thanks Mike, it's working. Here's what I did.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My Processing Page</title>
<script type="text/javascript" src="../../processingjs/processing.js"></script>
<script type="text/javascript"> //This is for communicating between Processing and Javascript
function showXYCoordinates(x, y) {
document.getElementById('xcoord').value = x;
document.getElementById('ycoord').value = y;
}
var bound = false;
function bindJavascript(instance) {
var pjs = Processing.getInstanceById(instance);
if(pjs != null) {
pjs.bindJavascript(this);
bound = true;
}
if(!bound) {
setTimeout(bindJavascript, 250);
}
}
bindJavascript('B104');
//var processingOutput = Processing.getInstanceByID('B_104');
//var img = processingOutput.mouseOut();
function postAjax(){
var canvasB104 = document.getElementById('B104');
var canvasData = canvasB104.toDataURL('image/png');
var ajax = new XMLHttpRequest();
ajax.open("POST",'testSave.php',false);
ajax.setRequestHeader('Content-Type', 'application/upload');
ajax.send(canvasData);
}
</script>
</head>
<body>
<canvas id="B104" data-processing-sources="B_104/B_104.pde" width="300px" height="300px" onmouseout="postAjax()"></canvas>
Plus, I have a PHP file, that I got from this tutorial: http://permadi.com/blog/2010/10/html5-saving-canvas-image-data-using-php-and-ajax/
One of the things I goofed up, which is probably a rookie thing to do, was I had the variable canvasData in quotes, which I see now is incorrect of course (because I wanted the string not the actual word 'canvasData')
In case anyone wants to see it working: http://graphic-interaction.com/mfa-thesis/testing-group02/pro-ex-07.php

Related

How can I get continuous landmarks from video for Mediapipe Handpose

I am new to Javascript. I am trying to get output from MediaPipe Handpose. When I give an image into this model, I easily get an output. But when I try for a video, it doesn't work.
This is the head
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-core"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-converter"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-backend-webgl"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow-models/handpose"></script>
My video ID details
Source<br>
<video id="video" src="o_new.mp4" width="640" height="480" controls>
</video>
<canvas id="canvas" style="overflow:auto"></canvas>
Inside the script
<script>
const video = document.getElementById("video");
async function main() {
// Load the MediaPipe handpose model.
const model = await handpose.load(maxContinuousChecks = 60);
console.log('Model Loaded')
// Pass in a video stream (or an image, canvas, or 3D tensor) to obtain a
// hand prediction from the MediaPipe graph.
const predictions = await model.estimateHands(video);
console.log('Estimated Hand')
console.log(predictions)
if (predictions.length > 0) {
/*
`predictions` is an array of objects describing each detected hand, for example:
[
{
handInViewConfidence: 1, // The probability of a hand being present.
boundingBox: { // The bounding box surrounding the hand.
topLeft: [162.91, -17.42],
bottomRight: [548.56, 368.23],
},
landmarks: [ // The 3D coordinates of each hand landmark.
[472.52, 298.59, 0.00],
[412.80, 315.64, -6.18],
...
],
annotations: { // Semantic groupings of the `landmarks` coordinates.
thumb: [
[412.80, 315.64, -6.18]
[350.02, 298.38, -7.14],
...
],
...
}
}
]
*/
for (let i = 0; i < predictions.length; i++) {
const keypoints = predictions[i].landmarks;
console.log('keypoints Loop')
// Log hand keypoints.
for (let i = 0; i < keypoints.length; i++) {
const [x, y, z] = keypoints[i];
console.log(`Keypoint ${i}: [${x}, ${y}, ${z}]`);
}
}
}
}
main();
</script>
How can I get continuous landmarks in an output object for video?
Here is the error.
I am updating my previous answer. You don't want to use set interval like I put in my former solution. When I used it for more than a few minutes it filled up my gpu memory and crashed webgl. I was able to comb through the developers demo.js file, and found a solution. In your js file replace your main() function with the below code:
const state = {
backend: 'webgl'
};
let model;
async function main() {
await tf.setBackend(state.backend);
model = await handpose.load();
landmarksRealTime(video);
}
const landmarksRealTime = async (video) => {
async function frameLandmarks() {
const predictions = await model.estimateHands(video);
if (predictions.length > 0) {
const result = predictions[0].landmarks;
console.log(result, predictions[0].annotations);
}
rafID = requestAnimationFrame(frameLandmarks);
};
frameLandmarks();
};
video.addEventListener("loadeddata", main);
This console logs continuous landmarks. It doesn't log anything if a hand is not detected. Also, it looks like the developers updated the recommended script tags a few days ago, so I would recommend updating your index.html file. They should be:
<!-- Require the peer dependencies of handpose. -->
<script src="https://unpkg.com/#tensorflow/tfjs-core#2.1.0/dist/tf-core.js"></script>
<script src="https://unpkg.com/#tensorflow/tfjs-converter#2.1.0/dist/tf-converter.js"></script>
<!-- You must explicitly require a TF.js backend if you're not using the tfs union bundle. -->
<script src="https://unpkg.com/#tensorflow/tfjs-backend-webgl#2.1.0/dist/tf-backend-webgl.js"></script>
<!-- Alternatively you can use the WASM backend: <script src="https://unpkg.com/#tensorflow/tfjs-backend-wasm#2.1.0/dist/tf-backend-wasm.js"></script> -->
<script src="https://unpkg.com/#tensorflow-models/handpose#0.0.6/dist/handpose.js"></script></head>

wijmo 5 scripts concatenation fails, anyone else found the same issue.?

Did anyone ever tried minified wijmo 5 angular js files?
I fails after concatenation, I tried putting all js files inside IIFE still it fails to execute.
Please let me know if any one has ever tried the same.
FYI: I do not have unminified files as wijmo provides it after buying licences.
Link to wijmo : http://wijmo.com/5/docs/static/references.html
You can also use CDN link for the same. Please refer to 'Deploying Wijmo from CDN' at the same link mentioned above. Here is the code snippet for using Wijmo 5 FlexGrid with AngularJS.
<html>
<head>
<link href="http://cdn.wijmo.com/5.20163.254/styles/wijmo.min.css" rel="stylesheet"/>
<script src="http://cdn.wijmo.com/5.20163.254/controls/wijmo.min.js"></script>
<script src="http://cdn.wijmo.com/5.20163.254/controls/wijmo.input.min.js"></script>
<script src="http://cdn.wijmo.com/5.20163.254/controls/wijmo.grid.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://cdn.wijmo.com/5.20163.254/interop/angular/wijmo.angular.min.js"></script>
<script>
var app = angular.module('app', ['wj']);
// app controller provides data
app.controller('appCtrl', function($scope){
// generate some random data
var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','),
data = [];
for (var i = 0; i < 50; i++) {
data.push({
id: i,
country: countries[i % countries.length],
date: new Date(2014, i % 12, i % 28),
amount: Math.random() * 10000,
active: i % 4 == 0
});
}
// add data array to scope
$scope.data = data;
});
</script>
</head>
<body>
<div ng-app="app" ng-controller="appCtrl" >
<wj-flex-grid items-source="data" style="height:200px;">
</wj-flex-grid>
</div>
</body>
</html>
Thanks,
Manish Kumar Gupta

automation of dimple.js charts with a configuration file

I wanted to be able to change the type of charts made with dimple.js using variables.
I am able to do it using local variables, set up manually, thanks to this post: change chart type in dimple.js to automate chart production
However, when I am trying to go a step further and place all my variables in a configuration file, it does no longer work anymore. I'm pretty sure I'm missing something with the "objects", but can't figure what.
Sorry, it might be an obvious thing I'm missing, but I'm a data analyst, not a developer and quite a rookie concerning d3.js and dimple.js.
My code: (see below) http://plnkr.co/McEDMkovXaQpsn5z9mmV
I have put 2 html pages : "Manual" is where it works with local variables declared manually.
"Dynamic" is the same code except I've put the variables in a configuration file and I read the configuration file using D3.csv function (a line par chart). It does not work.
Thank you for your help!
Code : http://plnkr.co/McEDMkovXaQpsn5z9mmV
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="http://dimplejs.org/dist/dimple.v2.1.0.min.js"></script>
<script type="text/javascript" src="script.js"</script>
</head>
<body>
<div id="chartContainer">
<script type="text/javascript">
var chartType1 = "bar";
var chartDimple1 = dimple.plot[chartType1];
var chartSerie1 = "Channel";
var chartGroup1 = ["Month", "Channel"];
var chartMeasure1 = "Unit Sales";
var filterField1 = "Owner";
var filterValues1 = ["Aperture", "LexCorp"];
var svg1 = dimple.newSvg("#chartContainer", 590, 400);
d3.csv("data.csv", function (data1) { //d3.tsv("data/example_data.tsv", function (data) {
var data1 = dimple.filterData(data1, filterField1, filterValues1) // dataFiltered = dimple.filterData(data, "Owner", ["Aperture", "LexCorp"])
var myChart1 = new dimple.chart(svg1, data1);
myChart1.setBounds(60, 30, 510, 305)
var x1 = myChart1.addCategoryAxis("x", chartGroup1); // var x = myChart.addCategoryAxis("x", ["Channel" , "Month"]);
x1.addOrderRule("Date");
var y1 = myChart1.addMeasureAxis("y", chartMeasure1);
myChart1.addSeries(chartSerie1, chartDimple1); // myChart.addSeries("Channel", dimple.plot.bar);
myChart1.addLegend(60, 10, 510, 20, "right");
myChart1.draw();
});
</script>
</div>
<div id="chart2"></div>
<div id="chart3"></div>
<script type="text/javascript">
pageLayout(configFile);
</script>
</body>
</html>
I'm having a tough time getting the example working, lots of files doing lots of things. I think the basic problem is that when you import the dsv config file, your group still comes back as a string like "["Month", "Channel"]". When you pass this to chart.addCategoryAxis it's going to look at it like a string rather than an array. You should be able to do
chart.addCategoryAxis(JSON.parse(d.chartGroup));
and have it correctly set it as an array. This only works if you know it's going to be an array, if it may only be one string you would need to check beforehand to know if you need to parse it or not.
Also some of the code I don't think works on that site because it's still looking for the static dsv/csv files in a data/ directory that isn't there, but I think the string/array issue is probably the one holding you up.

Open Web Analytics tracking doesn't work

I am a new owa(Open Web Analytics) user, I have installed owa in /owa/apache/htdocs/owa
and create one index.html under /owa/apache/htdocs with blow content
However I won’t be able to see any analytic statistics from owa after I refreshed index.html several times
<html>
<header>
<!– Start Open Web Analytics Tracker –>
<script type=”text/javascript”>
//<![CDATA[
var owa_baseUrl = 'http://localhost/owa/';
var owa_cmds = owa_cmds || [];
owa_cmds.push(['setSiteId', '4f9312bd29c7edd4d492210b8599a383']);
owa_cmds.push(['trackPageView']);
owa_cmds.push(['trackClicks']);
owa_cmds.push(['trackDomStream']);
(function() {
var _owa = document.createElement(‘script’); _owa.type = ‘text/javascript’; _owa.async = true;
owa_baseUrl = (‘https:’ == document.location.protocol ? window.owa_baseSecUrl || owa_baseUrl.replace(/http:/, ‘https:’) : owa_baseUrl );
_owa.src = owa_baseUrl + ‘modules/base/js/owa.tracker-combined-min.js’;
var _owa_s = document.getElementsByTagName(‘script’)[0]; _owa_s.parentNode.insertBefore(_owa, _owa_s);
}());
//]]>
</script>
<!– End Open Web Analytics Code –>
</header>
<body>
<h1>It works!</h1>
</body>
</html>
As you ca see here: https://github.com/Open-Web-Analytics/Open-Web-Analytics/wiki/Troubleshooting
OWA uses cookies for tracking and for logging not the the admin interface. Therefor you must run OWA under a fully qualified domain (FQD) such as my.domain.com. Accessing and running OWA under http://localhost or an IP address will create errors.
Hoe this helps you :)
There are a few issues with your HTML. For instance, you need to specify a doctype for your html tag. Also, should be .
I've cleaned up your code, but haven't check to see if this works. Give this a shot though:
<!DOCTYPE html>
<head>
<title>Blah</title>
<script>
//<![CDATA[
var owa_baseUrl = 'http://localhost/owa/';
var owa_cmds = owa_cmds || [];
owa_cmds.push(['setSiteId', '4f9312bd29c7edd4d492210b8599a383']);
owa_cmds.push(['trackPageView']);
owa_cmds.push(['trackClicks']);
owa_cmds.push(['trackDomStream']);
(function() {
var _owa = document.createElement('script'); _owa.type = 'text/javascript'; _owa.async = true;
owa_baseUrl = ('https:' == document.location.protocol ? window.owa_baseSecUrl || owa_baseUrl.replace(/http:/, 'https:') : owa_baseUrl );
_owa.src = owa_baseUrl + 'modules/base/js/owa.tracker-combined-min.js';
var _owa_s = document.getElementsByTagName('script')[0]; _owa_s.parentNode.insertBefore(_owa, _owa_s);
}());
//]]>
</script>
</head>
<body>
<h1>It works!</h1>
</body>
</html>

Leaflet - updating a keyword search call to a restful api and refreshing map

My Question (UPDATED): How do I get my keyword to change in the API URL Search Query based off of an AJAX Call (having a scope problem here) ?
I connected a leaflet map to an an API to plot Wikipedia articles with geocoordinates. An example URL looks like: http://api.infochimps.com/encyclopedic/wikipedia/dbpedia/wikipedia_articles/search?g.radius=10000&g.latitude=30.3&g.longitude=-97.75&f.q=park&apikey=api_test-W1cipwpcdu9Cbd9pmm8D4Cjc469
So far so good. But I am stuck on how to implement an AJAX call that would allow the user to search for a new query term and reload the map. When I click the search box, the keyword alerts that the keyword is the text in the search box. But the map does not update based on the new keyword.
So I have as a JS script:
var map;
var pointsLayer;
var markerMap = {};
var keyword; //instantiating keyword for global scope
$(document).ready(function(){
map = new L.Map('mapContainer');
var url = 'http://{s}.tiles.mapbox.com/v3/mapbox.mapbox-streets/{z}/{x}/{y}.png';
var copyright = 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade';
var tileLayer = new L.TileLayer(url, {attribution:copyright});
//var startPosition = new L.LatLng(42.33143, -83.04575);//detroit
var startPosition = new L.LatLng(41.883333, -87.633333);//chicago
//var startPosition = new L.LatLng(40.7143528, -74.0059731);//new york
map.on('load', function(){
keyword = 'history'; //setting keyword to history on first load
requestUpdatedPoints();
keyword = ''; //clearing keyword after first load
});
map.setView(startPosition, 13).addLayer(tileLayer);
map.on('moveend', function(){
requestUpdatedPoints();
});
//////////////
/// WRONG ADDITION OF ADDING KEYWORD SEARCH?
//////////////
$('a#submitSearch').on('click', function(e, keyword){
e.preventDefault();
//keyword = '';
keyword = $('input#keyword').val(); //setting keyword to whatever is in the search box
alert(keyword); //did it set it?
requestUpdatedPoints(keyword); //send in new AJAX call with new keyword
location.reload();
});
});
function requestUpdatedPoints(keyword){
$.ajax({
type: 'GET',
url: 'http://api.infochimps.com/encyclopedic/wikipedia/dbpedia/wikipedia_articles/search?g.radius=100000&g.latitude=41.883333&g.longitude=-87.633333&f.q='+this.keyword+'&apikey=api_test-W1cipwpcdu9Cbd9pmm8D4Cjc469',
dataType: 'jsonp',
//data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
success: function(result){
for( var i=0; i<result.results.length - 1; i++ ){
console.log("adding " + result.results[i].wikipedia_id + " to the map")
var marker = L.marker([result.results[i].coordinates[1], result.results[i].coordinates[0]]).addTo(map);
marker.bindPopup(''+result.results[i].wikipedia_id+'');
}
},
error: function(){
alert('check your error log.');
}
});
}
the HTML is:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./style.css">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.4/leaflet.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="http://cdn.leafletjs.com/leaflet-0.4/leaflet.js"></script>
<script type="text/javascript" src="./map.js"></script>
</head>
<body>
<h1>WikiMap</h1>
<div id="mapContainer"></div>
<div id="infoContainer">
<div id="search">
<form id="searchForm">
<label>Keyword:</label>
<input type="text" id="keyword" name="keyword" placeholder="search by keyword"/>
<a id="submitSearch" href="#">search</a>
</form>
</div>
</div>
</body>
</html>
My Question (UPDATED): How do I get my keyword to change in the API URL Search Query based off of an AJAX Call (having a scope problem here) ?
I've finally figured that my layout is poor for accomplishing what I want to get done. Even if the keyword is updating, the map.on() load function is reverting everything back to the beginning. I've decided to use Backbone.js to help me organize my data flows.
var searchControl = L.esri.Geocoding.Controls.geosearch({
providers: [
new L.esri.Geocoding.Controls.Geosearch.Providers.MapService({
label: 'States and Counties',
url: 'http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer',
layers: [2, 3],
searchFields: ['NAME', 'STATE_NAME']
})
]
}).addTo(map);
I am using leaflet map search api by address but I find an autosuggestion searching api something that.