title: Smooth foreground extraction
body: <p>I am trying to do smooth foreground extraction couple of days.I tried many things but nothing seems to work ;( ;(</p>
  
  <p>I just want smooth human body extraction just like this:<a href="https://www.youtube.com/watch?v=rGMqXBvYxog" rel="nofollow noreferrer">https://www.youtube.com/watch?v=rGMqXBvYxog</a></p>
  
  <p>1-)I use Morphological Transformations and BackgroundSubstraction to do this.
  <a href="https://docs.opencv.org/3.4.0/d9/d61/tutorial_py_morphological_ops.html" rel="nofollow noreferrer">Documentation</a> says 
  "Opening for removing background noise and closing image for closing small holes inside the foreground objects" But It didn't work  ;(</p>
  
  <p>Without Closing and Opening : <a href="https://streamable.com/xh368" rel="nofollow noreferrer">https://streamable.com/xh368</a></p>
  
  <p>With Closing and Opening : <a href="https://streamable.com/bixmm" rel="nofollow noreferrer">https://streamable.com/bixmm</a></p>
  
  <p>Closing and Opening Javascript Code : </p>
  
  <pre><code>let video = document.getElementById('videoInput');
  let cap = new cv.VideoCapture(video);
  
  let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
  let fgmask = new cv.Mat(video.height, video.width, cv.CV_8UC1);
  let fgbg = new cv.BackgroundSubtractorMOG2(500, 16,false);
  
  const FPS = 30;
  function processVideo() {
      try {
          if (!streaming) {
              // clean and stop.
              frame.delete(); fgmask.delete(); fgbg.delete();
              return;
          }
          let begin = Date.now();
          // start processing.
          cap.read(frame);
          fgbg.apply(frame, fgmask); //Apply Background Substraction
          cv.bitwise_not(fgmask,fgmask);//Set background color black and foreground color white for Morphological Transformations
          let M = cv.Mat.ones(5,5, cv.CV_8U); 
          let anchor = new cv.Point(-1, -1);
      cv.morphologyEx(fgmask, fgmask, cv.MORPH_OPEN, M, anchor, 1,
          cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
      cv.morphologyEx(fgmask,fgmask, cv.MORPH_CLOSE, M);
          frame.copyTo(fgmask, fgmask);   //Copy original colors
          cv.imshow('canvasOutput', fgmask);
          // schedule the next one.
          let delay = 100/FPS - (Date.now() - begin);
          setTimeout(processVideo, delay);
      } catch (err) {
          utils.printError(err);
      }
  };
  
  // schedule the first one.
  setTimeout(processVideo, 0);
  </code></pre>
  
  <p>Full HTML:<a href="https://anotepad.com/notes/ne7n4w" rel="nofollow noreferrer">https://anotepad.com/notes/ne7n4w</a></p>
  
  <p>All files:<a href="https://files.fm/u/c9egsgqe" rel="nofollow noreferrer">https://files.fm/u/c9egsgqe</a></p>
  
  <p>2-))I am using haarcascades to extract human bodies in this technique , just like this:<a href="https://www.bytefish.de/blog/extracting_contours_with_opencv/" rel="nofollow noreferrer">https://www.bytefish.de/blog/extracting_contours_with_opencv/</a></p>
  
  <p>This algorithm run on following 5 steps.These algorithm not work very well because sometimes haar cascades cannot detect objects
  Javascript Code</p>
  
  <pre><code>let src = cv.imread('canvasInput');
  let gray = new cv.Mat();
  cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
  let faces = new cv.RectVector();
  let poly=new cv.MatVector();
  let faceCascade = new cv.CascadeClassifier();
  faceCascade.load('haarcascade_frontalface_default.xml');
  let msize = new cv.Size(0, 0);
  faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, msize, msize);
  
  
  //1-Create a mask with the rectangular coordinates
  let rect = new cv.Rect(faces.get(0).x, faces.get(0).y,faces.get(0).width,faces.get(0).height);
  
  //2-Mask out
  dst = src.roi(rect);
  
  //3-Edge detection using canny 
  let cannyoutput=new cv.Mat();
  cv.Canny(dst, cannyoutput, 0, 100, 3, true);
  
  //4-Find contours
  let contours = new cv.MatVector();
  let hierarchy = new cv.Mat(); 
  cv.findContours(cannyoutput,contours, hierarchy, cv.RETR_CCOMP, cv.CHAIN_APPROX_NONE);
  
  //cv.drawContours(); 
  
  
  cv.imshow('canvasOutput', cannyoutput);
  src.delete(); gray.delete(); faceCascade.delete();
  faces.delete(); 
  contours.delete(); hierarchy.delete();
  </code></pre>
  
  <p>3-)I tried to apply erosion then dialatios ,it didn't work.<a href="https://stackoverflow.com/questions/48809225/how-can-i-fill-the-gaps-and-improve-foreground-extraction">This Answer</a></p>
  
  <p>Without Erosion And Dilation : <a href="https://streamable.com/xh368" rel="nofollow noreferrer">https://streamable.com/xh368</a> </p>
  
  <p>With Erosion And Dilation : <a href="https://streamable.com/fffsn" rel="nofollow noreferrer">https://streamable.com/fffsn</a>    </p>
  
  <p>My javascript code:</p>
  
  <pre><code>let video = document.getElementById('videoInput');
  let cap = new cv.VideoCapture(video);
  
  let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
  let fgmask = new cv.Mat(video.height, video.width, cv.CV_8UC1);
  let fgbg = new cv.BackgroundSubtractorMOG2(500, 16,false);
  
  const FPS = 30;
  function processVideo() {
      try {
          if (!streaming) {
              // clean and stop.
              frame.delete(); fgmask.delete(); fgbg.delete();
              return;
          }
          let begin = Date.now();
          // start processing.
          cap.read(frame);
          fgbg.apply(frame, fgmask);
          cv.bitwise_not(fgmask,fgmask);  
          let M = cv.Mat.ones(5,5, cv.CV_8U); 
          let anchor = new cv.Point(-1, -1);
          cv.erode(fgmask, fgmask, M, anchor, 1, 
          cv.BORDER_CONSTANT, cv.morphologyDefaultBorderValue());
          cv.dilate(fgmask, fgmask, M, anchor, 1, cv.BORDER_CONSTANT, 
          cv.morphologyDefaultBorderValue());
          frame.copyTo(fgmask, fgmask);   
          cv.imshow('canvasOutput', fgmask);
          // schedule the next one.
          let delay = 1000/FPS - (Date.now() - begin);
          setTimeout(processVideo, delay);
      } catch (err) {
          utils.printError(err);
      }
  };
  
  // schedule the first one.
  setTimeout(processVideo, 0);
  </code></pre>
  
  <p>My full html:<a href="https://anotepad.com/notes/gg5esk" rel="nofollow noreferrer">https://anotepad.com/notes/gg5esk</a></p>