eduardolundgren / tracking.js

A modern approach for Computer Vision on the web
http://trackingjs.com
Other
9.44k stars 1.45k forks source link

How to count the number of time two colors appears in color camera. #310

Open FritzAgency opened 6 years ago

FritzAgency commented 6 years ago

Hi,

I want to do a color comparison using the color camera in tracking.js. So I want to ask whether I can count the number of times two colors appear during a specific timeframe.

Something like getting the number of times green appears and at the same know the time red appears in the same timeframe.

I need guidance on this.

Thanks.

murat-aka commented 6 years ago

context.strokeStyle = rect.color;. //tells you what color is detected


tracker.on('track', function(event) {
        context.clearRect(0, 0, canvas.width, canvas.height);

        event.data.forEach(function(rect) {
          if (rect.color === 'custom') {
            rect.color = tracker.customColor;
          }

          context.strokeStyle = rect.color; // detected colour type.
          context.strokeRect(rect.x, rect.y, rect.width, rect.height);
          context.font = '11px Helvetica';
          context.fillStyle = "#fff";
          context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
          context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
        });
      });
murat-aka commented 6 years ago

305

FritzAgency commented 6 years ago

@murat-aka The issue you linked to, the example you provided there is not working at all. Please check.

murat-aka commented 6 years ago

Here is the working code, tested this time.

http://murat-aka.github.io/tracking.js/examples/color_hello_world2.html

You need to workout the camera one yourself. My camera is not working

FritzAgency commented 6 years ago

@murat-aka This is really great. But is there a way to just count the number of appearance instead of calculating the area.

This is what I want to achieve:

Compare two colors (eg. red and green) and count the number of times each of them appears within a time frame.

How can we achieve this?

Really appreciate your help so far.

murat-aka commented 6 years ago

I have already answered what you are trying to achieve. You just need to adapt the code to the camera one. Can I ask why you need all this. Sounds like you are not a programmer but been given a final project on programming. Tell me what bit you can't work out. I ll help you. Although, you should easily work out the answer from existing code, Anyways.

FritzAgency commented 6 years ago

@murat-aka You are right on what you said above.

Why I need this: It's a project that has a deadline and am new to Javascript.

I will need your help on how to work on just two colors and count them as they are being detected separately.

E.g. Just detect green and red and count once a color is detected.

murat-aka commented 6 years ago

I havent got a camera, Can you run this code. And let me know whether it runs, if it runs tell me what you see. once its running, we ll go onto counting business.

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>tracking.js - color with camera</title>
  <link rel="stylesheet" href="assets/demo.css">

  <script src="../build/tracking-min.js"></script>

  <script src="../build/build2/dat.gui.min.js"></script>
  <!--script src="../node_modules/dat.gui/build2/dat.gui.min.js"></script-->
  <script src="assets/stats.min.js"></script>
  <script src="assets/color_camera_gui.js"></script>

  <style>
  video, canvas {
    margin-left: 100px;
    margin-top: 35px;
    position: absolute;
  }
  </style>
</head>

<body>

    <div id="color_detected_div">
        color_type 
    </div>

  <div class="demo-title">
    <p><a href="http://trackingjs.com" target="_parent">tracking.js</a> - choose the colors you want 
     to detect through the controls on the right</p>
  </div>

  <div class="demo-frame">
    <div class="demo-container">
      <video id="video" width="600" height="450" camera="true" preload autoplay loop muted controls></video>
      <canvas id="canvas" width="600" height="450"></canvas>
    </div>
  </div>

  <script>

    window.onload = function() {
      var video = document.getElementById('video');
      var canvas = document.getElementById('canvas');
      var context = canvas.getContext('2d');

      var tracker = new tracking.ColorTracker();

      tracking.track('#video', tracker, { camera: true });

      tracking.ColorTracker.registerColor('green', function(r, g, b) {
            if (r < 50 && g > 200 && b < 50) {
              return true;
            }
            return false;
      });

      tracking.ColorTracker.registerColor('red', function(r, g, b) {
            if (r < 255 && g > 0 && b < 0) {
              return true;
            }
            return false;
      });

      tracker.on('track', function(event) {

        if (event.data.length === 0) {

               //No colors were detected in this frame

         } else {

               context.clearRect(0, 0, canvas.width, canvas.height);
               event.data.forEach(function(rect) {
                    if (rect.color === 'custom') {
                         rect.color = tracker.customColor;
                         var color_div = document.getElementById('color_detected_div');
                         color_div.innerHTML = rect.color;
                    }

                   context.strokeStyle = rect.color;
                   context.strokeRect(rect.x, rect.y, rect.width, rect.height);
                   context.font = '11px Helvetica';
                   context.fillStyle = "#fff";
                   context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
                   context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
              });

         }

      });

      initGUIControllers(tracker);
    };

  </script>

</body>
</html>
FritzAgency commented 6 years ago

I'm about to test now.

FritzAgency commented 6 years ago

@murat-aka It's running normally. The same as what is in the demo.

murat-aka commented 6 years ago

Can you paste a screen output here.

FritzAgency commented 6 years ago

ed

That's it.

murat-aka commented 6 years ago

I thought you were already detecting colours. The screen is blank. First get the detection right. Are you able to detect anything with the camera

FritzAgency commented 6 years ago

Yes. It's detecting colors already. The rectangle stuff...

murat-aka commented 6 years ago

Send me a screenshot of that

FritzAgency commented 6 years ago

I will do that now.

FritzAgency commented 6 years ago

screenshot_20180507-125850 That's it.

murat-aka commented 6 years ago

here a working video.

http://murat-aka.github.io/tracking.js/examples/color_video2.html


<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>tracking.js - color with video</title>
  <link rel="stylesheet" href="assets/demo.css">

  <script src="../build/tracking-min.js"></script>
   <!--<script src="../node_modules/dat.gui/build/dat.gui.min.js"></script>-->
  <!--<script src="assets/stats.min.js"></script>-->
  <!--<script src="assets/color_camera_gui.js"></script>-->

  <style>
  .demo-container {
    background-color: black;
  }

  video, canvas {
    position: absolute;
  }
  </style>
</head>
<body>
  <div class="demo-title">
    <p><a href="http://trackingjs.com" target="_parent">tracking.js</a> - detect certain colors in a video</p>
  </div>

  <div class="demo-frame">
    <div id="color_type_div">color_type</div>
    <div class="demo-container">

      <div id="rectangle"></div>
      <video id="video" width="800" height="530" preload autoplay loop muted controls>
        <source src="assets/minions.mp4" type="video/mp4">
        <source src="assets/minions.ogv" type="video/ogg">
      </video>
      <canvas id="canvas" width="800" height="500"></canvas>
    </div>
  </div>

  <script>
    window.onload = function() {
      var canvas = document.getElementById('canvas');
      var context = canvas.getContext('2d');
      var div_cType = document.getElementById('color_type_div');
      var counter = 0;

      // tracking.ColorTracker.registerColor('purple', function(r, g, b) {
      //   var dx = r - 120;
      //   var dy = g - 60;
      //   var dz = b - 210;

      //   if ((b - g) >= 100 && (r - g) >= 60) {
      //     return true;
      //   }
      //   return dx * dx + dy * dy + dz * dz < 3500;
      // });

      // var tracker = new tracking.ColorTracker(['yellow', 'purple']);
      var tracker = new tracking.ColorTracker(['yellow']);
      tracker.setMinDimension(65);

      tracking.track('#video', tracker);

      tracker.on('track', function(event) {
        context.clearRect(0, 0, canvas.width, canvas.height);

        event.data.forEach(function(rect) {
          if (rect.color === 'custom') {
            rect.color = tracker.customColor;

          }

          if(rect.color === 'yellow'){
            counter++;
            div_cType.innerHTML = rect.color + " detected " + counter + " times";

          }

          context.strokeStyle = rect.color;
          context.strokeRect(rect.x, rect.y, rect.width, rect.height);
          context.font = '11px Helvetica';
          context.fillStyle = "#fff";
          context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
          context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
        });
      });

      // initGUIControllers(tracker);
    };
  </script>

</body>
</html>
FritzAgency commented 6 years ago

Nothing is working after I used your last code.

FritzAgency commented 6 years ago

screenshot_20180507-141346 That's the screenshot this time around.

murat-aka commented 6 years ago

I see you are on mobile. It should work though. does the above link i gave work. and you should click on that little [> 0:00] play icon for video to play. Make sure you copied the code above as it is.

FritzAgency commented 6 years ago

I don't have the assets/minions.mp4 video though.

FritzAgency commented 6 years ago

Oh! Yeah. I've seen the minion video. I will include it now.

FritzAgency commented 6 years ago

Wow! This is working. You are the best @murat-aka

Two more questions:

  1. Can I make this work for a second color? e.g. green. All running at the same time.

  2. Can this work for the color camera as well?

trac

murat-aka commented 6 years ago

here is the camera one. it works on mobile version of chrome,

https://murat-aka.github.io/tracking.js/examples/color_camera2.html


<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>tracking.js - color with camera</title>
  <link rel="stylesheet" href="assets/demo.css">

  <script src="../build/tracking-min.js"></script>
  <!--<script src="../node_modules/dat.gui/build/dat.gui.min.js"></script>-->
  <script src="assets/stats.min.js"></script>
  <!--<script src="assets/color_camera_gui.js"></script>-->

  <style>
  video, canvas {
    margin-left: 100px;
    margin-top: 35px;
    position: absolute;
  }
  </style>
</head>
<body>

  <div class="demo-title">
    <p><a href="http://trackingjs.com" target="_parent">tracking.js</a> - choose the colors you want to detect through the controls on the right</p>
  </div>

  <div class="demo-frame">
    <div id="color_type_yellow_div">color_type_yellow</div>
    <div id="color_type_green_div">color_type_green</div>
    <div class="demo-container">
      <video id="video" width="600" height="450" preload autoplay loop muted controls></video>
      <canvas id="canvas" width="600" height="450"></canvas>
    </div>
  </div>

  <script>
    window.onload = function() {
      var video = document.getElementById('video');
      var canvas = document.getElementById('canvas');
      var context = canvas.getContext('2d');
      var div_cType_yellow = document.getElementById('color_type_yellow_div');
      var div_cType_green = document.getElementById('color_type_green_div');
      var counter_yellow = 0;
      var counter_green = 0;

      tracking.ColorTracker.registerColor('green', function(r, g, b) {
          if ((r < 200) && (g > 200) && (b < 150)) {
           return true;
          }
          return false;
      });

      var tracker = new tracking.ColorTracker(['yellow','green']);

      tracking.track('#video', tracker, { camera: true });

      tracker.on('track', function(event) {
        context.clearRect(0, 0, canvas.width, canvas.height);

        event.data.forEach(function(rect) {
          if (rect.color === 'custom') {
            rect.color = tracker.customColor;
          }

          if(rect.color === 'yellow'){
            counter_yellow++;
            div_cType_yellow.innerHTML = rect.color + " detected " + counter_yellow + " times";

          }

          if(rect.color === 'green'){
            counter_green++;
            div_cType_green.innerHTML = rect.color + " detected " + counter_green + " times";

          }

          context.strokeStyle = rect.color;
          context.strokeRect(rect.x, rect.y, rect.width, rect.height);
          context.font = '11px Helvetica';
          context.fillStyle = "#fff";
          context.fillText('x: ' + rect.x + 'px', rect.x + rect.width + 5, rect.y + 11);
          context.fillText('y: ' + rect.y + 'px', rect.x + rect.width + 5, rect.y + 22);
        });
      });

    // initGUIControllers(tracker);
    };
  </script>

</body>
</html>
FritzAgency commented 6 years ago

Yeah, everything now working well. In fact, you did all the work. I appreciate.

The last question though: I want the number counting to be on another web page. More like a separate output for what the camera is capturing. We want to use this thing for voting. So the user can just see the output number, not the camera tracking.

I know this question is out of scope but if there is a way to make this work, you can guide me to it.

I do appreciate your kind gesture. @murat-aka.

murat-aka commented 6 years ago

The steps to achieve that.

Write a server side script, could be PHP, nodejs, Python, java, even c++, whichever you know.

You need to send the number of counts to that server which will then either write to a database or a file.

Finally fetch data back to display it.

FritzAgency commented 6 years ago

Is it possible to count real-time?. Because those language are backend and will require writing to the database before output

MD00414 commented 6 years ago

I've been monitoring this thread because it spawned some interesting thoughts on possible design patterns.

First, big kudos to murat-aka for what he's shared/developed so far.

@FritzAgency: The challenge you have is transaction latency and broadcasting the updates to all voting participants. One way to deal with this is to add a time-stamp to the latest count and then communicate the 'vote' total as of the time stamp to all voting participants.

As a thought experiment, I thought about how you might accomplish this workflow without using your own private server to register the count. What your design would need is a public repository that would allow you to post all the counts.

If you're not concerned with your vote total being potentially hacked (requiring a level of trust with your users), you could use a public Google spreadsheet as a repository and use the API to read/write to it (see: https://developers.google.com/sheets/api/quickstart/apps-script )

Suverymonkey has an API as well, though its not totally clear if the API service is free: https://api.surveymonkey.net/v3/docs?api_key=3yr7n6m8sjwvm48x8nhxej52

eSurveyspro claims to allow you to do polls for free, but its not immediately clear from the documentation if they have an API. At worst, you would have to 'scrape'/parse the HTML from the poll site to communicate the results back to your users, or just show the eSurveyspro poll in an iFrame: https://www.esurveyspro.com/Survey-Templates.aspx Same design pattern (showing poll results in a iFrame) might work for SurveyMonkey as well.