自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用 YOLO11 和霍夫變換追蹤站臺黃線穿越者

人工智能
本文我們不僅揭開了智能視頻監(jiān)控系統(tǒng)的神秘面紗,還深入了解了如何利用前沿的AI技術(shù)來守護(hù)我們的出行安全。

大家都知道,在地鐵站等車時,廣播里總是提醒我們:“別越過黃線哦!”但是,總有那么一些人,因?yàn)榉中幕蛘卟蛔⒁?,就站在了黃線邊上,甚至跨了過去。這可是很危險的!今天,就讓我?guī)Т蠹铱纯?,怎么用人工智能來做個智能監(jiān)控系統(tǒng),一旦有人跨過黃線,系統(tǒng)就能立刻發(fā)出警告,保護(hù)大家的安全。

這篇文章,咱們分三步走:

  • 第一步:聊聊怎么用YOLO11來檢測和跟蹤站臺上的行人。
  • 第二步:看看怎么用Hough變換和OpenCV技術(shù)找出站臺邊的黃線,并找到它的方程。
  • 第三步:把上面兩個技術(shù)結(jié)合起來,做個AI系統(tǒng),專門盯著那些等車時越過黃線的人。系統(tǒng)會一幀一幀地檢查,一旦發(fā)現(xiàn)有人越線,就會發(fā)出警告。在實(shí)際應(yīng)用中,系統(tǒng)會在遵守黃線的人周圍畫個綠框,一旦有人越線,框就變紅。如果真的用在車站,這個系統(tǒng)還能發(fā)出聲音警報,提醒大家注意安全。

1. 使用YOLO11檢測和跟蹤行人

目標(biāo)檢測模型,就是幫我們找出圖像或視頻里的對象在哪兒,是啥。結(jié)果就是一堆框框,把檢測到的對象框起來,還標(biāo)上類別和置信度。這個技術(shù)特別適合用來找那些靠近軌道的人,不用知道他們具體長啥樣。YOLO11有五個預(yù)訓(xùn)練模型,專門干這個的。下面的腳本,咱們就用最小的那個yolo11n.pt,來識別圖像里的人,給他們畫框。用ultralytics庫的plot()函數(shù),直接在圖像上畫框,特別方便。具體代碼如下所示:

from ultralytics import YOLO
import argparse
import cv2

if __name__ == '__main__':
'''    Apply bbox to detected persons    '''
    parser = argparse.ArgumentParser()
    parser.add_argument('--image_path', type=str, default="resources/images/frame_yellow_line_0.png")
    opt = parser.parse_args()
    image_path = opt.image_path

# Load a pretrained YOLO11n model
    model = YOLO("yolo11n.pt")
    image = cv2.imread(image_path)
    results = model.predict(image)

# check that person has index name=0
    print("results[0].names: ", results[0].names)

# iter over results. If there is only one frame then results has only one component
for image_pred in results:
        class_names = image_pred.names
        boxes = image_pred.boxes

# iter over the detected boxes and select thos of the person if exists
for box in boxes:
if class_names[int(box.cls)] == "person":
                print("person")
                print("person bbox: ", box.xyxy)
        image_pred.plot()
    image_pred.show()

上面的程序輸入圖片后得到如下的結(jié)果:

YOLO11給檢測到的人畫的框。用ultralytics庫的plot()函數(shù)畫的。

用同樣的模型,我還能提取每個人的框的坐標(biāo),用OpenCV畫線。下面的腳本,效果和之前的差不多。畫框的方法在后面的部分會用到。具體代碼如下所示:


from ultralytics import YOLO
import cv2
font = cv2.FONT_HERSHEY_DUPLEX

# Load a pretrained YOLO11n model
model = YOLO("yolo11n.pt")
path_image = "resources/images/frame_yellow_line_900.png"
image = cv2.imread(path_image)
annotated_frame = image.copy()

# set in the predict function the interested classes to detect. Here I want to detect persons, whose index is 0
results = model.predict(image, classes=[0], conf=0.54)
image_pred = results[0]
boxes = image_pred.boxes

# iter over all the detected boxes of persons
for box in boxes:

    x1 = int(box.xyxy[0][0])
    y1 = int(box.xyxy[0][1])
    x2 = int(box.xyxy[0][2])
    y2 = int(box.xyxy[0][3])
    coords = (x1, y1 - 10)
    text = "person"
    print("x1: {} - y1: {} - x2: {} - y2: {}".format(x1, y1, x2, y2))

    color = (0, 255, 0) # colors in BGR
    thickness = 3
    annotated_frame = cv2.rectangle(image, (x1, y1), (x2, y2), color, thickness)
    annotated_frame = cv2.putText(annotated_frame, text, coords, font, 0.7, color, 2)

annotated_frame_path = "/home/enrico/Projects/VideoSurveillance/resources/images/annotated_frame_900.png"
cv2.imwrite(annotated_frame_path, annotated_frame)

用坐標(biāo)和OpenCV畫的YOLO11檢測到的人的框

姿態(tài)檢測

姿態(tài)檢測模型在某些情況下特別有用,比如我們需要知道人身體的某個部位在哪兒。YOLO11就有一套預(yù)訓(xùn)練模型,專門干這個的。這些模型會輸出一系列關(guān)鍵點(diǎn),代表圖像里人的關(guān)鍵部位。每個人身上,YOLO11能找到17個關(guān)鍵點(diǎn)。下面的腳本,我展示了怎么在圖像里提取這些關(guān)鍵點(diǎn)。YOLO11有五個預(yù)訓(xùn)練的姿態(tài)估計(jì)模型。這次,因?yàn)橛行┤丝赡茈x相機(jī)比較遠(yuǎn),我用了更強(qiáng)的模型yolo11m-pose.pt。用這些關(guān)鍵點(diǎn),我們還能畫個框,把人框起來。這個框是通過取x和y坐標(biāo)的最小值和最大值,連起來形成一個封閉人的矩形。具體代碼如下所示:


from ultralytics import YOLO
import cv2
font = cv2.FONT_HERSHEY_DUPLEX
# Load a pretrained YOLO11n-pose Pose model
model = YOLO("yolo11m-pose.pt")
# Run inference on an image
path_image = "resources/images/frame_yellow_line_900.png"
image = cv2.imread(path_image)
cv2.imwrite(annotated_frame_bbox_path, annotated_frame_bbox)
annotated_frame_keypoints = image.copy()
annotated_frame_bbox = image.copy()
results = model(image)  # results list

# extract keypoints
keypoints = results[0].keypoints
conf = keypoints.conf
xy = keypoints.xy
print(xy.shape)  # (N, K, 2) where N is the number of person detected
print("Detected person: ", xy.shape[0])

# iter over persons
for idx_person in range(xy.shape[0]):

print("idx_person: ", idx_person)

    #iter over keypoints of a fixed person
list_x = []
list_y = []
for i, th in enumerate(xy[idx_person]):
x = int(th[0])
y = int(th[1])

if x !=0.0 and y!=0.0:

list_x.append(x)
list_y.append(y)
print("x: {} - y: {}".format(x, y))
annotated_frame_keypoints = cv2.circle(annotated_frame_keypoints, (x,y), radius=3, color=(0, 0, 255), thickness=-1)
annotated_frame_keypoints = cv2.putText(annotated_frame_keypoints, str(i), (x, y-5), font, 0.7, (0, 0, 255), 2)

if len(list_x) > 0 and len(list_y) > 0:
min_x = min(list_x)
max_x = max(list_x)
min_y = min(list_y)
max_y = max(list_y)
print("min_x: {} - max_x: {} - min_y: {} - max_y: {}".format(min_x, max_x, min_y, max_y))
w = max_x - min_x
h = max_y - min_y
dx = int(w/3)
x0 = min_x - dx
x1 = max_x + dx
y0 = min_y - dx
y1 = max_y + dx
print("x0: {} - x1: {} - y0: {} - y1: {}".format(x0, x1, y0, y1))

coords = (x0, y0 - 10)
text = "person"
color = (0, 255, 0) # colors in BGR
thickness = 3
annotated_frame_bbox = cv2.rectangle(annotated_frame_bbox, (x0, y0), (x1, y1), color, thickness)
annotated_frame_bbox = cv2.putText(annotated_frame_bbox, text, coords, font, 0.7, color, 2)


annotated_frame_path = "/home/enrico/Projects/VideoSurveillance/resources/images/annotated_frame_keypoints_900.png"
cv2.imwrite(annotated_frame_path, annotated_frame_keypoints)

annotated_frame_bbox_path = "/home/enrico/Projects/VideoSurveillance/resources/images/annotated_frame_keypoints_bbox_900.png"

下面圖片顯示了程序應(yīng)用于同一圖像的結(jié)果。每個人的關(guān)鍵點(diǎn)從 0 到 16。如果某些關(guān)鍵點(diǎn)未被檢測到,系統(tǒng)不會產(chǎn)生錯誤,只會將其從輸出圖像中刪除。在邊界框方面,我們可以看到與物體檢測模型相比存在微小差異,這主要是由于關(guān)鍵點(diǎn)位于人物內(nèi)部。

左邊是每個人檢測到的關(guān)鍵點(diǎn)。右邊是根據(jù)關(guān)鍵點(diǎn)坐標(biāo)確定的每個人的框

2. 黃線檢測

Hough變換是個特征提取技術(shù),能幫我們在圖像里檢測線條。這篇文章里,我們會學(xué)習(xí)怎么用Hough變換技術(shù),在圖像里檢測線條和圓形。

為了找出站臺邊的黃線并確定它的線性方程,我們需要這么做:

首先,得把黃線從圖像里分離出來。如果把圖像從BGR顏色空間換成HSV顏色空間,這個任務(wù)會簡單很多。轉(zhuǎn)換用的代碼如下,結(jié)果看【圖4-step1】。

# 把圖像轉(zhuǎn)換成hsv顏色空間
frame_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

第二步,得定義一個包含黃線顏色的黃色范圍。我測試了幾次,找到了合適的值。用這個范圍,我能分離出落在指定黃色譜系內(nèi)的像素,得到一個黃線的掩碼,看【圖4-setp2】。

# 設(shè)置HSV空間中的黃色范圍
yellow_light = np.array([20, 140, 200], np.uint8)
yellow_dark = np.array([35, 255, 255], np.uint8)

# 隔離黃線
mask_yellow = cv2.inRange(frame_hsv, yellow_light, yellow_dark)
kernel = np.ones((4, 4), "uint8")

# 形態(tài)學(xué)閉操作,填充白色區(qū)域的黑色斑點(diǎn)
mask_yellow = cv2.morphologyEx(mask_yellow, cv2.MORPH_CLOSE, kernel)
# 形態(tài)學(xué)開操作,填充黑色區(qū)域的白色斑點(diǎn)
mask_yellow = cv2.morphologyEx(mask_yellow, cv2.MORPH_OPEN, kernel)

第三步,用Canny邊緣檢測算法處理第二步得到的掩碼。這樣就能得出帶有邊緣的圖像??础緢D4-setp3】。

# 找出隔離黃線的邊緣
edges_yellow = cv2.Canny(mask_yellow, 50, 150)

步驟1是HSV顏色空間的圖像。步驟2是檢測到的黃線掩碼。步驟3是用Canny算法得到的邊緣。

接下來準(zhǔn)備好用Probabilistic Hough Transform函數(shù)來提取圖像中所有可能的線條段。這個函數(shù)的語法是這樣的:

lines = cv2.HoughLinesP(image, rho, theta, threshold, minLineLength=None, maxLineGap=None)

參數(shù)包括:

  • image:輸入的二值灰度圖像。在我們的例子里,就是Canny算法提取的邊緣圖像。
  • rho:累加器在距離維度上的分辨率(像素)。這決定了線到原點(diǎn)的距離的精度。值越小,精度越高。
  • theta:累加器在角度維度上的分辨率(弧度)。它定義了線角度的量化精度。
  • threshold:認(rèn)為一條線有效所需的最小投票數(shù)(Hough累加器中的交點(diǎn))。值越高,檢測越嚴(yán)格。
  • minLineLength:線段的最小長度。比這短的線段會被丟棄。
  • maxLineGap:將兩個線段連接成一條線的像素最大間隙。這決定了如何處理同一條線上不連續(xù)的部分。

我在下面的腳本中應(yīng)用了HoughLinesP函數(shù)和斜率與y截距的公式。調(diào)整不同的閾值、minLineLength和maxLineGap值,我找到了能得出黃線單一直線的值。

import cv2
import numpy as np


def find_slope(x1, y1, x2, y2):
if x2 != x1:
return ((y2 - y1) / (x2 - x1))
else:
return np.inf


def find_m_and_q(edges):

    lines = cv2.HoughLinesP(
            image=edges, # Input edge image
            rho=1, # Distance resolution in pixels
            theta=np.pi/180, # Angle resolution in radians
            threshold=120, # Min number of votes for valid line
            minLineLength=80, # Min allowed length of line
            maxLineGap=10 # Max allowed gap between line for joining them
            )

    coefficient_list = []

# Iterate over points
if lines is None:
# if line is None return an empty list of coefficients
return coefficient_list
else:
for points in lines:
            x_vertical = None

# Extracted points nested in the list
            x1,y1,x2,y2=points[0]

            slope = find_slope(x1, y1, x2, y2)
if slope == np.inf:
# if the slope is infinity the intercept is None and set the x vertical
                intercept = None
                x_vertical = x1
else:
                intercept = y1-(x1*(y2-y1)/(x2-x1))

            coefficient_list.append((slope, intercept, x_vertical))
    print("coefficient_list: ", coefficient_list)
return coefficient_list


def draw_lines(image, list_coefficient):
    image_line = image.copy()
    h, w = image_line.shape[:2]
for coeff in list_coefficient:
        m, q, x_v = coeff
        y0 = 0
        y1 = h
if m != np.inf:
            x0 = -q/m
            x1 = (h-q)/m
else:
            x0 = x1 = x_v
        cv2.line(image_line, (int(x0), int(y0)), (int(x1), int(y1)), (0, 255, 0), 6)
return image_line

綠色線條是Hough變換確定的黃線對應(yīng)的直線

3. 越過黃線檢測

現(xiàn)在,把檢測人和黃線的技術(shù)結(jié)合起來。我找了個在車站錄制的視頻,里面有人靠近軌道,還越過了黃線。因?yàn)橄鄼C(jī)是固定的,黃線在視頻的每一幀里位置都一樣。所以,確定黃線的方程,我只需要看第一幀。確定了黃線對應(yīng)的直線方程后,對于每一幀,我用預(yù)訓(xùn)練的YOLO11模型檢測所有可能的人。接下來,就是要判斷一個人是否越過了黃線。最簡單的辦法是看一個人的框是否和線相交。但是,因?yàn)橄鄼C(jī)和人的位置,可能會出現(xiàn)透視問題:框可能和線相交,但人實(shí)際上并沒有越過線。實(shí)際上,人是用腳越過黃線的,所以得關(guān)注離腳最近的點(diǎn)。下面,我聊聊兩種可能的方法,并分析它們的結(jié)果。在兩種情況下,如果一個人保持在黃線后面,他們的人框會顯示為綠色,一旦系統(tǒng)檢測到未經(jīng)授權(quán)的越過,框就變紅。

兩個腳本都在Google Colab上運(yùn)行,用它提供的免費(fèi)GPU。為了避免內(nèi)存不夠用,我減小了視頻的原始大小。

??【第一種方法】:用框的右下角

一個簡單的辦法是看框的右下角。如果這個點(diǎn)在黃線外,那這個人就跨線了。下面的腳本,就是我解決這個問題的第一次嘗試。

把腳本用在原始視頻上,我跟蹤了靠近站臺的人,并根據(jù)他們是否越過(紅色框)或沒有越過(綠色框)黃線來改變他們的框顏色。

??【第二種方法】:用腳部關(guān)鍵點(diǎn)

之前的解決方案不太準(zhǔn)確。比如,如果一個人伸出手臂,框的右下角可能會更接近黃線——甚至越過它——但實(shí)際上這個人并沒有越過線。一個更精確的解決方案是使用腳部關(guān)鍵點(diǎn)。當(dāng)一個或兩個腳部關(guān)鍵點(diǎn)在黃線外時,就可以確定這個人確實(shí)越過了線。下面的腳本,就是我解決這個問題的更準(zhǔn)確嘗試。一旦檢測到一個人的

結(jié)束語

通過今天的分享,我們不僅揭開了智能視頻監(jiān)控系統(tǒng)的神秘面紗,還深入了解了如何利用前沿的AI技術(shù)來守護(hù)我們的出行安全。從YOLO11的精準(zhǔn)檢測到Hough變換的巧妙應(yīng)用,每一步都是科技與智慧的結(jié)晶。讓我們一起期待,這些技術(shù)在未來能夠更廣泛地應(yīng)用,為我們的日常生活帶來更多的便利和安全保障。感謝您的閱讀,如果您對AI技術(shù)在安全領(lǐng)域的應(yīng)用有更多的想法或建議,歡迎在評論區(qū)留言分享。讓我們攜手科技,共創(chuàng)更加智能、安全的未來!

本文完整的程序可以在https://gist.github.com/enrico310786/deef59964251117652d25f3b1a6ee5de#file-crossing_yellow_line_bbox-py獲取。

責(zé)任編輯:趙寧寧 來源: 小白玩轉(zhuǎn)Python
相關(guān)推薦

2024-10-10 16:02:34

2024-10-15 10:47:12

2024-11-20 16:06:20

2024-10-10 14:56:39

2024-10-28 16:12:26

2024-10-30 16:34:56

2020-08-29 18:17:35

物聯(lián)網(wǎng)接觸者追蹤IOT

2024-11-27 10:27:56

2024-10-07 11:12:55

2025-02-10 16:00:00

OpenCVYOLOv8計(jì)算機(jī)視覺

2013-06-05 09:55:34

云音樂丁磊

2013-01-25 10:31:28

2011-06-22 16:01:23

2024-01-05 16:14:14

2024-09-12 17:19:43

YOLO目標(biāo)檢測深度學(xué)習(xí)

2018-11-14 10:20:15

SonarQube開源追蹤代碼

2014-11-27 10:16:09

2024-11-28 15:56:05

YOLOEasyOCRPython

2024-07-03 12:15:01

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號