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

1 Like

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);
  }
2 Likes

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);
1 Like

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

1 Like

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