<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: wangzc</title>
    <description>The latest articles on DEV Community by wangzc (@wangzc).</description>
    <link>https://dev.to/wangzc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F630479%2F1ef23560-d4be-490e-9f2f-ba1d769d0030.png</url>
      <title>DEV Community: wangzc</title>
      <link>https://dev.to/wangzc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wangzc"/>
    <language>en</language>
    <item>
      <title>【You don't know about canvas】Replace the green screen video background</title>
      <dc:creator>wangzc</dc:creator>
      <pubDate>Thu, 13 May 2021 08:21:13 +0000</pubDate>
      <link>https://dev.to/wangzc/you-don-t-know-about-canvas-replace-the-green-screen-video-background-2ld7</link>
      <guid>https://dev.to/wangzc/you-don-t-know-about-canvas-replace-the-green-screen-video-background-2ld7</guid>
      <description>&lt;h1&gt;
  
  
  canvas Api Brief introduction
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/zh-CN/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content" rel="noopener noreferrer"&gt;Video_and_audio_content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas" rel="noopener noreferrer"&gt;ImageData&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;ImageData&lt;/code&gt; object represents the underlying pixel data of an area of a canvas object. It contains the following read-only attributes:：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;width&lt;/code&gt;：The width of the image in pixels.&lt;br&gt;
&lt;code&gt;height&lt;/code&gt;：The height of the image in pixels.&lt;br&gt;
&lt;code&gt;data&lt;/code&gt;：A &lt;a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray" rel="noopener noreferrer"&gt;Uint8ClampedArray&lt;/a&gt;representing a one-dimensional array containing the data in the RGBA order, with integer values between 0 and 255 (included).&lt;/p&gt;

&lt;p&gt;The data property returns a&lt;code&gt;Uint8ClampedArray&lt;/code&gt; which can be accessed to look at the raw pixel data; each pixel is represented by four one-byte values (red, green, blue, and alpha, in that order; that is, "RGBA" format). Each color component is represented by an integer between 0 and 255. Each component is assigned a consecutive index within the array, with the top left pixel's red component being at index 0 within the array. Pixels then proceed from left to right, then downward, throughout the array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short, we need to group every four pixels to get the &lt;code&gt;rgba&lt;/code&gt; value of each pixel&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then we combine the features of 'Canvas' to operate the video to make green screen matting and change the background&lt;/p&gt;

&lt;p&gt;First, the renderings：&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2m81hcclpwbq7x8q3gzt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2m81hcclpwbq7x8q3gzt.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code address&lt;/strong&gt;：&lt;a href="https://github.com/wzc570738205/canvas-viideo" rel="noopener noreferrer"&gt;canvas-viideo&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;preview address&lt;/strong&gt;：&lt;a href="https://wzc570738205.github.io/canvas-viideo/" rel="noopener noreferrer"&gt;githubPage&lt;/a&gt;、&lt;a href="https://static-8e76dff9-ce38-4577-9e5c-398943705060.bspapp.com/" rel="noopener noreferrer"&gt;阿里云&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Realization idea&lt;br&gt;
&lt;strong&gt;&lt;code&gt;Video '= = &amp;gt;'video screenshot' = = &amp;gt;'process green pixels as transparent '= = &amp;gt;'map to the top of the background image&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Take a screenshot of the video, and then make the green pixel block transparent&lt;br&gt;
Then put the processed image above the prepared background image&lt;/p&gt;
&lt;h1&gt;
  
  
  Implementation
&lt;/h1&gt;
&lt;h3&gt;
  
  
  1. Prepare videos and canvases
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body onload="processor.doLoad()"&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;video id="video" src="./q.mp4" width="350" controls="true"&amp;gt;&amp;lt;/video&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;!-- Video capture --&amp;gt;
      &amp;lt;canvas id="c1" width="260" height="190"&amp;gt;&amp;lt;/canvas&amp;gt;
      &amp;lt;!-- Processing green pixels as transparent --&amp;gt;
      &amp;lt;canvas id="c2" width="260" height="190"&amp;gt;&amp;lt;/canvas&amp;gt;
      &amp;lt;!-- Map to top of background map --&amp;gt;
      &amp;lt;canvas id="c3" width="260" height="190"&amp;gt;&amp;lt;/canvas&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2.Add video playback monitor
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;doLoad: function doLoad() {
  this.video = document.getElementById("video");
  this.c1 = document.getElementById("c1");
  this.ctx1 = this.c1.getContext("2d");
  this.c2 = document.getElementById("c2");
  this.ctx2 = this.c2.getContext("2d");
  this.c3 = document.getElementById("c3");
  this.ctx3 = this.c3.getContext("2d");
  let self = this;
  this.video.addEventListener(
    "play",
    function() {
      self.width = self.video.videoWidth / 5;
      self.height = self.video.videoHeight / 3;
      self.timerCallback();
    },
    false
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3.Add timer
&lt;/h3&gt;

&lt;p&gt;Call after video playback, and capture screenshot of each frame&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;timerCallback: function timerCallback() {
  if (this.video.paused || this.video.ended) {
    return;
  }
  this.computeFrame();
  let self = this;
  setTimeout(function () {
    self.timerCallback();
  }, 0);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4.Video frame operation
&lt;/h3&gt;

&lt;p&gt;Set the green background to transparent and map it to the custom background image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;computeFrame: function computeFrame() {
  this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
  let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
  let l = frame.data.length / 4;

  for (let i = 0; i &amp;lt; l; i++) {
    let r = frame.data[i * 4 + 0];
    let g = frame.data[i * 4 + 1];
    let b = frame.data[i * 4 + 2];
    //rgb(8 204 4)
    if (r &amp;gt; 4 &amp;amp;&amp;amp; g &amp;gt; 100 &amp;amp;&amp;amp; b &amp;lt; 100) {
      frame.data[i * 4 + 3] = 0;
    }
  }
  this.ctx2.putImageData(frame, 0, 0);
  this.ctx3.putImageData(frame, 0, 0);
  return;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5.Fine tuning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    //rgb(8 204 4)
    The green video color is not pure, not always RGB (82004), so a simple fine-tuning has been made..
    if (r &amp;gt; 4 &amp;amp;&amp;amp; g &amp;gt; 100 &amp;amp;&amp;amp; b &amp;lt; 100) {
      frame.data[i * 4 + 3] = 0;
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  END
&lt;/h1&gt;

&lt;p&gt;Thank you for reading&lt;br&gt;
My English is not good. I want to share this good technology with you，This is my Chinese blog address:&lt;a href="https://segmentfault.com/a/1190000039975476" rel="noopener noreferrer"&gt;segmentfault&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code address：&lt;a href="https://github.com/wzc570738205/canvas-viideo" rel="noopener noreferrer"&gt;canvas-viideo&lt;/a&gt;&lt;br&gt;
preview addrss：&lt;a href="https://static-8e76dff9-ce38-4577-9e5c-398943705060.bspapp.com/" rel="noopener noreferrer"&gt;阿里云&lt;/a&gt;、&lt;a href="https://wzc570738205.github.io/canvas-viideo/" rel="noopener noreferrer"&gt;githubPage&lt;/a&gt;&lt;br&gt;
green video download：&lt;a href="https://pixabay.com/zh/videos/search/green%20screen/" rel="noopener noreferrer"&gt;pixabay&lt;/a&gt;&lt;/p&gt;

</description>
      <category>html</category>
      <category>canvas</category>
      <category>javascript</category>
      <category>css</category>
    </item>
  </channel>
</rss>
