mercoledì 2 aprile 2014

Depth Map di Kinect con PyOpenNi e Meshlab

Su richiesta di un amico, ho provato ad usare il Kinect per fare un modello 3D del viso
Il lavoro e' diviso in due parti. In fase di acquisizione vengono salvati i dati del sensore di distanza del Kinect ogni 5 secondi (il Kinect genera una mappa di 640x480 punti per ogni immagini ed i dati acquisiti da PyOpenNi sono espressi direttamente in millimetri)



Successivamente si lancia lo script di lettura.py come

python lettura.py > dati.asc

il file .asc viene poi utilizzato dal programma Meshlab (presenti anche repository di Ubuntu) per visualizzare la nuvola dei punti. (Nell'esempio sono stati i punti a distanza maggiore di 1 metro per selezionare solo i punti del volto) 


acquisisci.py
-----------------------------------------------
import time
import pickle
import numpy as np
import Image
import scipy


ctx = Context()
ctx.init()

# Create a depth generator
depth = DepthGenerator()
depth.create(ctx)

# Set it to VGA maps at 30 FPS
depth.set_resolution_preset(RES_VGA)
depth.fps = 30

# Start generating
ctx.start_generating_all()

contatore =1
while True:
    # Update to next frame
    nRetVal = ctx.wait_one_update_all(depth)

    depthMap = depth.map
    depthMap2 = np.array(depthMap)
    f = open("faccia"+str(contatore)+".txt","w+b")
    pickle.dump(depthMap2,f)
    f.close()

    print contatore

    contatore = contatore + 1
    time.sleep(5)
-----------------------------------------------
lettura.py
-----------------------------------------------
import pickle
import numpy

posizione = 0

f = open("faccia5.txt")
data = pickle.load(f)
f.close

for i in range(img.size[0]):
for j in range(img.size[1]):
print str(i)+","+str(j)+","+str(data[posizione]) 
posizione = posizione + 1


lunedì 31 marzo 2014

Copiare linee da file testo con Bash

Su richiesta di un amico, c'era la necessita' di estrarre solo le righe pari (o dispari) da un file testo puro usando Bash

il primo tentativo e' stato fatto con un ciclo for
--------------------------------------------
for i in `seq 1 2 10`;
do
   
    comando="sed -n "$i"p file1.txt >> file2.txt"
    eval $comando
done
---------------------------------------------

in realta' il comando sed ha gia' al suo interno questa possibilita', infatti lo switch p permette di indicare a quale riga iniziare a quante righe saltare. per esempio nell'esempio sottostante vengono salvate una riga si' ed una no partendo da 1
---------------------------------------------
sed -n 1~2p file1.txt >> file2.txt
---------------------------------------------

Geocompass per FirefoxOS


Questa applicazione e' un porting della precedente Geocompass per Android per FirefoxOS
A parte il linguaggio differente, il codice condivide larghe parte di righe che sono state semplicemente copiate complice una sintassi uguale tra Java e Javascript
Il programma e' stato scritto con l'aiuto di Cordova/Phonegap.
Per istruzioni si puo' consultare Wikipedia o questa pagina




L'applicazione puo' essere scaricata a questo link


index.html
----------------------------------------------------
<!DOCTYPE html>
<html>
  <head>
    <title>Geocompass</title>
<style>
    #content {
       width: 100px;
       height:100px;
       margin: 0px auto;
}
</style>

    <script type="text/javascript" charset="utf-8" src="./js/cordova.js"></script>
    <script type="text/javascript" charset="utf-8" src="./js/misura.js"></script>
  </head>

  <body onload="drawCanvas();">
  <div id="content">
    <canvas id="myCanvas"  width="256" height="256">Your browser doesn't support canvas tag</canvas>
</div>
 <p id="ang" style="text-align:center;font-family:arial;color:red;font-size:30px;"></p>
 <p  style="text-align:center;font-family:arial;color:red;font-size:30px;">Strike/Dip</p><center>
 <p><a style='text-align:center;font-family:arial;color:red;font-size:20px;' href='http://en.wikipedia.org/wiki/Strike_and_dip'>Help</a></p></center>
 <p style="text-align:center;font-family:arial;color:red;font-size:15px;">Contact : lucainnoc@gmail.com</p></center>
  </body>
</html>
----------------------------------------------------

misura.js
----------------------------------------------------
var surface;
     var misura; 
     var angle = 0;
var ang_maxpendenza = 0;
function drawCanvas() {
screen.mozLockOrientation("portrait-primary");
    surface = document.getElementById("myCanvas");
if (surface.getContext) {
misura = new Image();
misura.onload = loadingComplete;
misura.src = "./img/misura.png";
if (ang_maxpendenza < 10) 
{
misura.src = "./img/orizzontale.png";
}
if (ang_maxpendenza > 80) 
{
misura.src = "./img/verticale.png";
}
}
}

 function loadingComplete(e) {
     var surfaceContext = surface.getContext('2d');
     surfaceContext.fillStyle = "rgb(255,255,255)";
     surfaceContext.fillRect(0, 0, surface.width, surface.height);
     surfaceContext.save();
surfaceContext.translate(misura.width * 0.5, misura.height * 0.5);
if ((ang_maxpendenza > 10) && (ang_maxpendenza < 80))
{
surfaceContext.rotate(angle* 0.0174532925199432957);
}
surfaceContext.translate(-misura.width * 0.5, -misura.height * 0.5);
surfaceContext.drawImage(misura, 0, 0);
     surfaceContext.restore();
}

function converti2deg(angolo) {
return angolo*(180/Math.PI);
}
function converti2rad(angolo) {
return angolo*(Math.PI/180);
}

    
    window.addEventListener('deviceorientation', function(event) {
var azimuth = event.alpha;
    var pitch = event.beta;
    var roll = event.gamma;
pitch = converti2rad(pitch);
    roll = converti2rad(roll);
var cosalfa = Math.cos(roll-(Math.PI/2));
    var cosbeta = Math.cos(pitch-(Math.PI/2));
var dir_maxpendenza = -converti2deg(Math.atan(cosalfa/cosbeta));  
if ((pitch < 0) && (roll<=0)) dir_maxpendenza =  dir_maxpendenza + 180;
if ((pitch <= 0) && (roll>0)) dir_maxpendenza =  dir_maxpendenza + 180;

    if ((pitch > 0) && (roll>0)) dir_maxpendenza =  dir_maxpendenza + 360;
    if ((pitch == 0) && (roll>0)) dir_maxpendenza =  270;
    if ((pitch > 0) && (roll==0)) dir_maxpendenza =  0;

    ang_maxpendenza = 90-converti2deg(Math.acos(Math.sqrt((cosalfa*cosalfa)+(cosbeta*cosbeta))));
var dir_maxpendenza_reale = (azimuth+dir_maxpendenza)%360;

document.getElementById("ang").innerHTML = dir_maxpendenza_reale.toFixed(0)+"/"+ang_maxpendenza.toFixed(0);
if (ang_maxpendenza < 10) document.getElementById("ang").innerHTML = "Horizontal";
if (ang_maxpendenza > 80) document.getElementById("ang").innerHTML = "Vertical " + azimuth.toFixed(0) + "-" + (azimuth.toFixed(0)+180)%360;


angle = dir_maxpendenza;
drawCanvas()
}, false);
----------------------------------------------------

manifest.webapp
----------------------------------------------------
{
"name": "Geocompass",
  "description": "Compass for Geologists",
"launch_path":"/index.html",
"installs_allowed_from":["*"],
"version":"0.9.0","name":"Geocompass",
"orientation": "portrait-primary",
 "icons": {
    "256": "/img/icon-256.png",
    "128": "/img/icon-128.png",
"120": "/img/icon-120.png",
"90": "/img/icon-90.png",
"60": "/img/icon-60.png",
"32": "/img/icon-32.png"
  },
  "developer": {
    "name": "Luca Innocenti",
    "url": "http://debiaonoldcomputers.blogspot.com/"
  },
  "default_locale": "en"

}
----------------------------------------------------


giovedì 27 marzo 2014

Sviluppo e pubblicazione su Firefox OS

Dopo aver scritto la mia prima applicazione per Firefox Os, ho provato a pubblicarla sul Market di Firefox Os.

Di seguito viene descritto come sviluppare e pubblicare su questa piattaforma

Di fatto non esiste un SDK e tutte le operazioni di sviluppo si possono svolgere all'interno dell'emulatore di Firefox OS che si installa aprendo l'indirizzo

about:app-manager

nell'url di Firefox (versione 26 e successive)
Al primo avvio viene richiesto di installare l'emulatore e l'adb helper (per sviluppare direttamente sul telefono)


Nella finestra App si indica la posizione (directory) delle varie applicazioni in fase di sviluppo mentre nella finestra Dispositivo si puo' gestire il lancio e la chiusura dell'applicazione sia nell'emulatore che nel telefono fisico


In basso alla finestra Dispositivo si ha la modalita' di connessione (nel caso di utilizzo di telefono fisico per ottenere la connessione e' necessario confermare anche sul telefono)
Per ogni modifica si deve effettuare un Aggiorna sulla finestra App e poi lanciare l'applicazione da dispositivi

Una volta terminato il lavoro si crea un file .zip che contiene l'applicazione (compresa di immagini, javascript e file manifest secondo le specifiche di Firefox e si va sul Firefox MarketPlace (usando Firefox), ci si registra (utilizzando Mozilla Persona) e poi si sottomette l'applicazione come file .zip


A questo punto il sito effettua dei controlli  e si rieffettua la procedura fino a quando non ci sono errori
(Non e' richiesto nessun pagamento, a differenza di Google dove e' forfettario o Apple dove e' annuale)

Si risponde ad una serie di domande (alcune anche curiose del tipo se l'applicazione fa propaganda nazista???)

E si attende pazientemente che l'applicazione sia approvata (e' un procedimento piuttosto lento al confronto di Play Store)




mercoledì 26 marzo 2014

Android Wear

Dopo aver modificato il telefono per avere un dispositivo ad Android 4.4, ho provato Android Wear, la versione per i futuri Smart Watch di Google.

Al momento e' disponibile solo una developer preview (per cui bisogna essere registrati) all'interno dell'emulatore

Sul telefono si installa l'applicazione Android Wear Preview App mentre dall'Android SDK Manager si deve scaricare Android Wear ARM EABI v7a System Image.


e si crea una nuova macchina virtuale AVD basata sull'immagine di Android Wear

A questo punto si esegue l'emulatore, si connette il telefono via USB e si attiva l'applicazione sul telefono.
Al computer si digita quindi il comando

adb -d forward tcp:5601 tcp:5601

l'applicazione sul telefono mostra lo stato di connessione e l'icona sull'emulatore mostra lo stato di connessione.
Per generare quindi una notifica ho effettuato una telefonata al cellulare e sul display dello Smart  Watch e' comparsa la notizia

Di fatto il sistema reagisce sostanzialmente alle notifiche che gli  derivano dal telefono a cui e' accoppiato.
Non e' necessario che le notifiche siano di sistema. Si puo' creare una applicazione che generi notifiche e queste vengono instradate verso lo smartwatch


Per esempio il codice sottostante genera una piccola applicazione che lancia una notifica all'avvio (codice modificato dal post originale, da notare che il codice originale non era stato concepito per Android Wear a dimostrazione di come si possa importare semplicemente codice relativo ad altre API)
Per compilare il codice e' necessario inserire tra le librerie wereable-preview-support.jar tra le Referenced Libraries
-----------------------------------------------------------------------------
package com.wear.orologio;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;


public class MainActivity extends Activity {

NotificationManager notificationManager;
Notification myNotification;
private static final int MY_NOTIFICATION_ID=1;
private final String myBlog = "http://www.google.com/";



@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Context context = getApplicationContext();
   Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(myBlog));
   PendingIntent pendingIntent = PendingIntent.getActivity(
     MainActivity.this, 
     0, 
     myIntent, 
     Intent.FLAG_ACTIVITY_NEW_TASK);
     
   myNotification = new Notification.Builder(context)
         .setContentTitle("Notifica")
         .setContentText("Dal Luca Innocenti")
         .setTicker("Notifica")
         .setWhen(System.currentTimeMillis())
         .setContentIntent(pendingIntent)
         .setDefaults(Notification.DEFAULT_SOUND)
         .setAutoCancel(true)
         .setSmallIcon(R.drawable.ic_launcher)
         .build();
   
   notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
   notificationManager.notify(MY_NOTIFICATION_ID, myNotification);


    }

}

-----------------------------------------------------------------------------
Ma Android Wear sara' solo notifiche???
Non sembra in quanto sull'emulatore dello Smart Watch funziona tranquillamente Hello World per cui il dispositivo sembra avere una propria autonomia dal telefono








Cyanogenmod 11 KitKat su Nexus S

Volevo provare ad usare Android Wear ma e' necessario avere un telefono con almeno Android 4.3 (non e' contemplato l'uso di tablet come il Nexus 7 2012) per cui ho deciso di modificare il Nexus S (rimasto fermo ad Android 4.1) per installare la Cyanogenmod 11 Android KitKat 4.4



La procedura prevede di scarica l'immagine Cyanogenmod da questo link e si carica il file cm-11-20131122-UNOFFICIAL-crespo.zip sulla memoria del telefono

Per poter installare il file e' necessario utilizzare la CWM Recovery da questo link ed in particolare il file recovery-clockwork-6.0.4.3-crespo.img (ho provato con la recovery gia' installata ma non ha funzionato)

per installare la CWM si collega il telefono, lo si accende con la combinazione Power + Vol Su e da shell si digita

fastboot flash recovery recovery-clockwork-6.0.4.3-crespo.img

a questo punto si rispenge e si riaccende il telefono sempre con la combinazione Power + Vol Su e si seleziona l'opzione Recovery (Vol Su e Vol Giu'per spostarsi, Power per selezionare), si effettua il wipe dei dati e si installa da zip file cm-11-20131122-UNOFFICIAL-crespo.zip

Le applicazioni Gooogle si scaricano da questo link e si installano con procedura simile (install from zip file)



Alla fine il telefono si riavvia con Android 4.4. E' forse un filino piu' lento della versione 4.1 ma e' assolutamente usabile (unico appunto e' che la tastiera di Unlock del pin della Sim card e' schiacciata ed i tasti non sono cosi' comodi da selezionare)

Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...