3737
3838import cv2
3939import argparse
40- import depthai as dai
4140import collections
4241import time
4342from itertools import cycle
4443from pathlib import Path
44+ import sys
45+ import cam_test_gui
46+ import signal
47+
4548
4649def socket_type_pair (arg ):
4750 socket , type = arg .split (',' )
48- if not (socket in ['rgb' , 'left' , 'right' , 'camd' ]): raise ValueError ("" )
49- if not (type in ['m' , 'mono' , 'c' , 'color' ]): raise ValueError ("" )
51+ if not (socket in ['rgb' , 'left' , 'right' , 'camd' ]):
52+ raise ValueError ("" )
53+ if not (type in ['m' , 'mono' , 'c' , 'color' ]):
54+ raise ValueError ("" )
5055 is_color = True if type in ['c' , 'color' ] else False
5156 return [socket , is_color ]
5257
58+
5359parser = argparse .ArgumentParser ()
5460parser .add_argument ('-cams' , '--cameras' , type = socket_type_pair , nargs = '+' ,
55- default = [['rgb' , True ], ['left' , False ], ['right' , False ], ['camd' , True ]],
61+ default = [['rgb' , True ], ['left' , False ],
62+ ['right' , False ], ['camd' , True ]],
5663 help = "Which camera sockets to enable, and type: c[olor] / m[ono]. "
5764 "E.g: -cams rgb,m right,c . Default: rgb,c left,m right,m camd,c" )
5865parser .add_argument ('-mres' , '--mono-resolution' , type = int , default = 800 , choices = {480 , 400 , 720 , 800 },
@@ -71,8 +78,25 @@ def socket_type_pair(arg):
7178 help = "Make OpenCV windows resizable. Note: may introduce some artifacts" )
7279parser .add_argument ('-tun' , '--camera-tuning' , type = Path ,
7380 help = "Path to custom camera tuning database" )
81+ parser .add_argument ('-d' , '--device' , default = "" , type = str ,
82+ help = "Optional MX ID of the device to connect to." )
83+
84+ parser .add_argument ('-ctimeout' , '--connection-timeout' , default = 30000 ,
85+ help = "Connection timeout in ms. Default: %(default)s (sets DEPTHAI_CONNECTION_TIMEOUT environment variable)" )
86+
87+ parser .add_argument ('-btimeout' , '--boot-timeout' , default = 30000 ,
88+ help = "Boot timeout in ms. Default: %(default)s (sets DEPTHAI_BOOT_TIMEOUT environment variable)" )
89+
7490args = parser .parse_args ()
7591
92+ # Set timeouts before importing depthai
93+ os .environ ["DEPTHAI_CONNECTION_TIMEOUT" ] = str (args .connection_timeout )
94+ os .environ ["DEPTHAI_BOOT_TIMEOUT" ] = str (args .boot_timeout )
95+ import depthai as dai
96+
97+ if len (sys .argv ) == 1 :
98+ cam_test_gui .main ()
99+
76100cam_list = []
77101cam_type_color = {}
78102print ("Enabled cameras:" )
@@ -85,24 +109,24 @@ def socket_type_pair(arg):
85109print ("DepthAI path:" , dai .__file__ )
86110
87111cam_socket_opts = {
88- 'rgb' : dai .CameraBoardSocket .RGB , # Or CAM_A
89- 'left' : dai .CameraBoardSocket .LEFT , # Or CAM_B
90- 'right' : dai .CameraBoardSocket .RIGHT , # Or CAM_C
91- 'camd' : dai .CameraBoardSocket .CAM_D ,
112+ 'rgb' : dai .CameraBoardSocket .RGB , # Or CAM_A
113+ 'left' : dai .CameraBoardSocket .LEFT , # Or CAM_B
114+ 'right' : dai .CameraBoardSocket .RIGHT , # Or CAM_C
115+ 'camd' : dai .CameraBoardSocket .CAM_D ,
92116}
93117
94118cam_socket_to_name = {
95- 'RGB' : 'rgb' ,
96- 'LEFT' : 'left' ,
119+ 'RGB' : 'rgb' ,
120+ 'LEFT' : 'left' ,
97121 'RIGHT' : 'right' ,
98122 'CAM_D' : 'camd' ,
99123}
100124
101125rotate = {
102- 'rgb' : args .rotate in ['all' , 'rgb' ],
103- 'left' : args .rotate in ['all' , 'mono' ],
126+ 'rgb' : args .rotate in ['all' , 'rgb' ],
127+ 'left' : args .rotate in ['all' , 'mono' ],
104128 'right' : args .rotate in ['all' , 'mono' ],
105- 'camd' : args .rotate in ['all' , 'rgb' ],
129+ 'camd' : args .rotate in ['all' , 'rgb' ],
106130}
107131
108132mono_res_opts = {
@@ -134,9 +158,11 @@ def __init__(self, window_size=30):
134158 self .fps = 0
135159
136160 def update (self , timestamp = None ):
137- if timestamp == None : timestamp = time .monotonic ()
161+ if timestamp == None :
162+ timestamp = time .monotonic ()
138163 count = len (self .dq )
139- if count > 0 : self .fps = count / (timestamp - self .dq [0 ])
164+ if count > 0 :
165+ self .fps = count / (timestamp - self .dq [0 ])
140166 self .dq .append (timestamp )
141167
142168 def get (self ):
@@ -145,7 +171,7 @@ def get(self):
145171# Start defining a pipeline
146172pipeline = dai .Pipeline ()
147173# Uncomment to get better throughput
148- #pipeline.setXLinkChunkSize(0)
174+ # pipeline.setXLinkChunkSize(0)
149175
150176control = pipeline .createXLinkIn ()
151177control .setStreamName ('control' )
@@ -159,21 +185,21 @@ def get(self):
159185 cam [c ] = pipeline .createColorCamera ()
160186 cam [c ].setResolution (color_res_opts [args .color_resolution ])
161187 cam [c ].setIspScale (1 , args .isp_downscale )
162- #cam[c].initialControl.setManualFocus(85) # TODO
188+ # cam[c].initialControl.setManualFocus(85) # TODO
163189 cam [c ].isp .link (xout [c ].input )
164190 else :
165191 cam [c ] = pipeline .createMonoCamera ()
166192 cam [c ].setResolution (mono_res_opts [args .mono_resolution ])
167193 cam [c ].out .link (xout [c ].input )
168194 cam [c ].setBoardSocket (cam_socket_opts [c ])
169195 # Num frames to capture on trigger, with first to be discarded (due to degraded quality)
170- #cam[c].initialControl.setExternalTrigger(2, 1)
171- #cam[c].initialControl.setStrobeExternal(48, 1)
172- #cam[c].initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
196+ # cam[c].initialControl.setExternalTrigger(2, 1)
197+ # cam[c].initialControl.setStrobeExternal(48, 1)
198+ # cam[c].initialControl.setFrameSyncMode(dai.CameraControl.FrameSyncMode.INPUT)
173199
174- #cam[c].initialControl.setManualExposure(15000, 400) # exposure [us], iso
200+ # cam[c].initialControl.setManualExposure(15000, 400) # exposure [us], iso
175201 # When set, takes effect after the first 2 frames
176- #cam[c].initialControl.setManualWhiteBalance(4000) # light temperature in K, 1000..12000
202+ # cam[c].initialControl.setManualWhiteBalance(4000) # light temperature in K, 1000..12000
177203 control .out .link (cam [c ].inputControl )
178204 if rotate [c ]:
179205 cam [c ].setImageOrientation (dai .CameraImageOrientation .ROTATE_180_DEG )
@@ -183,13 +209,26 @@ def get(self):
183209if args .camera_tuning :
184210 pipeline .setCameraTuningBlobPath (str (args .camera_tuning ))
185211
212+ def exit_cleanly (signum , frame ):
213+ print ("Exiting cleanly" )
214+ cv2 .destroyAllWindows ()
215+ sys .exit (0 )
216+
217+ signal .signal (signal .SIGINT , exit_cleanly )
218+
219+
186220# Pipeline is defined, now we can connect to the device
187- with dai .Device (pipeline ) as device :
188- #print('Connected cameras:', [c.name for c in device.getConnectedCameras()])
221+ device = dai .Device .getDeviceByMxId (args .device )
222+ dai_device_args = [pipeline ]
223+ if device [0 ]:
224+ dai_device_args .append (device [1 ])
225+ with dai .Device (* dai_device_args ) as device :
226+ # print('Connected cameras:', [c.name for c in device.getConnectedCameras()])
189227 print ('Connected cameras:' )
190228 cam_name = {}
191229 for p in device .getConnectedCameraFeatures ():
192- print (f' -socket { p .socket .name :6} : { p .sensorName :6} { p .width :4} x { p .height :4} focus:' , end = '' )
230+ print (
231+ f' -socket { p .socket .name :6} : { p .sensorName :6} { p .width :4} x { p .height :4} focus:' , end = '' )
193232 print ('auto ' if p .hasAutofocus else 'fixed' , '- ' , end = '' )
194233 print (* [type .name for type in p .supportedTypes ])
195234 cam_name [cam_socket_to_name [p .socket .name ]] = p .sensorName
@@ -237,9 +276,12 @@ def get(self):
237276 dotIntensity = 0
238277 floodIntensity = 0
239278
240- awb_mode = cycle ([item for name , item in vars (dai .CameraControl .AutoWhiteBalanceMode ).items () if name .isupper ()])
241- anti_banding_mode = cycle ([item for name , item in vars (dai .CameraControl .AntiBandingMode ).items () if name .isupper ()])
242- effect_mode = cycle ([item for name , item in vars (dai .CameraControl .EffectMode ).items () if name .isupper ()])
279+ awb_mode = cycle ([item for name , item in vars (
280+ dai .CameraControl .AutoWhiteBalanceMode ).items () if name .isupper ()])
281+ anti_banding_mode = cycle ([item for name , item in vars (
282+ dai .CameraControl .AntiBandingMode ).items () if name .isupper ()])
283+ effect_mode = cycle ([item for name , item in vars (
284+ dai .CameraControl .EffectMode ).items () if name .isupper ()])
243285
244286 ae_comp = 0
245287 ae_lock = False
@@ -252,34 +294,43 @@ def get(self):
252294 chroma_denoise = 0
253295 control = 'none'
254296
255- print ("Cam:" , * [' ' + c .ljust (8 ) for c in cam_list ], "[host | capture timestamp]" )
297+ print ("Cam:" , * [' ' + c .ljust (8 )
298+ for c in cam_list ], "[host | capture timestamp]" )
256299
257300 capture_list = []
258301 while True :
259302 for c in cam_list :
260- pkt = q [c ].tryGet ()
303+ try :
304+ pkt = q [c ].tryGet ()
305+ except Exception as e :
306+ print (e )
307+ exit_cleanly (0 , 0 )
261308 if pkt is not None :
262309 fps_host [c ].update ()
263310 fps_capt [c ].update (pkt .getTimestamp ().total_seconds ())
264311 frame = pkt .getCvFrame ()
265312 if c in capture_list :
266313 width , height = pkt .getWidth (), pkt .getHeight ()
267314 capture_file_name = ('capture_' + c + '_' + cam_name [c ]
268- + '_' + str (width ) + 'x' + str (height )
269- + '_exp_' + str (int (pkt .getExposureTime ().total_seconds ()* 1e6 ))
270- + '_iso_' + str (pkt .getSensitivity ())
271- + '_lens_' + str (pkt .getLensPosition ())
272- + '_' + capture_time
273- + '_' + str (pkt .getSequenceNum ())
274- + ".png"
275- )
315+ + '_' + str (width ) + 'x' + str (height )
316+ + '_exp_' +
317+ str (int (
318+ pkt .getExposureTime ().total_seconds ()* 1e6 ))
319+ + '_iso_' + str (pkt .getSensitivity ())
320+ + '_lens_' +
321+ str (pkt .getLensPosition ())
322+ + '_' + capture_time
323+ + '_' + str (pkt .getSequenceNum ())
324+ + ".png"
325+ )
276326 print ("\n Saving:" , capture_file_name )
277327 cv2 .imwrite (capture_file_name , frame )
278328 capture_list .remove (c )
279329
280330 cv2 .imshow (c , frame )
281331 print ("\r FPS:" ,
282- * ["{:6.2f}|{:6.2f}" .format (fps_host [c ].get (), fps_capt [c ].get ()) for c in cam_list ],
332+ * ["{:6.2f}|{:6.2f}" .format (fps_host [c ].get (),
333+ fps_capt [c ].get ()) for c in cam_list ],
283334 end = '' , flush = True )
284335
285336 key = cv2 .waitKey (1 )
@@ -297,26 +348,33 @@ def get(self):
297348 elif key == ord ('f' ):
298349 print ("Autofocus enable, continuous" )
299350 ctrl = dai .CameraControl ()
300- ctrl .setAutoFocusMode (dai .CameraControl .AutoFocusMode .CONTINUOUS_VIDEO )
351+ ctrl .setAutoFocusMode (
352+ dai .CameraControl .AutoFocusMode .CONTINUOUS_VIDEO )
301353 controlQueue .send (ctrl )
302354 elif key == ord ('e' ):
303355 print ("Autoexposure enable" )
304356 ctrl = dai .CameraControl ()
305357 ctrl .setAutoExposureEnable ()
306358 controlQueue .send (ctrl )
307359 elif key in [ord (',' ), ord ('.' )]:
308- if key == ord (',' ): lensPos -= LENS_STEP
309- if key == ord ('.' ): lensPos += LENS_STEP
360+ if key == ord (',' ):
361+ lensPos -= LENS_STEP
362+ if key == ord ('.' ):
363+ lensPos += LENS_STEP
310364 lensPos = clamp (lensPos , lensMin , lensMax )
311365 print ("Setting manual focus, lens position: " , lensPos )
312366 ctrl = dai .CameraControl ()
313367 ctrl .setManualFocus (lensPos )
314368 controlQueue .send (ctrl )
315369 elif key in [ord ('i' ), ord ('o' ), ord ('k' ), ord ('l' )]:
316- if key == ord ('i' ): expTime -= EXP_STEP
317- if key == ord ('o' ): expTime += EXP_STEP
318- if key == ord ('k' ): sensIso -= ISO_STEP
319- if key == ord ('l' ): sensIso += ISO_STEP
370+ if key == ord ('i' ):
371+ expTime -= EXP_STEP
372+ if key == ord ('o' ):
373+ expTime += EXP_STEP
374+ if key == ord ('k' ):
375+ sensIso -= ISO_STEP
376+ if key == ord ('l' ):
377+ sensIso += ISO_STEP
320378 expTime = clamp (expTime , expMin , expMax )
321379 sensIso = clamp (sensIso , sensMin , sensMax )
322380 print ("Setting manual exposure, time: " , expTime , "iso: " , sensIso )
@@ -356,21 +414,33 @@ def get(self):
356414 floodIntensity = 0
357415 device .setIrFloodLightBrightness (floodIntensity )
358416 elif key >= 0 and chr (key ) in '34567890[]' :
359- if key == ord ('3' ): control = 'awb_mode'
360- elif key == ord ('4' ): control = 'ae_comp'
361- elif key == ord ('5' ): control = 'anti_banding_mode'
362- elif key == ord ('6' ): control = 'effect_mode'
363- elif key == ord ('7' ): control = 'brightness'
364- elif key == ord ('8' ): control = 'contrast'
365- elif key == ord ('9' ): control = 'saturation'
366- elif key == ord ('0' ): control = 'sharpness'
367- elif key == ord ('[' ): control = 'luma_denoise'
368- elif key == ord (']' ): control = 'chroma_denoise'
417+ if key == ord ('3' ):
418+ control = 'awb_mode'
419+ elif key == ord ('4' ):
420+ control = 'ae_comp'
421+ elif key == ord ('5' ):
422+ control = 'anti_banding_mode'
423+ elif key == ord ('6' ):
424+ control = 'effect_mode'
425+ elif key == ord ('7' ):
426+ control = 'brightness'
427+ elif key == ord ('8' ):
428+ control = 'contrast'
429+ elif key == ord ('9' ):
430+ control = 'saturation'
431+ elif key == ord ('0' ):
432+ control = 'sharpness'
433+ elif key == ord ('[' ):
434+ control = 'luma_denoise'
435+ elif key == ord (']' ):
436+ control = 'chroma_denoise'
369437 print ("Selected control:" , control )
370438 elif key in [ord ('-' ), ord ('_' ), ord ('+' ), ord ('=' )]:
371439 change = 0
372- if key in [ord ('-' ), ord ('_' )]: change = - 1
373- if key in [ord ('+' ), ord ('=' )]: change = 1
440+ if key in [ord ('-' ), ord ('_' )]:
441+ change = - 1
442+ if key in [ord ('+' ), ord ('=' )]:
443+ change = 1
374444 ctrl = dai .CameraControl ()
375445 if control == 'none' :
376446 print ("Please select a control first using keys 3..9 0 [ ]" )
0 commit comments