基于AidLux+YOLOV5的人流統(tǒng)計(jì)項(xiàng)目部署教程

1.AidLux介紹

1.AidLux是基于ARM架構(gòu)的跨生態(tài)(Android/鴻蒙+Linux)一站式AIoT應(yīng)用快速開(kāi)發(fā)和部署平臺(tái)APP

2.通過(guò)共享 Linux 內(nèi)核實(shí)現(xiàn)Android 和 Linux 生態(tài)融合田巴,為單一設(shè)備同時(shí)提供Android和Linux運(yùn)行環(huán)境

3.集成國(guó)際主流AI框架和多種開(kāi)發(fā)環(huán)境攀甚、后臺(tái)服務(wù)程序静陈、編譯器及圖形開(kāi)發(fā)組件僧免,無(wú)須配置開(kāi)箱即用,極大地簡(jiǎn)化了開(kāi)發(fā)步驟法希;自主研發(fā)的AI智能加速技術(shù)可實(shí)現(xiàn)CPU+GPU+NPU智能加速,大幅提高AI應(yīng)用運(yùn)行效率;平臺(tái)廣泛而深度的適配外設(shè)接口油啤,省去大量調(diào)試工作冗锁;內(nèi)置完整的跨平臺(tái)桌面和命令行終端連接(SSH)擂错,一個(gè)平臺(tái)完成多終端協(xié)同開(kāi)發(fā)子房、測(cè)試乎莉、部署

4.可使用APK包安裝方式快速部署在ARM架構(gòu)的手機(jī)健盒、平板、電腦和板卡等智能終端上

5.AidLux能廣泛應(yīng)用在智能工業(yè)、AI教育操骡、智慧人居炫彩、智慧城市、智慧物流、智慧交通低飒、智慧零售和機(jī)器人等諸多場(chǎng)景中

博主覺(jué)得田藐,AidLux最大的優(yōu)勢(shì)在于:常規(guī)Al應(yīng)用開(kāi)發(fā)需要C++、Java蜓肆、Python早芭、Linux等不同工程師相互配合武翎,而在AidLux平臺(tái)屠阻,開(kāi)發(fā)者僅需使用Python一種編程語(yǔ)言即可進(jìn)行開(kāi)發(fā)蝇闭,并支持將其他平臺(tái)(PC死嗦、服務(wù)器)上使用Python開(kāi)發(fā)的AI應(yīng)用直接遷移至AidLux調(diào)試運(yùn)行狼渊。

也就是說(shuō)我們只需要熟悉python語(yǔ)言即可尘执,再也不用學(xué)令人頭疼的C++了救崔!

2.環(huán)境搭建

2.1 手機(jī)版AidLux的安裝

目前使用Aidlux主要有兩種方式:

1.邊緣設(shè)備的方式:阿加犀用高通芯片的S855散怖,和S865制作了兩款邊緣設(shè)備惑申,一款提供7T算力具伍,一款提供15T算力。

2.手機(jī)設(shè)備的方式:沒(méi)有邊緣設(shè)備的情況下圈驼,也可以使用手機(jī)版本的Aidlux沿猜,嘗試邊緣設(shè)備的所有功能。

并且目前Aidlux已對(duì)基本市面上所有的芯片都進(jìn)行了適配碗脊,在手機(jī)上運(yùn)行算法模型啼肩,也可以體驗(yàn)優(yōu)化的效果。當(dāng)然在使用過(guò)程中衙伶,有個(gè)共同點(diǎn)祈坠,即手機(jī)設(shè)備和邊緣設(shè)備采用的Aidlux軟件,都是一樣的矢劲。因此可以先嘗試手機(jī)設(shè)備的方式赦拘,在后期需要更多算力的時(shí)候,使用邊緣設(shè)備芬沉,就可以無(wú)縫銜接躺同。所以我們先下載一下手機(jī)Aidlux的APP軟件。打開(kāi)安卓手機(jī)的應(yīng)用商城丸逸,搜索Aidlux即可下載安裝蹋艺。

?打開(kāi)手機(jī)版本的Aidlux軟件APP,第一次進(jìn)入的時(shí)候黄刚,APP自帶的系統(tǒng)會(huì)進(jìn)行初始化捎谨。

初始化好后,進(jìn)入系統(tǒng)登錄頁(yè)面,這一步最好可以用手機(jī)注冊(cè)一下涛救,當(dāng)然也可以直接點(diǎn)擊“我已閱讀并同意”畏邢,然后點(diǎn)擊跳過(guò)登錄。

注意:軟件獲取存儲(chǔ)權(quán)限后會(huì)有提示检吆,如果是安卓版本12的手機(jī)舒萎,請(qǐng)點(diǎn)擊確認(rèn),跟著提示完成相關(guān)步驟蹭沛,以便后續(xù)開(kāi)發(fā)逆甜。

?進(jìn)入主頁(yè)面后,可以點(diǎn)擊左上角的紅色叉號(hào)致板,將說(shuō)明頁(yè)面關(guān)閉交煞。

?為了方便編程,aidlux還提供了電腦接口(需要手機(jī)和電腦連接同一網(wǎng)絡(luò)):

?點(diǎn)擊下圖中的Cloud_ip斟或,即可顯示電腦鏈接

在電腦中輸入第一個(gè)網(wǎng)址即可素征,登陸時(shí)需要密碼,默認(rèn)密碼為:?aidlux

?登錄成功后可以發(fā)現(xiàn)萝挤,電腦的界面和手機(jī)端是同步的:

因此在開(kāi)發(fā)的時(shí)候我們將寫好的代碼上傳到文件中御毅,就可以利用VSCode運(yùn)行和調(diào)試?.

2.2 Aidlux軟件設(shè)置默認(rèn)后臺(tái)運(yùn)行

這里列舉了多款手機(jī)設(shè)置的方式,大家可以參照相應(yīng)的設(shè)置教程:

(1)小米手機(jī)和平板設(shè)置教程:https://community.aidlux.com/postDetail/832

(2)OPPO手機(jī)與平板設(shè)置教程:https://community.aidlux.com/postDetail/834

(3)vivo手機(jī)與平板設(shè)置教程:https://community.aidlux.com/postDetail/835

(4)華為鴻蒙/HarmonyOS 2.0設(shè)置教程:https://community.aidlux.com/postDetail/828

(5)華為鴻蒙/HarmonyOS 3.0設(shè)置教程:https://community.aidlux.com/postDetail/827

2.3 VSCode遠(yuǎn)程連接

?新建遠(yuǎn)程連接:config如圖所示怜珍,連接的密碼同樣是aidlux

HostName即上文提到的Cloud_ip地址端蛆,Port默認(rèn)9022,連接成功后酥泛,打開(kāi)我們上傳到aidlux中的文件夾:

注:打開(kāi)文件夾的時(shí)候會(huì)再次輸入密碼 aidlux

接下來(lái)就可以通過(guò)vscode進(jìn)行代碼調(diào)試了今豆。

3 人流統(tǒng)計(jì)實(shí)戰(zhàn)

然后我們來(lái)看一個(gè)運(yùn)行YOLOv5+目標(biāo)追蹤bytetrack進(jìn)行人流統(tǒng)計(jì)的案例,話不多說(shuō)柔袁,先上效果:

3.1 目錄結(jié)構(gòu):

其中yolov5n_best-fp16.tflite是從yolov5訓(xùn)練好的best.pt權(quán)重文件轉(zhuǎn)換來(lái)的呆躲。

3.2 相關(guān)代碼:

yolov5_overstep.py:

# aidlux相關(guān)

from cvs import *

import aidlite_gpu

from utils import detect_postprocess, preprocess_img, draw_detect_res,is_passing_line

import cv2

# bytetrack

from track.tracker.byte_tracker import BYTETracker

from track.utils.visualize import plot_tracking

import requests

import time

# 加載模型

model_path = '/home/lesson5_codes/aidlux/yolov5n_best-fp16.tflite'

in_shape = [1 * 640 * 640 * 3 * 4]

out_shape = [1 * 25200 * 6 * 4]

# 載入模型

aidlite = aidlite_gpu.aidlite()

# 載入yolov5檢測(cè)模型

aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)

tracker = BYTETracker(frame_rate=30)

track_id_status = {}

cap = cvs.VideoCapture("/home/lesson5_codes/aidlux/video.mp4")

frame_id = 0

count_person = 0

while True:

? ? frame = cap.read()

? ? if frame is None:

? ? ? ? print('camera is over!')

? ? ? ? # 統(tǒng)計(jì)打印人數(shù)流量

? ? ? ? # 填寫對(duì)應(yīng)的喵碼

? ? ? ? id = 'tOqH04S'

? ? ? ? # 填寫喵提醒中,發(fā)送的消息捶索,這里放上前面提到的圖片外鏈

? ? ? ? text = "人流統(tǒng)計(jì)數(shù):"+str(count_person)

? ? ? ? ts = str(time.time())? # 時(shí)間戳

? ? ? ? type = 'json'? # 返回內(nèi)容格式

? ? ? ? request_url = "http://miaotixing.com/trigger?"

? ? ? ? headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.47'}

? ? ? ? result = requests.post(request_url + "id=" + id + "&text=" + text + "&ts=" + ts + "&type=" + type,headers=headers)

? ? ? ? break

? ? frame_id += 1

? ? if frame_id % 3 != 0:

? ? ? ? continue

? ? # 預(yù)處理

? ? img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)

? ? # 數(shù)據(jù)轉(zhuǎn)換:因?yàn)閟etTensor_Fp32()需要的是float32類型的數(shù)據(jù)插掂,所以送入的input的數(shù)據(jù)需為float32,大多數(shù)的開(kāi)發(fā)者都會(huì)忘記將圖像的數(shù)據(jù)類型轉(zhuǎn)換為float32

? ? aidlite.setInput_Float32(img, 640, 640)

? ? # 模型推理API

? ? aidlite.invoke()

? ? # 讀取返回的結(jié)果

? ? pred = aidlite.getOutput_Float32(0)

? ? # 數(shù)據(jù)維度轉(zhuǎn)換

? ? pred = pred.reshape(1, 25200, 6)[0]

? ? # 模型推理后處理

? ? pred = detect_postprocess(pred, frame.shape, [640, 640, 3], conf_thres=0.4, iou_thres=0.45)

? ? # 繪制推理結(jié)果

? ? res_img = draw_detect_res(frame, pred)

? ? # 目標(biāo)追蹤相關(guān)功能

? ? det = []

? ? # Process predictions

? ? for box in pred[0]:? # per image

? ? ? ? box[2] += box[0]

? ? ? ? box[3] += box[1]

? ? ? ? det.append(box)

? ? if len(det):

? ? ? ? # Rescale boxes from img_size to im0 size

? ? ? ? online_targets = tracker.update(det, [frame.shape[0], frame.shape[1]])

? ? ? ? online_tlwhs = []

? ? ? ? online_ids = []

? ? ? ? online_scores = []

? ? ? ? # 取出每個(gè)目標(biāo)的追蹤信息

? ? ? ? for t in online_targets:

? ? ? ? ? ? # 目標(biāo)的檢測(cè)框信息

? ? ? ? ? ? tlwh = t.tlwh

? ? ? ? ? ? # 目標(biāo)的track_id信息

? ? ? ? ? ? tid = t.track_id

? ? ? ? ? ? online_tlwhs.append(tlwh)

? ? ? ? ? ? online_ids.append(tid)

? ? ? ? ? ? online_scores.append(t.score)

? ? ? ? ? ? # 針對(duì)目標(biāo)繪制追蹤相關(guān)信息

? ? ? ? ? ? res_img = plot_tracking(res_img, online_tlwhs, online_ids, 0,0)

? ? ? ? ? ? ### 人流計(jì)數(shù)識(shí)別功能實(shí)現(xiàn) ###

? ? ? ? ? ? # 1.繪制直線

? ? ? ? ? ? lines = [[186,249],[1235,366]]

? ? ? ? ? ? cv2.line(res_img,(186,249),(1235,266),(255,255,0),3)

? ? ? ? ? ? # 2.計(jì)算得到人體下方中心點(diǎn)的位置(人體檢測(cè)監(jiān)測(cè)點(diǎn)調(diào)整)

? ? ? ? ? ? pt = [tlwh[0]+1/2*tlwh[2],tlwh[1]+tlwh[3]]

? ? ? ? ? ? # 3. 人體和違規(guī)區(qū)域的判斷(人體狀態(tài)追蹤判斷)

? ? ? ? ? ? track_info = is_passing_line(pt, lines)

? ? ? ? ? ? if tid not in track_id_status.keys():

? ? ? ? ? ? ? ? track_id_status.update( {tid:[track_info]})

? ? ? ? ? ? else:

? ? ? ? ? ? ? ? if track_info != track_id_status[tid][-1]:

? ? ? ? ? ? ? ? ? ? track_id_status[tid].append(track_info)

? ? ? ? ? ? # 4. 判斷是否有track_id越界,有的話保存成圖片

? ? ? ? ? ? # 當(dāng)某個(gè)track_id的狀態(tài)腥例,上一幀是-1辅甥,但是這一幀是1時(shí),說(shuō)明越界了

? ? ? ? ? ? if track_id_status[tid][-1] == 1 and len(track_id_status[tid]) >1:

? ? ? ? ? ? ? ? # 判斷上一個(gè)狀態(tài)是否是-1燎竖,是否的話說(shuō)明越界璃弄,為了防止繼續(xù)判別,隨機(jī)的賦了一個(gè)3的值

? ? ? ? ? ? ? ? if? track_id_status[tid][-2] == -1:

? ? ? ? ? ? ? ? ? ? track_id_status[tid].append(3)

? ? ? ? ? ? ? ? ? ? count_person+=1

? ? cv2.putText(res_img,"-1 to 1 person_count:? "+str(count_person),(50,105),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,255),2)

? ? cvs.imshow(res_img)? ? ? ? ? ? ?

utils.py:

import time

import cv2

import numpy as np

coco_class = ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',

? ? ? ? 'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',

? ? ? ? 'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',

? ? ? ? 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',

? ? ? ? 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',

? ? ? ? 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',

? ? ? ? 'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',

? ? ? ? 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',

? ? ? ? 'hair drier', 'toothbrush']

def xywh2xyxy(x):

? ? '''

? ? Box (center x, center y, width, height) to (x1, y1, x2, y2)

? ? '''

? ? y = np.copy(x)

? ? y[:, 0] = x[:, 0] - x[:, 2] / 2? # top left x

? ? y[:, 1] = x[:, 1] - x[:, 3] / 2? # top left y

? ? y[:, 2] = x[:, 0] + x[:, 2] / 2? # bottom right x

? ? y[:, 3] = x[:, 1] + x[:, 3] / 2? # bottom right y

? ? return y

def xyxy2xywh(box):

? ? '''

? ? Box (left_top x, left_top y, right_bottom x, right_bottom y) to (left_top x, left_top y, width, height)

? ? '''

? ? box[:, 2:] = box[:, 2:] - box[:, :2]

? ? return box

def NMS(dets, thresh):

? ? '''

? ? 單類NMS算法

? ? dets.shape = (N, 5), (left_top x, left_top y, right_bottom x, right_bottom y, Scores)

? ? '''

? ? x1 = dets[:,0]

? ? y1 = dets[:,1]

? ? x2 = dets[:,2]

? ? y2 = dets[:,3]

? ? areas = (y2-y1+1) * (x2-x1+1)

? ? scores = dets[:,4]

? ? keep = []

? ? index = scores.argsort()[::-1]

? ? while index.size >0:

? ? ? ? i = index[0]? ? ? # every time the first is the biggst, and add it directly

? ? ? ? keep.append(i)

? ? ? ? x11 = np.maximum(x1[i], x1[index[1:]])? ? # calculate the points of overlap

? ? ? ? y11 = np.maximum(y1[i], y1[index[1:]])

? ? ? ? x22 = np.minimum(x2[i], x2[index[1:]])

? ? ? ? y22 = np.minimum(y2[i], y2[index[1:]])

? ? ? ? w = np.maximum(0, x22-x11+1)? ? # the weights of overlap

? ? ? ? h = np.maximum(0, y22-y11+1)? ? # the height of overlap

? ? ? ? overlaps = w*h

? ? ? ? ious = overlaps / (areas[i]+areas[index[1:]] - overlaps)

? ? ? ? idx = np.where(ious<=thresh)[0]

? ? ? ? index = index[idx+1]? # because index start from 1

? ? return dets[keep]

def letterbox(img, new_shape=(640, 640), color=(114, 114, 114), auto=True, scaleFill=False, scaleup=True, stride=32):

? ? # Resize and pad image while meeting stride-multiple constraints

? ? shape = img.shape[:2]? # current shape [height, width]

? ? if isinstance(new_shape, int):

? ? ? ? new_shape = (new_shape, new_shape)

? ? # Scale ratio (new / old)

? ? r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])

? ? if not scaleup:? # only scale down, do not scale up (for better test mAP)

? ? ? ? r = min(r, 1.0)

? ? # Compute padding

? ? ratio = r, r? # width, height ratios

? ? new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))

? ? dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]? # wh padding

? ? if auto:? # minimum rectangle

? ? ? ? dw, dh = np.mod(dw, stride), np.mod(dh, stride)? # wh padding

? ? elif scaleFill:? # stretch

? ? ? ? dw, dh = 0.0, 0.0

? ? ? ? new_unpad = (new_shape[1], new_shape[0])

? ? ? ? ratio = new_shape[1] / shape[1], new_shape[0] / shape[0]? # width, height ratios

? ? dw /= 2? # divide padding into 2 sides

? ? dh /= 2

? ? if shape[::-1] != new_unpad:? # resize

? ? ? ? img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)

? ? top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1))

? ? left, right = int(round(dw - 0.1)), int(round(dw + 0.1))

? ? img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)? # add border

? ? return img, ratio, (dw, dh)

def preprocess_img(img, target_shape:tuple=None, div_num=255, means:list=[0.485, 0.456, 0.406], stds:list=[0.229, 0.224, 0.225]):

? ? '''

? ? 圖像預(yù)處理:

? ? target_shape: 目標(biāo)shape

? ? div_num: 歸一化除數(shù)

? ? means: len(means)==圖像通道數(shù)底瓣,通道均值, None不進(jìn)行zscore

? ? stds: len(stds)==圖像通道數(shù)谢揪,通道方差, None不進(jìn)行zscore

? ? '''

? ? img_processed = np.copy(img)

? ? # resize

? ? if target_shape:

? ? ? ? # img_processed = cv2.resize(img_processed, target_shape)

? ? ? ? img_processed = letterbox(img_processed, target_shape, stride=None, auto=False)[0]

? ? img_processed = img_processed.astype(np.float32)

? ? img_processed = img_processed/div_num

? ? # z-score

? ? if means is not None and stds is not None:

? ? ? ? means = np.array(means).reshape(1, 1, -1)

? ? ? ? stds = np.array(stds).reshape(1, 1, -1)

? ? ? ? img_processed = (img_processed-means)/stds

? ? # unsqueeze

? ? img_processed = img_processed[None, :]

? ? return img_processed.astype(np.float32)

def convert_shape(shapes:tuple or list, int8=False):

? ? '''

? ? 轉(zhuǎn)化為aidlite需要的格式

? ? '''

? ? if isinstance(shapes, tuple):

? ? ? ? shapes = [shapes]

? ? out = []

? ? for shape in shapes:

? ? ? ? nums = 1 if int8 else 4

? ? ? ? for n in shape:

? ? ? ? ? ? nums *= n

? ? ? ? out.append(nums)

? ? return out

def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None):

? ? # Rescale coords (xyxy) from img1_shape to img0_shape

? ? if ratio_pad is None:? # calculate from img0_shape

? ? ? ? gain = min(img1_shape[0] / img0_shape[0], img1_shape[1] / img0_shape[1])? # gain? = old / new

? ? ? ? pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2? # wh padding

? ? else:

? ? ? ? gain = ratio_pad[0][0]

? ? ? ? pad = ratio_pad[1]

? ? coords[:, [0, 2]] -= pad[0]? # x padding

? ? coords[:, [1, 3]] -= pad[1]? # y padding

? ? coords[:, :4] /= gain

? ? clip_coords(coords, img0_shape)

? ? return coords

def clip_coords(boxes, img_shape):

? ? # Clip bounding xyxy bounding boxes to image shape (height, width)

? ? boxes[:, 0].clip(0, img_shape[1], out=boxes[:, 0])? # x1

? ? boxes[:, 1].clip(0, img_shape[0], out=boxes[:, 1])? # y1

? ? boxes[:, 2].clip(0, img_shape[1], out=boxes[:, 2])? # x2

? ? boxes[:, 3].clip(0, img_shape[0], out=boxes[:, 3])? # y2

def detect_postprocess(prediction, img0shape, img1shape, conf_thres=0.25, iou_thres=0.45):

? ? '''

? ? 檢測(cè)輸出后處理

? ? prediction: aidlite模型預(yù)測(cè)輸出

? ? img0shape: 原始圖片shape

? ? img1shape: 輸入圖片shape

? ? conf_thres: 置信度閾值

? ? iou_thres: IOU閾值

? ? return: list[np.ndarray(N, 5)], 對(duì)應(yīng)類別的坐標(biāo)框信息, xywh、conf

? ? '''

? ? h, w, _ = img1shape

? ? cls_num = prediction.shape[-1] - 5

? ? valid_condidates = prediction[prediction[..., 4] > conf_thres]

? ? valid_condidates[:, 0] *= w

? ? valid_condidates[:, 1] *= h

? ? valid_condidates[:, 2] *= w

? ? valid_condidates[:, 3] *= h

? ? valid_condidates[:, :4] = xywh2xyxy(valid_condidates[:, :4])

? ? valid_condidates = valid_condidates[(valid_condidates[:, 0] > 0) & (valid_condidates[:, 1] > 0) & (valid_condidates[:, 2] > 0) & (valid_condidates[:, 3] > 0)]

? ? box_cls = valid_condidates[:, 5:].argmax(1)

? ? cls_box = []

? ? for i in range(cls_num):

? ? ? ? temp_boxes = valid_condidates[box_cls == i]

? ? ? ? if(len(temp_boxes) == 0):

? ? ? ? ? ? cls_box.append([])

? ? ? ? ? ? continue

? ? ? ? temp_boxes = NMS(temp_boxes, iou_thres)

? ? ? ? temp_boxes[:, :4] = scale_coords([h, w], temp_boxes[:, :4] , img0shape).round()

? ? ? ? temp_boxes[:, :4] = xyxy2xywh(temp_boxes[:, :4])

? ? ? ? cls_box.append(temp_boxes[:, :5])

? ? return cls_box

def draw_detect_res(img, all_boxes):

? ? '''

? ? 檢測(cè)結(jié)果繪制

? ? '''

? ? img = img.astype(np.uint8)

? ? color_step = int(255/len(all_boxes))

? ? for bi in range(len(all_boxes)):

? ? ? ? if len(all_boxes[bi]) == 0:

? ? ? ? ? ? continue

? ? ? ? for box in all_boxes[bi]:

? ? ? ? ? ? x, y, w, h = [int(t) for t in box[:4]]

? ? ? ? ? ? score = str(box[4:5][0])

? ? ? ? ? ? cv2.putText(img, str(round(float(score),2)), (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

? ? ? ? ? ? cv2.rectangle(img, (x,y), (x+w, y+h),(0, bi*color_step, 255-bi*color_step),thickness = 2)

? ? return img

def process_points(img,points,color_light_green):

? ? points = np.array([points], dtype=np.int32)

? ? ###繪制mask

? ? zeros = np.zeros((img.shape), dtype=np.uint8)

? ? mask = cv2.fillPoly(zeros, points, color=color_light_green)? ####填充顏色

? ? ##繪制輪廓

? ? cv2.drawContours(img, points, -1, (144, 238, 144), 5)? ###繪制輪廓

? ? ##疊加mask和普通圖片

? ? mask_img = 0.01 * mask + img

? ? return mask_img

def is_in_poly(p, poly):

? ? """

? ? :param p: [x, y]

? ? :param poly: [[], [], [], [], ...]

? ? :return:

? ? """

? ? px, py = p

? ? is_in = False

? ? for i, corner in enumerate(poly):

? ? ? ? next_i = i + 1 if i + 1 < len(poly) else 0

? ? ? ? x1, y1 = corner

? ? ? ? x2, y2 = poly[next_i]

? ? ? ? if (x1 == px and y1 == py) or (x2 == px and y2 == py):? # if point is on vertex

? ? ? ? ? ? is_in = True

? ? ? ? ? ? break

? ? ? ? if min(y1, y2) < py <= max(y1, y2):? # find horizontal edges of polygon

? ? ? ? ? ? x = x1 + (py - y1) * (x2 - x1) / (y2 - y1)

? ? ? ? ? ? if x == px:? # if point is on edge

? ? ? ? ? ? ? ? is_in = True

? ? ? ? ? ? ? ? break

? ? ? ? ? ? elif x > px:? # if point is on left-side of line

? ? ? ? ? ? ? ? is_in = not is_in

? ? if is_in == True:

? ? ? ? person_status = 1

? ? else:

? ? ? ? person_status = -1

? ? return person_status

def is_passing_line(point, polyline):

? ? # 在直線下方,status =-1

? ? # 在直線上方,status =1

? ? status = 1

? ? # 點(diǎn)映射在直線的高度

? ? poly_y = ((polyline[1][1] - polyline[0][1]) * (point[0] - polyline[0][0])) / (polyline[1][0] - polyline[0][0]) + \

? ? ? ? ? ? ? polyline[0][1]

? ? if point[1] > poly_y:

? ? ? ? status = -1

? ? return status

3.3喵提醒公眾號(hào)的使用

?在yolov5_overstep.py中我們可以看到捐凭,有這樣一段代碼:

它可以用來(lái)實(shí)現(xiàn)如下效果:

即:當(dāng)我們預(yù)測(cè)完一段視頻拨扶,或者一個(gè)時(shí)段之后,通過(guò)公眾號(hào)通知我們?nèi)肆髁繛槎嗌佟?/p>

使用方法我們已經(jīng)在上面給出茁肠,大家只需要把喵碼ID換成自己的患民,這樣才會(huì)發(fā)送到自己的微信上。

下面來(lái)介紹一下如何獲取喵碼id:

(1)關(guān)注“喵提醒”公眾號(hào)垦梆,關(guān)注成功后匹颤,公眾號(hào)會(huì)給我們發(fā)送一條消息,可以直接點(diǎn)擊注冊(cè)賬號(hào)托猩,或者給公眾號(hào)發(fā)送“注冊(cè)賬號(hào)”印蓖。

?(2)在底部菜單欄中,點(diǎn)擊提醒--新建

(3)填寫完標(biāo)題和備注后京腥,點(diǎn)擊保存赦肃,系統(tǒng)會(huì)自動(dòng)生成喵碼id。

?(4)此時(shí)公浪,我們只需要復(fù)制喵碼id他宛,并且替換代碼中原有的id即可

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市欠气,隨后出現(xiàn)的幾起案子厅各,更是在濱河造成了極大的恐慌,老刑警劉巖预柒,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件队塘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡宜鸯,警方通過(guò)查閱死者的電腦和手機(jī)人灼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)顾翼,“玉大人投放,你說(shuō)我怎么就攤上這事∈拭常” “怎么了灸芳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拜姿。 經(jīng)常有香客問(wèn)我烙样,道長(zhǎng),這世上最難降的妖魔是什么蕊肥? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任谒获,我火速辦了婚禮蛤肌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘批狱。我一直安慰自己裸准,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布赔硫。 她就那樣靜靜地躺著炒俱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爪膊。 梳的紋絲不亂的頭發(fā)上权悟,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音推盛,去河邊找鬼峦阁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛耘成,可吹牛的內(nèi)容都是我干的拇派。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼凿跳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼件豌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起控嗜,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茧彤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后疆栏,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體曾掂,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年壁顶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珠洗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡若专,死狀恐怖许蓖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情调衰,我是刑警寧澤膊爪,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站嚎莉,受9級(jí)特大地震影響米酬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜趋箩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一赃额、第九天 我趴在偏房一處隱蔽的房頂上張望加派。 院中可真熱鬧,春花似錦跳芳、人聲如沸芍锦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)醉旦。三九已至饶米,卻和暖如春桨啃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背檬输。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工照瘾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丧慈。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓析命,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逃默。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鹃愤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容