Tensorflow版本yolo v3源碼閱讀筆記(3)

了解了yolov3模型和損失函數(shù)的計算后,我們來分析yolov3訓(xùn)練和測試數(shù)據(jù)集的制作代碼客税。

這里有必要說明一下况褪,這里的數(shù)據(jù)集就是我們在訓(xùn)練yolov3神經(jīng)網(wǎng)絡(luò)時所需要的圖片資源和相應(yīng)的真實框標(biāo)記。

數(shù)據(jù)集的制作流程如下:

    1. 從文件中讀取圖片數(shù)據(jù)和標(biāo)記的真實框數(shù)據(jù)(2個左上角數(shù)據(jù)+2個右下角數(shù)據(jù))更耻、真實框的類別(用一個整數(shù)表示)
    1. 生成3個尺度的特征圖测垛,找出每個特征圖中真實框位置處對應(yīng)的3個先驗框,然后這3個先驗框和真實框計算iou值秧均,然后根據(jù)iou值大于指定閾值的條件食侮,找出符合條件的先驗框,最后把真實框數(shù)據(jù)填充到先驗框在特征圖中對應(yīng)的位置處目胡。還有锯七,把類別通過one-hot編碼,也填充到先驗框在特征圖中對應(yīng)的位置處誉己。
    1. 生成3個尺度的真實框張量眉尸。在上一步中,我們可以找到每個尺度的特征圖中和真實框匹配的先驗框巨双,這樣噪猾,我們就可以把真實框保存進(jìn)這個尺度的真實框張量中。
    1. 數(shù)據(jù)基本已經(jīng)制作完成了筑累,返回3個尺度的特征圖和3個尺度的真實框張量袱蜡。

數(shù)據(jù)集的制作流程基本就是這樣的,下面我們看具體的代碼實現(xiàn)慢宗。

class Dataset(object):
    """implement Dataset here"""
    def __init__(self, dataset_type):
        self.annot_path  = cfg.TRAIN.ANNOT_PATH if dataset_type == 'train' else cfg.TEST.ANNOT_PATH
        self.input_sizes = cfg.TRAIN.INPUT_SIZE if dataset_type == 'train' else cfg.TEST.INPUT_SIZE
        self.batch_size  = cfg.TRAIN.BATCH_SIZE if dataset_type == 'train' else cfg.TEST.BATCH_SIZE
        self.data_aug    = cfg.TRAIN.DATA_AUG   if dataset_type == 'train' else cfg.TEST.DATA_AUG

        self.train_input_sizes = cfg.TRAIN.INPUT_SIZE#訓(xùn)練集圖片尺寸
        self.strides = np.array(cfg.YOLO.STRIDES)#每個特征圖中的一個格子代表原始圖像中的幾個格子
        self.classes = utils.read_class_names(cfg.YOLO.CLASSES)#類別的索引
        self.num_classes = len(self.classes)#類別的個數(shù)
        self.anchors = np.array(utils.get_anchors(cfg.YOLO.ANCHORS))#3個尺度的3個不同大小的先驗框坪蚁,一共有9個
        self.anchor_per_scale = cfg.YOLO.ANCHOR_PER_SCALE#一個尺度上有幾個先驗框,這里是3個
        self.max_bbox_per_scale = 150#一個尺度上的最大先驗框個數(shù)

        self.annotations = self.load_annotations(dataset_type)#加載訓(xùn)練集標(biāo)簽
        self.num_samples = len(self.annotations)#樣本數(shù)量
        self.num_batchs = int(np.ceil(self.num_samples / self.batch_size))#一共有幾個 batch
        self.batch_count = 0 # 計數(shù)
load_annotations
    def load_annotations(self, dataset_type):
        with open(self.annot_path, 'r') as f:
            txt = f.readlines()
            annotations = [line.strip() for line in txt if len(line.strip().split()[1:]) != 0]
        np.random.shuffle(annotations)
        return annotations

    def __iter__(self):
        return self
    def __next__(self):

        with tf.device('/cpu:0'):
            self.train_input_size = random.choice(self.train_input_sizes)#輸入的圖片尺寸大小
            self.train_output_sizes = self.train_input_size // self.strides#計算3個尺度的輸出大小

            # 初始化一個批次的樣本
            batch_image = np.zeros((self.batch_size, self.train_input_size, self.train_input_size, 3), dtype=np.float32)

            # 初始化一個批次的輸出(批次大小為4婆廊,三個尺度上的輸出尺寸分別為52迅细、26巫橄、13淘邻,一個尺度上共有3個先驗框,2個坐標(biāo)中心點+2個高寬信息+1個置信度信息+80個類別信息)
            batch_label_sbbox = np.zeros((self.batch_size, self.train_output_sizes[0], self.train_output_sizes[0],
                                          self.anchor_per_scale, 5 + self.num_classes), dtype=np.float32)#初始化小尺度的輸出湘换,shape = [4宾舅,52统阿,52,3筹我,85]
            batch_label_mbbox = np.zeros((self.batch_size, self.train_output_sizes[1], self.train_output_sizes[1],
                                          self.anchor_per_scale, 5 + self.num_classes), dtype=np.float32)#初始化中尺度的輸出扶平,shape = [4, 26, 26, 3, 85]
            batch_label_lbbox = np.zeros((self.batch_size, self.train_output_sizes[2], self.train_output_sizes[2],
                                          self.anchor_per_scale, 5 + self.num_classes), dtype=np.float32)# 初始化大尺度的輸出,shape = [4蔬蕊,13结澄,13,3岸夯,85]

            batch_sbboxes = np.zeros((self.batch_size, self.max_bbox_per_scale, 4), dtype=np.float32)#小尺度的真實框張量
            batch_mbboxes = np.zeros((self.batch_size, self.max_bbox_per_scale, 4), dtype=np.float32)#中尺度的真實框張量
            batch_lbboxes = np.zeros((self.batch_size, self.max_bbox_per_scale, 4), dtype=np.float32)#大尺度的真實框張量

            num = 0#記錄遍歷到一個批次(4張圖片)中的第幾張圖片了
            if self.batch_count < self.num_batchs:#如果記錄的 batch 個數(shù)還沒達(dá)到總 batch 個數(shù)
                while num < self.batch_size:#如果這個批次(4張圖片)還沒遍歷完
                    index = self.batch_count * self.batch_size + num#記錄現(xiàn)在是第幾個樣本
                    if index >= self.num_samples: index -= self.num_samples#如果這個樣本已經(jīng)超過了總個圖片數(shù)量麻献,那么從頭再開始
                    annotation = self.annotations[index]#根據(jù)索引取出這個圖片的信息(包括圖片,真實框信息猜扮,類別信息)
                    image, bboxes = self.parse_annotation(annotation)#解析出圖片信息和真實框信息
                    label_sbbox, label_mbbox, label_lbbox, sbboxes, mbboxes, lbboxes = self.preprocess_true_boxes(bboxes)#返回保存有真實框信息的3個尺度的特征圖和3個真實框張量信息

                    batch_image[num, :, :, :] = image
                    batch_label_sbbox[num, :, :, :, :] = label_sbbox
                    batch_label_mbbox[num, :, :, :, :] = label_mbbox
                    batch_label_lbbox[num, :, :, :, :] = label_lbbox
                    batch_sbboxes[num, :, :] = sbboxes
                    batch_mbboxes[num, :, :] = mbboxes
                    batch_lbboxes[num, :, :] = lbboxes
                    num += 1
                self.batch_count += 1
                batch_smaller_target = batch_label_sbbox, batch_sbboxes
                batch_medium_target  = batch_label_mbbox, batch_mbboxes
                batch_larger_target  = batch_label_lbbox, batch_lbboxes

                return batch_image, (batch_smaller_target, batch_medium_target, batch_larger_target)
            else:
                self.batch_count = 0
                np.random.shuffle(self.annotations)
                raise StopIteration
圖片的一系列增強(qiáng)操作
    # 圖片增強(qiáng)操作之-水平翻轉(zhuǎn)
    def random_horizontal_flip(self, image, bboxes):

        if random.random() < 0.5:
            _, w, _ = image.shape
            image = image[:, ::-1, :]
            bboxes[:, [0,2]] = w - bboxes[:, [2,0]]

        return image, bboxes

     # 圖片增強(qiáng)操作之-隨機(jī)裁剪
    def random_crop(self, image, bboxes):

        if random.random() < 0.5:
            h, w, _ = image.shape
            max_bbox = np.concatenate([np.min(bboxes[:, 0:2], axis=0), np.max(bboxes[:, 2:4], axis=0)], axis=-1)

            max_l_trans = max_bbox[0]
            max_u_trans = max_bbox[1]
            max_r_trans = w - max_bbox[2]
            max_d_trans = h - max_bbox[3]

            crop_xmin = max(0, int(max_bbox[0] - random.uniform(0, max_l_trans)))
            crop_ymin = max(0, int(max_bbox[1] - random.uniform(0, max_u_trans)))
            crop_xmax = max(w, int(max_bbox[2] + random.uniform(0, max_r_trans)))
            crop_ymax = max(h, int(max_bbox[3] + random.uniform(0, max_d_trans)))

            image = image[crop_ymin : crop_ymax, crop_xmin : crop_xmax]

            bboxes[:, [0, 2]] = bboxes[:, [0, 2]] - crop_xmin
            bboxes[:, [1, 3]] = bboxes[:, [1, 3]] - crop_ymin

        return image, bboxes

     # 圖片增強(qiáng)操作之-隨機(jī)移動
    def random_translate(self, image, bboxes):

        if random.random() < 0.5:
            h, w, _ = image.shape
            max_bbox = np.concatenate([np.min(bboxes[:, 0:2], axis=0), np.max(bboxes[:, 2:4], axis=0)], axis=-1)

            max_l_trans = max_bbox[0]
            max_u_trans = max_bbox[1]
            max_r_trans = w - max_bbox[2]
            max_d_trans = h - max_bbox[3]

            tx = random.uniform(-(max_l_trans - 1), (max_r_trans - 1))
            ty = random.uniform(-(max_u_trans - 1), (max_d_trans - 1))

            M = np.array([[1, 0, tx], [0, 1, ty]])
            image = cv2.warpAffine(image, M, (w, h))

            bboxes[:, [0, 2]] = bboxes[:, [0, 2]] + tx
            bboxes[:, [1, 3]] = bboxes[:, [1, 3]] + ty

        return image, bboxes
parse_annotation
    #解析出圖片信息和真實框信息
    def parse_annotation(self, annotation):

        line = annotation.split()
        image_path = line[0]
        if not os.path.exists(image_path):
            raise KeyError("%s does not exist ... " %image_path)
        image = cv2.imread(image_path)#讀取圖片信息
        bboxes = np.array([list(map(int, box.split(','))) for box in line[1:]])#將真實框數(shù)據(jù)由字符串型轉(zhuǎn)換為整型

        # 一系列的數(shù)據(jù)增強(qiáng)操作
        if self.data_aug:
            image, bboxes = self.random_horizontal_flip(np.copy(image), np.copy(bboxes))
            image, bboxes = self.random_crop(np.copy(image), np.copy(bboxes))
            image, bboxes = self.random_translate(np.copy(image), np.copy(bboxes))

        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image, bboxes = utils.image_preporcess(np.copy(image), [self.train_input_size, self.train_input_size], np.copy(bboxes))#將圖片尺寸處理成神經(jīng)網(wǎng)絡(luò)需要的圖片尺寸勉吻,相應(yīng)的真實框的數(shù)據(jù)信息也要進(jìn)行處理(主要是數(shù)據(jù)偏移處理)
        return image, bboxes

bbox_iou
    # 計算兩個框框的iou值,處理方法與yolov3.py文件中的bbox_iou方法大致相同
    def bbox_iou(self, boxes1, boxes2):

        boxes1 = np.array(boxes1)
        boxes2 = np.array(boxes2)

        boxes1_area = boxes1[..., 2] * boxes1[..., 3]
        boxes2_area = boxes2[..., 2] * boxes2[..., 3]

        boxes1 = np.concatenate([boxes1[..., :2] - boxes1[..., 2:] * 0.5,
                                boxes1[..., :2] + boxes1[..., 2:] * 0.5], axis=-1)
        boxes2 = np.concatenate([boxes2[..., :2] - boxes2[..., 2:] * 0.5,
                                boxes2[..., :2] + boxes2[..., 2:] * 0.5], axis=-1)

        left_up = np.maximum(boxes1[..., :2], boxes2[..., :2])
        right_down = np.minimum(boxes1[..., 2:], boxes2[..., 2:])

        inter_section = np.maximum(right_down - left_up, 0.0)
        inter_area = inter_section[..., 0] * inter_section[..., 1]
        union_area = boxes1_area + boxes2_area - inter_area

        return inter_area / union_area
preprocess_true_boxes
    def preprocess_true_boxes(self, bboxes):

        # 3個尺度的特征圖信息
        label = [np.zeros((self.train_output_sizes[i], self.train_output_sizes[i], self.anchor_per_scale,
                           5 + self.num_classes)) for i in range(3)]
        # 3個尺度的真實框張量
        bboxes_xywh = [np.zeros((self.max_bbox_per_scale, 4)) for _ in range(3)]
        bbox_count = np.zeros((3,))

        for bbox in bboxes:#遍歷真實框數(shù)組
            bbox_coor = bbox[:4]#取出每個真實框的坐標(biāo)信息(2個左上角坐標(biāo)+2個右下角坐標(biāo))
            bbox_class_ind = bbox[4]#每個真實框的類別

            #開始對類別進(jìn)行one-hot編碼
            onehot = np.zeros(self.num_classes, dtype=np.float)
            onehot[bbox_class_ind] = 1.0
            uniform_distribution = np.full(self.num_classes, 1.0 / self.num_classes)
            deta = 0.01
            #最終處理完成的類別one-hot編碼
            smooth_onehot = onehot * (1 - deta) + deta * uniform_distribution

            #將真實框的坐標(biāo)從(2個左上角坐標(biāo)+2個右下角坐標(biāo))轉(zhuǎn)換為(2個中心點坐標(biāo)+2個高寬)
            bbox_xywh = np.concatenate([(bbox_coor[2:] + bbox_coor[:2]) * 0.5, bbox_coor[2:] - bbox_coor[:2]], axis=-1)
           #將真實框的坐標(biāo)轉(zhuǎn)換為特征圖上的坐標(biāo)旅赢,bbox_xywh的shape=[1,4]齿桃,self.strides的shape=[3,1],于是bbox_xywh_scaled的shape=[1,3,4]煮盼,即計算出了每個真實框在3個尺度下的坐標(biāo)信息
            bbox_xywh_scaled = 1.0 * bbox_xywh[np.newaxis, :] / self.strides[:, np.newaxis]

            iou = []#保存真實框與9個先驗框計算的iou值
            exist_positive = False#真實框是否有相匹配的先驗框的標(biāo)志
            for i in range(3):#遍歷3個尺度
                #每個尺度下有3個先驗框
                anchors_xywh = np.zeros((self.anchor_per_scale, 4))
                #3個先驗框的中心坐標(biāo)短纵,讓它在真實框所在的格子的中心坐標(biāo)上。
                anchors_xywh[:, 0:2] = np.floor(bbox_xywh_scaled[i, 0:2]).astype(np.int32) + 0.5
                #3個先驗框的尺寸大小
                anchors_xywh[:, 2:4] = self.anchors[i]

                #計算真實框與這3個先驗框的iou值
                iou_scale = self.bbox_iou(bbox_xywh_scaled[i][np.newaxis, :], anchors_xywh)
                #保存iou值
                iou.append(iou_scale)
                #找出符合條件的iou值
                iou_mask = iou_scale > 0.3

                if np.any(iou_mask):
                    #到這一步孕似,說明有符合條件的先驗框踩娘,于是找出真實框所在的格子坐標(biāo),即第幾行幾列
                    xind, yind = np.floor(bbox_xywh_scaled[i, 0:2]).astype(np.int32)

                    #首先清除下該尺度下對應(yīng)格子的信息
                    label[i][yind, xind, iou_mask, :] = 0
                    #在該尺度的格子中填充進(jìn)真實框坐標(biāo)信息
                    label[i][yind, xind, iou_mask, 0:4] = bbox_xywh
                    #該尺度的格子中的置信度置為1喉祭,表明該格子中有檢測到物體
                    label[i][yind, xind, iou_mask, 4:5] = 1.0
                    #填充該尺度的格子中的類別信息养渴,就是前面已經(jīng)做好的類別one-hot編碼
                    label[i][yind, xind, iou_mask, 5:] = smooth_onehot

                    #找出該尺度下真實框張量中的索引
                    bbox_ind = int(bbox_count[i] % self.max_bbox_per_scale)
                    #在真實框張量的索引位置處填充進(jìn)真實框信息
                    bboxes_xywh[i][bbox_ind, :4] = bbox_xywh
                    #該索引下的值+1
                    bbox_count[i] += 1

                    #表明有符合真實框要求的先驗框
                    exist_positive = True

            if not exist_positive:
                #如果沒有符合真實框要求的先驗框,那就在9個iou值中找出最大的那個值的索引
                best_anchor_ind = np.argmax(np.array(iou).reshape(-1), axis=-1)
                #計算這個最大的先驗框所在的尺度
                best_detect = int(best_anchor_ind / self.anchor_per_scale)
                #計算在該尺度下的哪個先驗框
                best_anchor = int(best_anchor_ind % self.anchor_per_scale)
                #同樣泛烙,找出在該尺度下的格子坐標(biāo)理卑,即第幾行第幾列
                xind, yind = np.floor(bbox_xywh_scaled[best_detect, 0:2]).astype(np.int32)

                #和上面的處理過程一樣,首先清除該尺度下的對應(yīng)格子信息
                label[best_detect][yind, xind, best_anchor, :] = 0
                #在該格子中填充真實框信息
                label[best_detect][yind, xind, best_anchor, 0:4] = bbox_xywh
                #把該格子的置信度置為1
                label[best_detect][yind, xind, best_anchor, 4:5] = 1.0
                #填充該格子的類別one-hot
                label[best_detect][yind, xind, best_anchor, 5:] = smooth_onehot

                #這也和上面一樣蔽氨,找出該尺度下的真實框張量的索引
                bbox_ind = int(bbox_count[best_detect] % self.max_bbox_per_scale)
               #把真實框信息填充到真實框張量的索引位置處
                bboxes_xywh[best_detect][bbox_ind, :4] = bbox_xywh
                #該尺度下的索引值+1
                bbox_count[best_detect] += 1
        #3個尺度的特征信息
        label_sbbox, label_mbbox, label_lbbox = label
        #3個尺度的真實框張量信息
        sbboxes, mbboxes, lbboxes = bboxes_xywh
        return label_sbbox, label_mbbox, label_lbbox, sbboxes, mbboxes, lbboxes
len
    #返回數(shù)據(jù)集的批次大小
    def __len__(self):
        return self.num_batchs

這就是yolov3數(shù)據(jù)集的制作流程和代碼藐唠,在下一篇中我們來看yolov3是如何實現(xiàn)訓(xùn)練神經(jīng)網(wǎng)絡(luò)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鹉究,一起剝皮案震驚了整個濱河市宇立,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌自赔,老刑警劉巖妈嘹,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绍妨,居然都是意外死亡润脸,警方通過查閱死者的電腦和手機(jī)柬脸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毙驯,“玉大人倒堕,你說我怎么就攤上這事”郏” “怎么了垦巴?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铭段。 經(jīng)常有香客問我魂那,道長,這世上最難降的妖魔是什么稠项? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任涯雅,我火速辦了婚禮,結(jié)果婚禮上展运,老公的妹妹穿的比我還像新娘活逆。我一直安慰自己,他們只是感情好拗胜,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布蔗候。 她就那樣靜靜地躺著,像睡著了一般埂软。 火紅的嫁衣襯著肌膚如雪锈遥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天勘畔,我揣著相機(jī)與錄音所灸,去河邊找鬼。 笑死炫七,一個胖子當(dāng)著我的面吹牛爬立,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播万哪,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼侠驯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了奕巍?” 一聲冷哼從身側(cè)響起吟策,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎的止,沒想到半個月后檩坚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年效床,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片权谁。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡剩檀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旺芽,到底是詐尸還是另有隱情沪猴,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布采章,位于F島的核電站运嗜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏悯舟。R本人自食惡果不足惜担租,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望抵怎。 院中可真熱鬧奋救,春花似錦、人聲如沸反惕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姿染。三九已至背亥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間悬赏,已是汗流浹背狡汉。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留闽颇,地道東北人轴猎。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像进萄,于是被迫代替她去往敵國和親捻脖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 在上一篇中學(xué)習(xí)了yolov3中的darknet53模型中鼠,在這一篇中我們繼續(xù)來分析yolov3的源代碼可婶。 需要說明的...
    climb66的夏天閱讀 547評論 0 0
  • 這段時間學(xué)習(xí)了yolo v3的源代碼,作一下筆記援雇。這個tensorflow版本的yolo v3源碼出自這里mali...
    climb66的夏天閱讀 542評論 0 1
  • 近幾年來矛渴,目標(biāo)檢測算法取得了很大的突破。比較流行的算法可以分為兩類,一類是基于Region Proposal的R-...
    KyleLou閱讀 668評論 0 1
  • YOLOv3在YOLOv2的基礎(chǔ)進(jìn)行了一些改進(jìn)具温,這些更改使其效果變得更好蚕涤。 在320×320的圖像上,YOLOv3...
    Daisy丶閱讀 65,378評論 53 58
  • 久違的晴天铣猩,家長會揖铜。 家長大會開好到教室時,離放學(xué)已經(jīng)沒多少時間了达皿。班主任說已經(jīng)安排了三個家長分享經(jīng)驗天吓。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,523評論 16 22