吸煙檢測(cè)從零開始使用YOLOv5+PyQt5+OpenCV實(shí)現(xiàn)
全流程教程,從數(shù)據(jù)采集到模型使用到最終展示。若有任何疑問和建議歡迎評(píng)論區(qū)討論。
先放上最終實(shí)現(xiàn)效果
檢測(cè)效果
由上圖我們可以看到,使用YOLOV5完成了吸煙的目標(biāo)識(shí)別檢測(cè),可以達(dá)到mAP可達(dá)85.38%。通過對(duì)吸煙的自動(dòng)檢測(cè)可以方便商場(chǎng)、醫(yī)院、療養(yǎng)院等公共場(chǎng)合進(jìn)行禁煙管控。
mAP曲線和loss變換曲線。
1. 數(shù)據(jù)集的制作
已有一份數(shù)據(jù)形成了對(duì)應(yīng)的數(shù)據(jù)集。鏈接為數(shù)據(jù)集。總數(shù)據(jù)量為783張,且所有圖片均已標(biāo)注 。本數(shù)據(jù)集以對(duì)數(shù)據(jù)集進(jìn)行劃分,訓(xùn)練集:626, 驗(yàn)證集:78, 測(cè)試集:79
示例圖片
自己制作數(shù)據(jù)集可以參考如下步驟:
1.1 數(shù)據(jù)集采集
可以通過爬蟲爬取一些圖片。
1.2 使用labelme對(duì)圖片進(jìn)行標(biāo)注
labelme是圖形圖像注釋工具,它是用Python編寫的,并將Qt用于其圖形界面。說直白點(diǎn),它是有界面的, 像軟件一樣,可以交互,但是它又是由命令行啟動(dòng)的,比軟件的使用稍微麻煩點(diǎn)。其界面如下圖:
github鏈接: labelme https://github.com/wkentaro/labelme
它的功能很多,包括:
- 對(duì)圖像進(jìn)行多邊形,矩形,圓形,多段線,線段,點(diǎn)形式的標(biāo)注(可用于目標(biāo)檢-測(cè),圖像分割等任務(wù))。
- 對(duì)圖像進(jìn)行進(jìn)行 flag形式的標(biāo)注(可用于圖像分類 和 清理 任務(wù))。
- 視頻標(biāo)注 - 生成 VOC 格式的數(shù)據(jù)集(for semantic / instancesegmentation)
- 生成 COCO 格式的數(shù)據(jù)集(for instance segmentation)
2. YOLOv5
2.1YOLO算法簡(jiǎn)單介紹
YOLO框架(You Only Look Once)與RCNN系列算法不一樣,是以不同的方式處理對(duì)象檢測(cè)。它將整個(gè)圖像放在一個(gè)實(shí)例中,并預(yù)測(cè)這些框的邊界框坐標(biāo)和及所屬類別概率。使用YOLO算法最大優(yōu)的點(diǎn)是速度極快,每秒可處理45幀,也能夠理解一般的對(duì)象表示。
在本節(jié)中,將介紹YOLO用于檢測(cè)給定圖像中的對(duì)象的處理步驟。
首先,輸入圖像:
然后,YOLO將輸入圖像劃分為網(wǎng)格形式(例如3 X 3):
最后,對(duì)每個(gè)網(wǎng)格應(yīng)用圖像分類和定位處理,獲得預(yù)測(cè)對(duì)象的邊界框及其對(duì)應(yīng)的類概率。
整個(gè)過程是不是很清晰,下面逐一詳細(xì)介紹。首先需要將標(biāo)記數(shù)據(jù)傳遞給模型以進(jìn)行訓(xùn)練。假設(shè)已將圖像劃分為大小為3 X 3的網(wǎng)格,且總共只有3個(gè)類別,分別是行人(c1)、汽車(c2)和摩托車(c3)。因此,對(duì)于每個(gè)單元格,標(biāo)簽y將是一個(gè)八維向量:
其中:
pc定義對(duì)象是否存在于網(wǎng)格中(存在的概率);
bx、by、bh、bw指定邊界框;
c1、c2、c3代表類別。如果檢測(cè)對(duì)象是汽車,則c2位置處的值將為1,c1和c3處的值將為0;
假設(shè)從上面的例子中選擇第一個(gè)網(wǎng)格:
由于此網(wǎng)格中沒有對(duì)象,因此pc將為零,此網(wǎng)格的y標(biāo)簽將為:
?意味著其它值是什么并不重要,因?yàn)榫W(wǎng)格中沒有對(duì)象。下面舉例另一個(gè)有車的網(wǎng)格(c2=1):
在為此網(wǎng)格編寫y標(biāo)簽之前,首先要了解YOLO如何確定網(wǎng)格中是否存在實(shí)際對(duì)象。大圖中有兩個(gè)物體(兩輛車),因此YOLO將取這兩個(gè)物體的中心點(diǎn),物體將被分配到包含這些物體中心的網(wǎng)格中。中心點(diǎn)左側(cè)網(wǎng)格的y標(biāo)簽會(huì)是這樣的:
由于此網(wǎng)格中存在對(duì)象,因此pc將等于1,bx、by、bh、bw將相對(duì)于正在處理的特定網(wǎng)格單元計(jì)算。由于檢測(cè)出的對(duì)象是汽車,所以c2=1,c1和c3均為0。對(duì)于9個(gè)網(wǎng)格中的每一個(gè)單元格,都具有八維輸出向量。最終的輸出形狀為3X3X8。
使用上面的例子(輸入圖像:100X100X3,輸出:3X3X8),模型將按如下方式進(jìn)行訓(xùn)練:
使用經(jīng)典的CNN網(wǎng)絡(luò)構(gòu)建模型,并進(jìn)行模型訓(xùn)練。在測(cè)試階段,將圖像傳遞給模型,經(jīng)過一次前向傳播就得到輸出y。為了簡(jiǎn)單起見,使用3X3網(wǎng)格解釋這一點(diǎn),但通常在實(shí)際場(chǎng)景中會(huì)采用更大的網(wǎng)格(比如19X19)。
即使一個(gè)對(duì)象跨越多個(gè)網(wǎng)格,它也只會(huì)被分配到其中點(diǎn)所在的單個(gè)網(wǎng)格。可以通過增加更多網(wǎng)格來減少多個(gè)對(duì)象出現(xiàn)在同一網(wǎng)格單元中的幾率。
2.2 YOLOv5獲取與調(diào)試
2.2.1 下載yolov5代碼
如果你有g(shù)it,則使用git clone
git clone https://github.com/ultralytics/yolov5 # clone
如果你沒有g(shù)it,你可以使用Dwonload ZIP下載代碼項(xiàng)目。
yolov5代碼地址:yolov5
注意:yolov5的代碼是最新的v8.0版本
可以通過這個(gè)鏈接下載6.0版本https://github.com/ultralytics/yolov5/tree/v6.0
2.2.2 安裝yolov5訓(xùn)練所需的第三方庫:
- 檢查是否正確安裝好anaconda。
windows+r打開cmd,輸入 conda -V。若出現(xiàn)版本號(hào),則安裝成功。 - 檢查是否正確安裝好pytorch
import torch
if __name__ == '__main__':
print(torch.zeros(1))
- 進(jìn)入yolov5文件夾目錄安裝第三方庫
cd [path_to_yolov5]
如下圖所示
安裝第三方庫
pip install -r requirement.txt
如下圖所示,等待安裝完成
2.2.3 下載預(yù)訓(xùn)練的權(quán)重文件
我們需要下載其預(yù)訓(xùn)練的權(quán)重文件然后再此基礎(chǔ)上進(jìn)行調(diào)整訓(xùn)練,這樣在數(shù)據(jù)集數(shù)量較小時(shí)也能取得不錯(cuò)的檢測(cè)準(zhǔn)確率。
供選擇的有yolov5s,yolov5m,yolov5l,yolov5x。模型的大小逐漸增大,訓(xùn)練時(shí)間更長,準(zhǔn)確率提高。
這里我們以yolov5s為例訓(xùn)練。下載地址為yolov5s.pt
所有權(quán)重下載地址可在https://github.com/ultralytics/yolov5/releases/tag/v6.0界面找到
2.2.4 配置自己的yaml文件
配置models/yolov5s_mask.yaml 可以直接復(fù)制yolov5s.yaml文件,然后在nc即類別出進(jìn)行修改,對(duì)于吸煙檢測(cè)數(shù)量為1。其中anchors參數(shù)表示錨框的大小,可以通過對(duì)數(shù)據(jù)集進(jìn)行knn聚類得到,這里直接使用默認(rèn)即對(duì)COCO數(shù)據(jù)集進(jìn)行聚類的結(jié)果。
配置mask.yaml 。這里train指定訓(xùn)練數(shù)據(jù)集所在位置,val測(cè)試數(shù)據(jù)集所在位置,nc類別數(shù),names類別的名稱(注意順序)
# YOLOv5 ?? by Ultralytics, GPL-3.0 license
# Parameters
nc: 1 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 6, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3, [1024]],
[-1, 1, SPPF, [1024, 5]], # 9
]
# YOLOv5 v6.0 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
配置my.yaml 。這里train指定訓(xùn)練數(shù)據(jù)集所在位置,val測(cè)試數(shù)據(jù)集所在位置,nc類別數(shù),names類別的名稱(注意順序)
train: D:\\BaiduNetdiskDownload\\train
val: D:\\BaiduNetdiskDownload\\val
nc: 1
names: ['smoke']
2.2.5 開始訓(xùn)練
python3 train.py --img 640 --batch 8 --epochs 50 --data my.yaml --cfg yolov5s_my.yaml --weights "yolov5s.pt"
如果出現(xiàn)顯卡空間不足的情況可以改小–bath參數(shù)
會(huì)在/runs/train/exp/weights/best.pt下生成最終的權(quán)重文件。
將此文件復(fù)制到y(tǒng)olov5目錄下后續(xù)使用
2.2.5 編寫detection方法用于后續(xù)檢測(cè)的調(diào)用
后續(xù)進(jìn)行圖片或者視頻檢測(cè)時(shí),只需要傳入YOLOv5模型和圖片,便會(huì)返回檢測(cè)后圖片
import os
import sys
from pathlib import Path
import numpy as np
import torch
FILE = Path(__file__).resolve()
ROOT = FILE.parents[0] # YOLOv5 root directory
if str(ROOT) not in sys.path:
sys.path.append(str(ROOT)) # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
from models.experimental import attempt_load
from utils.general import apply_classifier, check_img_size, check_imshow, check_requirements, check_suffix, colorstr, \
increment_path, non_max_suppression, print_args, save_one_box, scale_coords, strip_optimizer, xyxy2xywh, LOGGER
from utils.plots import Annotator, colors
from utils.torch_utils import load_classifier, select_device, time_sync
from utils.augmentations import Albumentations, augment_hsv, copy_paste, letterbox, mixup, random_perspective
@torch.no_grad()
def detection(model,input_img):
imgsz = 640 # inference size (pixels)
conf_thres = 0.25 # confidence threshold
iou_thres = 0.45 # NMS IOU threshold
max_det = 1000 # maximum detections per image
device = '0' # cuda device, i.e. 0 or 0,1,2,3 or cpu
view_img = False # show results
save_txt = False # save results to *.txt
save_conf = False # save confidences in --save-txt labels
save_crop = False # save cropped prediction boxes
nosave = False # do not save images/videos
classes = None # filter by class: --class 0, or --class 0 2 3
agnostic_nms = False # class-agnostic NMS
augment = False # augmented inference
project = ROOT / 'runs/detect', # save results to project/name
name = 'exp' # save results to project/name
exist_ok = False, # existing project/name ok, do not increment
line_thickness = 3 # bounding box thickness (pixels)
hide_labels = False # hide labels
hide_conf = False # hide confidences
half = False # use FP16 half-precision inference
# Directories
# Initialize
device = select_device(device)
weights = 'best.pt'
# # Load model
w = str(weights[0] if isinstance(weights, list) else weights)
classify, suffix, suffixes = False, Path(w).suffix.lower(), ['.pt', '.onnx', '.tflite', '.pb', '']
check_suffix(w, suffixes) # check weights have acceptable suffix
pt, onnx, tflite, pb, saved_model = (suffix == x for x in suffixes) # backend booleans
stride = int(model.stride.max())
names = model.module.names if hasattr(model, 'module') else model.names # get class names
imgsz = check_img_size(imgsz, s=stride) # check image size
img0 = input_img # BGR
im0s=img0
# Padded resize
img = letterbox(img0, imgsz, stride=32, auto=pt)[0]
# Convert
img = img.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB
img = np.ascontiguousarray(img)
bs = 1 # batch_size
dt, seen = [0.0, 0.0, 0.0], 0
t1 = time_sync()
img = torch.from_numpy(img).to(device)
img = img.float() # uint8 to fp16/32
img /= 255.0 # 0 - 255 to 0.0 - 1.0
if len(img.shape) == 3:
img = img[None] # expand for batch dim
t2 = time_sync()
dt[0] += t2 - t1
# Inference
if pt:
pred = model(img, augment=augment)[0]
t3 = time_sync()
dt[1] += t3 - t2
# NMS
pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
dt[2] += time_sync() - t3
# Process predictions
for i, det in enumerate(pred): # per image
seen += 1
im0=im0s.copy()
annotator = Annotator(im0, line_width=line_thickness, example=str(names))
if len(det):
# Rescale boxes from img_size to im0 size
det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()
# Write results
for *xyxy, conf, cls in reversed(det):
# Add bbox to image
c = int(cls) # integer class
label = None if hide_labels else (names[c] if hide_conf else f'{names[c]} {conf:.2f}')
annotator.box_label(xyxy, label, color=colors(c, True))
# Stream results
im0 = annotator.result()
return im0
3. Pyqt5
我們通過pyqt來制作展示的界面
3.1介紹
PyQt5 是 Digia的一套 Qt5 應(yīng)用框架與 python 的結(jié)合,同時(shí)支持 python2.x和 python3.x。
這里使用的是Python 3.x。Qt庫由 Riverbank Computing開發(fā),是最強(qiáng)大的GUI庫之一 。
PyQt5 是由一系列 Python 模塊組成。超過 620 個(gè)類,6000 函數(shù)和方法。能在諸如 Unix、Windows 和Mac OS 等主流操作系統(tǒng)上運(yùn)行。PyQt5 有兩種證書,GPL和 商業(yè)證書。
3.2 window平臺(tái)安裝
PyQt5 有兩種安裝方式,一種是從官網(wǎng)下載源碼安裝,另外一種是使用 pip 安裝。
這里我推薦大家使用pip 安裝。因?yàn)樗鼤?huì)自動(dòng)根據(jù)你的Python 版本來選擇合適的 PyQt5 版本,如果是手動(dòng)下載源碼安裝,難免會(huì)選擇出錯(cuò)。建議使用比較穩(wěn)妥的安裝方式。
pip3 install PyQt5
另外,如果你的網(wǎng)絡(luò)訪問外網(wǎng)不是很好的話建議使用豆瓣的鏡像下載,不然會(huì)很很慢或者直接安裝失敗。
pip install PyQt5 -i https://pypi.douban.com/simple
執(zhí)行以下代碼:
import sys
from PyQt5.QtWidgets import QWidget, QApplication
app = QApplication(sys.argv)
widget = QWidget()
widget.resize(640, 480)
widget.setWindowTitle("Hello, PyQt5!")
widget.show()
sys.exit(app.exec())
如果沒有報(bào)錯(cuò),彈出了一個(gè)標(biāo)題為"Hello, PyQt5!"的窗口,則說明安裝成功。
若pip安裝pyqt5報(bào)錯(cuò) error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build Tools”: https://visualstudio.microsoft.com/visual-cpp-build-tools/
error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/
可參考我另外一篇文章 已解決(pip安裝pyqt5報(bào)錯(cuò)) error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft
對(duì)于運(yùn)行項(xiàng)目做到此即可,若對(duì)pyqt感興趣如圖形界面開發(fā)工具Qt Designer等可以參考文章https://zhuanlan.zhihu.com/p/162866700
4. OpenCV
OpenCV(開源的計(jì)算機(jī)視覺庫)是基于BSD協(xié)議,因此它可免費(fèi)用于學(xué)術(shù)和商業(yè)用途。其提供C++,C,Python和Java接口,支持Windows,Linux,Mac OS,iOS和Android。
我們使用OpenCV來處理圖片和視頻,以便于將圖片轉(zhuǎn)為Yolov5模型需要的輸入。
安裝
首先我們得先安裝另一個(gè)第三方庫numpy,這是opencv的依賴庫,沒有它無法進(jìn)行python-opencv開發(fā)。
安裝numpy:pip install numpy
安裝opencv-python: pip install opencv-python
5. 圖片檢測(cè)
5.1界面布局
首先使用pyqt設(shè)計(jì)我們界面的布局,主要為一個(gè)上傳圖片的按鈕和兩個(gè)展示板,一個(gè)展示原始圖片,一個(gè)展示我們模型進(jìn)行檢測(cè)后的圖片。這里主要使用的是網(wǎng)格布局QGridLayout()
class Qdetection1(QWidget):
def __init__(self,model):
super(Qdetection1, self).__init__()
self.initUI()
self.model=model
def initUI(self):
self.main_layout = QGridLayout() # 創(chuàng)建主部件的網(wǎng)格布局
self.setLayout(self.main_layout) # 設(shè)置窗口主部件布局為網(wǎng)格布局
self.button1 = QPushButton('上傳圖片')
self.button1.clicked.connect(self.loadImage)
self.main_layout.addWidget(self.button1)
self.imageLabel1 = QLabel()
self.main_layout.addWidget(self.imageLabel1)
self.imageLabel2 = QLabel()
self.main_layout.addWidget(self.imageLabel2)
self.main_layout.addWidget(self.button1, 0, 0, 1, 2)
self.main_layout.addWidget(self.imageLabel1, 2, 0, 1, 1)
self.main_layout.addWidget(self.imageLabel2, 2, 1, 1, 1)
因?yàn)楹罄m(xù)有視頻檢測(cè)和攝像頭實(shí)時(shí)檢測(cè),為了將其集成在同一個(gè)界面里,可以使用QTabWidget()
my_tabwidget=QTabWidget()
tab1_widget=Qdetection1(model)
tab2_widget = Qdetection2(model)
tab3_widget = Qdetection3(model)
my_tabwidget.setWindowTitle('目標(biāo)檢測(cè)演示 ')
my_tabwidget.addTab(tab1_widget, '圖片檢測(cè)')
my_tabwidget.addTab(tab2_widget, '視頻檢測(cè)')
my_tabwidget.addTab(tab3_widget, '攝像頭實(shí)時(shí)檢測(cè)')
my_tabwidget.show()
pyqt原始提供的組件并不美觀,為了美化組件可以使用qt_material。其安裝和使用都比較簡(jiǎn)單。
安裝
pip install qt_material
使用
import sys
from PyQt5 import QtWidgets
from qt_material import apply_stylesheet
# create the application and the main window
app = QtWidgets.QApplication(sys.argv)
window = QtWidgets.QMainWindow()
# setup stylesheet
apply_stylesheet(app, theme='dark_teal.xml')
# run
window.show()
app.exec_()
對(duì)比效果
5.2 模型加載
我們需要將訓(xùn)練好的模型讀取加載從而使用。為了提交響應(yīng)速度和防止每個(gè)功能都重復(fù)加載,這里采用了在啟動(dòng)窗口的時(shí)候就進(jìn)行加載。
if __name__ == '__main__':
device = select_device('0')
# Load model
weights = 'best.pt'
w = str(weights[0] if isinstance(weights, list) else weights)
classify, suffix, suffixes = False, Path(w).suffix.lower(), ['.pt', '.onnx', '.tflite', '.pb', '']
check_suffix(w, suffixes) # check weights have acceptable suffix
pt, onnx, tflite, pb, saved_model = (suffix == x for x in suffixes) # backend booleans
stride, names = 64, [f'class{i}' for i in range(1000)] # assign defaults
if pt:
model = torch.jit.load(w) if 'torchscript' in w else attempt_load(weights, map_location=device)
stride = int(model.stride.max()) # model stride
names = model.module.names if hasattr(model, 'module') else model.names # get class names
5.3點(diǎn)擊上傳按鈕事件和檢測(cè)展示綁定
當(dāng)我們點(diǎn)擊上傳按鈕后通過cv2讀取文件,通過detection方法檢測(cè)圖片。然后將結(jié)果暫時(shí)到對(duì)應(yīng)的展示板上。文章來源:http://www.zghlxwxcb.cn/news/detail-489686.html
def loadImage(self):
fname, _ = QFileDialog.getOpenFileName(self, '打開文件', '.', '圖像文件(*.jpg *.png)')
if fname is None or fname=="":
print("未選擇圖片")
else:
img = cv2.imread(fname)
np_img=detection(self.model,img)
np_img = cv2.cvtColor(np_img, cv2.COLOR_BGR2RGB)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.imageLabel1.setPixmap(QPixmap(QImage(img.data, img.shape[1], img.shape[0], img.shape[1]*3, QImage.Format_RGB888)))
self.imageLabel2.setPixmap(QPixmap(QImage(np_img.data, np_img.shape[1], np_img.shape[0], np_img.shape[1]*3, QImage.Format_RGB888)))
5.4完整代碼
import torch
from utils.general import check_suffix
from utils.torch_utils import select_device
from pathlib import Path
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import time
import cv2
from mydetection import detection
from yolov5.models.experimental import attempt_load
class Qdetection1(QWidget):
def __init__(self,model):
super(Qdetection1, self).__init__()
self.initUI()
self.model=model
def initUI(self):
self.main_layout = QGridLayout() # 創(chuàng)建主部件的網(wǎng)格布局
self.setLayout(self.main_layout) # 設(shè)置窗口主部件布局為網(wǎng)格布局
self.button1 = QPushButton('上傳圖片')
self.button1.clicked.connect(self.loadImage)
self.main_layout.addWidget(self.button1)
self.imageLabel1 = QLabel()
self.main_layout.addWidget(self.imageLabel1)
self.imageLabel2 = QLabel()
self.main_layout.addWidget(self.imageLabel2)
self.main_layout.addWidget(self.button1, 0, 0, 1, 2)
self.main_layout.addWidget(self.imageLabel1, 2, 0, 1, 1)
self.main_layout.addWidget(self.imageLabel2, 2, 1, 1, 1)
def loadImage(self):
fname, _ = QFileDialog.getOpenFileName(self, '打開文件', '.', '圖像文件(*.jpg *.png)')
if fname is None or fname=="":
print("未選擇圖片")
else:
img = cv2.imread(fname)
np_img=detection(self.model,img)
np_img = cv2.cvtColor(np_img, cv2.COLOR_BGR2RGB)
img=cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.imageLabel1.setPixmap(QPixmap(QImage(img.data, img.shape[1], img.shape[0], img.shape[1]*3, QImage.Format_RGB888)))
self.imageLabel2.setPixmap(QPixmap(QImage(np_img.data, np_img.shape[1], np_img.shape[0], np_img.shape[1]*3, QImage.Format_RGB888)))
if __name__ == '__main__':
app = QApplication(sys.argv)
device = select_device('0')
# Load model
weights = 'best.pt'
w = str(weights[0] if isinstance(weights, list) else weights)
classify, suffix, suffixes = False, Path(w).suffix.lower(), ['.pt', '.onnx', '.tflite', '.pb', '']
check_suffix(w, suffixes) # check weights have acceptable suffix
pt, onnx, tflite, pb, saved_model = (suffix == x for x in suffixes) # backend booleans
stride, names = 64, [f'class{i}' for i in range(1000)] # assign defaults
if pt:
model = torch.jit.load(w) if 'torchscript' in w else attempt_load(weights, map_location=device)
stride = int(model.stride.max()) # model stride
names = model.module.names if hasattr(model, 'module') else model.names # get class names
my_tabwidget=QTabWidget()
tab1_widget=Qdetection1(model)
my_tabwidget.setWindowTitle('目標(biāo)檢測(cè)演示 ')
my_tabwidget.addTab(tab1_widget, '圖片檢測(cè)')
my_tabwidget.show()
apply_stylesheet(app, theme='light_blue.xml')
sys.exit(app.exec_())
最終效果文章來源地址http://www.zghlxwxcb.cn/news/detail-489686.html
到了這里,關(guān)于吸煙檢測(cè)從零開始使用YOLOv5+PyQt5+OpenCV實(shí)現(xiàn)(支持圖片、視頻、攝像頭實(shí)時(shí)檢測(cè))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!