Multiple filters live video feed possible?

Hi all,

I’m trying to add two different filters to a video feed from a webcam. What I try to accomplish is an inverted, grayscale image to feed to multiple led strips. I also add a tint to make the strips a bit warmer.

The problem is though that I can’t seem to be able to add two filters at once. Either only the filter(GRAY) is working, or when I only have the filter(INVERT) in the code my video is flickering.

I have the following code at the end of the sketch:

void draw(){
        background(0);

if (video.available()) {
video.read();
}
video.filter(INVERT);
video.filter(GRAY);
tint(255, 200, 145);

image(video, 0, 0, width, height,);
}

I’m pretty new to Processing and programming in general, maybe it’s just a simple line of code I am missing.

I hope you all can help me out?

Thanks,

Nick

The flickering occurs, because you are inverting the image on every frame.
Your webcam does not give you a new image on every frame, so when “video.available()” is false, you are inverting the the image from the last frame. An easy solution should be to put the filter-code inside of your conditional:

  if (video.available()) {
    video.read();
    video.filter(INVERT);
    video.filter(GRAY);
  }

Hi Benja,

Thanks for your reply! I tried it and indeed the flickering stops. The only other problem I still have is that both filters don’t work together. It only does the invert now and not the greyscale, any idea how I fix that?

Again, thanks a lot!

Nick

In a simple test, INVERT and GRAY work fine together on a PImage. They also seem to work fine when added to the basic Video Library “Loop” example sketch, in the movieEvent. Can you give an example of this not working?

size(512,512);
PImage img;
img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Processing_3_logo.png/480px-Processing_3_logo.png");
image(img, 0, 0);
filter(GRAY);
filter(INVERT);

Hi Jeremy,

Sorry for the late reply, I was abroad for the week. Thanks for looking into it! It’s weird that I don’t seem to get it to work. My processing patch is:

import processing.video.*;
import gohai.glvideo.*;
GLCapture video;

float zoom = 2;

OPC opc;
GLCapture capture;
PImage cam;

void setup()
{
  size(40, 295, P2D);

  
 String[] devices = GLCapture.list();
  println("Devices:");
  printArray(devices);
  if (0 < devices.length) {
    String[] configs = GLCapture.configs(devices[0]);
    println("Configs:");
    printArray(configs);
  } 
  
   video = new GLCapture(this);

   video.start();
   


  opc = new OPC(this, "127.0.0.1", 7890);

  for(int i=0; i<8; i++) {
    opc.ledStrip(i * 59, 59, i * width / 8.0 + width / 16.0,
      height * 0.5, width / 8.0, PI * 0.5, false);
  }

}


void draw(){
    background(0);
    
  if (video.available()) {
    video.read();
        video.filter(GRAY);

  }

  tint(235, 150, 90);

  image(video, 0, 0, width, height);
 }

I took the INVERT filter out, but normally I put it right after the GRAY filter as you mentioned in your working example.

Maybe it has to do with the grabbing of the webcam feed?

Nick

Your approach seems too complicated a place to try to debug your problem – and the sketch you shared isn’t testable, because I don’t know what an OPC is.

Can you start with a cam or video example, filter it, and see what happens?

Here is one based on the GettingStartedCapture example:

import processing.video.*;
Capture cam;

void setup() {
  size(640, 480);
  String[] cameras = Capture.list();
  cam = new Capture(this, cameras[0]);
  cam.start();
}

void draw() {
  if (cam.available() == true) {
    cam.read();
    cam.loadPixels();
    cam.filter(GRAY);
    cam.filter(INVERT);
    cam.updatePixels();
  }
  image(cam, 0, 0, width, height);
}

and here is one based on the Loop example:

import processing.video.*;
Movie movie;

void setup() {
  size(560, 406);
  background(0);
  movie = new Movie(this, "launch2.mp4");
  movie.loop();
}

void draw() {
  if (movie.available() == true) {
    movie.read(); 
    movie.loadPixels();
    movie.filter(GRAY);
    movie.filter(INVERT);
    movie.updatePixels();
  }
  image(movie, 0, 0, width, height);
}

They seem to work fine. Using loadPixels and updatePixels may not be necessary, but are included just in case given your problem.

I was able to reproduce flickering on the Loop example if I added filtering to the function movieEvent(Movie m) rather than doing it in the draw() loop. Don’t modify the resulting pixels in the event helper function – that may be threaded / racing. Instead, modify pixels in the draw() loop as shown.

Capture_GRAY_INVERT--screenshot Loop_GRAY_INVERT--screenshot