You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

example.md 9.7 kB

4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. ---
  2. sidebar: false
  3. ---
  4. # Dora + YOLOV8 快速目标检测
  5. ## 安装`dora`
  6. * 一键安装
  7. ```bash
  8. $ curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/dora-rs/dora/main/install.sh | bash
  9. ```
  10. * `cargo安装`
  11. ```bash
  12. $ cargo install dora-cli
  13. ```
  14. * `手动安装`
  15. ```
  16. https://github.com/dora-rs/dora/releases
  17. ```
  18. ## 验证
  19. 终端输入命令`dora --version`,现实版本号即成功安装
  20. ```bash
  21. $ dora --version
  22. dora-cli 0.3.7
  23. ```
  24. ## 实时摄像头检测
  25. 1、创建数据流文件
  26. ```yaml title="dataflow.yml"
  27. nodes:
  28. - id: webcam
  29. operator:
  30. python: webcam.py
  31. inputs:
  32. tick: dora/timer/millis/50
  33. outputs:
  34. - image
  35. - id: object_detection
  36. operator:
  37. send_stdout_as: stdout
  38. python: object_detection.py
  39. inputs:
  40. image: webcam/image
  41. outputs:
  42. - bbox
  43. - stdout
  44. - id: plot
  45. operator:
  46. python: plot.py
  47. inputs:
  48. image: webcam/image
  49. bbox: object_detection/bbox
  50. assistant_message: object_detection/stdout
  51. ```
  52. 2、编写业务代码
  53. * 摄像头采集
  54. ```py title="webcam.py"
  55. import os
  56. import time
  57. import cv2
  58. import numpy as np
  59. import pyarrow as pa
  60. from dora import DoraStatus
  61. CAMERA_WIDTH = 640
  62. CAMERA_HEIGHT = 480
  63. CAMERA_INDEX = int(os.getenv("CAMERA_INDEX", 0))
  64. CI = os.environ.get("CI")
  65. font = cv2.FONT_HERSHEY_SIMPLEX
  66. class Operator:
  67. """
  68. Sending image from webcam to the dataflow
  69. """
  70. def __init__(self):
  71. self.video_capture = cv2.VideoCapture(CAMERA_INDEX)
  72. self.start_time = time.time()
  73. self.video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, CAMERA_WIDTH)
  74. self.video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, CAMERA_HEIGHT)
  75. self.failure_count = 0
  76. def on_event(
  77. self,
  78. dora_event: str,
  79. send_output,
  80. ) -> DoraStatus:
  81. event_type = dora_event["type"]
  82. if event_type == "INPUT":
  83. ret, frame = self.video_capture.read()
  84. if ret:
  85. frame = cv2.resize(frame, (CAMERA_WIDTH, CAMERA_HEIGHT))
  86. self.failure_count = 0
  87. ## Push an error image in case the camera is not available.
  88. else:
  89. if self.failure_count > 10:
  90. frame = np.zeros((CAMERA_HEIGHT, CAMERA_WIDTH, 3), dtype=np.uint8)
  91. cv2.putText(
  92. frame,
  93. "No Webcam was found at index %d" % (CAMERA_INDEX),
  94. (int(30), int(30)),
  95. font,
  96. 0.75,
  97. (255, 255, 255),
  98. 2,
  99. 1,
  100. )
  101. else:
  102. self.failure_count += 1
  103. return DoraStatus.CONTINUE
  104. send_output(
  105. "image",
  106. pa.array(frame.ravel()),
  107. dora_event["metadata"],
  108. )
  109. elif event_type == "STOP":
  110. print("received stop")
  111. else:
  112. print("received unexpected event:", event_type)
  113. if time.time() - self.start_time < 20 or CI != "true":
  114. return DoraStatus.CONTINUE
  115. else:
  116. return DoraStatus.STOP
  117. def __del__(self):
  118. self.video_capture.release()
  119. ```
  120. * 目标检测
  121. ```py title="object_detection.py"
  122. import numpy as np
  123. import pyarrow as pa
  124. from dora import DoraStatus
  125. from ultralytics import YOLO
  126. CAMERA_WIDTH = 640
  127. CAMERA_HEIGHT = 480
  128. model = YOLO("yolov8n.pt")
  129. class Operator:
  130. """
  131. Inferring object from images
  132. """
  133. def on_event(
  134. self,
  135. dora_event,
  136. send_output,
  137. ) -> DoraStatus:
  138. if dora_event["type"] == "INPUT":
  139. frame = (
  140. dora_event["value"].to_numpy().reshape((CAMERA_HEIGHT, CAMERA_WIDTH, 3))
  141. )
  142. frame = frame[:, :, ::-1] # OpenCV image (BGR to RGB)
  143. results = model(frame, verbose=False) # includes NMS
  144. # Process results
  145. boxes = np.array(results[0].boxes.xyxy.cpu())
  146. conf = np.array(results[0].boxes.conf.cpu())
  147. label = np.array(results[0].boxes.cls.cpu())
  148. # concatenate them together
  149. arrays = np.concatenate((boxes, conf[:, None], label[:, None]), axis=1)
  150. send_output("bbox", pa.array(arrays.ravel()), dora_event["metadata"])
  151. return DoraStatus.CONTINUE
  152. ```
  153. * 查看
  154. ```py title="plot.py"
  155. import os
  156. import cv2
  157. from dora import DoraStatus
  158. from utils import LABELS
  159. CI = os.environ.get("CI")
  160. CAMERA_WIDTH = 640
  161. CAMERA_HEIGHT = 480
  162. FONT = cv2.FONT_HERSHEY_SIMPLEX
  163. class Operator:
  164. """
  165. Plot image and bounding box
  166. """
  167. def __init__(self):
  168. self.bboxs = []
  169. self.buffer = ""
  170. self.submitted = []
  171. self.lines = []
  172. def on_event(
  173. self,
  174. dora_event,
  175. send_output,
  176. ):
  177. if dora_event["type"] == "INPUT":
  178. id = dora_event["id"]
  179. value = dora_event["value"]
  180. if id == "image":
  181. image = (
  182. value.to_numpy().reshape((CAMERA_HEIGHT, CAMERA_WIDTH, 3)).copy()
  183. )
  184. for bbox in self.bboxs:
  185. [
  186. min_x,
  187. min_y,
  188. max_x,
  189. max_y,
  190. confidence,
  191. label,
  192. ] = bbox
  193. cv2.rectangle(
  194. image,
  195. (int(min_x), int(min_y)),
  196. (int(max_x), int(max_y)),
  197. (0, 255, 0),
  198. )
  199. cv2.putText(
  200. image,
  201. f"{LABELS[int(label)]}, {confidence:0.2f}",
  202. (int(max_x), int(max_y)),
  203. FONT,
  204. 0.5,
  205. (0, 255, 0),
  206. )
  207. cv2.putText(
  208. image, self.buffer, (20, 14 + 21 * 14), FONT, 0.5, (190, 250, 0), 1
  209. )
  210. i = 0
  211. for text in self.submitted[::-1]:
  212. color = (
  213. (0, 255, 190)
  214. if text["role"] == "user_message"
  215. else (0, 190, 255)
  216. )
  217. cv2.putText(
  218. image,
  219. text["content"],
  220. (
  221. 20,
  222. 14 + (19 - i) * 14,
  223. ),
  224. FONT,
  225. 0.5,
  226. color,
  227. 1,
  228. )
  229. i += 1
  230. for line in self.lines:
  231. cv2.line(
  232. image,
  233. (int(line[0]), int(line[1])),
  234. (int(line[2]), int(line[3])),
  235. (0, 0, 255),
  236. 2,
  237. )
  238. if CI != "true":
  239. cv2.imshow("frame", image)
  240. if cv2.waitKey(1) & 0xFF == ord("q"):
  241. return DoraStatus.STOP
  242. elif id == "bbox":
  243. self.bboxs = value.to_numpy().reshape((-1, 6))
  244. elif id == "keyboard_buffer":
  245. self.buffer = value[0].as_py()
  246. elif id == "line":
  247. self.lines += [value.to_pylist()]
  248. elif "message" in id:
  249. self.submitted += [
  250. {
  251. "role": id,
  252. "content": value[0].as_py(),
  253. }
  254. ]
  255. return DoraStatus.CONTINUE
  256. ```
  257. * 依赖的`utils`
  258. ```py title="utils.py"
  259. LABELS = [
  260. "person",
  261. "bicycle",
  262. "car",
  263. "motorcycle",
  264. "airplane",
  265. "bus",
  266. "train",
  267. "truck",
  268. "boat",
  269. "traffic light",
  270. "fire hydrant",
  271. "stop sign",
  272. "parking meter",
  273. "bench",
  274. "bird",
  275. "cat",
  276. "dog",
  277. "horse",
  278. "sheep",
  279. "cow",
  280. "elephant",
  281. "bear",
  282. "zebra",
  283. "giraffe",
  284. "backpack",
  285. "umbrella",
  286. "handbag",
  287. "tie",
  288. "suitcase",
  289. "frisbee",
  290. "skis",
  291. "snowboard",
  292. "sports ball",
  293. "kite",
  294. "baseball bat",
  295. "baseball glove",
  296. "skateboard",
  297. "surfboard",
  298. "tennis racket",
  299. "bottle",
  300. "wine glass",
  301. "cup",
  302. "fork",
  303. "knife",
  304. "spoon",
  305. "bowl",
  306. "banana",
  307. "apple",
  308. "sandwich",
  309. "orange",
  310. "broccoli",
  311. "carrot",
  312. "hot dog",
  313. "pizza",
  314. "donut",
  315. "cake",
  316. "chair",
  317. "couch",
  318. "potted plant",
  319. "bed",
  320. "dining table",
  321. "toilet",
  322. "tv",
  323. "laptop",
  324. "mouse",
  325. "remote",
  326. "keyboard",
  327. "cell phone",
  328. "microwave",
  329. "oven",
  330. "toaster",
  331. "sink",
  332. "refrigerator",
  333. "book",
  334. "clock",
  335. "vase",
  336. "scissors",
  337. "teddy bear",
  338. "hair drier",
  339. "toothbrush",
  340. ]
  341. ```
  342. * `YOLOV8.pt`模型文件,通过下面的源码链接可下载到
  343. ## 运行!
  344. ```bash
  345. $ dora up # 启动dora服务
  346. $ dora start dataflow.yml --attach --hot-reload # 热重载模式运行
  347. ```
  348. ## 源码下载
  349. Dora yolov8 目标检测示例代码:https://pan.baidu.com/s/1uXXjFkpgeT_iHdNJzrCsqg?pwd=oibc
  350. ## 问题汇总
  351. 1. 摄像头打不开
  352. - 检查权限(Linux/macOS需要sudo),或者检查摄像头是否正常
  353. 2. YAML报错
  354. - 注意缩进必须使用空格,不能用tab
  355. 3. python包缺失
  356. ```bash
  357. $ pip install numpy opencv-python pyarrow ultralytics
  358. ```
  359. 内容编写 : **`李扬`**

Dora中文社区官网

Contributors (1)