detect.Top return value not iterable

my software detects objects and I want it to identify the closest to the center of the frame, but the return from int(detect. Top) is impossible to use when more than an object is detected. It returns 2 numbers that I need to range from lower to highest but it says that the object is not iterable when I use min().

for detect in detections:
#print(detect)
ID=detect.ClassID
top=int(detect.Top)
left=int(detect.Left)
bottom=int(detect.Bottom)
right=int(detect.Right)
item=net.GetClassDesc(ID)
cv2.rectangle(img,(left,top),(right,bottom),(0,225,0),1)
cv2.putText(img,item,(left,top+20),font,.5,(0,255,0),2)

m = min(realdistance)
TypeError: ‘float’ object is not iterable
Exiting…
Cleaning up pins

Normally the output of the Detect.Top is like this
302.0
New cicle
-242.0
304.5
New cicle
-248.0
304.5
New cicle
-256.0
304.5
New cicle
-244.0
New cicle
-246.0
304.5

The two numbers come from the same variable and I only need the smallest.

Hi @cespedesk, the detectNet.Detection.Top attribute only ever returns one number.

Can you post more of the code that is causing the error and the console log? Is it the m = min(realdistance) line that triggers the exception?

Hi dusty, it is an honor been helped by you.
this is my code

import jetson.inference
import jetson.utils
import time
import cv2
import numpy as np
import math
import os
import pyttsx3
a = 200
engine=pyttsx3.init()
engine.setProperty(‘rate’,150)
engine.setProperty(‘voice’,‘english+f1’)
text=‘initialising’
text1=’ Powering down’
engine.say(text)
engine.runAndWait()

timeStamp=time.time()
fpsFilt=0

net=jetson.inference.detectNet(‘ssd-mobilenet-v1’,[’–model=/media/kc/1.0T/jetson-inference/python/training/detection/ssd/models/tg3/ssd-mobilenet.onnx’,’–input-blob=input_0’,’–labels=/media/kc/1.0T/jetson-inference/python/training/detection/ssd/models/tg3/labels.txt’,’–output-cvg=scores’,’–output-bbox=boxes’,’–camera=/dev/video0’],threshold=.6)

dispW=1280
dispH=720
snapy=100
snapy2=.5
th1=5
th2=100
reset=0
font=cv2.FONT_HERSHEY_SIMPLEX

Servo Code

from adafruit_servokit import ServoKit
myKit=ServoKit(channels=16)
pan=90
tilt=100
myKit.servo[0].angle=pan
myKit.servo[2].angle=tilt

cam=cv2.VideoCapture(’/dev/video0’)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, dispW)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, dispH)

while True:

_,img = cam.read()
img=cv2.resize(img,(854,480))
height=img.shape[0]
width=img.shape[1]

frame=cv2.cvtColor(img,cv2.COLOR_BGR2RGBA).astype(np.float32)
frame=jetson.utils.cudaFromNumpy(frame)

img=cv2.circle(img,(427,240),5,(0,0,200),2)

detections=net.Detect(frame, width, height)
for detect in detections:
    #print(detect)
    ID=detect.ClassID
    top=int(detect.Top)
    left=int(detect.Left)
    bottom=int(detect.Bottom)
    right=int(detect.Right)
    item=net.GetClassDesc(ID)
    cv2.rectangle(img,(left,top),(right,bottom),(0,225,0),1)
    cv2.putText(img,item,(left,top+20),font,.5,(0,255,0),2)
    if item=='Car':
        reset=0
        Xcenter=(right-left)/2+left
        Ycenter=(bottom-top)/2+top
        errorPan=Xcenter-854/2
        errorTilt=Ycenter-480/2
        realdistance = math.sqrt(pow(errorPan, 2)+pow(errorTilt, 2))
        #print(str(errorPan))
        #print(errorPan)
        print(realdistance)
        if errorPan>th1:
            pan=pan-(errorPan/snapy)**snapy2
        if errorPan<-th1:
            pan=pan+(abs(errorPan)/snapy)**snapy2
        if errorTilt>th1:
            tilt=tilt-(errorTilt/snapy)**snapy2
        if errorTilt<-th1:
            tilt=tilt+(abs(errorTilt)/snapy)**snapy2
        if pan>180:
            pan=180  
        if pan<0:
            pan=0
        if tilt>120:
            tilt=120
        if tilt<30:
            tilt=30
        myKit.servo[0].angle=pan
        myKit.servo[2].angle=tilt
        

#display.RenderOnce(img,width,height)
dt=time.time()-timeStamp
timeStamp=time.time()
fps=1/dt
fpsFilt=.9*fpsFilt + .1*fps
#print(str(round(fps,1))+' fps')
cv2.putText(img,str(round(fpsFilt,1))+' fps',(0,30),font,1,(0,0,255),2)
cv2.imshow('detCam',img)
reset=reset+1
print("New cicle")


#cv2.moveWindow('detCam',0,0)
if cv2.waitKey(1)==ord('q'):
    myKit.servo[0].angle=90
    myKit.servo[2].angle=100
    engine.say(text1)
    engine.runAndWait()
    #time.sleep(1)
    break

cam.release()
cv2.destroyAllWindows()

the result of print(realdistance) is
New cicle
118.15773355984787
277.15203408959496
New cicle
119.57006314291216
277.55224733372273
New cicle
119.67664768032233
276.1892467131912
New cicle
121.06403264388643
276.1892467131912
New cicle

As you see when exposed to 2 cars it returns 2 values but I only need the smallest one to know which care is closest to the center of the frame.So I used min(realdistance) and it gave me this

New cicle
New cicle
Traceback (most recent call last):
File “/media/kc/1.0T/jetson-inference/python/training/detection/ssd/robot.py”, line 75, in
m = min(realdistance)
TypeError: ‘float’ object is not iterable
Exiting…
Cleaning up pins

I very new to this and I put this together through tutorials and blogs so please help me out.

OK, I think I see the issue - when you do min(realdistance), you are taking the min of a single number, and not an array. This is because you defined realdistance as:

realdistance = math.sqrt(pow(errorPan, 2)+pow(errorTilt, 2))

(which is just a single number an not an interable list/array)

Instead, you can keep track of the current minimum like this (psuedocode)

mindistance = 100000.0    # large sentinel value to start
mindetection = None

for detect in detections:
       # your other code goes here
       realdistance = math.sqrt(pow(errorPan, 2)+pow(errorTilt, 2))

       if realdistance < mindistance:
               mindistance = realdistance
               mindetection = detect

# at the end of the loop, mindetection should hold the closest detection
# (unless there were no detections that frame and it is None)
if mindetection is not None:
        # do something with mindetection

Thank you very much, very helpful.