Thumbnail

Darknet YOLO (Obj Detection)

Avatarptp

You only look once (YOLO) is a state-of-the-art, real-time object detection system. using Tiny YOLOv3 a very small model as well for constrained environments (CPU Only, NO GPU)

Requires ARC v5 (Updated 11/3/2020)

How to add the Darknet YOLO (Obj Detection) robot skill

  1. Load the most recent release of ARC (Get ARC).
  2. Press the Project tab from the top menu bar in ARC.
  3. Press Add Robot Skill from the button ribbon bar in ARC.
  4. Choose the Camera category tab.
  5. Press the Darknet YOLO (Obj Detection) icon to add the robot skill to your project.

Don't have a robot yet?

Follow the Getting Started Guide to build a robot and use the Darknet YOLO (Obj Detection) robot skill.


How to use the Darknet YOLO (Obj Detection) robot skill

You only look once (YOLO) is a state-of-the-art, real-time object detection system. using Tiny YOLOv3 a very small model as well for constrained environments (CPU Only, NO GPU)

Darket YOLO website: https://pjreddie.com/darknet/yolo/

Requirements: You only need a camera control, the detection is done offline (no cloud services).

User-inserted image

User-inserted image

  1. start the camera.
  2. check the Running (check box)

The detection will run continuously when the detection results change an On Changes script is executed (check the configuration area):

User-inserted image

  1. Press config
  2. Edit the on changes script
  3. on changes Javascript script

you can run the detection on demand, javascript:

controlCommand("Darknet YOLO", "Run");

The above command runs the configured on demand script.

An example of script:

var numberOfRegions=getVar('$YOLONumberOfRegions');
if (numberOfRegions==0)
{
   Audio.sayWait('No regions found');
}
else
{
   Audio.sayWait('Found ' + numberOfRegions + ' regions');
        var classes = getVar('$YOLOClasses');
        var scores = getVar('$YOLOScores');
        for(var ix=0; ix        {
           Audio.sayWait('Found ' + classes[ix] + ' with score: ' + (classes[ix]*100) + '%');
   }
}

ARC Pro

Upgrade to ARC Pro

Experience the transformation – subscribe to Synthiam ARC Pro and watch your robot evolve into a marvel of innovation and intelligence.

PRO
USA
#34  

Quote:

PPS. FEATURE REQUEST: Can you give us the coordinates of the bounding boxes, or at least the center of the bounding boxes?
Yes. It's possible, I'll add in the next update.

PRO
USA
#36   — Edited

I like the the code with a few things off, I highlighted it

var numberOfRegions=getVar('$YOLONumberOfRegions'); if (numberOfRegions==0) { // Audio.sayWait('No regions found'); } else { // Audio.sayWait('Found ' + numberOfRegions + 'regions'); //Audio.sayWait('Found '); var classes = getVar('$YOLOClasses'); for(var ix=0; ix { //Audio.sayWait("I see a " + (classes[ix]));  or Audio.sayWait(classes[ix]); }

        }

So the audio only comes out with the item it detects

EzAng

PRO
Synthiam
#37  

I get this error during detection


17:46:40.200>Debug>>Id=[9c45498b-14a1-4044-81e3-a8feedd06984] Version=[2020.10.13.1]
17:46:40.338>Debug>>Native Id=[342AD9BC-8A21-4908-8048-F5575614F95F] Version=[2020.9.9.1]
17:46:40.344>Info>>Process new configuration isSetConfiguration=[True]
17:46:59.476>Debug>>Detection Took:1264 seconds
# Regions found: 1
..class=[tvmonitor] confidence=[0.9448678] X=[84] Y=[108] 

17:46:59.519>Error>> Exception=[
System.Runtime.InteropServices.ExternalException (0x80004005): A generic error occurred in GDI+.
   at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
   at System.Drawing.Image.Save(String filename, ImageFormat format)
   at YOLO.Plugin.MainForm.RunDetector(Bitmap bitmap)]
17:47:05.510>Debug>>Finished script=[YOLO.OnChanges] took=[00:00:06.0018869]
17:47:28.520>Info>>Process new configuration isSetConfiguration=[False]
17:47:30.346>Debug>>Detection Took:336 seconds
# Regions found: 1
..class=[tvmonitor] confidence=[0.9381291] X=[85] Y=[108] 

17:47:30.362>Error>> Exception=[
System.Runtime.InteropServices.ExternalException (0x80004005): A generic error occurred in GDI+.
   at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
   at System.Drawing.Image.Save(String filename, ImageFormat format)
   at YOLO.Plugin.MainForm.RunDetector(Bitmap bitmap)]

I'm guessing the detection is done in a new task (new thread)? If so, you'll have to make a copy of the bitmap if it's not being manipulated in the OnNewFrame event. Working with any camera image has to be done either in the new frame event, or a copy of itself needs to be made to work in another thread.

PRO
USA
#38  

It works here, pretty well

EzAng

PRO
USA
#39  

@DJ:

User-inserted image

:

var cameraBitmap = new Bitmap(bitmap);
this.RunDetection(cameraBitmap);

Maybe is not enough to copy the bitmap ? Do you recommend another method to copy the bitmap ?

PRO
Synthiam
#40   — Edited

That won't copy the bitmap - it'll create a new object wrapped around the memory of the bitmap. The bitmap memory actually never changes in ARC. The memory is allocated when the camera starts and is re-used for every frame. A new Bitmap(bitmap) will create a wrapper around the memory that's being used.

An old version of ARC (when ARC days) used to create a new bitmap and dispose it for every frame. But that was super expensive on garbage collection. With the new method, the memory is reused - and that's also why a camera image can exist on many skill controls without a ton of cpu being used or memory. It's because every instance of that bitmap is actually referencing the same memory location and only the screen needs to be refreshed when the memory updates:)

So the solution for yours is actually quite easy - i would recommend taking the Camera's bitmap and "draw" it to a bitmap for your own detection thread. That way, you can keep your own bitmap or dispose of it how you wish etc etc and it lives for long as you want it to.

Something like...


Bitmap _myBitmap;
FormCameraDevice _camera;

void main() {

  var tmpCamera = get the current camera instance control
  tmpCamera.Camera.OnStart += Camera_OnStart;
  tmpCamera.Camera.OnStop += Camera_OnStop;
  _camera = tmpCamera;
}

    private void Camera_OnStart() {

  _myBitmap = new Bitmap(_cameraDevice.Camera.CaptureWidth, _cameraDevice.Camera.CaptureHeight, _cameraDevice.Camera.GetPixelFormat);
}

    private void Camera_OnStop() {

  if (_myBitmap != null) {

    _myBitmap.Dispose();
    _myBitmap = null;
  }
}

void Camera_OnNewFrame() {

  using (Graphics g = Graphics.FromImage(_myBitmap))
    g.DrawImageUnscaled(_cameraDevice.Camera.GetCurrentBitmapManaged, 0, 0);

 // now do what you wish with myBitmap   
}

OR fastest way is....... you can use memcpy and get an instance of your Bitmap's BitmapData - and memcpy the Camera.GetCurrentBitmapUnmanaged.Data to your bitmap's Data0