• YOLOv3目标检测全过程记录


    前提:

    软硬件环境:
    python 3.6.5
    Ubuntu18.04 LTS
    PyTorch 1.1.0
    CUDA 10.0
    cudnn 7.5.0
    GPU: NVIDIA TITAN XP

    一  准备数据集

    1. 准备图片

            这个可以需要自己拍摄,一般识别一件物体准备500张图片即可

    2. 进行数据标定

            这需要使用labelImg来进行数据的标定工作

            labelImg的安装方式如下所示:

    1. sudo apt-get install pyqt5-dev-tools
    2. sudo pip3 install -r requirements/requirements-linux-python3.txt
    3. make qt5py3
    4. python3 labelImg.py

            在运行第二行命令时可能会出现缺少pip3之类的提示,可以通过运行以下命令解决:

    sudo apt-get install python3-pip 

     关于 labelImg的具体使用可以参考网上的具体教程

    二  下载并安装darknet

    1. 官方代码下载地址:https://github.com/pjreddie/darknet

    当然,你也可以采用以下命令进行下载

    git clone https://github.com/pjreddie/darknet
    

    2. 现在开始编译

    1. cd darknet
    2. sudo gedit Makefile

    打开后,根据自己的需求修改文件夹,因为我用GPU,所以修改为GPU=1,CUDNN=1,OPENCV我设为0,因为我不使用摄像头。

    make

    接着用make命令进行编译,出现以下界面,编译成功:

    三  实验数据集整理与准备

            1. 将上一步解压的darknet文件夹放到home根目录下,然后再建立一个文件夹,命名为VOCdekit,再在VOCdekit文件夹下建立一个VOC2022,然后再在VOC2022下面创建三个文件夹,分别为Annotations,JPEGImages和ImageSets. 将标注的数据集放在 Annotations 下,即.xml格式的文件,  将所有用到的图片放到JPEGImages下,再在ImageSets下建立一个Main文件夹。
            2. 刚才建立这么多文件夹,解释一下它们要做的事:VOC2022建立,因为要制作VOC2022格式的数据集,源码中的路径命名都是按照这样的格式来的。那么在VOC2022中的Annotations又有什么用?它是为存放xml格式的标签文件的,也就是你刚才用Labelmg制作的标签文件,里面保存了每张图片的尺寸、物体类别、boundingbox等等信息,每一张xml文件都对应了JPEGImages中的一张图片。JPEGImages自然而然就是存放数据集图片的文件夹,也就是你自己收集的训练和测试图片。ImageSets里面本来时包含了三个文件夹的,但是我们只强调存放图像数据的Main文件,这个Main文件存着训练、测试和验证集的图片名称,也就是起到分割三个集的作用。
            3. 在VOC2022下建立一个test.py文件,将以下代码拷进去

    1. import os
    2. import random
    3. trainval_percent = 0.1
    4. train_percent = 0.9
    5. xmlfilepath = 'Annotations'
    6. txtsavepath = 'ImageSets\Main'
    7. total_xml = os.listdir(xmlfilepath)
    8. num = len(total_xml)
    9. list = range(num)
    10. tv = int(num * trainval_percent)
    11. tr = int(tv * train_percent)
    12. trainval = random.sample(list, tv)
    13. train = random.sample(trainval, tr)
    14. ftrainval = open('ImageSets/Main/trainval.txt', 'w')
    15. ftest = open('ImageSets/Main/test.txt', 'w')
    16. ftrain = open('ImageSets/Main/train.txt', 'w')
    17. fval = open('ImageSets/Main/val.txt', 'w')
    18. for i in list:
    19. name = total_xml[i][:-4] + '\n'
    20. if i in trainval:
    21. ftrainval.write(name)
    22. if i in train:
    23. ftest.write(name)
    24. else:
    25. fval.write(name)
    26. else:
    27. ftrain.write(name)
    28. ftrainval.close()
    29. ftrain.close()
    30. fval.close()
    31. ftest.close()

    4. 在VOC2022下打开终端,运行上述的python文件

    python test.py

    运行成功后会看到Main文件下多了四个txt文件

    四  加入自己的数据集

    1. 在darknet文件夹下打开终端(注意是在darknet文件下打开终端),然后输入如下命令

    wget https://pjreddie.com/media/files/voc_label.py

    如果不能下载的话也可以直接复制网址自己去下载, 下载完后将voc_label.py放到darknet文件夹下

    2. 进行voc_label.py文件的修改:

            (1)首先删除包含2007的所有项

            (2)将剩余的2012全部改为2022(注意:这里的2022即为上述我们所建立的VOC2022,如果是VOC2033则改为2033)

            (3)classes保存自己要检测的类别即可

    3. 再darknet文件夹下打开终端,输入如下命令:

    1. python voc_label.py
    2. cat 2022_train.txt 2022_val.txt > train.txt

    注意:这里的2022_train.txt和后面的2022_val.txt要和自己上面所建立的VOC2022保持一致

    结束后,应该会发现,出现三个txt文件2022_train.txt,2022_val.txt,2022_test.txt,这是真正有用的三个文件。

    五 修改配置

    1. 在darknet文件下的cfg文件夹下面创建一个zp_test.data文件夹,.data文件夹的创建方式可以直接复制cfg文件夹下面已有的.data文件,然后做相应的修改即可

    具体的修改方式如下所示:

    1. classes=<你需要检测的类别数量>
    2. train = <2007_train.txt 文件所在的位置>
    3. valid = <2007_test.txt/2007_valid.txt 文件所在位置,这不太重要>
    4. names = <names文件所在位置>
    5. backup = <backup文件夹所在位置,没有就自己建一个>---这个即为最后数据训练完成后权重文件所存放的位置

    比如我的data文件的内容如下所示:

    1. classes=11
    2. train=/home/robot/darknet/2022_train.txt
    3. valid=/home/robot/darknet/2022_test.txt
    4. names=/home/robot/darknet/data/cell.names
    5. backup=backup/zp_test

    2. 在darknet文件下的data文件夹下面创建一个zp_test.names文件夹,.names文件夹的创建方式可以直接复制data文件夹下面已有的.names文件,然后做相应的修改即可

    具体的修改方式如下所示:即按照从上到下的顺序依次填写自己训练物品的名称

     

    3. 网络配置在cfg中,此次采用yolov3.cfg,这里需要修改cfg文件。每个[yolo]及其前的卷积层都要修改,主要修改卷积层中的filters的数量,数量计算公式是 filters= 3*(5+类别数),比如我这里有11个类别,filters=48. 还要修改[yolo]中的classes数,几个类别写几,我是11个类别,就写11。

    (注意:如果正常的话,应该只有三处需要修改的地方!!! 可以直接Ctrl+F搜索[yolo]进行查找,只有三次需要修改的地方!!!)

    一下是我的修改后的文件

    1. [net]
    2. # Testing
    3. # batch=1
    4. # subdivisions=1
    5. # Training
    6. batch=64
    7. subdivisions=16
    8. width=608
    9. height=608
    10. channels=3
    11. momentum=0.9
    12. decay=0.0005
    13. angle=0
    14. saturation = 1.5
    15. exposure = 1.5
    16. hue=.1
    17. learning_rate=0.001
    18. burn_in=1000
    19. max_batches = 500200
    20. policy=steps
    21. steps=400000,450000
    22. scales=.1,.1
    23. [convolutional]
    24. batch_normalize=1
    25. filters=32
    26. size=3
    27. stride=1
    28. pad=1
    29. activation=leaky
    30. # Downsample
    31. [convolutional]
    32. batch_normalize=1
    33. filters=64
    34. size=3
    35. stride=2
    36. pad=1
    37. activation=leaky
    38. [convolutional]
    39. batch_normalize=1
    40. filters=32
    41. size=1
    42. stride=1
    43. pad=1
    44. activation=leaky
    45. [convolutional]
    46. batch_normalize=1
    47. filters=64
    48. size=3
    49. stride=1
    50. pad=1
    51. activation=leaky
    52. [shortcut]
    53. from=-3
    54. activation=linear
    55. # Downsample
    56. [convolutional]
    57. batch_normalize=1
    58. filters=128
    59. size=3
    60. stride=2
    61. pad=1
    62. activation=leaky
    63. [convolutional]
    64. batch_normalize=1
    65. filters=64
    66. size=1
    67. stride=1
    68. pad=1
    69. activation=leaky
    70. [convolutional]
    71. batch_normalize=1
    72. filters=128
    73. size=3
    74. stride=1
    75. pad=1
    76. activation=leaky
    77. [shortcut]
    78. from=-3
    79. activation=linear
    80. [convolutional]
    81. batch_normalize=1
    82. filters=64
    83. size=1
    84. stride=1
    85. pad=1
    86. activation=leaky
    87. [convolutional]
    88. batch_normalize=1
    89. filters=128
    90. size=3
    91. stride=1
    92. pad=1
    93. activation=leaky
    94. [shortcut]
    95. from=-3
    96. activation=linear
    97. # Downsample
    98. [convolutional]
    99. batch_normalize=1
    100. filters=256
    101. size=3
    102. stride=2
    103. pad=1
    104. activation=leaky
    105. [convolutional]
    106. batch_normalize=1
    107. filters=128
    108. size=1
    109. stride=1
    110. pad=1
    111. activation=leaky
    112. [convolutional]
    113. batch_normalize=1
    114. filters=256
    115. size=3
    116. stride=1
    117. pad=1
    118. activation=leaky
    119. [shortcut]
    120. from=-3
    121. activation=linear
    122. [convolutional]
    123. batch_normalize=1
    124. filters=128
    125. size=1
    126. stride=1
    127. pad=1
    128. activation=leaky
    129. [convolutional]
    130. batch_normalize=1
    131. filters=256
    132. size=3
    133. stride=1
    134. pad=1
    135. activation=leaky
    136. [shortcut]
    137. from=-3
    138. activation=linear
    139. [convolutional]
    140. batch_normalize=1
    141. filters=128
    142. size=1
    143. stride=1
    144. pad=1
    145. activation=leaky
    146. [convolutional]
    147. batch_normalize=1
    148. filters=256
    149. size=3
    150. stride=1
    151. pad=1
    152. activation=leaky
    153. [shortcut]
    154. from=-3
    155. activation=linear
    156. [convolutional]
    157. batch_normalize=1
    158. filters=128
    159. size=1
    160. stride=1
    161. pad=1
    162. activation=leaky
    163. [convolutional]
    164. batch_normalize=1
    165. filters=256
    166. size=3
    167. stride=1
    168. pad=1
    169. activation=leaky
    170. [shortcut]
    171. from=-3
    172. activation=linear
    173. [convolutional]
    174. batch_normalize=1
    175. filters=128
    176. size=1
    177. stride=1
    178. pad=1
    179. activation=leaky
    180. [convolutional]
    181. batch_normalize=1
    182. filters=256
    183. size=3
    184. stride=1
    185. pad=1
    186. activation=leaky
    187. [shortcut]
    188. from=-3
    189. activation=linear
    190. [convolutional]
    191. batch_normalize=1
    192. filters=128
    193. size=1
    194. stride=1
    195. pad=1
    196. activation=leaky
    197. [convolutional]
    198. batch_normalize=1
    199. filters=256
    200. size=3
    201. stride=1
    202. pad=1
    203. activation=leaky
    204. [shortcut]
    205. from=-3
    206. activation=linear
    207. [convolutional]
    208. batch_normalize=1
    209. filters=128
    210. size=1
    211. stride=1
    212. pad=1
    213. activation=leaky
    214. [convolutional]
    215. batch_normalize=1
    216. filters=256
    217. size=3
    218. stride=1
    219. pad=1
    220. activation=leaky
    221. [shortcut]
    222. from=-3
    223. activation=linear
    224. [convolutional]
    225. batch_normalize=1
    226. filters=128
    227. size=1
    228. stride=1
    229. pad=1
    230. activation=leaky
    231. [convolutional]
    232. batch_normalize=1
    233. filters=256
    234. size=3
    235. stride=1
    236. pad=1
    237. activation=leaky
    238. [shortcut]
    239. from=-3
    240. activation=linear
    241. # Downsample
    242. [convolutional]
    243. batch_normalize=1
    244. filters=512
    245. size=3
    246. stride=2
    247. pad=1
    248. activation=leaky
    249. [convolutional]
    250. batch_normalize=1
    251. filters=256
    252. size=1
    253. stride=1
    254. pad=1
    255. activation=leaky
    256. [convolutional]
    257. batch_normalize=1
    258. filters=512
    259. size=3
    260. stride=1
    261. pad=1
    262. activation=leaky
    263. [shortcut]
    264. from=-3
    265. activation=linear
    266. [convolutional]
    267. batch_normalize=1
    268. filters=256
    269. size=1
    270. stride=1
    271. pad=1
    272. activation=leaky
    273. [convolutional]
    274. batch_normalize=1
    275. filters=512
    276. size=3
    277. stride=1
    278. pad=1
    279. activation=leaky
    280. [shortcut]
    281. from=-3
    282. activation=linear
    283. [convolutional]
    284. batch_normalize=1
    285. filters=256
    286. size=1
    287. stride=1
    288. pad=1
    289. activation=leaky
    290. [convolutional]
    291. batch_normalize=1
    292. filters=512
    293. size=3
    294. stride=1
    295. pad=1
    296. activation=leaky
    297. [shortcut]
    298. from=-3
    299. activation=linear
    300. [convolutional]
    301. batch_normalize=1
    302. filters=256
    303. size=1
    304. stride=1
    305. pad=1
    306. activation=leaky
    307. [convolutional]
    308. batch_normalize=1
    309. filters=512
    310. size=3
    311. stride=1
    312. pad=1
    313. activation=leaky
    314. [shortcut]
    315. from=-3
    316. activation=linear
    317. [convolutional]
    318. batch_normalize=1
    319. filters=256
    320. size=1
    321. stride=1
    322. pad=1
    323. activation=leaky
    324. [convolutional]
    325. batch_normalize=1
    326. filters=512
    327. size=3
    328. stride=1
    329. pad=1
    330. activation=leaky
    331. [shortcut]
    332. from=-3
    333. activation=linear
    334. [convolutional]
    335. batch_normalize=1
    336. filters=256
    337. size=1
    338. stride=1
    339. pad=1
    340. activation=leaky
    341. [convolutional]
    342. batch_normalize=1
    343. filters=512
    344. size=3
    345. stride=1
    346. pad=1
    347. activation=leaky
    348. [shortcut]
    349. from=-3
    350. activation=linear
    351. [convolutional]
    352. batch_normalize=1
    353. filters=256
    354. size=1
    355. stride=1
    356. pad=1
    357. activation=leaky
    358. [convolutional]
    359. batch_normalize=1
    360. filters=512
    361. size=3
    362. stride=1
    363. pad=1
    364. activation=leaky
    365. [shortcut]
    366. from=-3
    367. activation=linear
    368. [convolutional]
    369. batch_normalize=1
    370. filters=256
    371. size=1
    372. stride=1
    373. pad=1
    374. activation=leaky
    375. [convolutional]
    376. batch_normalize=1
    377. filters=512
    378. size=3
    379. stride=1
    380. pad=1
    381. activation=leaky
    382. [shortcut]
    383. from=-3
    384. activation=linear
    385. # Downsample
    386. [convolutional]
    387. batch_normalize=1
    388. filters=1024
    389. size=3
    390. stride=2
    391. pad=1
    392. activation=leaky
    393. [convolutional]
    394. batch_normalize=1
    395. filters=512
    396. size=1
    397. stride=1
    398. pad=1
    399. activation=leaky
    400. [convolutional]
    401. batch_normalize=1
    402. filters=1024
    403. size=3
    404. stride=1
    405. pad=1
    406. activation=leaky
    407. [shortcut]
    408. from=-3
    409. activation=linear
    410. [convolutional]
    411. batch_normalize=1
    412. filters=512
    413. size=1
    414. stride=1
    415. pad=1
    416. activation=leaky
    417. [convolutional]
    418. batch_normalize=1
    419. filters=1024
    420. size=3
    421. stride=1
    422. pad=1
    423. activation=leaky
    424. [shortcut]
    425. from=-3
    426. activation=linear
    427. [convolutional]
    428. batch_normalize=1
    429. filters=512
    430. size=1
    431. stride=1
    432. pad=1
    433. activation=leaky
    434. [convolutional]
    435. batch_normalize=1
    436. filters=1024
    437. size=3
    438. stride=1
    439. pad=1
    440. activation=leaky
    441. [shortcut]
    442. from=-3
    443. activation=linear
    444. [convolutional]
    445. batch_normalize=1
    446. filters=512
    447. size=1
    448. stride=1
    449. pad=1
    450. activation=leaky
    451. [convolutional]
    452. batch_normalize=1
    453. filters=1024
    454. size=3
    455. stride=1
    456. pad=1
    457. activation=leaky
    458. [shortcut]
    459. from=-3
    460. activation=linear
    461. ######################
    462. [convolutional]
    463. batch_normalize=1
    464. filters=512
    465. size=1
    466. stride=1
    467. pad=1
    468. activation=leaky
    469. [convolutional]
    470. batch_normalize=1
    471. size=3
    472. stride=1
    473. pad=1
    474. filters=1024
    475. activation=leaky
    476. [convolutional]
    477. batch_normalize=1
    478. filters=512
    479. size=1
    480. stride=1
    481. pad=1
    482. activation=leaky
    483. [convolutional]
    484. batch_normalize=1
    485. size=3
    486. stride=1
    487. pad=1
    488. filters=1024
    489. activation=leaky
    490. [convolutional]
    491. batch_normalize=1
    492. filters=512
    493. size=1
    494. stride=1
    495. pad=1
    496. activation=leaky
    497. [convolutional]
    498. batch_normalize=1
    499. size=3
    500. stride=1
    501. pad=1
    502. filters=1024
    503. activation=leaky
    504. [convolutional]
    505. size=1
    506. stride=1
    507. pad=1
    508. filters=48
    509. activation=linear
    510. [yolo]
    511. mask = 6,7,8
    512. anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
    513. classes=11
    514. num=9
    515. jitter=.3
    516. ignore_thresh = .7
    517. truth_thresh = 1
    518. random=1
    519. [route]
    520. layers = -4
    521. [convolutional]
    522. batch_normalize=1
    523. filters=256
    524. size=1
    525. stride=1
    526. pad=1
    527. activation=leaky
    528. [upsample]
    529. stride=2
    530. [route]
    531. layers = -1, 61
    532. [convolutional]
    533. batch_normalize=1
    534. filters=256
    535. size=1
    536. stride=1
    537. pad=1
    538. activation=leaky
    539. [convolutional]
    540. batch_normalize=1
    541. size=3
    542. stride=1
    543. pad=1
    544. filters=512
    545. activation=leaky
    546. [convolutional]
    547. batch_normalize=1
    548. filters=256
    549. size=1
    550. stride=1
    551. pad=1
    552. activation=leaky
    553. [convolutional]
    554. batch_normalize=1
    555. size=3
    556. stride=1
    557. pad=1
    558. filters=512
    559. activation=leaky
    560. [convolutional]
    561. batch_normalize=1
    562. filters=256
    563. size=1
    564. stride=1
    565. pad=1
    566. activation=leaky
    567. [convolutional]
    568. batch_normalize=1
    569. size=3
    570. stride=1
    571. pad=1
    572. filters=512
    573. activation=leaky
    574. [convolutional]
    575. size=1
    576. stride=1
    577. pad=1
    578. filters=48
    579. activation=linear
    580. [yolo]
    581. mask = 3,4,5
    582. anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
    583. classes=11
    584. num=9
    585. jitter=.3
    586. ignore_thresh = .7
    587. truth_thresh = 1
    588. random=1
    589. [route]
    590. layers = -4
    591. [convolutional]
    592. batch_normalize=1
    593. filters=128
    594. size=1
    595. stride=1
    596. pad=1
    597. activation=leaky
    598. [upsample]
    599. stride=2
    600. [route]
    601. layers = -1, 36
    602. [convolutional]
    603. batch_normalize=1
    604. filters=128
    605. size=1
    606. stride=1
    607. pad=1
    608. activation=leaky
    609. [convolutional]
    610. batch_normalize=1
    611. size=3
    612. stride=1
    613. pad=1
    614. filters=256
    615. activation=leaky
    616. [convolutional]
    617. batch_normalize=1
    618. filters=128
    619. size=1
    620. stride=1
    621. pad=1
    622. activation=leaky
    623. [convolutional]
    624. batch_normalize=1
    625. size=3
    626. stride=1
    627. pad=1
    628. filters=256
    629. activation=leaky
    630. [convolutional]
    631. batch_normalize=1
    632. filters=128
    633. size=1
    634. stride=1
    635. pad=1
    636. activation=leaky
    637. [convolutional]
    638. batch_normalize=1
    639. size=3
    640. stride=1
    641. pad=1
    642. filters=256
    643. activation=leaky
    644. [convolutional]
    645. size=1
    646. stride=1
    647. pad=1
    648. filters=48
    649. activation=linear
    650. [yolo]
    651. mask = 0,1,2
    652. anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
    653. classes=11
    654. num=9
    655. jitter=.3
    656. ignore_thresh = .7
    657. truth_thresh = 1
    658. random=1

    4. 下载yolov3的初始权重,还要下载一下darknet53.conv.74的模型参数

    wget https://pjreddie.com/media/files/darknet53.conv.74
    

    如果无法下载的话,也可以直接复制网址自己进行下载,下载完后将darknet53.conv.74放在darknet文件夹下.

    六  进行数据训练

    在darknet中打开终端,输入如下命令进行训练:

    ./darknet detector train cfg/zp_test.data cfg/yolov3.cfg darknet53.conv.74
    

    这里再提醒一下,上面那句代码,zp_test.data换为你自己刚才建立的data文件,yolov3.cfg是因为我使用的是yolov3模型,如果用其他模型,就输入其他模型比如yolov3-tiny.cfg之类的,那么就要在第5步下载相对应的权重。 

    当这个数字下降到0.0x的时候说明已经训练可以. 最前面的29表示训练的轮数

     七  开始进行识别

            1. 将之前训练好的bakeup里面的权重文件.weights文件放到 /catkin_ws/src/darknet_ros/darknet_ros/yolo_network_config/weights里面

            2. 将之前改好的 .cfg 文件放到 /catkin_ws/src/darknet_ros/darknet_ros/yolo_network_config/cfg

    这个.cfg文件即为上面的yolov3.cfg文件,这里建议粘贴复制一份,即将yolov3.cfg拷贝一份命名比如为yolov3-voc-zp.cfg,然后将yolov3-voc-zp.cfg放到/catkin_ws/src/darknet_ros/darknet_ros/yolo_network_config/cfg下面. 这样可以避免命名重复

            3. 将这个/catkin_ws/src/darknet_ros/darknet_ros/config/yolov3-voc.yaml文件拷贝一份(位置也在当前文件夹,比如命名为yolov3-zp.yaml),然后将中的config_fileweight_filenames根据实际情况修改,其实就是之前添加进来的两个文件

     

     注意:这里的权重文件有许多,选择最后那个,因为训练的时候每一轮都会产生一个权重文件,然后将前面的权重文件进行覆盖,所以这里只写最后那个生成的权重文件即可

            4. 修改ros.yaml文件

    找到/home/robot/catkin_ws/src/darknet_ros/darknet_ros/config目录下的ros.yaml文件,进行摄像头的配置工作.根据自己的需要选择不同的摄像头的topic

    5. 创建相关的启动launch文件

    在该目录下:/home/robot/catkin_ws/src/darknet_ros/darknet_ros/launch, 创建一个launch文件,模板可以复制之前的,然后进行相应的修改即可,比如我创建了一个yolo_v3_zp.launch

     然后对里面的内容进行相应的修改,主要就修改下图中标注的地方即可,后面的yaml文件即为/catkin_ws/src/darknet_ros/darknet_ros/config目录下刚刚自己所创建的那个yaml文件

     6.  开始进行识别

    我使用的是realsense摄像头进行识别

    首先运行刚刚创建的那个launch文件,下面命令根据自己所创建的launch文件进行修改即可

    roslaunch darknet_ros yolo_v3_zp.launch

    然后摄像头的启动项,我使用的是realsense摄像头,具体代码配置自行编写

    rosrun realsense_test realsense_recognition

    下面是我的代码

    1. //realsense
    2. #include <librealsense2/rs.hpp>
    3. //ros
    4. # include "ros/ros.h"
    5. //C++
    6. # include <bits/stdc++.h>
    7. //Opencv
    8. # include "opencv2/opencv.hpp"
    9. # include <cv_bridge/cv_bridge.h>
    10. # include <image_transport/image_transport.h>
    11. //darknet
    12. # include "realsense_test/BoundingBoxes.h"
    13. # include "realsense_test/BoundingBox.h"
    14. using namespace cv;
    15. using namespace std;
    16. //物体识别
    17. struct Objects
    18. {
    19. int xmin, ymin, xmax, ymax; //一个物品的左上角和右下角坐标
    20. Objects(int a, int b, int c, int d) : xmin(a), ymin(b), xmax(c), ymax(d) {}
    21. };
    22. struct target_object
    23. {
    24. int xmid, ymid, distance; //物体中间坐标和距离
    25. };
    26. multimap<string, Objects> all_objects; //存储所有的物品信息,因为一张图片中可能会出现多种一样的东西,所以用multimap
    27. void ObjectCallback(const realsense_test::BoundingBoxes::ConstPtr &msg)
    28. {
    29. for (int i = 0; i < msg->bounding_boxes.size(); ++i)
    30. {
    31. realsense_test::BoundingBox temp = msg->bounding_boxes[i];
    32. if (temp.probability > 0.6)
    33. { //大于0.6,我们就认为可信
    34. all_objects.insert(make_pair(temp.Class, Objects(temp.xmin, temp.ymin, temp.xmax, temp.ymax)));
    35. }
    36. }
    37. }
    38. //测量物体位置(返回物体中心点坐标和物体的距离)
    39. target_object ObjectMark(Mat &color, Mat &depth, int xmin, int ymin, int xmax, int ymax)
    40. {
    41. //计算图像中间30*30个像素点深度的众数
    42. int xmid = (int)(xmin + xmax) * 0.5;
    43. int ymid = (int)(ymin + ymax) * 0.5;
    44. map<int, int> depthmap; //用于计算众数
    45. for(int i = ymid - 10; i <= ymid + 10; i ++)
    46. {
    47. const uint16_t *pD = depth.ptr<uint16_t>(i);
    48. for(int j = xmid - 10; j <= xmid + 10; j ++)
    49. {
    50. int distance;
    51. distance = *(pD + j);
    52. depthmap[distance] ++;
    53. }
    54. }
    55. int max = -1;
    56. int temp_distance = -1;
    57. for(auto value : depthmap)
    58. {
    59. if(value.second > max)
    60. {
    61. max = value.second;
    62. temp_distance = value.first;
    63. }
    64. }
    65. depthmap.clear();
    66. int final_distance = temp_distance;
    67. if(final_distance < 0) final_distance = 0;
    68. //int final_distance = depth.at<uint16_t>(xmid, ymid);
    69. putText(color, to_string(final_distance), Point(xmid, ymid), FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, 8, false);
    70. rectangle(color, Point(xmin, ymin), Point(xmax, ymax), Scalar(0, 255, 0), 3);
    71. target_object tobj;
    72. tobj.distance = final_distance;
    73. tobj.xmid = xmid;
    74. tobj.ymid = ymid;
    75. //imshow("color", color);
    76. return tobj;
    77. }
    78. int main(int argc, char *argv[])
    79. {
    80. //=================ros初始化==============
    81. ros::init(argc, argv, "move_test");
    82. ros::NodeHandle n;
    83. //realsense RGB图像发布者
    84. image_transport::ImageTransport it(n);
    85. image_transport::Publisher rgb_pub = it.advertise("realsense/RGBImage", 1);
    86. cout<<"11111"<<endl;
    87. ros::Subscriber sub = n.subscribe("/darknet_ros/bounding_boxes", 2, ObjectCallback);
    88. cout<<"222222"<<endl;
    89. //开启realsense
    90. //创建数据管道
    91. rs2::pipeline p;
    92. rs2::config pipe_config;
    93. pipe_config.enable_stream(RS2_STREAM_DEPTH,1280,720,RS2_FORMAT_Z16,30);
    94. pipe_config.enable_stream(RS2_STREAM_COLOR,1280,720,RS2_FORMAT_RGB8,30);
    95. //start()函数返回数据管道的profile
    96. rs2::pipeline_profile profile = p.start(pipe_config);
    97. Mat color, depth;
    98. while(waitKey(30) != 27)
    99. {
    100. //捕获RGB和深度图像
    101. rs2::frameset frames = p.wait_for_frames();
    102. rs2::video_frame rs_color = frames.get_color_frame();
    103. rs2::depth_frame rs_depth = frames.get_depth_frame();
    104. //将RBG图像转为opencv类型
    105. const int wc = rs_color.as<rs2::video_frame>().get_width();
    106. const int hc = rs_color.as<rs2::video_frame>().get_height();
    107. Mat color1(Size(wc, hc), CV_8UC3, (void*)rs_color.get_data(), Mat::AUTO_STEP);
    108. cvtColor(color1, color, cv::COLOR_RGB2BGR);
    109. //将深度图像转为opencv类型
    110. const int wd = rs_depth.as<rs2::depth_frame>().get_width();
    111. const int hd = rs_depth.as<rs2::depth_frame>().get_height();
    112. Mat depth(Size(wd, hd), CV_16U, (void*)rs_depth.get_data(), Mat::AUTO_STEP);
    113. //发布RGB图像
    114. sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", color).toImageMsg();
    115. ros::Rate loop_rate(30);
    116. loop_rate.sleep();
    117. ros::spinOnce();
    118. rgb_pub.publish(msg);
    119. target_object tobj; //目标物体
    120. //imshow("zp",color);
    121. for(auto value : all_objects)
    122. {
    123. tobj = ObjectMark(color, depth, value.second.xmin,
    124. value.second.ymin, value.second.xmax, value.second.ymax);
    125. ros::Rate loop_rate(100);
    126. loop_rate.sleep();
    127. }
    128. all_objects.clear();
    129. }
    130. return 0;
    131. }

  • 相关阅读:
    不同图像工具读取图片的区别
    transformer
    js控制台输出佛祖保佑图形图案/彩色图形图案实例代码
    设计模式 | 简单工厂模式
    修谱是一件好事:薪火相传,让老一辈庇护和提携后辈,造福乡里宗亲
    深度学习03-卷积神经网络(CNN)
    点击化学试剂DBCO-PEG-PLL 二苯并环辛炔-聚乙二醇-聚赖氨酸
    MATLAB实现改进M-K趋势分析
    c++基础2
    【原创】java+swing+mysql宠物领养管理系统设计与实现
  • 原文地址:https://blog.csdn.net/qq_58011370/article/details/125541838