0

Is there a solution to stream a video ( live webcam ) in black and white continuously using javascript,

I want to test every single pixel if the average of rgb [(red + green + blue)/3] is higher than x turn it to white ( 255 ) else turn it to black ( 0 )

I've found this code but it only shows one frame and then crashes, it can not stream with no stop,

const videoElement = document.getElementById('videoElement');

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

// Function to process each frame
function processFrame() {
  // Set canvas dimensions to match the video element

  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;

  // Draw the current frame of the video onto the canvas
  ctx.drawImage(videoElement, 0, 0);

  // Get the image data of the current frame
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;

  // Iterate over each pixel in the image data
  for (let i = 0; i < data.length; i += 4) {
    // Extract RGB values of the pixel

    const red = data[i];
    const green = data[i + 1];
    const blue = data[i + 2];

    // Calculate the average brightness of the pixel

    const brightness = (red + green + blue) / 3;

    // Define the threshold value
    const threshold = 120; // Adjust this value as needed

    // Compare the brightness with the threshold
    if (brightness > threshold) {

      // Turn the pixel to white
      data[i] = 255; // Red
      data[i + 1] = 255; // Green
      data[i + 2] = 255; // Blue
    } else {
      data[i] = 0; // Red
      data[i + 1] = 0; // Green
      data[i + 2] = 0; // Blue   
    }
  }

  // Put the modified image data back onto the canvas

  ctx.putImageData(imageData, 0, 0);

  // Draw the modified canvas onto the video element

  videoElement.srcObject = canvas.captureStream();

  // Call the processFrame function recursively to continuously process frames

  requestAnimationFrame(processFrame);
}


videoElement.addEventListener('play', processFrame);
mplungjan
  • 169,008
  • 28
  • 173
  • 236

2 Answers2

1

Perhaps shorten the code that is looping and move static values outside the function

const videoElement = document.getElementById('videoElement');

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const w = canvas.width = videoElement.videoWidth;
const h = canvas.height = videoElement.videoHeight;
const threshold = 120;

// Function to process each frame
function processFrame() {
  // Draw the current frame of the video onto the canvas
  ctx.drawImage(videoElement, 0, 0);

  // Get the image data of the current frame
  const imageData = ctx.getImageData(0, 0, w, h);
  const data = imageData.data;

  for (let i = 0; i < data.length; i += 4) {
    const brightness = (data[i] + data[i + 1] + data[i + 2]) / 3;
    const color = brightness > threshold ? 255 : 0;
    data[i] = data[i + 1] = data[i + 2] = color;
  }

  // Put the modified image data back onto the canvas

  ctx.putImageData(imageData, 0, 0); 

  // Draw the modified canvas onto the video element

  videoElement.srcObject = canvas.captureStream();

  // Call the processFrame function recursively to continuously process frames

  requestAnimationFrame(processFrame); // or look into webworkers/webGL
}

videoElement.addEventListener('play', processFrame);
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • Hello, does not change anything, in consol mode i get this error : Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0. at processFrame (http://127.0.0.1:8044/dashboard/:360:31) – mohammed yazid Berrached Jul 19 '23 at 15:58
  • @mohammedyazidBerrached Does it work if you move `videoElement.srcObject = canvas.captureStream();` to become outside of the function? Also you might need `videoElement.play()` to start displaying the received pixels from Canvas... – VC.One Jul 19 '23 at 17:27
-1

First, you should make sure that the videoElement has the correct id assigned to it in your HTML code. It should match the getElementById parameter in your JavaScript code.

Second, to prevent the code from crashing and running continuously without stopping, you need to add a condition to stop the processing when the video stops. You can do this by modifying the processFrame function