当前位置:   article > 正文

nx上darknet的使用-目标检测-在python中的使用

nx上darknet的使用-目标检测-在python中的使用

1  内置的代码

在darknet中已经内置了两个py文件

darknet_video.py与darknet_images.py用法类似,都是改一改给的参数就行了,我们说一下几个关键的参数

  • input 要预测哪张图像
  • weights 要使用哪个权重
  • config_file 要使用哪个cfg文件
  • data_file 要使用哪个data文件
  • thresh 置信度给多少

改完上面这些参数就可以直接运行了

用鼠标点一下图片然后按q可以关闭图片

调用视频有时可以正常用,有时不可以,会报下面的错,可能是opencv的版本问题

这两个代码都很好,想的很周道,但是看起来太麻烦,我通常用下面两个简化版的

2  opencv使用模型

优点:只要有python,有opencv-python,有numpy就能用(不需要编译darknet,只要有names、cfg、weights就行)

缺点:只能搞CPU版,用摄像头搞效果较差

2.1  识别图像

你需要一张预测图像,训练时的classes.names yolov4-tiny-cfg yolov4-tiny_final.weights

yolo_opencv.py的内容如下

  1. import cv2
  2. import numpy as np
  3. LABELS = open("classes.names").read().strip().split("\n")
  4. net = cv2.dnn.readNetFromDarknet('yolov4-tiny.cfg', 'yolov4-tiny_final.weights')
  5. layer = net.getUnconnectedOutLayersNames()
  6. frame = cv2.imread('000003.jpg')
  7. (H, W) = frame.shape[:2]
  8. blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),swapRB=True, crop=False)
  9. net.setInput(blob)
  10. layerOutputs = net.forward(layer)
  11. boxes = []
  12. confidences = []
  13. classIDs = []
  14. for output in layerOutputs:
  15. for detection in output:
  16. scores = detection[5:]
  17. classID = np.argmax(scores)
  18. confidence = scores[classID]
  19. box = detection[0:4] * np.array([W, H, W, H])
  20. (centerX, centerY, width, height) = box.astype("int")
  21. x = int(centerX - (width / 2))
  22. y = int(centerY - (height / 2))
  23. boxes.append([x, y, int(width), int(height)])
  24. confidences.append(float(confidence))
  25. classIDs.append(classID)
  26. idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
  27. if len(idxs) > 0:
  28. for i in idxs.flatten():
  29. (x, y) = (boxes[i][0], boxes[i][1])
  30. (w, h) = (boxes[i][2], boxes[i][3])
  31. cv2.rectangle(frame, (x, y), (x + w, y + h), (0,255,0), 1, lineType=cv2.LINE_AA)
  32. text = "{}: {:.4f}".format(LABELS[classIDs[i]], confidences[i])
  33. cv2.putText(frame, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,0.5, (255,0,0), 1, lineType=cv2.LINE_AA)
  34. cv2.imshow('frame',frame)
  35. cv2.waitKey(0)
  36. cv2.destroyAllWindows()

运行后可以显示预测结果

2.2  flask起服务

我们可以搞一个接口来处理识别的功能

服务端

  1. import numpy as np
  2. import cv2
  3. from flask import Flask,request
  4. import base64
  5. LABELS = open("classes.names").read().strip().split("\n")
  6. net = cv2.dnn.readNetFromDarknet('yolov4-tiny.cfg', 'yolov4-tiny_final.weights')
  7. layer = net.getUnconnectedOutLayersNames()
  8. app = Flask(__name__)
  9. @app.route('/predict',methods=["POST"])
  10. def predict():
  11. if request.method == 'POST':
  12. image_base64 = request.json['img_b64']
  13. img = base64.b64decode(image_base64)
  14. img = np.fromstring(img,np.uint8)
  15. frame = cv2.imdecode(img,cv2.IMREAD_COLOR)
  16. (H, W) = frame.shape[:2]
  17. blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416),
  18. swapRB=True, crop=False)
  19. net.setInput(blob)
  20. layerOutputs = net.forward(layer)
  21. boxes = []
  22. confidences = []
  23. classIDs = []
  24. for output in layerOutputs:
  25. for detection in output:
  26. scores = detection[5:]
  27. classID = np.argmax(scores)
  28. confidence = scores[classID]
  29. box = detection[0:4] * np.array([W, H, W, H])
  30. (centerX, centerY, width, height) = box.astype("int")
  31. x = int(centerX - (width / 2))
  32. y = int(centerY - (height / 2))
  33. boxes.append([x, y, int(width), int(height)])
  34. confidences.append(float(confidence))
  35. classIDs.append(classID)
  36. idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
  37. result = []
  38. if len(idxs) > 0:
  39. for i in idxs.flatten():
  40. (x, y) = (boxes[i][0], boxes[i][1])
  41. (w, h) = (boxes[i][2], boxes[i][3])
  42. result_obj = {}
  43. result_obj['x'] = x
  44. result_obj['y'] = y
  45. result_obj['w'] = w
  46. result_obj['h'] = h
  47. result_obj['name'] = LABELS[classIDs[i]]
  48. result_obj['confidence'] = confidences[i]
  49. result.append(result_obj)
  50. return {'result':result}
  51. if __name__ == '__main__':
  52. app.run(host='192.168.0.105')

客户端

  1. import cv2
  2. import requests
  3. import base64
  4. def get_result(url,frame):
  5. retval, buffer = cv2.imencode('.jpg', frame)
  6. image = str(base64.b64encode(buffer), 'utf-8')
  7. json_data = {'img_b64': image}
  8. response = eval(requests.post(url, json=json_data).text).get('result')
  9. return response
  10. if __name__ == '__main__':
  11. url = 'http://192.168.0.105:5000/predict'
  12. frame = cv2.imread('000003.jpg')
  13. response = get_result(url,frame)
  14. for result in response:
  15. confidence = result.get('confidence')
  16. x = int(result.get('x'))
  17. y = int(result.get('y'))
  18. w = int(result.get('w'))
  19. h = int(result.get('h'))
  20. name = result.get('name')
  21. frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
  22. frame = cv2.putText(frame, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
  23. cv2.imshow('img',frame)
  24. cv2.waitKey(0)
  25. cv2.destroyAllWindows()

请求结果

2.3  摄像头识别

原理是图像识别+多线程

  1. import cv2
  2. import numpy as np
  3. import queue
  4. import threading
  5. import time
  6. LABELS = open("classes.names").read().strip().split("\n")
  7. net = cv2.dnn.readNetFromDarknet('yolov4-tiny.cfg', 'yolov4-tiny_final.weights')
  8. layer = net.getUnconnectedOutLayersNames()
  9. cap = cv2.VideoCapture(0)
  10. frame_queue = queue.Queue()
  11. detection_result_queue = queue.Queue(maxsize=1)
  12. def video_capture():
  13. while cap.isOpened():
  14. ret, frame = cap.read()
  15. if ret:
  16. frame_queue.put(frame)
  17. cap.release()
  18. def predict():
  19. while cap.isOpened():
  20. start_time = time.time()
  21. predict_frame = frame_queue.get()
  22. (H, W) = predict_frame.shape[:2]
  23. blob = cv2.dnn.blobFromImage(predict_frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
  24. net.setInput(blob)
  25. layerOutputs = net.forward(layer)
  26. boxes = []
  27. confidences = []
  28. classIDs = []
  29. for output in layerOutputs:
  30. for detection in output:
  31. scores = detection[5:]
  32. classID = np.argmax(scores)
  33. confidence = scores[classID]
  34. box = detection[0:4] * np.array([W, H, W, H])
  35. (centerX, centerY, width, height) = box.astype("int")
  36. x = int(centerX - (width / 2))
  37. y = int(centerY - (height / 2))
  38. boxes.append([x, y, int(width), int(height)])
  39. confidences.append(float(confidence))
  40. classIDs.append(classID)
  41. idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3)
  42. if len(idxs) > 0:
  43. result_list = []
  44. for i in idxs.flatten():
  45. result_dic = {}
  46. (x, y) = (boxes[i][0], boxes[i][1])
  47. (w, h) = (boxes[i][2], boxes[i][3])
  48. label = LABELS[classIDs[i]]
  49. confidence = confidences[i]
  50. result_dic.__setitem__('x',x)
  51. result_dic.__setitem__('y',y)
  52. result_dic.__setitem__('w',w)
  53. result_dic.__setitem__('h',h)
  54. result_dic.__setitem__('label',label)
  55. result_dic.__setitem__('confidence',confidence)
  56. result_list.append(result_dic)
  57. detection_result_queue.put(result_list)
  58. print(time.time()-start_time)
  59. cap.release()
  60. def draw():
  61. while cap.isOpened():
  62. draw_frame = frame_queue.get()
  63. try:
  64. predict_results = detection_result_queue.get(block=False)
  65. for predict_result in predict_results:
  66. x = predict_result.get('x')
  67. y = predict_result.get('y')
  68. w = predict_result.get('w')
  69. h = predict_result.get('h')
  70. label = predict_result.get('label')
  71. confidence = predict_result.get('confidence')
  72. cv2.rectangle(draw_frame, (x, y), (x + w, y + h), (0,255,0), 1, lineType=cv2.LINE_AA)
  73. text = "{}: {:.4f}".format(label, confidence)
  74. cv2.putText(draw_frame, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX,0.5, (255,0,0), 1, lineType=cv2.LINE_AA)
  75. except:
  76. pass
  77. cv2.imshow('draw_frame',draw_frame)
  78. cv2.waitKey(1)
  79. cap.release()
  80. threading.Thread(target=video_capture).start()
  81. threading.Thread(target=predict).start()
  82. threading.Thread(target=draw).start()

由于是CPU运行,效果根据CPU的性能会有差异,我是用NX上的6核CPU运行yolov4-tiny,大约0.5s一张。这个速度如果在摄像头上的连续识别就非常慢了,至少要1秒30帧才能有流畅的感觉,也就是0.03秒需要预测一张

  • 0.5/0.03 = 16.6 或许搞个17线程能够达成流畅的效果,没尝试过

3  darknet使用模型

优点:可以使用GPU

缺点:需要编译darknet才能使用

下面在代码中import darknet指的是import下面这个文件。下面这个py文件依赖了darknet文件夹下的其他文件,所以建议把下面的代码放在darknet的根目录下使用

3.1  识别图像

在模型读取的时候是通过data文件找names文件,而不是直接找names文件

  1. import cv2
  2. import darknet
  3. import time
  4. network, class_names, class_colors = darknet.load_network(
  5. '/home/suyu/darknet/yolo_opencv/yolov7-tiny.cfg',
  6. '/home/suyu/darknet/custom_training/custom_training.data',
  7. '/home/suyu/darknet/yolo_opencv/yolov7-tiny_final_origin.weights',
  8. batch_size=1
  9. )
  10. width = darknet.network_width(network)
  11. height = darknet.network_height(network)
  12. darknet_image = darknet.make_image(width, height, 3)
  13. image = cv2.imread('/home/suyu/darknet/yolo_opencv/280.jpg')
  14. image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  15. image_resized = cv2.resize(image_rgb, (width, height),interpolation=cv2.INTER_LINEAR)
  16. darknet.copy_image_from_bytes(darknet_image, image_resized.tobytes())
  17. start_time = time.time()
  18. detections = darknet.detect_image(network, class_names, darknet_image, thresh=0.8)
  19. print(time.time()-start_time)
  20. darknet.free_image(darknet_image)
  21. image = darknet.draw_boxes(detections, image_resized, class_colors)
  22. image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  23. cv2.imshow('image',image)
  24. cv2.waitKey(0)
  25. cv2.destroyAllWindows()

在终端上可以看到对模型进行了读取

画框的颜色每次都是随机的

在预测中,如果出现了下面这种情况,我们就需要减少预测的结果,可以通过标签后面的置信度减少,但是我们可以看到有两个框的置信度都在0.99以上,这个时候我们就需要用到其他减少框的办法

darknet.detect_image()这个方法,除了通过置信度减少预测结果,还可以通过非最大值抑制消除冗余,也就是最后一个的nms

  • hier_thresh也是消除冗余的一个参数,叫控制层次性阈值(与nms类似),没用过,如果nms不行的化再尝试使用它

nms数值越小,消除冗余的效果就越好,我这里直接改成了0.05

改完之后可以得到还不错的效果

3.2  摄像头识别

原理是识别图像+多线程,我用yolov7-tiny大概能到0.03秒预测一张,这个预测速度不加多线程应该也可以

  1. import cv2
  2. import numpy as np
  3. import queue
  4. import threading
  5. import time
  6. import darknet
  7. network, class_names, class_colors = darknet.load_network(
  8. '/home/suyu/darknet/yolo_opencv/yolov7-tiny.cfg',
  9. '/home/suyu/darknet/custom_training/custom_training.data',
  10. '/home/suyu/darknet/yolo_opencv/yolov7-tiny_final_origin.weights',
  11. batch_size=1
  12. )
  13. width = darknet.network_width(network)
  14. height = darknet.network_height(network)
  15. darknet_image = darknet.make_image(width, height, 3)
  16. cap = cv2.VideoCapture(0)
  17. frame_queue = queue.Queue()
  18. detection_result_queue = queue.Queue(maxsize=1)
  19. def video_capture():
  20. while cap.isOpened():
  21. ret, frame = cap.read()
  22. if ret:
  23. image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  24. image_resized = cv2.resize(image_rgb, (width, height), interpolation=cv2.INTER_LINEAR)
  25. frame_queue.put(image_resized)
  26. cap.release()
  27. def predict():
  28. while cap.isOpened():
  29. start_time = time.time()
  30. image_resized = frame_queue.get()
  31. darknet.copy_image_from_bytes(darknet_image, image_resized.tobytes())
  32. detections = darknet.detect_image(network, class_names, darknet_image, thresh=0.8)
  33. # darknet.free_image(darknet_image)
  34. print(time.time()-start_time)
  35. detection_result_queue.put(detections)
  36. cap.release()
  37. def draw():
  38. while cap.isOpened():
  39. draw_frame = frame_queue.get()
  40. # print(draw_frame)
  41. try:
  42. detections = detection_result_queue.get(block=False)
  43. draw_frame = darknet.draw_boxes(detections, draw_frame, class_colors)
  44. except:
  45. pass
  46. draw_frame = cv2.cvtColor(draw_frame, cv2.COLOR_BGR2RGB)
  47. cv2.imshow('draw_frame',draw_frame)
  48. cv2.waitKey(1)
  49. cap.release()
  50. threading.Thread(target=video_capture).start()
  51. threading.Thread(target=predict).start()
  52. threading.Thread(target=draw).start()

如果你想对预测的结果进行别的操作你可以用到detection_result_queue中的detections,打印出来是这样的

列表套元组,元组的第一个值是label,第二个值是置信

操作的时候建议多开一个线程,然后将detection_result_queue置为2或者更高,避免两个线程抢数据的情况

4  onnx使用模型

onnx(Open Neural Network eXchange) 开放式神经网络交换,好多模型都可以转换为onnx类型的模型,相当于是人工智能模型界的docker了。以高适配性而著名。在性能上并没有优于其他模型。

4.1  用到的库

onnx,这个是将其他类型的模型转换为onnx类型的库,在arm端上安装可能会有些麻烦,但在amd上直接用pip就可以安装了

onnxruntime是跑onnx模型用的,onnxruntime在arm端可以直接用pip安装

4.2  darknet的weight转onnx

参考 https://zhuanlan.zhihu.com/p/543345367

源码 GitHub - Tianxiaomo/pytorch-YOLOv4: PyTorch ,ONNX and TensorRT implementation of YOLOv4

安装完onnx与onnxruntime后运行demo_darknet2onnx.py,第一个参数是cfg,第二个参数是names,第三个参数是weights,第四个参数是图,第五个参数是batch_size,直接写1就行了

python demo_darknet2onnx.py /home/suyu/darknet/cfg/yolov4.cfg /home/suyu/darknet/data/coco.names /home/suyu/darknet/yolov4.weights /home/suyu/darknet/data/dog.jpg 1

如果opencv版本过高会爆出下面两个问题,是cv2.rectangele()与cv2.putText()的参数需为int

我们需要更改 /pytorch-YOLOv4-master/tool/utils.py

把画红线的地方改成int

成功使用会显示下面这些东西

在文件夹中可以找到通过onnx预测成功的图像和onnx模型

4.3  识别图像

识别的代码是用的上面提供的源码中的东西,有的代码直接从utils中复制过来了,用的时候不需要引入其他py文件了,只需要.onnx文件与.names文件

  1. import sys
  2. import onnx
  3. import os
  4. import argparse
  5. import numpy as np
  6. import cv2
  7. import onnxruntime
  8. import time
  9. import math
  10. def load_class_names(namesfile):
  11. class_names = []
  12. with open(namesfile, 'r') as fp:
  13. lines = fp.readlines()
  14. for line in lines:
  15. line = line.rstrip()
  16. class_names.append(line)
  17. return class_names
  18. def nms_cpu(boxes, confs, nms_thresh=0.5, min_mode=False):
  19. # print(boxes.shape)
  20. x1 = boxes[:, 0]
  21. y1 = boxes[:, 1]
  22. x2 = boxes[:, 2]
  23. y2 = boxes[:, 3]
  24. areas = (x2 - x1) * (y2 - y1)
  25. order = confs.argsort()[::-1]
  26. keep = []
  27. while order.size > 0:
  28. idx_self = order[0]
  29. idx_other = order[1:]
  30. keep.append(idx_self)
  31. xx1 = np.maximum(x1[idx_self], x1[idx_other])
  32. yy1 = np.maximum(y1[idx_self], y1[idx_other])
  33. xx2 = np.minimum(x2[idx_self], x2[idx_other])
  34. yy2 = np.minimum(y2[idx_self], y2[idx_other])
  35. w = np.maximum(0.0, xx2 - xx1)
  36. h = np.maximum(0.0, yy2 - yy1)
  37. inter = w * h
  38. if min_mode:
  39. over = inter / np.minimum(areas[order[0]], areas[order[1:]])
  40. else:
  41. over = inter / (areas[order[0]] + areas[order[1:]] - inter)
  42. inds = np.where(over <= nms_thresh)[0]
  43. order = order[inds + 1]
  44. return np.array(keep)
  45. def post_processing(img, conf_thresh, nms_thresh, output):
  46. # anchors = [12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401]
  47. # num_anchors = 9
  48. # anchor_masks = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
  49. # strides = [8, 16, 32]
  50. # anchor_step = len(anchors) // num_anchors
  51. # [batch, num, 1, 4]
  52. box_array = output[0]
  53. # [batch, num, num_classes]
  54. confs = output[1]
  55. t1 = time.time()
  56. if type(box_array).__name__ != 'ndarray':
  57. box_array = box_array.cpu().detach().numpy()
  58. confs = confs.cpu().detach().numpy()
  59. num_classes = confs.shape[2]
  60. # [batch, num, 4]
  61. box_array = box_array[:, :, 0]
  62. # [batch, num, num_classes] --> [batch, num]
  63. max_conf = np.max(confs, axis=2)
  64. max_id = np.argmax(confs, axis=2)
  65. t2 = time.time()
  66. bboxes_batch = []
  67. for i in range(box_array.shape[0]):
  68. argwhere = max_conf[i] > conf_thresh
  69. l_box_array = box_array[i, argwhere, :]
  70. l_max_conf = max_conf[i, argwhere]
  71. l_max_id = max_id[i, argwhere]
  72. bboxes = []
  73. # nms for each class
  74. for j in range(num_classes):
  75. cls_argwhere = l_max_id == j
  76. ll_box_array = l_box_array[cls_argwhere, :]
  77. ll_max_conf = l_max_conf[cls_argwhere]
  78. ll_max_id = l_max_id[cls_argwhere]
  79. keep = nms_cpu(ll_box_array, ll_max_conf, nms_thresh)
  80. if (keep.size > 0):
  81. ll_box_array = ll_box_array[keep, :]
  82. ll_max_conf = ll_max_conf[keep]
  83. ll_max_id = ll_max_id[keep]
  84. for k in range(ll_box_array.shape[0]):
  85. bboxes.append([ll_box_array[k, 0], ll_box_array[k, 1], ll_box_array[k, 2], ll_box_array[k, 3], ll_max_conf[k], ll_max_conf[k], ll_max_id[k]])
  86. bboxes_batch.append(bboxes)
  87. t3 = time.time()
  88. print('-----------------------------------')
  89. print(' max and argmax : %f' % (t2 - t1))
  90. print(' nms : %f' % (t3 - t2))
  91. print('Post processing total : %f' % (t3 - t1))
  92. print('-----------------------------------')
  93. return bboxes_batch
  94. def plot_boxes_cv2(img, boxes, savename=None, class_names=None, color=None):
  95. import cv2
  96. img = np.copy(img)
  97. colors = np.array([[1, 0, 1], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 0, 0]], dtype=np.float32)
  98. def get_color(c, x, max_val):
  99. ratio = float(x) / max_val * 5
  100. i = int(math.floor(ratio))
  101. j = int(math.ceil(ratio))
  102. ratio = ratio - i
  103. r = (1 - ratio) * colors[i][c] + ratio * colors[j][c]
  104. return int(r * 255)
  105. width = img.shape[1]
  106. height = img.shape[0]
  107. for i in range(len(boxes)):
  108. box = boxes[i]
  109. x1 = int(box[0] * width)
  110. y1 = int(box[1] * height)
  111. x2 = int(box[2] * width)
  112. y2 = int(box[3] * height)
  113. bbox_thick = int(0.6 * (height + width) / 600)
  114. if color:
  115. rgb = color
  116. else:
  117. rgb = (255, 0, 0)
  118. if len(box) >= 7 and class_names:
  119. cls_conf = box[5]
  120. cls_id = box[6]
  121. print('%s: %f' % (class_names[cls_id], cls_conf))
  122. classes = len(class_names)
  123. offset = cls_id * 123457 % classes
  124. red = get_color(2, offset, classes)
  125. green = get_color(1, offset, classes)
  126. blue = get_color(0, offset, classes)
  127. if color is None:
  128. rgb = (red, green, blue)
  129. msg = str(class_names[cls_id])+" "+str(round(cls_conf,3))
  130. t_size = cv2.getTextSize(msg, 0, 0.7, thickness=bbox_thick // 2)[0]
  131. c1, c2 = (x1,y1), (x2, y2)
  132. c3 = (c1[0] + t_size[0], c1[1] - t_size[1] - 3)
  133. cv2.rectangle(img, (int(x1),int(y1)), (int(np.float32(c3[0])), int(np.float32(c3[1]))), rgb, -1)
  134. img = cv2.putText(img, msg, (int(c1[0]), int(np.float32(c1[1] - 2))), cv2.FONT_HERSHEY_SIMPLEX,0.7, (0,0,0), bbox_thick//2,lineType=cv2.LINE_AA)
  135. img = cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), rgb, bbox_thick)
  136. if savename:
  137. print("save plot results to %s" % savename)
  138. cv2.imwrite(savename, img)
  139. return img
  140. def detect(session, image_src, namesfile):
  141. IN_IMAGE_H = session.get_inputs()[0].shape[2]
  142. IN_IMAGE_W = session.get_inputs()[0].shape[3]
  143. # Input
  144. resized = cv2.resize(image_src, (IN_IMAGE_W, IN_IMAGE_H), interpolation=cv2.INTER_LINEAR)
  145. img_in = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
  146. img_in = np.transpose(img_in, (2, 0, 1)).astype(np.float32)
  147. img_in = np.expand_dims(img_in, axis=0)
  148. img_in /= 255.0
  149. #print("Shape of the network input: ", img_in.shape)
  150. # Compute
  151. input_name = session.get_inputs()[0].name
  152. outputs = session.run(None, {input_name: img_in})
  153. boxes = post_processing(img_in, 0.4, 0.6, outputs)
  154. class_names = load_class_names(namesfile)
  155. return plot_boxes_cv2(image_src, boxes[0], class_names=class_names)
  156. if __name__ == '__main__':
  157. session = onnxruntime.InferenceSession('yolov4_1_3_640_640_static.onnx')
  158. namesfile = 'classes.names'
  159. image_src = cv2.imread('3.png')
  160. detected_img = detect(session, image_src, namesfile)
  161. cv2.imshow('detected_img',detected_img)
  162. cv2.waitKey(0)
  163. cv2.destroyAllWindows()

4.4  摄像头识别

用的采集、预测、画 三线程。模型输入width与height都为320,两分类,在树莓派4B中大概是0.5s一张,大概是1秒2个识别帧

  1. import cv2
  2. import numpy as np
  3. import queue
  4. import threading
  5. import time
  6. import sys
  7. import onnx
  8. import os
  9. import argparse
  10. import onnxruntime
  11. import math
  12. def load_class_names(namesfile):
  13. class_names = []
  14. with open(namesfile, 'r') as fp:
  15. lines = fp.readlines()
  16. for line in lines:
  17. line = line.rstrip()
  18. class_names.append(line)
  19. return class_names
  20. def nms_cpu(boxes, confs, nms_thresh=0.5, min_mode=False):
  21. x1 = boxes[:, 0]
  22. y1 = boxes[:, 1]
  23. x2 = boxes[:, 2]
  24. y2 = boxes[:, 3]
  25. areas = (x2 - x1) * (y2 - y1)
  26. order = confs.argsort()[::-1]
  27. keep = []
  28. while order.size > 0:
  29. idx_self = order[0]
  30. idx_other = order[1:]
  31. keep.append(idx_self)
  32. xx1 = np.maximum(x1[idx_self], x1[idx_other])
  33. yy1 = np.maximum(y1[idx_self], y1[idx_other])
  34. xx2 = np.minimum(x2[idx_self], x2[idx_other])
  35. yy2 = np.minimum(y2[idx_self], y2[idx_other])
  36. w = np.maximum(0.0, xx2 - xx1)
  37. h = np.maximum(0.0, yy2 - yy1)
  38. inter = w * h
  39. if min_mode:
  40. over = inter / np.minimum(areas[order[0]], areas[order[1:]])
  41. else:
  42. over = inter / (areas[order[0]] + areas[order[1:]] - inter)
  43. inds = np.where(over <= nms_thresh)[0]
  44. order = order[inds + 1]
  45. return np.array(keep)
  46. def post_processing(img, conf_thresh, nms_thresh, output):
  47. box_array = output[0]
  48. confs = output[1]
  49. if type(box_array).__name__ != 'ndarray':
  50. box_array = box_array.cpu().detach().numpy()
  51. confs = confs.cpu().detach().numpy()
  52. num_classes = confs.shape[2]
  53. box_array = box_array[:, :, 0]
  54. max_conf = np.max(confs, axis=2)
  55. max_id = np.argmax(confs, axis=2)
  56. bboxes_batch = []
  57. for i in range(box_array.shape[0]):
  58. argwhere = max_conf[i] > conf_thresh
  59. l_box_array = box_array[i, argwhere, :]
  60. l_max_conf = max_conf[i, argwhere]
  61. l_max_id = max_id[i, argwhere]
  62. bboxes = []
  63. for j in range(num_classes):
  64. cls_argwhere = l_max_id == j
  65. ll_box_array = l_box_array[cls_argwhere, :]
  66. ll_max_conf = l_max_conf[cls_argwhere]
  67. ll_max_id = l_max_id[cls_argwhere]
  68. keep = nms_cpu(ll_box_array, ll_max_conf, nms_thresh)
  69. if (keep.size > 0):
  70. ll_box_array = ll_box_array[keep, :]
  71. ll_max_conf = ll_max_conf[keep]
  72. ll_max_id = ll_max_id[keep]
  73. for k in range(ll_box_array.shape[0]):
  74. bboxes.append([ll_box_array[k, 0], ll_box_array[k, 1], ll_box_array[k, 2], ll_box_array[k, 3], ll_max_conf[k], ll_max_conf[k], ll_max_id[k]])
  75. bboxes_batch.append(bboxes)
  76. return bboxes_batch
  77. def get_color(c, x, max_val):
  78. colors = np.array([[1, 0, 1], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 0, 0]], dtype=np.float32)
  79. ratio = float(x) / max_val * 5
  80. i = int(math.floor(ratio))
  81. j = int(math.ceil(ratio))
  82. ratio = ratio - i
  83. r = (1 - ratio) * colors[i][c] + ratio * colors[j][c]
  84. return int(r * 255)
  85. def detect(session, image_src, namesfile):
  86. IN_IMAGE_H = session.get_inputs()[0].shape[2]
  87. IN_IMAGE_W = session.get_inputs()[0].shape[3]
  88. # Input
  89. resized = cv2.resize(image_src, (IN_IMAGE_W, IN_IMAGE_H), interpolation=cv2.INTER_LINEAR)
  90. img_in = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB)
  91. img_in = np.transpose(img_in, (2, 0, 1)).astype(np.float32)
  92. img_in = np.expand_dims(img_in, axis=0)
  93. img_in /= 255.0
  94. # Compute
  95. input_name = session.get_inputs()[0].name
  96. outputs = session.run(None, {input_name: img_in})
  97. boxes = post_processing(img_in, 0.4, 0.6, outputs)
  98. return boxes[0]
  99. session = onnxruntime.InferenceSession('yolov4_1_3_640_640_static.onnx')
  100. namesfile = 'classes.names'
  101. class_names = load_class_names(namesfile)
  102. cap = cv2.VideoCapture(0)
  103. frame_queue = queue.Queue()
  104. detection_result_queue = queue.Queue(maxsize=1)
  105. def video_capture():
  106. while cap.isOpened():
  107. ret, frame = cap.read()
  108. if ret:
  109. frame_queue.put(frame)
  110. cap.release()
  111. def predict():
  112. while cap.isOpened():
  113. start_time = time.time()
  114. predict_frame = frame_queue.get()
  115. result_list = detect(session, predict_frame, namesfile)
  116. detection_result_queue.put(result_list)
  117. print(time.time()-start_time)
  118. cap.release()
  119. def draw():
  120. while cap.isOpened():
  121. draw_frame = frame_queue.get()
  122. try:
  123. boxes = detection_result_queue.get(block=False)
  124. img = draw_frame
  125. width = img.shape[1]
  126. height = img.shape[0]
  127. for i in range(len(boxes)):
  128. box = boxes[i]
  129. x1 = int(box[0] * width)
  130. y1 = int(box[1] * height)
  131. x2 = int(box[2] * width)
  132. y2 = int(box[3] * height)
  133. bbox_thick = int(0.6 * (height + width) / 600)
  134. rgb = (255, 0, 0)
  135. if len(box) >= 7 and class_names:
  136. cls_conf = box[5]
  137. cls_id = box[6]
  138. print('%s: %f' % (class_names[cls_id], cls_conf))
  139. classes = len(class_names)
  140. offset = cls_id * 123457 % classes
  141. red = get_color(2, offset, classes)
  142. green = get_color(1, offset, classes)
  143. blue = get_color(0, offset, classes)
  144. rgb = (red, green, blue)
  145. msg = str(class_names[cls_id])+" "+str(round(cls_conf,3))
  146. t_size = cv2.getTextSize(msg, 0, 0.7, thickness=bbox_thick // 2)[0]
  147. c1, c2 = (x1,y1), (x2, y2)
  148. c3 = (c1[0] + t_size[0], c1[1] - t_size[1] - 3)
  149. cv2.rectangle(img, (int(x1),int(y1)), (int(np.float32(c3[0])), int(np.float32(c3[1]))), rgb, -1)
  150. img = cv2.putText(img, msg, (int(c1[0]), int(np.float32(c1[1] - 2))), cv2.FONT_HERSHEY_SIMPLEX,0.7, (0,0,0), bbox_thick//2,lineType=cv2.LINE_AA)
  151. img = cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), rgb, bbox_thick)
  152. draw_frame = img
  153. #except Exception as e:
  154. #print(e)
  155. except:
  156. pass
  157. cv2.imshow('draw_frame',draw_frame)
  158. cv2.waitKey(1)
  159. cap.release()
  160. threading.Thread(target=video_capture).start()
  161. threading.Thread(target=predict).start()
  162. threading.Thread(target=draw).start()

在树莓派4B上是下面这个效果

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/838526
推荐阅读
相关标签
  

闽ICP备14008679号