How can I let my face grow?

edited December 2016 in Kinect

I am doing a project about obesitas.

I am using my webcam, then I used the face tracker. I copied my face into a rectangle. What I want is my face (rectangle) is getting bigger and bigger within 2/3 minutes.

I hope somebody can help me with that! :)

Below is my code:

import gab.opencv.*;
import processing.video.*;
import java.awt.*;

Capture video;
OpenCV opencv;
PImage cam;

void setup() {
  size(640, 480);
  video = new Capture(this, 640/2, 480/2);
  opencv = new OpenCV(this, 640/2, 480/2);
  opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);  

  video.start();
}

void draw() {
  scale(2);
  opencv.loadImage(video);

  image(video, 0, 0 );

  noFill();
  stroke(0, 255, 0);
  strokeWeight(3);
  Rectangle[] faces = opencv.detect();
  println(faces.length);


  for (int i = 0; i < faces.length; i++) {
    println(faces[i].x + "," + faces[i].y);
    //rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
    copy(cam, faces[i].x, faces[i].y, faces[i].width, faces[i].height, faces[i].x - faces[i].width/2, faces[i].y, faces[i].width * 2,             
faces[i].height);
  }
}

void captureEvent(Capture c) {
  c.read();
  cam = c.get();
}

Answers

  • Answer ✓

    Look at scale

  • edited December 2016 Answer ✓

    @Adinda123 -- Are you trying to zoom or stretch? Or are you trying to create a fisheye lens effect?

    1. scale(), as @Chrisir said
    2. image() -- it optionally takes a width and height argument, so you can change image(video, 0, 0 ); to accept a changing value "bigger", e.g. image(video, 0, 0, width+bigger, height+bigger);
  • Answer ✓

    @Adinda123

    Interesting project. Here is a working code, an one way to do it. You have the following parameters to play with:

    obesaLowerLimit Starting proportion
    obesaUpperLimit Final proportion
    timeRange Time it takes to go from low to high proportion

    You challenge asked for two minutes. You can change timeRange to 20 seconds to see a faster effect. Setup back to 120 to see the real 2 min effect.

    Now I understand why you only want to change the width and not the height. Very clever effect. I agree with @jeremydouglass: in a more realistic effect you want to simulate a fisheye effect. It is probably doable with shaders (just my guess... not much experience there). However this algorithm is a nice trick as well.

    Kf

    import gab.opencv.*;
    import processing.video.*;
    import java.awt.*;
    
    Capture video;
    OpenCV opencv;
    PImage cam;
    PImage fc;
    
    final float obesaLowerLimit=1.0;    
    final float obesaUpperLimit=2.0;
    float obesaPar;
    float orate;
    
    final int timeRange=120;  // 120 seconds or 2 min.
    
    
    void setup() {
      size(640, 480); 
      video = new Capture(this, 640, 480);
      opencv = new OpenCV(this, 640, 480);
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);  
    
      video.start();
      orate=lerp(0, obesaUpperLimit-obesaLowerLimit, 1.0/timeRange);  //Set rate in such way that in two minutes, the proportion goes from 1 to 2 in even steps
      obesaPar=obesaLowerLimit;  //Initialize value
      //timeLimit=millis()+timeRange;  //Initialize 
      println("obesa " + orate);
    }
    
    void draw() {
      //scale(2);
      opencv.loadImage(video);
    
      image(video, 0, 0);
    
      noFill();
      stroke(0, 255, 0);
      strokeWeight(3);
      Rectangle[] faces = opencv.detect();
      //println(faces.length);
    
    
      for (int i = 0; i < faces.length; i++) {
        //println(faces[i].x + "," + faces[i].y);
        int x=faces[i].x;
        int y=faces[i].y;
        int w=faces[i].width;
        int h=faces[i].height;
        int xoffset=w/2-round(w/1.0*obesaPar)/2;
        int yoffset=h/2-round(h/1.0*obesaPar)/2;
    
        //EITHER of the next two lines work. The first line only affects the img's width. Second line affects both width and height
        copy(cam, x, y, w, h, x+xoffset, y, round(w/1.0*obesaPar), h);
        //copy(cam, x, y, w, h, x+xoffset, y+yoffset, round(w/1.0*obesaPar), round(h/1.0*obesaPar));
    
      }
    
      obesaPar+=orate;
      //Next reset proportion parameter if reaches limit
      if (obesaPar>obesaUpperLimit)
        obesaPar=obesaLowerLimit;
      // println(orate+" obesa " + obesaPar);  //DEBUGGING purposes
    }
    
    void captureEvent(Capture c) {
      c.read();
      cam = c.get();
    }
    
  • You could probably recreate fish eye effect with pixel handling in code, but it will be way slower because the code will run on CPU and not GPU.

  • You can use shaders for fast pixel processing effects like lens distortion. I haven't written shaders and they are complex -- but @quark wrote a demo fisheye lens shader recently:

    https://forum.processing.org/two/discussion/14788/fisheye-lens-shader

    For beginners, however, writing your own shader is definitely not recommended.

  • Answer ✓

    You could probably recreate fish eye effect with pixel handling in code, but it will be way slower because the code will run on CPU and not GPU.

    Actually I have a version of the fish eye shader in using straight pixel manipulation code and it is more than fast enough. :) It can also be used to create a magnifying lens (no fish-eye distortion) by simply changing a variable.

    Here is the code and the image you may find it useful.

    /**
    This sketch demonstrates how to implement a fishey lens effect.
    
    If you set k = 0 then you have a simple magnifying lens.
    
    */
    
    PImage imgOrg;
    
    // Lens properties
    int lsize = 90, lsize2 = lsize * lsize;
    float mag = 2.0f;
    float k = -0.00016f;
    
    int offX, offY;
    int border, borderViaLens;
    
    public void setup() {
      size(580, 404);
      cursor(CROSS);
      imgOrg = loadImage("london.jpg");
      // Calculate image offsets reqd to centre image
      offX = (width - imgOrg.width)/2;
      offY = (height - imgOrg.height)/2;
      // border colours
      border = color(200);
      borderViaLens = color(180);
    }
    
    public void draw() {
      background(200);
      image(imgOrg, offX, offY);
      showLens(mouseX, mouseY);
    }
    
    public void showLens(int x, int y) {
      int u, v, r2;
      float f;
      for (int vd = - lsize; vd < lsize; vd++) {
        for (int ud = - lsize; ud < lsize; ud++) {
          r2 = ud*ud + vd*vd;
          if (r2 <= lsize2) {
            f = mag + k * r2;
            u = floor(ud/f) + x - offX;
            v = floor(vd/f) + y - offY;
            if (u >= 0 && u < imgOrg.width && v >=0 && v < imgOrg.height)
              set(ud + x, vd + y, imgOrg.get(u, v));
            else 
              set(ud + x, vd + y, borderViaLens);
          }
        }
      }
    }
    

    london

  • I can't check now, but I get the feeling it will be slower than 60fps on my low-end laptop.

  • I am managing 390-400 fps with JAVA2D and 300-320 fps with P2D so I would be interested to know what you get.

  • edited December 2016

    Beautiful, @quark -- and so smooth! Thanks for sharing this.

    After adding a text() to display the frameRate I got ~270fps on a late 2015 iMac 1.6 GHz Intel Core i5 w/16GB RAM.

    Screen Shot 2016-12-02 at 4.37.40 PM

  • @quark

    Which one would perform better? In your opinion, which one to go for, using shaders or straight pixel manipulation?

    For these two codes, did you just use the same concept? How did you figure out the magnifying algorithm for the showLens() function? Just from mapping or using some Physics concepts?

    How do you get fps values > 60? I tried and it tops in 60 in my machine... :-??

    Kf

  • edited December 2016

    I've managed to tweak @quark's original sketch from ~120 FPS to ~150 FPS here: $-)

    /**
     * FishEye Effect (v2.0.2)
     * Quark (2016-Dec-02)
     * Mod GoToLoop (2016-Dec-03)
     * forum.Processing.org/two/discussion/19452/how-can-i-let-my-face-grow#Item_11
     */
    
    static final int DIAM = 90, DIAM_SQ = DIAM*DIAM, OFF = 50;
    static final float MAG = 2, K = -.00016, FPS = -1;
    static final color BORDER = 200, LENS = 180;
    static final String FILENAME = "london.jpg", RENDERER = JAVA2D;
    
    PImage img;
    int offX, offY;
    
    void settings() {
      img = loadImage(FILENAME);
      size(img.width + OFF, img.height + OFF, RENDERER);
      smooth(3);
    }
    
    void setup() {
      frameRate(FPS);
      cursor(CROSS);
      offX = width  - img.width  >> 1;
      offY = height - img.height >> 1;
    }
    
    void draw() {
      background(BORDER);
      set(offX, offY, img);
      fishLens(getGraphics(), img, mouseX, mouseY, offX, offY);
      getSurface().setTitle("FPS: " + round(frameRate));
    }
    
    static void fishLens(PImage pg, PImage im, int x, int y, int xoff, int yoff) {
      final int w = im.width, h = im.height;
      final int xo = x - xoff, yo = y - yoff;
    
      for (int vd = -DIAM; vd < DIAM; ++vd)  for (int ud = -DIAM; ud < DIAM; ++ud) {
        final int r = ud*ud + vd*vd;
        if (r > DIAM_SQ)  continue;
    
        final float f = r*K + MAG;
        final int u = round(ud/f) + xo;
        final int v = round(vd/f) + yo;
    
        final boolean within = u>=0 & u<w & v>=0 & v<h;
        pg.set(ud + x, vd + y, within? im.get(u, v) : LENS);
      }
    }
    
  • @kfrajer --

    How do you get fps values > 60? I tried and it tops in 60 in my machine

    frameRate() defaults to 60 if you do not set it. It is common to use frameRate(1) etc. for certain slow refresh effects, but try setting frameRate(300) in setup().

    Your milage may very based on how fast your machine is and how much work your sketch draw loop is!

  • @kfrajer The pixel-array-manipulation version was the first one, the shader-version was my first (and last) attempt at using shaders came later. Starting with physical concepts would almost certainly end up with a program using the atan2() trigonometric function which I wanted to avoid. The solution uses a mapping approach where data in a larger circle is mapped into a smaller circle (the lens) based on the amount of magnification (variable m) and the level of distortion (variable k). Setting k to zero means there is no distortion a straight magnification which might be used to enlarge the face. Small negative values give you the fisheye effect and small positive values a concave view.

  • @kfrajer And also remember that to get >60fps in reality you need a screen capable of more than 60fps refresh rate. Most low-end screens have a refresh rate of max 60fps(like my laptop screen), though there are many with good refresh rates like 120hz, 144hz(like my tv), 240hz(rare) and maybe even more.
    Another side note, the CPU+GPU on your system must be capable of doing that high fps.

  • @jeremydouglass and @quark how do you get such high fps?? Can you please tell the specs of your computer(include everything you know) and screen?

  • I have a 6 year old iMac 27" (2560x1440 LCD display) with Intel Core i7 2.93Ghz processor and 8GB RAM. The graphics card is an ATI Radeon HD 5750 with 1GB VRAM.

  • How come it runs at >60fps? Does that mean that the screen doesn't refresh at the speed of the graphics render? Or is it on some sort of off-screen graphics renderer?

  • THANK YOU ALL!!!!

  • ALSO LIKE THE FISHEYE!!!!

  • edited December 2016

    @Adinda123 good luck!

    @Lord_of_the_Galaxy -- your screen refreshes based on the Hz in your display settings (and/or the fixed rate of your laptop LCD screen, eg 60 fps). So having a Processing frame rate of 200 doesn't mean your actual screen is updating that fast. It just means that the sketch draw() is updating the pixels that fast. If you had a faster screen refresh rate -- say 120 --the sketch could keep up.

  • @quark Thanks for your explanation. Very interesting stuff.

    @jeremydouglass and @Lord_of_the_Galaxy , thxs for your comments.

    So using straight pix manipulation I get btw 460 and 560 fps.
    Using the shader example, I get about ~1200 even with a frameRate(600) in setup. Using GoTo I get from 500 to 700 or even 800. I notice he sets the frameRate to -1. Is that the way to tell that there is no limit?

    Kf

  • @jeremydouglass I realised that anyways. Thanks still.
    Even considering that, and the fact that Processing has an inbuilt default limit of 60fps, I've never got an fps of greater than 60. Why is that?

  • @kfrajer How did you get 1200fps with frameRate(600)? Is that even possibles? Or is it a bug?

  • @Lord_of_the_Galaxy

    I have no idea, I was just experimenting with the frameRate() :(|)

    Kf

  • Getting 1200 when your limit is 600 sounds like a bug that might need to be reported...? If you set 60 and check you sometimes get 61-65, I believe, but not 120.

    I'm not really sure what the point would be of having Processing output above 600Hz -- even if it weren't beyond the physical capacity of commercially available screens, (I believe) most scientists believe that humans are incapable of perceiving changes at rates anywhere near that high.

    https://en.m.wikipedia.org/wiki/Refresh_rate

  • In fact, AFAIK, this is done to test the performance of the computer - higher refresh rates = better performance.

Sign In or Register to comment.