大家好,我是小F~
YOLO(You Only Look Once)是由Joseph Redmon和Ali开发的一种对象检测和图像分割模型。
YOLO的第一个版本于2015年发布,由于其高速度和准确性,瞬间得到了广大AI爱好者的喜爱。
Ultralytics YOLOv8则是一款前沿、最先进(SOTA)的模型,基于先前YOLO版本的成功,引入了新功能和改进,进一步提升性能和灵活性。
YOLOv8设计快速、准确且易于使用,使其成为各种物体检测与跟踪、实例分割、图像分类和姿态估计任务的绝佳选择。
项目地址:
https://github.com/ultralytics/ultralytics
其中官方提供了示例,通过Python代码即可实现YOLOv8对象检测算法模型,使用预训练模型来检测我们的目标。
而且对电脑需求也不高,CPU就能运行代码。
今天小F就给大家介绍三个使用YOLOv8制作的计数器,非常实用。
使用到Python版本以及相关Python库。
Python 3.9.7
ultralytics 8.0.178
opencv-contrib-python 4.8.1.78
opencv-python 4.8.0.74
cvzone 1.5.6
/ 01 /
客流检测器
使用OpenCV检测顾客,并且设定客人进出区域,实现实时计算进出顾客的数量。
客流量统计对于零售行业来说是非常重要的。
统计每天的进出店人数、过店人数以及人均驻留时间等。
依据这些数据,经营者可以对店铺的经营策略进行调整,实现店铺的经营效益最大化。
接下来就来看一下客流计数器的检测代码吧!
import cv2
import numpy as np
from tracker import *
import cvzone
import time
bg_subtractor = cv2.createBackgroundSubtractorMOG2(history=200, varThreshold=140)
# 打开视频
video_capture = cv2.VideoCapture(r"store.mp4")
def RGB(event, x, y, flags, param):
if event == cv2.EVENT_MOUSEMOVE:
point = [x, y]
print(point)
cv2.namedWindow('RGB')
cv2.setMouseCallback('RGB', RGB)
tracker = Tracker()
area1 = [(213, 165), (200, 189), (693, 373), (697, 341)]
area2 = [(195, 199), (186, 213), (683, 404), (689, 388)]
er = {}
counter1 = []
ex = {}
counter2 = []
while True:
ret, frame = video_capture.read()
if not ret:
break
frame = cv2.resize(frame, (1028, 500))
mask = bg_subtractor.apply(frame)
_, mask = cv2.threshold(mask, 245, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
list = []
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 1500:
# cv2.drawContours(frame, [cnt], -1, (0, 255, 0), 2)
x, y, w, h = cv2.boundingRect(cnt)
list.append([x, y, w, h])
bbox_idx = tracker.update(list)
for bbox in bbox_idx:
x1, y1, x2, y2, id = bbox
cx = int(x1 + x1 + x2) // 2
cy = int(y1 + y1 + y2) // 2
result = cv2.pointPolygonTest(np.array(area1, np.int32), ((cx, cy)), False)
if result >= 0:
er[id] = (cx, cy)
if id in er:
result1 = cv2.pointPolygonTest(np.array(area2, np.int32), ((cx, cy)), False)
if result1 >= 0:
cv2.rectangle(frame, (x1, y1), (x2 + x1, y2 + y1), (0, 255, 0), 3)
cvzone.putTextRect(frame, f'{id}', (cx, cy), 2, 2)
cv2.circle(frame, (cx, cy), 5, (0, 255, 0), -1)
if counter1.count(id) == 0:
counter1.append(id)
result2 = cv2.pointPolygonTest(np.array(area2, np.int32), ((cx, cy)), False)
if result2 >= 0:
ex[id] = (cx, cy)
if id in ex:
result3 = cv2.pointPolygonTest(np.array(area1, np.int32), ((cx, cy)), False)
if result3 >= 0:
cv2.rectangle(frame, (x1, y1), (x2 + x1, y2 + y1), (0, 0, 255), 3)
cvzone.putTextRect(frame, f'{id}', (cx, cy), 2, 2)
cv2.circle(frame, (cx, cy), 5, (0, 255, 0), -1)
if counter2.count(id) == 0:
counter2.append(id)
cv2.polylines(frame, [np.array(area1, np.int32)], True, (0, 0, 255), 2)
cv2.polylines(frame, [np.array(area2, np.int32)], True, (0, 0, 255), 2)
Enter = len(counter1)
Exit = len(counter2)
cvzone.putTextRect(frame, f'ENTER:-{Enter}', (50, 60), 2, 2)
cvzone.putTextRect(frame, f'EXIT:-{Exit}', (50, 130), 2, 2)
cv2.imshow('RGB', frame)
time.sleep(0.01)
if cv2.waitKey(1) & 0xFF == 27: # Press 'Esc' to exit
break
# 释放资源, 关闭窗口
video_capture.release()
cv2.destroyAllWindows()
结果如下。
/ 02 /
鸡蛋计数器
使用OpenCV和YOLOv8检测鸡蛋个数。
能够高效、准确、安全可靠的完成鸡蛋个数的统计工作。
基于yolov8-seg实例分割的实时检测。
具体代码如下。
import cv2
from yolo_segmentation import YOLOSEG
import cvzone
from tracker import *
import numpy as np
ys = YOLOSEG("best.pt")
my_file = open("coco1.txt", "r")
data = my_file.read()
class_list = data.split("\n")
cap = cv2.VideoCapture('egg.mp4')
count = 0
def RGB(event, x, y, flags, param):
if event == cv2.EVENT_MOUSEMOVE:
point = [x, y]
print(point)
cv2.namedWindow('RGB')
cv2.setMouseCallback('RGB', RGB)
tracker = Tracker()
area = [(434, 39), (453, 629), (473, 634), (456, 36)]
counter1 = []
while True:
ret, frame = cap.read()
if not ret:
break
frame = cv2.resize(frame, (1020, 700))
overlay = frame.copy()
alpha = 0.5
bboxes, classes, segmentations, scores = ys.detect(frame)
bbox_idx = tracker.update(bboxes)
for bbox, seg in zip(bbox_idx, segmentations):
x3, y3, x4, y4, id = bbox
cx = int(x3 + x4) // 2
cy = int(y3 + y4) // 2
result = cv2.pointPolygonTest(np.array(area, np.int32), ((cx, cy)), False)
if result >= 0:
# cv2.rectangle(frame, (x3, y3), (x4, y4), (255, 0, 0), 2)
# cv2.polylines(frame, [seg], True, (0, 0, 255), 4)
cv2.circle(frame, (cx, cy), 4, (0, 255, 0), -1)
cv2.fillPoly(overlay, [seg], (0, 0, 255))
cv2.addWeighted(overlay, alpha, frame, 1 - alpha, 2, frame)
cvzone.putTextRect(frame, f'{id}', (x3, y3), 1, 1)
if counter1.count(id) == 0:
counter1.append(id)
cv2.polylines(frame, [np.array(area, np.int32)], True, (255, 0, 0), 2)
ca1 = len(counter1)
cvzone.putTextRect(frame, f'Egg: {ca1}', (50, 60), 2, 2)
cv2.imshow("RGB", frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
运行代码,结果如下。
/ 03 /
停车位计数器
使用OpenCV和YOLOv8检测停车场剩余车位。
提醒车主停车场各个区域的剩余车位信息。
使停车场车位管理更加规范有序,提高车位使用率。
import cv2
import pandas as pd
import numpy as np
from ultralytics import YOLO
import time
model = YOLO('yolov8s.pt')
def RGB(event, x, y, flags, param):
if event == cv2.EVENT_MOUSEMOVE:
colorsBGR = [x, y]
print(colorsBGR)
cv2.namedWindow('RGB')
cv2.setMouseCallback('RGB', RGB)
cap = cv2.VideoCapture('parking1.mp4')
my_file = open("coco.txt", "r")
data = my_file.read()
class_list = data.split("\n")
area1 = [(52, 364), (30, 417), (73, 412), (88, 369)]
area2 = [(105, 353), (86, 428), (137, 427), (146, 358)]
area3 = [(159, 354), (150, 427), (204, 425), (203, 353)]
area4 = [(217, 352), (219, 422), (273, 418), (261, 347)]
area5 = [(274, 345), (286, 417), (338, 415), (321, 345)]
area6 = [(336, 343), (357, 410), (409, 408), (382, 340)]
area7 = [(396, 338), (426, 404), (479, 399), (439, 334)]
area8 = [(458, 333), (494, 397), (543, 390), (495, 330)]
area9 = [(511, 327), (557, 388), (603, 383), (549, 324)]
area10 = [(564, 323), (615, 381), (654, 372), (596, 315)]
area11 = [(616, 316), (666, 369), (703, 363), (642, 312)]
area12 = [(674, 311), (730, 360), (764, 355), (707, 308)]
while True:
ret, frame = cap.read()
if not ret:
break
time.sleep(1)
frame = cv2.resize(frame, (1020, 500))
results = model.predict(frame)
# print(results)
a = results[0].boxes.boxes
px = pd.DataFrame(a).astype("float")
# print(px)
list1 = []
list2 = []
list3 = []
list4 = []
list5 = []
list6 = []
list7 = []
list8 = []
list9 = []
list10 = []
list11 = []
list12 = []
for index, row in px.iterrows():
# print(row)
x1 = int(row[0])
y1 = int(row[1])
x2 = int(row[2])
y2 = int(row[3])
d = int(row[5])
c = class_list[d]
if 'car' in c:
cx = int(x1 + x2) // 2
cy = int(y1 + y2) // 2
results1 = cv2.pointPolygonTest(np.array(area1, np.int32), ((cx, cy)), False)
if results1 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list1.append(c)
cv2.putText(frame, str(c), (x1, y1), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
results2 = cv2.pointPolygonTest(np.array(area2, np.int32), ((cx, cy)), False)
if results2 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list2.append(c)
results3 = cv2.pointPolygonTest(np.array(area3, np.int32), ((cx, cy)), False)
if results3 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list3.append(c)
results4 = cv2.pointPolygonTest(np.array(area4, np.int32), ((cx, cy)), False)
if results4 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list4.append(c)
results5 = cv2.pointPolygonTest(np.array(area5, np.int32), ((cx, cy)), False)
if results5 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list5.append(c)
results6 = cv2.pointPolygonTest(np.array(area6, np.int32), ((cx, cy)), False)
if results6 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list6.append(c)
results7 = cv2.pointPolygonTest(np.array(area7, np.int32), ((cx, cy)), False)
if results7 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list7.append(c)
results8 = cv2.pointPolygonTest(np.array(area8, np.int32), ((cx, cy)), False)
if results8 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list8.append(c)
results9 = cv2.pointPolygonTest(np.array(area9, np.int32), ((cx, cy)), False)
if results9 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list9.append(c)
results10 = cv2.pointPolygonTest(np.array(area10, np.int32), ((cx, cy)), False)
if results10 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list10.append(c)
results11 = cv2.pointPolygonTest(np.array(area11, np.int32), ((cx, cy)), False)
if results11 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list11.append(c)
results12 = cv2.pointPolygonTest(np.array(area12, np.int32), ((cx, cy)), False)
if results12 >= 0:
cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
list12.append(c)
a1 = (len(list1))
a2 = (len(list2))
a3 = (len(list3))
a4 = (len(list4))
a5 = (len(list5))
a6 = (len(list6))
a7 = (len(list7))
a8 = (len(list8))
a9 = (len(list9))
a10 = (len(list10))
a11 = (len(list11))
a12 = (len(list12))
o = (a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12)
space = (12 - o)
print(space)
if a1 == 1:
cv2.polylines(frame, [np.array(area1, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('1'), (50, 441), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area1, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('1'), (50, 441), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a2 == 1:
cv2.polylines(frame, [np.array(area2, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('2'), (106, 440), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area2, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('2'), (106, 440), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a3 == 1:
cv2.polylines(frame, [np.array(area3, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('3'), (175, 436), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area3, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('3'), (175, 436), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a4 == 1:
cv2.polylines(frame, [np.array(area4, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('4'), (250, 436), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area4, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('4'), (250, 436), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a5 == 1:
cv2.polylines(frame, [np.array(area5, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('5'), (315, 429), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area5, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('5'), (315, 429), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a6 == 1:
cv2.polylines(frame, [np.array(area6, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('6'), (386, 421), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area6, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('6'), (386, 421), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a7 == 1:
cv2.polylines(frame, [np.array(area7, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('7'), (456, 414), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area7, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('7'), (456, 414), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a8 == 1:
cv2.polylines(frame, [np.array(area8, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('8'), (527, 406), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area8, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('8'), (527, 406), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a9 == 1:
cv2.polylines(frame, [np.array(area9, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('9'), (591, 398), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area9, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('9'), (591, 398), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a10 == 1:
cv2.polylines(frame, [np.array(area10, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('10'), (649, 384), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area10, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('10'), (649, 384), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a11 == 1:
cv2.polylines(frame, [np.array(area11, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('11'), (697, 377), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area11, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('11'), (697, 377), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
if a12 == 1:
cv2.polylines(frame, [np.array(area12, np.int32)], True, (0, 0, 255), 2)
cv2.putText(frame, str('12'), (752, 371), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
else:
cv2.polylines(frame, [np.array(area12, np.int32)], True, (0, 255, 0), 2)
cv2.putText(frame, str('12'), (752, 371), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1)
cv2.putText(frame, 'parking lots: ' + str(space), (23, 40), cv2.FONT_HERSHEY_PLAIN, 2, (255, 0, 255), 2)
cv2.imshow("RGB", frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
# stream.stop()
运行代码,结果如下。
发现效果还不错~
/ 04 /
总结
以上操作,就是三个使用YOLOv8实现的计数视觉项目。
当然我们还可以通过预训练模型实现其它功能。
如果预训练模型的检测效果在你要使用的场景不太好,那就是需要加加数据了~
万水千山总是情,点个 👍 行不行。
··· END ···