Huskylens with servo advice

I wonder if anyone can give me some help/advice as I am new to Arduino code and am struggling to find a solution to the camera/servo jogging (slightly) back and forth when looking at a target. The cause is Huskylens outputs the x coordinate +- 6 positions from the centre variable. I think that some sort of averaging would help as the data comes in from the camera. Maybe just accumulating 10 samples and / by 5 may help, a median filter would be best, but this is past my current Arduino coding abilities. Below is the code, any help would be greatly appreciated from you Arduino experts! Thanks for reading.

/***********************************************
*  HUSKYLENS face recog PAN (servo)  *
*  Author:                                                  *
*  Date:06/10/24 - working                        *
*  Camera protocol = I2C                          *
*  Target Micro - Uno                                 *
 ***********************************************/
#include <HUSKYLENS.h>
#include <Wire.h>
#include <Servo.h>

HUSKYLENS huskylens;
Servo servo;

int lastServoPosition = 90; // Initial position
int threshold = 1; // Set a threshold for position changes

void setup() {
    servo.attach(9); // Connect the servo to pin 9
    servo.write(90);
    Serial.begin(115200);
    Wire.begin();
    while (!huskylens.begin(Wire)) {
        Serial.println(F("HUSKYLENS not connected!"));
        delay(100);
    }
    huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION);
}

void loop() {
    if (!huskylens.request()) return;
   
    for (int i = 0; i < huskylens.countBlocks(); i++){
        HUSKYLENSResult result = huskylens.getBlock(i);
       
        int x_center = result.xCenter;
        int width = result.width;
        int y_center = result.yCenter;
        int height = result.height;
        int ID = result.ID;
       
        Serial.print("Object tracked at X: ");
        Serial.print(x_center);
        Serial.print(", Y: ");
        Serial.print(y_center);
        Serial.print(", Width: ");
        Serial.print(width);
        Serial.print(", Height: ");
        Serial.println(height);
        Serial.print("Tracked ID: ");
        Serial.println(ID);
        delay(100);

        // Map the x-coordinate to the servo range (0-180 degrees)
        int servoPosition = map(x_center, 0, 320, 180, 0);
       
        // Calculate the adjustment needed
        int servoAdjustment = servoPosition - lastServoPosition;

        // Limit the adjustment to prevent the servo from moving too quickly
        if (servoAdjustment > threshold) {
            servoAdjustment = threshold;
        } else if (servoAdjustment < -threshold) {
            servoAdjustment = -threshold;
        }

        // Adjust the servo position and update the last position
        servo.attach(9);
        servo.write(lastServoPosition + servoAdjustment);
        lastServoPosition += servoAdjustment;

        delay(150); // Add a delay to allow the servo to move to the new position
        //servo.detach();
    }
}

Hi @toymaker2,

unfortunatly I have no experience with Huskylens ...

What I see from your code is that you are requesting one or more blocks from the device and use those data to control the servo angle. The delay between two blocks is around 250 ms (100 ms after printing and 150 ms after writing to the servo).

If the device returns more than one block I would assume that their coordinates will be different. That might make simple averaging difficult as the differences may depend on the learning data. And - depending on what the AI has detected in a certain frame - the blocks are ordered by the received sequence. To my understanding you cannot be sure that a block with index 2 in one loop() is the same as index 2 in the next loop().

In that case you had to use "result.ID" to make sure it's the same item. An unlearned item would return ID == 0.

Could you post

  • If you receive more than one block per loop()?
  • How many different IDs are you receiving?

as a (possible) solution depends on the answers .

Would be more efficient of course if someone pops up with some Huskylens experience :wink:

Good luck!

1 Like

Hi ec2021

Many thanks for replying to my post! The variable that's of interest is result.Xcenter this keeps updating the x coordinate which I need to stabilise (on a stationary face). Only receiving one ID (face recognised). Thanks for all your help!

You wrote +/- 6 steps.

Could you provide some samples of xCenter values that you receive in sequence?

That might help to find an appropriate way to reduce the difference to the expected value.

For a simple moving average you could check this example

that is based on the movingAvg Library.

The example shows how to feed a moving average object of 10 samples and to retrieve the average in each step.

P.S.: I got some time to integrate the averaging in your sketch (
No guarantee that it will work straight away as I cannot compile and test it.)

/***********************************************
*  HUSKYLENS face recog PAN (servo)  *
*  Author:                                                  *
*  Date:06/10/24 - working                        *
*  Camera protocol = I2C                          *
*  Target Micro - Uno                                 *
 ***********************************************/
/*

 Added movingAvg lib 2024/01/09 
 and used it for averaging the xCenter values

 Not compiled nor tested ...
 ec2021

*/

#include <HUSKYLENS.h>
#include <Wire.h>
#include <Servo.h>
// Added movingAvg lib
#include <movingAvg.h>

HUSKYLENS huskylens;
Servo servo;

// Added xCenter to average result.xCenter
movingAvg xCenter(10);

int lastServoPosition = 90; // Initial position
int threshold = 1; // Set a threshold for position changes

void setup() {
    servo.attach(9); // Connect the servo to pin 9
    servo.write(90);
    Serial.begin(115200);
    Wire.begin();
    while (!huskylens.begin(Wire)) {
        Serial.println(F("HUSKYLENS not connected!"));
        delay(100);
    }
    huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION);
// Added xCenter.begin() to initiate the averaging object    
    xCenter.begin();
}

void loop() {
    if (!huskylens.request()) return;
   
    for (int i = 0; i < huskylens.countBlocks(); i++){
        HUSKYLENSResult result = huskylens.getBlock(i);
       
 // Changed the next line to feed the moving average object
 // and to retrieve the averaged result as x_center
 // The averaging will take a number of repetitions first
 // until an effect can be expected
        int x_center = xCenter.reading(result.xCenter);
        int width = result.width;
        int y_center = result.yCenter;
        int height = result.height;
        int ID = result.ID;
       
        Serial.print("Object tracked at X: ");
        Serial.print(x_center);
        Serial.print(", Y: ");
        Serial.print(y_center);
        Serial.print(", Width: ");
        Serial.print(width);
        Serial.print(", Height: ");
        Serial.println(height);
        Serial.print("Tracked ID: ");
        Serial.println(ID);
        delay(100);

        // Map the x-coordinate to the servo range (0-180 degrees)
        int servoPosition = map(x_center, 0, 320, 180, 0);
       
        // Calculate the adjustment needed
        int servoAdjustment = servoPosition - lastServoPosition;

        // Limit the adjustment to prevent the servo from moving too quickly
        if (servoAdjustment > threshold) {
            servoAdjustment = threshold;
        } else if (servoAdjustment < -threshold) {
            servoAdjustment = -threshold;
        }

        // Adjust the servo position and update the last position
        servo.attach(9);
        servo.write(lastServoPosition + servoAdjustment);
        lastServoPosition += servoAdjustment;

        delay(150); // Add a delay to allow the servo to move to the new position
        //servo.detach();
    }
}

Hope it works and good luck!

1 Like

ec2021 - Thanks again for all your brilliant help!!

With a face in exact center = val of 160
The xCenter would vary like this:-

154
155
156
157
158
159
160 - Huskylens x center
161
162
163
164
165
166

Thanks for the code, I will check it out!

Hi ec2021

I tried your code and it compiled fine, unfortunately the jigging (oscillation) is still occurring. I am not sure of the reason, as it looks like the right thing to solve my problem?

Thanks again for all your help here, it is much appreciated!

Post 5 just shows a linear movement from 154 to 166 but you wrote it is oscillating. Could you possibly post a longer list of of the xCenter data so that the oscillation can be evaluated?

Another question came up when I looked at this part of your sketch:

        // Calculate the adjustment needed
        int servoAdjustment = servoPosition - lastServoPosition;

        // Limit the adjustment to prevent the servo from moving too quickly
        if (servoAdjustment > threshold) {
            servoAdjustment = threshold;
        } else if (servoAdjustment < -threshold) {
            servoAdjustment = -threshold;
        }

        // Adjust the servo position and update the last position
        servo.attach(9);  // You can remove this line as the servo has not been detached before!!!!!
        servo.write(lastServoPosition + servoAdjustment);
        lastServoPosition += servoAdjustment;

With

int threshold = 1; // Set a threshold for position changes

you will allow only one step per frame in the direction servoPosition regardless of the real difference. If the difference is equal to "n" it must therefore take "n" frames to get to the detected position.

I am wondering if there is a correlation between the steps and the oscillation. What happens if you set the threshold to e.g. 2, 3 or 6; will the oscillation change?

It's unfortunately some trial and error ... :wink:

And this

// Map the x-coordinate to the servo range (0-180 degrees)
        int servoPosition = map(x_center, 0, 320, 180, 0);

means that the x_center axis and the angles of the servo are pointing into the opposite directions. Is that correct (the larger the x_center the lower the angle and vice versa)?

And just a hint: You may also remove the line "servo.attach(9);" as the servo has not been detached before.

1 Like

Just a further hint:

If you write @ in a post and then choose the nickname (in this case ec2021) I will get an automatic notice from the forum that you answered ...

The member's name will be written like this: @toymaker2

Makes it easier to detect a response...

Thanks!

1 Like

@ec2021

Thanks for you continued help!

The Huskylens has frame x(horiz) = 0 to 320 - y (vert) = 0 to 240 - the center of frame = 160,120
To get the camera looking (following) the face the code needs to go to x=160,y=120 and stay until the face moves again where it continues to track to center again this is either left or right (from center). The code does exactly that but does not settle as the coordinates vary by +- 6 so you get a small oscillation. Any higher number of threshold than 1 makes the oscillation much worse.
Huskylens is a real cool device see. Gravity: HUSKYLENS AI Machine Vision Sensor - DFRobot Wiki
Are you in the UK, I can send you one FOC?
Thanks
Tony

Thanks, no I live in Germany (just a Brexit away ... :wink: )

Agree, I googled the Huskylens device and it seems to be quite cool. I do not have a real application for it but in the past played around with Raspberry Pi and PC using OpenCV with Python to do some image processing.

We should try to identify the reason for the oscillation ... Did you try to remove the adjustment for test purposes?

The following sketch will not move the servo but print data (result.xCenter ... and the averaged x_center) so we get an idea what happens without movement:

/***********************************************
*  HUSKYLENS face recog PAN (servo)  *
*  Author:                                                  *
*  Date:06/10/24 - working                        *
*  Camera protocol = I2C                          *
*  Target Micro - Uno                                 *
 ***********************************************/
/*

 Added movingAvg lib 2024/01/09 
 and used it for averaging the xCenter values

 2024/01/11
 Changed to just print Huskylens data and averaged x_center

 Not compiled nor tested ...
 ec2021

*/

#include <HUSKYLENS.h>
#include <Wire.h>
#include <Servo.h>
// Added movingAvg lib
#include <movingAvg.h>

HUSKYLENS huskylens;
Servo servo;

// Added xCenter to average result.xCenter
movingAvg xCenter(10);

int lastServoPosition = 90; // Initial position
int threshold = 1; // Set a threshold for position changes

void setup() {
    servo.attach(9); // Connect the servo to pin 9
    servo.write(90);
    Serial.begin(115200);
    Wire.begin();
    while (!huskylens.begin(Wire)) {
        Serial.println(F("HUSKYLENS not connected!"));
        delay(100);
    }
    huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION);
// Added xCenter.begin() to initiate the averaging object    
    xCenter.begin();
}

void loop() {
    if (!huskylens.request()) return;
   
    for (int i = 0; i < huskylens.countBlocks(); i++){
        HUSKYLENSResult result = huskylens.getBlock(i);
       
 // Changed the next line to feed the moving average object
 // and to retrieve the averaged result as x_center
 // The averaging will take a number of repetitions first
 // until an effect can be expected
        int x_center = xCenter.reading(result.xCenter);
        int width = result.width;
        int y_center = result.yCenter;
        int height = result.height;
        int ID = result.ID;
       
        Serial.print("Object tracked at X: ");
        Serial.print(result.xCenter);
        Serial.print(", Y: ");
        Serial.print(y_center);
        Serial.print(", Width: ");
        Serial.print(width);
        Serial.print(", Height: ");
        Serial.println(height);
        Serial.print("Tracked ID: ");
        Serial.println(ID);
        Serial.print("Averaged xCenter: ");
        Serial.println(x_center);
        delay(100);

/*
        // Map the x-coordinate to the servo range (0-180 degrees)
        int servoPosition = map(x_center, 0, 320, 180, 0);
       
        // Calculate the adjustment needed
        int servoAdjustment = servoPosition - lastServoPosition;

        // Limit the adjustment to prevent the servo from moving too quickly
        if (servoAdjustment > threshold) {
            servoAdjustment = threshold;
        } else if (servoAdjustment < -threshold) {
            servoAdjustment = -threshold;
        }

        // Adjust the servo position and update the last position
        servo.attach(9);
        servo.write(lastServoPosition + servoAdjustment);
        lastServoPosition += servoAdjustment;
*/
        delay(150); // Add a delay to allow the servo to move to the new position
        //servo.detach();
    }
}

1 Like

@ec2021

I will try the code tomorrow

I feel that with all your generous help, I would be happy to mail you out a HuskLens to Germany?

I work with advanced robots so this device is very useful!

Best Regards

Tony

Thank you, I really appreciate your suggestion but I feel like it's too much for my little help...

I'm happy if I can be of any assistance (so are most of the members I know here).

Let us see what the raw data may tell us!

And my best wishes to the UK!

1 Like

@ec2021

This is what happens with the last code, with the servo labelled out, the xCenter and Average xCenter are pretty much the same value - when I put back the servo track routine the difference becomes becomes enough to cause the jogging which is actually worse than the original code we started with - please see attached screen dump? Thanks again for all your generous help here!

I copied the result.xCenter data to LibreOffice Calc and got this:

It tells us that the raw data of xCenter are varying between minimum 118 and maximum 168 (if I copied correctly ... ). during roughly 4 seconds.

I assume that you kept the target and the Huskylens stable, didn't you?

If yes there seems to be either a problem with the face detection algorithm or with the training/target data. If the features of the tracked ID 2 are too weak the software may have problems to find a proper margin. Still just guesswork ... ;-(

I have reduced the last sketch again so that only a counter, the time in millis() and result.xCenter are displayed. I left the timing as before (100 ms plus 150 ms delay between the frames).

Would you mind to try the sketch with Huskylens and target (face) absolutely stable? Let it run for 30 s or more and copy the data from the serial terminal as text; copying the data from a screenshot is quite tedious and error prone ... :wink:

Please use code-tags also for the data!

It would be interesting to see how the raw xCenter values change over a longer periode.

Please switch off the timestamp of the Serial monitor; the millis() should be enough to evaluate the timing.

/***********************************************
*  HUSKYLENS face recog PAN (servo)  *
*  Author:                                                  *
*  Date:06/10/24 - working                        *
*  Camera protocol = I2C                          *
*  Target Micro - Uno                                 *
 ***********************************************/
/*

 Added movingAvg lib 2024/01/09 
 and used it for averaging the xCenter values

 2024/01/11
 Changed to just print Huskylens data and averaged x_center

 2024/01/12 
 Just print result.xCenter and a counter

 Not compiled nor tested ...
 ec2021

*/

#include <HUSKYLENS.h>
#include <Wire.h>
#include <Servo.h>
// Added movingAvg lib
#include <movingAvg.h>

HUSKYLENS huskylens;
Servo servo;

// Added xCenter to average result.xCenter
movingAvg xCenter(10);

int lastServoPosition = 90; // Initial position
int threshold = 1; // Set a threshold for position changes
int count = 0;

void setup() {
    servo.attach(9); // Connect the servo to pin 9
    servo.write(90);
    Serial.begin(115200);
    Wire.begin();
    while (!huskylens.begin(Wire)) {
        Serial.println(F("HUSKYLENS not connected!"));
        delay(100);
    }
    huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION);
// Added xCenter.begin() to initiate the averaging object    
    xCenter.begin();
}

void loop() {
    if (!huskylens.request()) return;
   
    for (int i = 0; i < huskylens.countBlocks(); i++){
        HUSKYLENSResult result = huskylens.getBlock(i);
       
 // Changed the next line to feed the moving average object
 // and to retrieve the averaged result as x_center
 // The averaging will take a number of repetitions first
 // until an effect can be expected
        int x_center = xCenter.reading(result.xCenter);
        int width = result.width;
        int y_center = result.yCenter;
        int height = result.height;
        int ID = result.ID;
        count++;
        Serial.print(count);
        Serial.print("\t");
        Serial.print(millis());
        Serial.print("\t");
        Serial.println(result.xCenter);
        delay(100);
/*       
        Serial.print("Object tracked at X: ");
        Serial.print(result.xCenter);
        Serial.print(", Y: ");
        Serial.print(y_center);
        Serial.print(", Width: ");
        Serial.print(width);
        Serial.print(", Height: ");
        Serial.println(height);
        Serial.print("Tracked ID: ");
        Serial.println(ID);
        Serial.print("Averaged xCenter: ");
        Serial.println(x_center);
        delay(100);

        // Map the x-coordinate to the servo range (0-180 degrees)
        int servoPosition = map(x_center, 0, 320, 180, 0);
       
        // Calculate the adjustment needed
        int servoAdjustment = servoPosition - lastServoPosition;

        // Limit the adjustment to prevent the servo from moving too quickly
        if (servoAdjustment > threshold) {
            servoAdjustment = threshold;
        } else if (servoAdjustment < -threshold) {
            servoAdjustment = -threshold;
        }

        // Adjust the servo position and update the last position
        servo.attach(9);
        servo.write(lastServoPosition + servoAdjustment);
        lastServoPosition += servoAdjustment;
*/
        delay(150); // Add a delay to allow the servo to move to the new position
        //servo.detach();
    }
}

1 Like

Hi, I found this code that might do everything I want (pan and tilt) it just wont compile as it does not recognise writeOSD or anything with mind_n_? I tried many things but just cannot figure this out - can you advise? Thanks Tony

/*!
 * Huskylens pan and tilt
 * uno
 *
 */
#include <DFRobot_Servo.h>
#include <DFRobot_HuskyLens.h>

// Dynamic variables
volatile float mind_n_currentx, mind_n_currenty;
// Create an object
DFRobot_HuskyLens huskylens;
Servo             servo_9;
Servo             servo_10;


// Main program start
void setup() {
	servo_9.attach(9);
	servo_10.attach(10);
	huskylens.writeOSD(String("wating..."), 230, 35);
	huskylens.beginI2CUntilSuccess();
	huskylens.writeAlgorithm(ALGORITHM_OBJECT_TRACKING);
	delay(1000);
	huskylens.writeOSD(String("ok"), 230, 35);
	mind_n_currentx = 40;
	mind_n_currenty = 150;
	servo_9.angle(abs(mind_n_currentx));
	servo_10.angle(abs(mind_n_currenty));
}
void loop() {
	huskylens.request();
	huskylens.writeOSD(String(huskylens.readBlockParameter(1).xCenter), 230, 35);

	if ((huskylens.readBlockParameter(1).xCenter>190)) {
		mind_n_currentx -= 1.5;
		servo_9.angle(abs((constrain(mind_n_currentx, 0, 120))));
	}

	else if (((huskylens.readBlockParameter(1).xCenter>10) && (huskylens.readBlockParameter(1).xCenter<130))) {
		mind_n_currentx += 1.5;
		servo_9.angle(abs((constrain(mind_n_currentx, 0, 120))));
	}

	if ((huskylens.readBlockParameter(1).yCenter>150)) {
		mind_n_currenty += 1.0;
		servo_10.angle(abs((constrain(mind_n_currenty, 0, 120))));
	}
	else if (((huskylens.readBlockParameter(1).yCenter>10) && (huskylens.readBlockParameter(1).yCenter<90))) {
		mind_n_currenty -= 1;
		servo_10.angle(abs((constrain(mind_n_currenty, 0, 120))));
	}
}

It not mind_n_ the problem, its "angle" that has no member?

I googled this lib and found it here

https://github.com/DFRobot/DFRobot_MAX/blob/master/DFRobot_Servo/DFRobot_Servo.h

If you have installed that one servo.angle() should create no error message.

I assume that writeOSD means "On Screen Display" and may write text to the husky lens image as an overlay. If that creates problems just remove those lines or comment them out.

One further question:

What's the viewing angle of the huskylens?

A servo is moved in steps of one degree. So the calculation should be

320/(viewing angle) = pixels per degree

servo angle correction = (delta x in pixels)/(pixels per degree)

1 Like

I been hunting around on the net, and it may be that I have an old version Huskylens library - I tried to install the latest off the wiki but it has not worked - I am new to arduino so I have probably not successfully updated the library as I struggle to understand the arduino compiler? See post extract below - thanks again for sticking with me with all this help/guidance!

"hello, when compiling the sketch, errors appear in these lines of code: DFRobot_Servo.h, huskylens.writeOSD, writeAlgorithm..., arduino says it does not recognize these parameters, what is the solution, where are they these bookstores? You have this sketch on your page, so, I think, you should give us free access to these bookstores. Thanks.
Avatar
Winster Daniel Torrens Tortosa
2 years ago
Seems you have not loaded the library file of huskylins. Please download the library file from Wiki and put it into your Arduino Library Directory"

Can you post the link to the page where you found the Pan and Tilt sketch?

I actually found a lib that provides the writeODS() function here

https://github.com/DFRobot/pxt-DFRobot_HuskyLens

but that is written in the language TypeScript and not in C++ ...

You seem to be not the first to encounter this problem (there is a post on a German website from July 2023 https://www.fambach.net/startseite/

Translation:

U. E. from Berlin wrote on July 22, 2023 at 8:15 a.m
Hello Stefan, I have had a HuskyLens module for a few days and am testing the first project "Object Tracking Pan Tilt" with it: GitHub - makertut/huskkylens-pan-tilt-object https://www.youtube .com/watch?v=k-LXs94nRaU Unfortunately I only get error messages when I compile the sketch on the Arduino UNO: class DFRobot_HuskyLens' has no member named 'writeOSD' I suspect that the library is no longer up to date. Can you perhaps give me a tip based on your experiences? I'm not a programmer and I'm looking for a working sketch for the UNO. Many greetings ULLI

In the meantime I may have a look at the Pan/Tilt software and can try to make it work with the recent libraries ...

1 Like

Hi I cannot find the viewing angle for the HL?
I gone back to the start code and taken a stationary face image (view center of screen) - serial details (below) this jiggles (left/right) from target only a little but will never lock on to target?

It looks like my servo.h is not the same as CFRobot servo.h I am going to try to add the DFRobot one to the sketch?

Tracked ID: 2
Object tracked at X: 147, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 154, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 161, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 165, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 164, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 158, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 154, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 153, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 161, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 165, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 165, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 158, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 153, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 153, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 161, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 165, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 165, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 158, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 153, Y: 125, Width: 48, Height: 65
Tracked ID: 2
Object tracked at X: 153, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 161, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 166, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 164, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 161, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 154, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 146, Y: 125, Width: 48, Height: 64
Tracked ID: 2
Object tracked at X: 147, Y: 125, Width: 48, Height: 65
Tracked ID: 2
Object tracked at X: 154, Y: 125, Width: 48, Height: 64