
在本文中,我们将学习如何使用 open-cv 和 YOLO 对象检测器每五秒捕获/保存和检测图像中的对象。然后我们将图像转换为字节数组并通过 MQTT 发布,这将在另一个远程设备上接收并保存为 JPG。
我们将使用 YoloV3 算法和一个免费的 MQTT 代理
YoloV3 算法:https://viso.ai/deep-learning/yolov3-overview/#:~:text=What's%20Next%3F-,What%20is%20YOLOv3%3F,Joseph%20Redmon%20and%20Ali%20Farhadi.
MQTT 代理:https://www.emqx.com/
在我们继续之前,我假设你具备以下基本知识:
· OpenCV:https://opencv.org/about/#:~:text=OpenCV%20(Open%20Source%20Computer%20Vision,perception%20in%20the%20commercial%20products.
· NumPy:https://numpy.org/doc/stable/user/whatisnumpy.html
· MQTT:https://mqtt.org/getting-started/
让我们首先在我们的第一台设备上编写 Python 脚本,该设备将充当监控系统。
安装:
· pip install opencv-python
· pip install numpy
· pip install paho-mqtt
如果你在安装 opencv 时仍然遇到问题,请遵循以下文章
· 在 Windows上安装:https://docs.opencv.org/3.4/d5/de5/tutorial_py_setup_in_windows.html
· 在 Ubuntu上安装:https://docs.opencv.org/3.4/d2/de6/tutorial_py_setup_in_ubuntu.html
我们还需要下载一些文件(YoloV3 的预训练权重、配置文件和名称文件)。
从以下链接下载它们
Yolov3.weights:https://pjreddie.com/media/files/yolov3.weights
Yolov3.cfg:https://github.com/pjreddie/darknet/blob/master/cfg/yolov3.cfg
coco.names:https://github.com/pjreddie/darknet/blob/master/data/coco.names
(确保以上 3 个下载的文件与 sendImage.py 保存在同一目录下)
在 IDE 中创建一个新文件并将文件保存为 sendImage.py
从导入所需的模块开始
- import paho.mqtt.client as mqtt
- import paho.mqtt.publish as publish
- import cv2
- import numpy as np
- import time
我们现在将为代理和图像初始化变量
- broker = "broker.emqx.io"
- port = 1883
- timelive=60
- image_name="capture.jpg"
我们的第一个函数将捕获/保存图像,并调用 process_image() 函数
- def save_image():
- #cv2.VideoCapture(0) this can be 0, 1, 2 depending on your device id
- videoCaptureObject = cv2.VideoCapture(0)
- ret, frame = videoCaptureObject.read()
- cv2.imwrite(image_name, frame)
- videoCaptureObject.release()
- process_image()
process_image() 函数是所有魔法发生的地方。
- def process_image():
- boxes = []
- confs = []
- class_ids = []
-
- #loading the YoloV3 weights and configuration file using the open-cv dnn module
- net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
-
- #storing all the trained object names from the coco.names file in the list names[]
- names = []
- with open("coco.names", "r") as n:
- names = [line.strip() for line in n.readlines()]
-
- #running a foward pass by passing the names of layers of the output to be computed by net.getUnconnectedOutLayersNames()
- output_layers = [layer_name for layer_name in net.getUnconnectedOutLayersNames()]
- colors = np.random.uniform(0, 255, size=(len(names), 3))
-
- #reading the image from the image_name variable (Same image which was saved by the save_image function)
- image = cv2.imread(image_name)
- height, width, channels = image.shape
-
- #using blobFromImage function to preprocess the data
- blob = cv2.dnn.blobFromImage(image, scalefactor=0.00392, size=(160, 160), mean=(0, 0, 0))
- net.setInput(blob)
-
- #getting X/Y cordinates of the object detected, scores for all the classes of objects in coco.names where the predicted object is class with the highest score, height/width of bounding box
- outputs = net.forward(output_layers)
- for output in outputs:
- for check in output:
- #this list scores stores confidence for each corresponding object
- scores = check[5:]
-
- #np.argmax() gets the class index with highest score which will help us get the name of the class for the index from the names list
- class_id = np.argmax(scores)
- conf = scores[class_id]
- #predicting with a confidence value of more than 40%
- if conf > 0.4:
- center_x = int(check[0] * width)
- center_y = int(check[1] * height)
- w = int(check[2] * width)
- h = int(check[3] * height)
- x = int(center_x - w / 2)
- y = int(center_y - h / 2)
- boxes.append([x, y, w, h])
- confs.append(float(conf))
- class_ids.append(class_id)
-
- #drawing bounding boxes and adding labels while removing duplicate detection for same object using non-maxima suppression
- indexes = cv2.dnn.NMSBoxes(boxes, confs, 0.5, 0.5)
- font = cv2.FONT_HERSHEY_PLAIN
- for i in range(len(boxes)):
- if i in indexes:
- x, y, w, h = boxes[i]
- label = str(names[class_ids[i]])
- color = colors[i]
- cv2.rectangle(image, (x, y), (x + w, y + h), color, 2)
- cv2.putText(image, label, (x, y - 5), font, 1, color, 1)
-
- #resizing and saving the the image
- width = int(image.shape[1] * 220 / 100)
- height = int(image.shape[0] * 220 / 100)
- dim = (width, height)
- resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
- cv2.imwrite('processed.jpg', resized)
-
- #reading the image and converting it to bytearray
- f = open("processed.jpg", "rb")
- fileContent = f.read()
- byteArr = bytes(fileContent)
-
- #topic to publish for our MQTT
- TOPIC = "IMAGE"
- client = mqtt.Client()
-
- #connecting to the MQTT broker
- client.connect(broker, port, timelive)
-
- #publishing the message with bytearr as the payload and IMAGE as topic
- publish.single(TOPIC, byteArr, hostname=broker)
- print("Published")
启动 save_image 函数并每 5 秒调用一次的最后几行代码
- while True:
- save_image()
- time.sleep(5)
现在让我们在第二个设备上编写第二个脚本,该脚本将用于下载和查看通过 MQTT 接收的检测到的对象文件
安装:
· pip install paho-mqtt
在 IDE 中创建一个新文件并将文件保存为 receiveImage.py
从导入所需的模块开始
import paho.mqtt.client as mqtt
为代理初始化变量
- broker = "broker.emqx.io"
- port = 1883
- timelive = 60
使用 on_connect() 函数连接代理并订阅主题 IMAGE
- def on_connect(client, userdata, flags, rc):
- print("Connected with result code " + str(rc))
- #subscribe to the topic IMAGE, this is the same topic which was used to published the image on the previous device
- client.subscribe("IMAGE")
编写 on_message() 函数以在收到有效负载后立即保存文件
- def on_message(client, userdata, msg):
- #create/open jpg file [detected_objects.jpg] to write the received payload
- f = open('detected_objects.jpg', "wb")
- f.write(msg.payload)
- f.close()
连接到代理并通过无限循环开始监听传入消息的根函数
- def mqtt_sub():
- client = mqtt.Client()
- client.connect(broker, port, timelive)
- client.on_connect = on_connect
- client.on_message = on_message
- client.loop_forever()
启动脚本的最后一行代码
mqtt_sub()
每隔5秒,你就会在脚本文件所在的目录中刷新名称为' detected_objects.jpg '的JPG图像。
就是这样。我们创建了一个监控系统,每 5 秒捕获一次图像,检测其中的物体,并使用 MQTT 通过互联网发送图像。
☆ END ☆
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。
↓扫描二维码添加小编↓
