js_meanshift.html 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>MeanShift Example</title>
  6. <link href="js_example_style.css" rel="stylesheet" type="text/css" />
  7. </head>
  8. <body>
  9. <h2>MeanShift Example</h2>
  10. <p>
  11. Click <b>Start/Stop</b> button to start or stop the video.<br>
  12. The <b>videoInput</b> is a &lt;video&gt; element used as meanShift input.
  13. The <b>canvasOutput</b> is a &lt;canvas&gt; element used as meanShift output.<br>
  14. The code of &lt;textarea&gt; will be executed when video is started.
  15. You can modify the code to investigate more.
  16. </p>
  17. <div>
  18. <div class="control"><button id="startAndStop" disabled>Start</button></div>
  19. <textarea class="code" rows="29" cols="100" id="codeEditor" spellcheck="false">
  20. </textarea>
  21. </div>
  22. <p class="err" id="errorMessage"></p>
  23. <div>
  24. <table cellpadding="0" cellspacing="0" width="0" border="0">
  25. <tr>
  26. <td>
  27. <video id="videoInput" width="320" height="240" muted loop></video>
  28. </td>
  29. <td>
  30. <canvas id="canvasOutput" width="320" height="240" ></canvas>
  31. </td>
  32. <td></td>
  33. <td></td>
  34. </tr>
  35. <tr>
  36. <td>
  37. <div class="caption">videoInput</div>
  38. </td>
  39. <td>
  40. <div class="caption">canvasOutput</div>
  41. </td>
  42. <td></td>
  43. <td></td>
  44. </tr>
  45. </table>
  46. </div>
  47. <script src="https://webrtc.github.io/adapter/adapter-5.0.4.js" type="text/javascript"></script>
  48. <script src="utils.js" type="text/javascript"></script>
  49. <script id="codeSnippet" type="text/code-snippet">
  50. let video = document.getElementById('videoInput');
  51. let cap = new cv.VideoCapture(video);
  52. // take first frame of the video
  53. let frame = new cv.Mat(video.height, video.width, cv.CV_8UC4);
  54. cap.read(frame);
  55. // hardcode the initial location of window
  56. let trackWindow = new cv.Rect(150, 60, 63, 125);
  57. // set up the ROI for tracking
  58. let roi = frame.roi(trackWindow);
  59. let hsvRoi = new cv.Mat();
  60. cv.cvtColor(roi, hsvRoi, cv.COLOR_RGBA2RGB);
  61. cv.cvtColor(hsvRoi, hsvRoi, cv.COLOR_RGB2HSV);
  62. let mask = new cv.Mat();
  63. let lowScalar = new cv.Scalar(30, 30, 0);
  64. let highScalar = new cv.Scalar(180, 180, 180);
  65. let low = new cv.Mat(hsvRoi.rows, hsvRoi.cols, hsvRoi.type(), lowScalar);
  66. let high = new cv.Mat(hsvRoi.rows, hsvRoi.cols, hsvRoi.type(), highScalar);
  67. cv.inRange(hsvRoi, low, high, mask);
  68. let roiHist = new cv.Mat();
  69. let hsvRoiVec = new cv.MatVector();
  70. hsvRoiVec.push_back(hsvRoi);
  71. cv.calcHist(hsvRoiVec, [0], mask, roiHist, [180], [0, 180]);
  72. cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX);
  73. // delete useless mats.
  74. roi.delete(); hsvRoi.delete(); mask.delete(); low.delete(); high.delete(); hsvRoiVec.delete();
  75. // Setup the termination criteria, either 10 iteration or move by at least 1 pt
  76. let termCrit = new cv.TermCriteria(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1);
  77. let hsv = new cv.Mat(video.height, video.width, cv.CV_8UC3);
  78. let dst = new cv.Mat();
  79. let hsvVec = new cv.MatVector();
  80. hsvVec.push_back(hsv);
  81. const FPS = 30;
  82. function processVideo() {
  83. try {
  84. if (!streaming) {
  85. // clean and stop.
  86. frame.delete(); dst.delete(); hsvVec.delete(); roiHist.delete(); hsv.delete();
  87. return;
  88. }
  89. let begin = Date.now();
  90. // start processing.
  91. cap.read(frame);
  92. cv.cvtColor(frame, hsv, cv.COLOR_RGBA2RGB);
  93. cv.cvtColor(hsv, hsv, cv.COLOR_RGB2HSV);
  94. cv.calcBackProject(hsvVec, [0], roiHist, dst, [0, 180], 1);
  95. // Apply meanshift to get the new location
  96. // and it also returns number of iterations meanShift took to converge,
  97. // which is useless in this demo.
  98. [, trackWindow] = cv.meanShift(dst, trackWindow, termCrit);
  99. // Draw it on image
  100. let [x, y, w, h] = [trackWindow.x, trackWindow.y, trackWindow.width, trackWindow.height];
  101. cv.rectangle(frame, new cv.Point(x, y), new cv.Point(x+w, y+h), [255, 0, 0, 255], 2);
  102. cv.imshow('canvasOutput', frame);
  103. // schedule the next one.
  104. let delay = 1000/FPS - (Date.now() - begin);
  105. setTimeout(processVideo, delay);
  106. } catch (err) {
  107. utils.printError(err);
  108. }
  109. };
  110. // schedule the first one.
  111. setTimeout(processVideo, 0);
  112. </script>
  113. <script type="text/javascript">
  114. let utils = new Utils('errorMessage');
  115. utils.loadCode('codeSnippet', 'codeEditor');
  116. let streaming = false;
  117. let videoInput = document.getElementById('videoInput');
  118. let startAndStop = document.getElementById('startAndStop');
  119. let canvasOutput = document.getElementById('canvasOutput');
  120. let canvasContext = canvasOutput.getContext('2d');
  121. startAndStop.addEventListener('click', () => {
  122. if (!streaming) {
  123. utils.clearError();
  124. videoInput.play().then(() => {
  125. onVideoStarted();
  126. });
  127. } else {
  128. videoInput.pause();
  129. videoInput.currentTime = 0;
  130. onVideoStopped();
  131. }
  132. });
  133. function onVideoStarted() {
  134. streaming = true;
  135. startAndStop.innerText = 'Stop';
  136. videoInput.height = videoInput.width * (videoInput.videoHeight / videoInput.videoWidth);
  137. utils.executeCode('codeEditor');
  138. }
  139. function onVideoStopped() {
  140. streaming = false;
  141. canvasContext.clearRect(0, 0, canvasOutput.width, canvasOutput.height);
  142. startAndStop.innerText = 'Start';
  143. }
  144. utils.loadOpenCv(() => {
  145. videoInput.addEventListener('canplay', () => {
  146. startAndStop.removeAttribute('disabled');
  147. });
  148. videoInput.src = 'cup.mp4';
  149. });
  150. </script>
  151. </body>
  152. </html>