Filtre vidéo (luminosité+netteté) par captation ultrason / Processing + Arduino


Application d'un filtre de netteté et de luminosité sur une vidéo en fonction de la distance entre un visiteur et un capteur ultrason géré par une carte Arduino;
- Le programme de la carte Arduino est destiné à un capteur SRF05. Il est à charger sur la carte avant d'utiliser Processing. Il est disponible dans le dossier // arduinoCapteurUltrason;
- La vidéo est nommée "myVid01.avi" et doit être stockée dans le dossier //data situé à la racine du fichier Processing;

Sources: filtreMovieSonarDetection.pde / Processing 3.0.1

/*  - filtreMovieSonarDetection.pde - processing 3.0.1 - transat@stephanecabee.net
    - DataArt - filtrage (netteté et luminosité) d'une vidéo en fonction de la 
    distance renvoyé par une carte arduido muni d'un capteur ultrason.
    - Programme arduino disponible dans le dossier //arduinoCapteurUltrason
*/

import processing.serial.*;
import processing.video.*;

//Initialisation des variables d'échange entre l'Arduino et Processing
Serial serialPort;
String serialData;
int sonarData;

//Initialisation des variables de gestion de la vidéo
Movie myMovie;
String mName = "myVid01.avi";
float mDuration;
int mBlur;
int mBrightness;
PImage imgBlur;

void setup()
{
  frameRate(25);
  size(720,596, P2D);
  //fullScreen();
  
  //Listing des port série disponible et initialisation du port série
  println(Serial.list());
  String portName = Serial.list()[0];
  serialPort = new Serial(this, portName, 9600);
  
  //Initialisation de la vidéo
  myMovie = new Movie(this, mName);
  myMovie.loop();
  myMovie.volume(5);
  mDuration = myMovie.duration();
  println("mDuration: " + mDuration);
  imgBlur = new PImage(width, height);
}

void draw()
{
  //Ecoute du port série
  if ( serialPort.available() > 0) {
    serialData = serialPort.readStringUntil('\n');
    if(serialData != null){
      try {
        //Stockage des données du capteur Ultrason
        sonarData=Integer.parseInt(serialData.trim());
        println("Distance: " + sonarData);
      } catch (NumberFormatException npe){
       // Non entier
      }
    }else{
      sonarData = 0;
    }
  }
  
  //Définition des filtres vidéos en fonction des données du sonar
  mBlur = int(map(sonarData, 0, 300, 10, 1));
  mBrightness = int(map(sonarData, 0, 300, 5, 1));
  
  //Application des filtres à la vidéo
  imgBlur.copy(myMovie, 0, 0, myMovie.width, myMovie.height, 0, 0, myMovie.width, myMovie.height);
  fastblur(imgBlur, mBlur);
  fastBrightness(imgBlur, mBrightness);
  
  //Dessin de la vidéo
  image(imgBlur, 0, 0);
}

void movieEvent(Movie m) {
  m.read();
}

//Fonction de luminosité
void fastBrightness(PImage img, int radius){
  if (radius<1){
    return;
  }
  img.loadPixels();
  for (int x = 0; x < img.width; x++) {
    for (int y = 0; y < img.height; y++ ) {
      int loc = x + y*img.width;
      float r = red   (img.pixels[loc]);
      float g = green (img.pixels[loc]);
      float b = blue  (img.pixels[loc]);
      float adjustBrightness = radius;
      /**/r *= adjustBrightness;
      g *= adjustBrightness;
      b *= adjustBrightness;
      r = constrain(r,0,255);
      g = constrain(g,0,255);
      b = constrain(b,0,255);
      //println(r + ", " + g + ", " + b);
      color c = color(r,g,b);
      img.pixels[loc] = c;
    }
  }
  img.updatePixels();
}

//Function de flou: Super Fast Blur v1.1 by Mario Klingemann http://incubator.quasimondo.com
void fastblur(PImage img,int radius)
{
 if (radius<1){
    return;
  }
  int w=img.width;
  int h=img.height;
  int wm=w-1;
  int hm=h-1;
  int wh=w*h;
  int div=radius+radius+1;
  int r[]=new int[wh];
  int g[]=new int[wh];
  int b[]=new int[wh];
  int rsum,gsum,bsum,x,y,i,p,p1,p2,yp,yi,yw;
  int vmin[] = new int[max(w,h)];
  int vmax[] = new int[max(w,h)];
  int[] pix=img.pixels;
  int dv[]=new int[256*div];
  for (i=0;i<256*div;i++){
    dv[i]=(i/div);
  }
 
  yw=yi=0;
 
  for (y=0;y<h;y++){
    rsum=gsum=bsum=0;
    for(i=-radius;i<=radius;i++){
      p=pix[yi+min(wm,max(i,0))];
      rsum+=(p & 0xff0000)>>16;
      gsum+=(p & 0x00ff00)>>8;
      bsum+= p & 0x0000ff;
    }
    for (x=0;x<w;x++){
 
      r[yi]=dv[rsum];
      g[yi]=dv[gsum];
      b[yi]=dv[bsum];
 
      if(y==0){
        vmin[x]=min(x+radius+1,wm);
        vmax[x]=max(x-radius,0);
      }
      p1=pix[yw+vmin[x]];
      p2=pix[yw+vmax[x]];
 
      rsum+=((p1 & 0xff0000)-(p2 & 0xff0000))>>16;
      gsum+=((p1 & 0x00ff00)-(p2 & 0x00ff00))>>8;
      bsum+= (p1 & 0x0000ff)-(p2 & 0x0000ff);
      yi++;
    }
    yw+=w;
  }
 
  for (x=0;x<w;x++){
    rsum=gsum=bsum=0;
    yp=-radius*w;
    for(i=-radius;i<=radius;i++){
      yi=max(0,yp)+x;
      rsum+=r[yi];
      gsum+=g[yi];
      bsum+=b[yi];
      yp+=w;
    }
    yi=x;
    for (y=0;y<h;y++){
      pix[yi]=0xff000000 | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum];
      if(x==0){
        vmin[y]=min(y+radius+1,hm)*w;
        vmax[y]=max(y-radius,0)*w;
      }
      p1=x+vmin[y];
      p2=x+vmax[y];
 
      rsum+=r[p1]-r[p2];
      gsum+=g[p1]-g[p2];
      bsum+=b[p1]-b[p2];
 
      yi+=w;
    }
  }
}