Intel Realsense D435 多摄像头多线程目标识别架构
每一個(gè)攝像頭單獨(dú)開(kāi)一個(gè)線程,攝像頭配置是否要放進(jìn)線程內(nèi)?
每一個(gè)攝像頭線程內(nèi)單獨(dú)處理錯(cuò)誤信息
每一個(gè)攝像頭要存儲(chǔ)最新彩色幀和深度幀(用于識(shí)別和獲取深度信息)
接收打擊信號(hào)要一個(gè)線程,對(duì)打擊信號(hào)進(jìn)行排序、分析、存儲(chǔ)。
識(shí)別線程去獲取存儲(chǔ)的打擊信號(hào)知道要識(shí)別哪個(gè),去調(diào)用指定攝像頭存儲(chǔ)的幀識(shí)別,存儲(chǔ)識(shí)別結(jié)果。
發(fā)送坐標(biāo)信息需要一個(gè)線程,用于獲取識(shí)別線程的存儲(chǔ)結(jié)果進(jìn)行發(fā)送
(因?yàn)槲覀儐螏R(shí)別時(shí)間較長(zhǎng),所以不能使用一直識(shí)別的方式,需要采用接收信號(hào)然后識(shí)別的方式【當(dāng)然也不排除可以使用預(yù)測(cè)方式,像商品推薦那樣,我預(yù)測(cè)你哪個(gè)機(jī)械臂會(huì)發(fā)來(lái)打擊信號(hào),然后提前識(shí)別然后直接給你發(fā)過(guò)去】)
20200330 更新
初步完成代碼
# -*- coding: utf-8 -*- """ @File : 20200324_多攝像頭多線程調(diào)度.py @Time : 2020/3/24 15:58 @Author : Dontla @Email : sxana@qq.com @Software: PyCharm """import sys import threading import time import traceback import cv2 import numpy as np import pyrealsense2 as rs import dontla_package.tensorflow_yolov3_algorithm as tya import core.utils as utils# Parameters # cam_serials = ['836612070298', '838212073806', '827312071616'] cam_serials = ['826212070395', '838212072365'] # cam_serials = ['826212070395']# Needn't modify cam_num = len(cam_serials) ctx = rs.context()# 【類】單個(gè)攝像頭幀傳輸線程 class CamThread(threading.Thread):def __init__(self, cam_serial):threading.Thread.__init__(self)self.cam_serial = cam_serial# 【類函數(shù)】def run(self):while True:try:print('攝像頭{}線程啟動(dòng):'.format(self.cam_serial))# 配置攝像頭并啟動(dòng)流# self.cam_cfg(self.cam_serial) # 放函數(shù)里就不行了不知為什么?(因?yàn)槟鞘蔷植孔兞堪∩底?#xff0c;只能在函數(shù)內(nèi)使用)locals()['pipeline' + self.cam_serial] = rs.pipeline(ctx)locals()['config' + self.cam_serial] = rs.config()locals()['config' + self.cam_serial].enable_device(self.cam_serial)locals()['config' + self.cam_serial].enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)locals()['config' + self.cam_serial].enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)locals()['pipeline' + self.cam_serial].start(locals()['config' + self.cam_serial])locals()['align' + self.cam_serial] = rs.align(rs.stream.color)# 從內(nèi)存循環(huán)讀取攝像頭傳輸幀while True:locals()['frames' + self.cam_serial] = locals()['pipeline' + self.cam_serial].wait_for_frames()locals()['aligned_frames' + self.cam_serial] = locals()['align' + self.cam_serial].process(locals()['frames' + self.cam_serial])globals()['aligned_depth_frame' + self.cam_serial] = locals()['aligned_frames' + self.cam_serial].get_depth_frame()locals()['color_frame' + self.cam_serial] = locals()['aligned_frames' + self.cam_serial].get_color_frame()locals()['color_profile' + self.cam_serial] = locals()['color_frame' + self.cam_serial].get_profile()locals()['cvsprofile' + self.cam_serial] = rs.video_stream_profile(locals()['color_profile' + self.cam_serial])locals()['color_intrin' + self.cam_serial] = locals()['cvsprofile' + self.cam_serial].get_intrinsics()globals()['color_intrin_part' + self.cam_serial] = [locals()['color_intrin' + self.cam_serial].ppx,locals()['color_intrin' + self.cam_serial].ppy,locals()['color_intrin' + self.cam_serial].fx,locals()['color_intrin' + self.cam_serial].fy]globals()['color_image' + self.cam_serial] = np.asanyarray(locals()['color_frame' + self.cam_serial].get_data())except Exception:# Dontla 20200326 下面這句主要擔(dān)心攝像頭掉線后,重新配置直到pipeline.start()時(shí),攝像頭還未連上,然后又重新執(zhí)行下面這句就會(huì)報(bào)管道無(wú)法在啟動(dòng)之前關(guān)閉的錯(cuò)誤,所以加個(gè)trytry:locals()['pipeline' + self.cam_serial].stop()except Exception:passprint('攝像頭{}線程{}掉線重連:'.format(self.cam_serial, self.name))# 【類】幀處理與顯示 class ImgProcess(threading.Thread):def __init__(self, cam_serial):threading.Thread.__init__(self)self.cam_serial = cam_serial# 【類函數(shù)】def run(self):while True:try:# 搞了半天我說(shuō)怎么卡住運(yùn)行不下去,原來(lái)是加鎖沒(méi)try,即使出錯(cuò)也不會(huì)釋放鎖。。。那如果對(duì)了不就?是不是不釋放鎖即使是擁有鎖的線程也沒(méi)法再次獲得鎖的?# TODO(Dontla)如果某個(gè)攝像頭掉線,它還一直占用鎖怎么辦?必須要用到隊(duì)列?現(xiàn)在的情況是所有都會(huì)卡住# 必須要檢測(cè)globals()['color_image' + self.cam_serial]是否為空if 'color_image{}'.format(self.cam_serial) not in globals():continuethreadLock.acquire()try:locals()['boxes_pr' + self.cam_serial] = YoloTest.predict(globals()['color_image' + self.cam_serial])except Exception:threadLock.release()continue# locals()['boxes_image' + self.cam_serial] = YoloTest.draw_bbox(# globals()['color_image' + self.cam_serial], locals()['boxes_pr' + self.cam_serial],# globals()['aligned_depth_frame' + self.cam_serial],# globals()['color_intrin_part' + self.cam_serial])locals()['boxes_image' + self.cam_serial] = YoloTest.draw_bbox(globals()['color_image' + self.cam_serial], locals()['boxes_pr' + self.cam_serial])cv2.imshow('{}'.format(self.cam_serial), locals()['boxes_image' + self.cam_serial])cv2.waitKey(1)except Exception:traceback.print_exc()pass# 【函數(shù)】攝像頭連續(xù)驗(yàn)證、連續(xù)驗(yàn)證機(jī)制 def cam_conti_veri(cam_num, ctx):# D·C 1911202:創(chuàng)建最大驗(yàn)證次數(shù)max_veri_times;創(chuàng)建連續(xù)穩(wěn)定值continuous_stable_value,用于判斷設(shè)備重置后是否處于穩(wěn)定狀態(tài)max_veri_times = 100continuous_stable_value = 5print('\n', end='')print('開(kāi)始連續(xù)驗(yàn)證,連續(xù)驗(yàn)證穩(wěn)定值:{},最大驗(yàn)證次數(shù):{}:'.format(continuous_stable_value, max_veri_times))continuous_value = 0veri_times = 0while True:devices = ctx.query_devices()# for dev in devices:# print(dev.get_info(rs.camera_info.serial_number), dev.get_info(rs.camera_info.usb_type_descriptor))connected_cam_num = len(devices)print('攝像頭個(gè)數(shù):{}'.format(connected_cam_num))if connected_cam_num == cam_num:continuous_value += 1if continuous_value == continuous_stable_value:breakelse:continuous_value = 0veri_times += 1if veri_times == max_veri_times:print("檢測(cè)超時(shí),請(qǐng)檢查攝像頭連接!")sys.exit()# 【函數(shù)】循環(huán)reset攝像頭 def cam_hardware_reset(ctx, cam_serials):# hardware_reset()后是不是應(yīng)該延遲一段時(shí)間?不延遲就會(huì)報(bào)錯(cuò)print('\n', end='')print('開(kāi)始初始化攝像頭:')for dev in ctx.query_devices():# 先將設(shè)備的序列號(hào)放進(jìn)一個(gè)變量里,免得在下面for循環(huán)里訪問(wèn)設(shè)備的信息過(guò)多(雖然不知道它會(huì)不會(huì)每次都重新訪問(wèn))dev_serial = dev.get_info(rs.camera_info.serial_number)# 匹配序列號(hào),重置我們需重置的特定攝像頭(注意兩個(gè)for循環(huán)順序,哪個(gè)在外哪個(gè)在內(nèi)很重要,不然會(huì)導(dǎo)致剛重置的攝像頭又被訪問(wèn)導(dǎo)致報(bào)錯(cuò))for serial in cam_serials:if serial == dev_serial:dev.hardware_reset()# 像下面這條語(yǔ)句居然不會(huì)報(bào)錯(cuò),不是剛剛才重置了dev嗎?莫非區(qū)別在于沒(méi)有通過(guò)for循環(huán)ctx.query_devices()去訪問(wèn)?# 是不是剛重置后可以通過(guò)ctx.query_devices()去查看有這個(gè)設(shè)備,但是卻沒(méi)有存儲(chǔ)設(shè)備地址?如果是這樣,# 也就能夠解釋為啥能夠通過(guò)len(ctx.query_devices())函數(shù)獲取設(shè)備數(shù)量,但訪問(wèn)序列號(hào)等信息就會(huì)報(bào)錯(cuò)的原因了print('攝像頭{}初始化成功'.format(dev.get_info(rs.camera_info.serial_number)))# 如果只有一個(gè)攝像頭,要讓它睡夠5秒(避免出錯(cuò),保險(xiǎn)起見(jiàn))time.sleep(5 / len(cam_serials))if __name__ == '__main__':# 連續(xù)驗(yàn)證cam_conti_veri(cam_num, ctx)# 攝像頭重置cam_hardware_reset(ctx, cam_serials)# 連續(xù)驗(yàn)證cam_conti_veri(cam_num, ctx)# 創(chuàng)建YoloTest對(duì)象YoloTest = tya.YoloTest()# 創(chuàng)建線程鎖threadLock = threading.Lock()globals()['flag'] = True# 創(chuàng)建新線程for serial in cam_serials:locals()['CamThread_{}'.format(serial)] = CamThread(serial)locals()['ImgProcess_{}'.format(serial)] = ImgProcess(serial)# 開(kāi)啟新線程for serial in cam_serials:locals()['CamThread_{}'.format(serial)].start()locals()['ImgProcess_{}'.format(serial)].start()# 阻塞主程序for serial in cam_serials:locals()['CamThread_{}'.format(serial)].join()print("退出主線程") # -*- coding: utf-8 -*- """ @File : tensorflow_yolov3_algorithm.py @Time : 2020/3/27 10:30 @Author : Dontla @Email : sxana@qq.com @Software: PyCharm """ import colorsys import randomimport cv2 import numpy as np import tensorflow as tf import core.utils as utils from core.config import cfg from core.yolov3 import YOLOV3# Dontla 191106注釋:創(chuàng)建能夠返回讀取class.names文件信息為字典參數(shù)的函數(shù) def read_class_names(class_file_name):"""loads class name from a file"""names = {}with open(class_file_name, 'r') as data:for ID, name in enumerate(data):names[ID] = name.strip('\n')return namesmy_classes = read_class_names(cfg.YOLO.CLASSES)class YoloTest(object):def __init__(self):# D·C 191111:__C.TEST.INPUT_SIZE = 544self.input_size = cfg.TEST.INPUT_SIZEself.anchor_per_scale = cfg.YOLO.ANCHOR_PER_SCALE# Dontla 191106注釋:初始化class.names文件的字典信息屬性self.classes = utils.read_class_names(cfg.YOLO.CLASSES)# D·C 191115:類數(shù)量屬性self.num_classes = len(self.classes)self.anchors = np.array(utils.get_anchors(cfg.YOLO.ANCHORS))# D·C 191111:__C.TEST.SCORE_THRESHOLD = 0.3self.score_threshold = cfg.TEST.SCORE_THRESHOLD# D·C 191120:__C.TEST.IOU_THRESHOLD = 0.45self.iou_threshold = cfg.TEST.IOU_THRESHOLDself.moving_ave_decay = cfg.YOLO.MOVING_AVE_DECAY# D·C 191120:__C.TEST.ANNOT_PATH = "./data/dataset/Dontla/20191023_Artificial_Flower/test.txt"self.annotation_path = cfg.TEST.ANNOT_PATH# D·C 191120:__C.TEST.WEIGHT_FILE = "./checkpoint/f_g_c_weights_files/yolov3_test_loss=15.8845.ckpt-47"self.weight_file = cfg.TEST.WEIGHT_FILE# D·C 191115:可寫標(biāo)記(bool類型值)self.write_image = cfg.TEST.WRITE_IMAGE# D·C 191115:__C.TEST.WRITE_IMAGE_PATH = "./data/detection/"(識(shí)別圖片畫(huà)框并標(biāo)注文本后寫入的圖片路徑)self.write_image_path = cfg.TEST.WRITE_IMAGE_PATH# D·C 191116:TEST.SHOW_LABEL設(shè)置為Trueself.show_label = cfg.TEST.SHOW_LABEL# D·C 191120:創(chuàng)建命名空間“input”with tf.name_scope('input'):# D·C 191120:建立變量(創(chuàng)建占位符開(kāi)辟內(nèi)存空間)self.input_data = tf.placeholder(dtype=tf.float32, name='input_data')self.trainable = tf.placeholder(dtype=tf.bool, name='trainable')model = YOLOV3(self.input_data, self.trainable)self.pred_sbbox, self.pred_mbbox, self.pred_lbbox = model.pred_sbbox, model.pred_mbbox, model.pred_lbbox# D·C 191120:創(chuàng)建命名空間“指數(shù)滑動(dòng)平均”with tf.name_scope('ema'):ema_obj = tf.train.ExponentialMovingAverage(self.moving_ave_decay)# D·C 191120:在允許軟設(shè)備放置的會(huì)話中啟動(dòng)圖形并記錄放置決策。(不懂啥意思。。。)allow_soft_placement=True表示允許tf自動(dòng)選擇可用的GPU和CPUself.sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))# D·C 191120:variables_to_restore()用于加載模型計(jì)算滑動(dòng)平均值時(shí)將影子變量直接映射到變量本身self.saver = tf.train.Saver(ema_obj.variables_to_restore())# D·C 191120:用于下次訓(xùn)練時(shí)恢復(fù)模型self.saver.restore(self.sess, self.weight_file)# 攝像頭序列號(hào)# self.cam_serials = ['838212073249', '827312070790']# self.cam_serials = ['838212073249', '827312070790', '838212071055', '838212074152', '838212073806',# '827312071616']self.cam_serials = ['838212074152', '838212072365', '827312070790', '838212073806', '826212070395']self.cam_num = len(self.cam_serials)# self.cam_num = 2def predict(self, image):# D·C 191107:復(fù)制一份圖片的鏡像,避免對(duì)圖片直接操作改變圖片的內(nèi)在屬性org_image = np.copy(image)# D·C 191107:獲取圖片尺寸org_h, org_w, _ = org_image.shape# D·C 191108:該函數(shù)將源圖結(jié)合input_size,將其轉(zhuǎn)換成預(yù)投喂的方形圖像(作者默認(rèn)544×544,中間為縮小尺寸的源圖,上下空區(qū)域?yàn)榛覉D):image_data = utils.image_preprocess(image, [self.input_size, self.input_size])# D·C 191108:打印維度看看:# print(image_data.shape)# (544, 544, 3)# D·C 191108:創(chuàng)建新軸,不懂要?jiǎng)?chuàng)建新軸干嘛?image_data = image_data[np.newaxis, ...]# D·C 191108:打印維度看看:# print(image_data.shape)# (1, 544, 544, 3)# D·C 191110:三個(gè)box可能存放了預(yù)測(cè)框圖(可能是N多的框,有用的沒(méi)用的重疊的都在里面)的信息(但是打印出來(lái)的值完全看不懂啊喂?)pred_sbbox, pred_mbbox, pred_lbbox = self.sess.run([self.pred_sbbox, self.pred_mbbox, self.pred_lbbox],feed_dict={self.input_data: image_data,self.trainable: False})# D·C 191110:打印三個(gè)box的類型、形狀和值看看:# print(type(pred_sbbox))# print(type(pred_mbbox))# print(type(pred_lbbox))# 都是<class 'numpy.ndarray'># print(pred_sbbox.shape)# print(pred_mbbox.shape)# print(pred_lbbox.shape)# (1, 68, 68, 3, 6)# (1, 34, 34, 3, 6)# (1, 17, 17, 3, 6)# print(pred_sbbox)# print(pred_mbbox)# print(pred_lbbox)# D·C 191110:(-1,6)表示不知道有多少行,反正你給我整成6列,然后concatenate又把它們仨給疊起來(lái),最終得到無(wú)數(shù)個(gè)6列數(shù)組(后面self.num_classes)個(gè)數(shù)存放的貌似是這個(gè)框?qū)儆陬惖母怕?#xff09;pred_bbox = np.concatenate([np.reshape(pred_sbbox, (-1, 5 + self.num_classes)),np.reshape(pred_mbbox, (-1, 5 + self.num_classes)),np.reshape(pred_lbbox, (-1, 5 + self.num_classes))], axis=0)# D·C 191111:打印pred_bbox和它的維度看看:# print(pred_bbox)# print(pred_bbox.shape)# (18207, 6)# D·C 191111:猜測(cè)是第一道過(guò)濾,過(guò)濾掉score_threshold以下的圖片,過(guò)濾完之后少了好多:# D·C 191115:bboxes維度為[n,6],前四列是坐標(biāo),第五列是得分,第六列是對(duì)應(yīng)類下標(biāo)bboxes = utils.postprocess_boxes(pred_bbox, (org_h, org_w), self.input_size, self.score_threshold)# D·C 191111:猜測(cè)是第二道過(guò)濾,過(guò)濾掉iou_threshold以下的圖片:bboxes = utils.nms(bboxes, self.iou_threshold)return bboxesdef draw_bbox(self, image, bboxes, aligned_depth_frame=None, color_intrin_part=None, show_label=True):"""bboxes: [x_min, y_min, x_max, y_max, probability, cls_id] format coordinates."""# D·C 191117:創(chuàng)建存放class.names文件中類數(shù)目的變量num_classes = len(my_classes)# Dontla 20191014# print(num_classes)# 80# D·A 191117# print(num_classes)# 1# D·A 191117:獲取圖片分辨率image_h, image_w, _ = image.shape# Dontla 20191014# print('(image_h,image_w):', image_h, '', image_w)# (image_h,image_w): 240 424# D·C 191118:hsv顏色模式第一個(gè)數(shù)表示色階,用于將不同類別的框分配給不同顏色,# 用RGB模式不好做顏色分配,用這種方法分配后再轉(zhuǎn)換成rgb模式,方便很多!hsv_tuples = [(1.0 * x / num_classes, 1., 1.) for x in range(num_classes)]# D·A 191118 打印hsv_tuples看看# print(hsv_tuples)# [(0.0, 1.0, 1.0)]# D·C 191118:將hsv顏色模式轉(zhuǎn)換成rgb顏色模式colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))# D·A 191118 打印colors看看# print(colors)# [(1.0, 0.0, 0.0)]# D·C 191118:將轉(zhuǎn)換后的值分配給0-255colors = list(map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)), colors))# Dontla 20191014# print(type(colors))# <class 'list'># print(colors)# [(255, 0, 0)]# D·C 191119:生成固定隨機(jī)數(shù)種子random.seed(0)# D·C 191119:將colors里的顏色打亂(由于設(shè)定了隨機(jī)數(shù)種子,每次打亂后的顏色順序都是一樣的)random.shuffle(colors)# D·C 191119:取消固定隨機(jī)數(shù)種子random.seed(None)# Dontla 20191017# print('*' * 50)# print(bboxes)# [array([1.57846606e+00, 3.41371887e+02, 8.33116150e+01, 4.69713715e+02, 3.56435806e-01, 7.30000000e+01]),# array([3.03579620e+02, 3.27595886e+02, 6.24216125e+02, 4.67514557e+02, 4.15683120e-01, 6.30000000e+01]),# array([356.42529297, 143.32351685, 424.81719971, 191.51617432,0.55459815, 62. ]),# array([468.05984497, 186.09997559, 638.58270264, 295.89181519,0.68913358, 57. ])]# 解釋:每個(gè)元素前四位數(shù)值為框左上角和右下角坐標(biāo),第五位為真實(shí)概率,第六位為類號(hào)。如book為73,laptop為63。# 識(shí)別出目標(biāo):book 中心點(diǎn)像素坐標(biāo):(42, 405) 深度:0.640m# 識(shí)別出目標(biāo):laptop 中心點(diǎn)像素坐標(biāo):(464, 397) 深度:0.479m# 識(shí)別出目標(biāo):tvmonitor 中心點(diǎn)像素坐標(biāo):(390, 167) 深度:4.274m# 識(shí)別出目標(biāo):sofa 中心點(diǎn)像素坐標(biāo):(553, 240) 深度:1.608m# Dontla 20191017# 提取ppx,ppy,fx,fy# Dontla 20191104 Dontla reformed at 20200301# 如果color_intrin_part不為空(因?yàn)閰?shù)在傳入之前color_frame和aligned_depth_frame都已經(jīng)判斷過(guò)了,這里沒(méi)必要再做判斷)if color_intrin_part:ppx = color_intrin_part[0]ppy = color_intrin_part[1]fx = color_intrin_part[2]fy = color_intrin_part[3]# D·C 191119:獲取行列索引作為下標(biāo)for i, bbox in enumerate(bboxes):# 取前四位數(shù)字作為畫(huà)框坐標(biāo)coor = np.array(bbox[:4], dtype=np.int32)# 創(chuàng)建標(biāo)注字符字體大小的變量?(將fontScale增加后,發(fā)現(xiàn)畫(huà)框左上角的文字變大了)fontScale = 0.5# 取第五位數(shù)字作為得分值score = bbox[4]# 取第六位數(shù)字作為類號(hào)class_ind = int(bbox[5])# print(class_ind)# 如:59# 以類序號(hào)分配顏色bbox_color = colors[class_ind]# print(bbox_color)# 如:(255, 0, 133) 不知道是咋跟序號(hào)對(duì)應(yīng)上的?(見(jiàn)前面,框顏色的創(chuàng)建) 【識(shí)別出目標(biāo):bed 中心點(diǎn)像素坐標(biāo):(322, 374) 深度:4.527m】# D·C 191119:設(shè)置框的邊寬?不過(guò)為啥不直接設(shè)置成:bbox_thick = int((image_h + image_w) / 1000)bbox_thick = int(0.6 * (image_h + image_w) / 600)# Dontla 20191014# print(type(bbox_thick))# <class 'int'># print(bbox_thick)# 640×480像素下固定為1,因?yàn)橹坝玫氖?24×248像素所以值為0# print(0.6 * (640 + 480) / 600)# 1.12# 創(chuàng)建存儲(chǔ)框左上角和右下角坐標(biāo)的變量c1, c2 = (coor[0], coor[1]), (coor[2], coor[3])# Dontla 20191014# print(c1, '', c2)# 貌似打印出的就是識(shí)別框的左上角和右下角坐標(biāo)(以圖像左上角為原點(diǎn),x軸水平向右,y軸垂直向下)# 如 (126, 77) (229, 206)# (363, 112) (423, 239)# D·C 191119:繪制矩形框cv2.rectangle(image, c1, c2, bbox_color, bbox_thick)# D·C 191119:如果允許顯示標(biāo)簽if show_label:# D·C 191119:創(chuàng)建需顯示在框左上角的字符信息(類名+得分)bbox_mess = '%s: %.2f' % (my_classes[class_ind], score)# Dontla 20191017# print(type(bbox_mess))# <class 'str'># print(bbox_mess)# 如:# keyboard: 0.66# laptop: 0.48# D·A 191119:獲取目標(biāo)的中心點(diǎn)坐標(biāo),round后默認(rèn)帶一位小數(shù),可用int去掉它target_xy_pixel = [int(round((coor[0] + coor[2]) / 2)), int(round((coor[1] + coor[3]) / 2))]# Dontla 20191104 Dontla reformed at 20200301# 如果aligned_depth_frame不為空(因?yàn)閰?shù)在傳入之前color_frame和aligned_depth_frame都已經(jīng)判斷過(guò)來(lái),這里沒(méi)必要再做判斷)if aligned_depth_frame:target_depth = aligned_depth_frame.get_distance(target_xy_pixel[0], target_xy_pixel[1])target_xy_true = [(target_xy_pixel[0] - ppx) * target_depth / fx,(target_xy_pixel[1] - ppy) * target_depth / fy]# Dontla commented out at 20200301(測(cè)試掉線不需要打印這個(gè),先注釋掉)# print('識(shí)別出目標(biāo):{} 中心點(diǎn)像素坐標(biāo):({}, {}) 實(shí)際坐標(biāo)(mm):({:.0f},{:.0f}) 深度(mm):{:.0f}'.format(classes[class_ind],# target_xy_pixel[0],# target_xy_pixel[1],# target_xy_true[# 0] * 1000,# -target_xy_true[# 1] * 1000,# target_depth * 1000))# print('識(shí)別出目標(biāo):{} 中心點(diǎn)像素坐標(biāo):({}, {}) 深度:{:.3f}m'.format(classes[class_ind], target_xy_pixel[0],# target_xy_pixel[1],# target_depth))# 識(shí)別出目標(biāo):cup 中心點(diǎn)像素坐標(biāo):(317, 148)# 識(shí)別出目標(biāo):keyboard 中心點(diǎn)像素坐標(biāo):(398, 162)# 識(shí)別出目標(biāo):bottle 中心點(diǎn)像素坐標(biāo):(321, 124)# D·C 191119:計(jì)算bbox_mess字符所占像素的大小t_size = cv2.getTextSize(bbox_mess, 0, fontScale, thickness=bbox_thick // 2)[0]# D·A 191119:打印t_size看看:# print(t_size)# (97, 12)# D·A 191119:打印cv2.getTextSize(bbox_mess, 0, fontScale, thickness=bbox_thick // 2)看看:# print(cv2.getTextSize(bbox_mess, 0, fontScale, thickness=bbox_thick // 2))# ((97, 12), 5) # 5是基線與中線的距離,我們這里用不到,所以就舍去了# D·C 191119:繪制裝載文字的矩形實(shí)心框# D·R 191119:當(dāng)框在頂端,標(biāo)簽顯示不出來(lái),我想把它弄到框內(nèi)# 原始為:cv2.rectangle(image, c1, (c1[0] + t_size[0], c1[1] - t_size[1] - 3), bbox_color, thickness=-1) # filledcv2.rectangle(image, c1, (c1[0] + t_size[0], c1[1] + t_size[1] + 3), bbox_color, thickness=-1) # filled# D·C 191119:繪制文字# D·R 191119:當(dāng)框在頂端,標(biāo)簽顯示不出來(lái),我想把它弄到框內(nèi)(bbox_thick是線寬。-2是底線到中線距離?)# 原始為:cv2.putText(image, bbox_mess, (c1[0], c1[1] - 2), cv2.FONT_HERSHEY_SIMPLEX,# fontScale, (0, 0, 0), bbox_thick // 2, lineType=cv2.LINE_AA)cv2.putText(image, bbox_mess, (c1[0], c1[1] + t_size[1] + bbox_thick - 2), cv2.FONT_HERSHEY_SIMPLEX,fontScale, (0, 0, 0), bbox_thick // 2, lineType=cv2.LINE_AA)return image總結(jié)
以上是生活随笔為你收集整理的Intel Realsense D435 多摄像头多线程目标识别架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: cpu,内核和逻辑处理器的关系
- 下一篇: 线程中start()与run()的区别