0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

把YOLOv11和Python Qt做个用户界面程序

安费诺传感器学堂 来源:安费诺传感器学堂 2024-11-28 10:18 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

早些时间,小编想把PID控制器优化部分通过Py Qt来实现用户界面化,不过看着窗口一堆参数,有点发怵:这玩意谁用啊?

9e185014-a936-11ef-93f3-92fbcf53809c.png

参考《PID控制器参数自动优化示例和比较》

后来就搁置了。 在通过Python以及YOLO来检测图中或者视频中的各种物体以及人物的时候,就会考虑:全部用代码来输出的?怎么通过一个简单直观的窗口界面来测试相应的功能?我觉得要再试一下,哪怕是最简单的方式呈现。这便是这篇文章的目的所在。 我们通过YOLO现成的各种检测模块,实现:

图中物体的识别检测

检出物体的区域分割

人体姿态的检测

还有其他的检测功能,感觉功能有重叠,就选了上面的三个功能简单地集成到一个windows的因为分类的功能只是软件界面中。 以下图片均有AI生成,但是人体姿态检测的结果可能看不清楚输出。

按照我们之前的惯例,先提供结果,后提供代码。

9e83512a-a936-11ef-93f3-92fbcf53809c.png

[1]物体检测

9eb9e1f4-a936-11ef-93f3-92fbcf53809c.png

[2]物体分割

9efb1868-a936-11ef-93f3-92fbcf53809c.png

[3]姿态检测

我们可以自己尝试运行一下。

# This program is part of a project developed by Amphenol Sensors.
#Copyright(C)2024,Leo Lu
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .


import sys
from PyQt5.QtWidgets import (QApplication, QLabel, QPushButton, QVBoxLayout, QWidget, 
                             QFileDialog, QComboBox, QHBoxLayout)
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt
import cv2
import numpy as np
import random


from ultralytics import YOLO
from ultralytics.models.yolo.pose.predict import PosePredictor


class YOLOInterface(QWidget):
    def __init__(self):
        super().__init__()


        self.initUI()
        self.model_detec = YOLO('./yolo_models/yolo11s.pt')
        self.model_seg = YOLO('./yolo_models/yolo11s-seg.pt')
        self.model_bd = './yolo_models/yolo11s-pose.pt'
        self.connections = ((2, 4), (1, 3), (10, 8), (8, 6), (6, 5), (5, 7), (7, 9), 
                            (6, 12), (12, 14), (14, 16), (5, 11), (11, 13), (13, 15))


    def initUI(self):
        self.setWindowTitle('YOLO 图像检测')
        self.setGeometry(100, 100, 1200, 600)
        self.setFixedSize(1200, 600)
        # 主布局
        main_layout = QVBoxLayout()


        # 图像显示布局
        image_layout = QHBoxLayout()


        self.image_label = QLabel(self)
        self.image_label.setFixedSize(600, 400)
        self.image_label.setAlignment(Qt.AlignCenter)
        image_layout.addWidget(self.image_label)


        self.result_label = QLabel(self)
        self.result_label.setFixedSize(600, 400)
        self.result_label.setAlignment(Qt.AlignCenter)
        image_layout.addWidget(self.result_label)


        main_layout.addLayout(image_layout)


        # 控制布局
        control_layout = QHBoxLayout()


        self.detect_button = QPushButton('选择图片', self)
        self.detect_button.clicked.connect(self.load_image)
        control_layout.addWidget(self.detect_button)


        self.yolo_combo = QComboBox(self)
        self.yolo_combo.addItems(['物体检测', '物体分割', '人体姿态识别'])  # 假设在此处添加不同的YOLO任务
        control_layout.addWidget(self.yolo_combo)


        self.run_button = QPushButton('开始检测', self)
        self.run_button.clicked.connect(self.run_yolo)
        control_layout.addWidget(self.run_button)


        self.quit_button = QPushButton('退出', self)
        self.quit_button.clicked.connect(self.close_application)
        control_layout.addWidget(self.quit_button)


        main_layout.addLayout(control_layout)
        self.setLayout(main_layout)


    def load_image(self):
        options = QFileDialog.Options()
        file_name, _ = QFileDialog.getOpenFileName(self, "选择图片文件", "", "Images (*.png *.jpg *.bmp)", options=options)
        if file_name:
            self.current_image = file_name
            pixmap = QPixmap(file_name)
            scaled_pixmap = pixmap.scaled(self.image_label.size(), Qt.KeepAspectRatio)
            self.image_label.setPixmap(scaled_pixmap)


    def plot_keypoints(self, image, keypoints, line_color=(60, 179, 113), point_color=(255, 0, 0),
                   offset=(0, 0), show_idx=False):
        if keypoints is None:
            return image
        
        for data in keypoints.xy:
            if len(data) == 0:
                continue
            # Draw connections between keypoints
            for start_index, end_index in self.connections:
                start_point, end_point = data[start_index], data[end_index]
                if all(start_point[:2] > 0) and all(end_point[:2] > 0):  # Ignore invalid points
                    cv2.line(image, 
                             tuple(map(lambda v, o: int(v + o), start_point[:2], offset)), 
                             tuple(map(lambda v, o: int(v + o), end_point[:2], offset)), 
                             line_color, 2)
            # Draw keypoints
            for index, (x, y) in enumerate(data[:, :2]):
                if x > 0 or y > 0:  # Ignore invalid points
                    cv2.circle(image, 
                               (int(x + offset[0]), int(y + offset[1])), 
                               5, point_color, -1)
                    if show_idx:
                        cv2.putText(image, 
                                    str(index), 
                                    (int(x + offset[0]), int(y + offset[1])), 
                                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, point_color, 1, cv2.LINE_AA)
    
        return image


    def run_yolo(self):
        if hasattr(self, 'current_image'):
            img = cv2.imread(self.current_image)
            
            # YOLO推理示例:
            task = self.yolo_combo.currentText()
            if task =='物体检测':
                #model = self.model_detec #YOLO('yolo11s.pt')
                results = self.model_detec(img)
                
                for result in results:
                    boxes = result.boxes                # Pseudo-code; adjust based on actual library


                    for box in boxes:
                        x1, y1, x2, y2 = box.xyxy[0]    # Extracting the bounding box coordinates
                        class_name = self.model_detec.names[int(box.cls[0])]  # Using class_id to get class_name from model
                        confidence = box.conf.item()
                        cv2.rectangle(img, (int(x1), int(y1)), (int(x2), int(y2)), (0, 255, 0), 2)
                        txt_y_pos = int(y1) - 10
                        if txt_y_pos <= 10:
                            txt_y_pos = int(y2) - 10
                        
                        class_name = class_name + " "+ "{:.2g}".format(confidence)
                        cv2.putText(img, class_name, (int(x1), txt_y_pos), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)


            elif task =='物体分割':
                #model = YOLO('yolo11s-seg.pt')
                results = self.model_seg(img)
                
                # Prepare an overlay image with the same dimensions
                overlay = img.copy()
                
                for result in results:
                    boxes = result.boxes  # Pseudo-code; adjust based on actual library
                    masks = result.masks
                    names = result.names
                    for box, mask in zip(boxes, masks):
                        for cls, contour in zip(box.cls, mask.xy):
                            class_id = cls.item()  # Get scalar from tensor
                            class_name = names[class_id]
                            #print(class_name)
                            #print(cv2.contourArea(contour))  # Calculate contour area
                            
                            # Generate a random color
                            color = [random.randint(0, 255) for _ in range(3)]
                            
                            # Fill the contour on the overlay with the random color
                            cv2.drawContours(overlay, [contour.astype(np.int32)], -1, color, thickness=cv2.FILLED)
                # Define the alpha (transparency factor)
                alpha = 0.4  # Value between 0 (transparent) and 1 (opaque)
                
                # Blend the overlay with the original image
                """
                Parameters
                overlay (src1):


                This is the first input array (image).
                In your context, this represents the overlay image, which typically contains modifications like semi-transparent masks drawn over contours.
                
                alpha:
                This is the weight of the first array (image).
                It controls the opacity of the overlay. A value closer to 1 makes the overlay more prominent, while a value closer to 0 makes it less prominent.
                
                img (src2):
                This is the second input array (image).
                It represents the original image onto which the overlay is being applied.
                
                1 - alpha (beta):
                This is the weight of the second array (image).
                Complementary to alpha, it controls the visibility of the original image. A value closer to 1 makes the original image more visible, while closer to 0 makes it less visible.
                
                0 (gamma):
                A scalar added to each sum.
                Typically set to 0 when blending for direct overlay purposes without additional brightness adjustment.
                
                img (dst):
                The destination array where the output is stored.
                It uses the same variable as the original image, implying that the blended result will overwrite this variable.
                """
                cv2.addWeighted(overlay, alpha, img, 1 - alpha, 0, img)


            elif task == '人体姿态识别':
                #model = YOLO('yolo11s-pose.pt')
                #results = model(img)
                
                overrides_Body_pose = {
                    "task": "pose",
                    "mode": "predict",
                    "model": self.model_bd,        #'yolo11s-pose.pt'
                    "verbose": False,
                    "classes": [0],
                    "iou": 0.5,
                    "conf": 0.3
                    }


                predictor_ren_pose = PosePredictor(overrides=overrides_Body_pose)
                pose_ren = predictor_ren_pose(img)[0]
                
                img = self.plot_keypoints(img, pose_ren.keypoints)
                
            # Convert the image to a format suitable for PyQt
            height, width, channel = img.shape
            bytes_per_line = 3 * width
            q_image = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
            pixmap = QPixmap.fromImage(q_image)
            self.display_results(pixmap)


    def display_results(self, pixmap):
        scaled_pixmap = pixmap.scaled(self.result_label.size(), Qt.KeepAspectRatio)
        self.result_label.setPixmap(scaled_pixmap)


    def close_application(self):
        self.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = YOLOInterface()
    ex.show()
    sys.exit(app.exec_())
小编甚至用它来检测一个AI生成的油画风格的图片。看图中哪些抽象的只有形态没有细节的人和物体,居然仍然可以检测出来。大家可以试一下看看检测的结果。

代码中涉及到的python软件包,需要额外安装,模型文件用的是YOLO现成的。小编把这个软件用打包工具生成的exe文件,因为攘括的软件多,简单的这些功能,打包后的文件压缩后的大小竟高达近900MB(分割压缩工具要收费咯),而很多平台不支持这么大的文件上传,所以这里也无法提供打包后的文件下载链接。

9f681a44-a936-11ef-93f3-92fbcf53809c.png

视线收回,我们心旷神怡一下。感谢AI的提供。

是否在怀疑这个世界的真实性?用传感器来检测一下吧,这个世界的冷热、正负压,振动,周围的空气......可以负责任地告诉各位,我们还是碳基生物。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 程序
    +关注

    关注

    117

    文章

    3836

    浏览量

    84745
  • PID控制器
    +关注

    关注

    2

    文章

    173

    浏览量

    19575
  • python
    +关注

    关注

    57

    文章

    4856

    浏览量

    89550

原文标题:把YOLOv11和Python Qt做个用户界面程序

文章出处:【微信号:安费诺传感器学堂,微信公众号:安费诺传感器学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    那些年我用OpenCV+Qt趟过哪些坑?写给视觉应用开发者的避坑指南

    重写半套程序11. 复杂场景:多路视频实时检测的界面与线程架构设计,以及如何用“读写者模式”管理共享数据,避免资源竞争。 第三阶段:实战 - 在真实项目中融会贯通 懂再多道理,不如亲手实现一遍。我
    发表于 12-02 09:43

    yolov11转kmodel,numpy是要降级为1.x吗?

    python3.9,yolo是最新的稳定版,和yolo捆绑pip安装的numpy是2.0.1 错误日志
    发表于 08-11 08:16

    RK3576 Yolov11训练部署教程

    1.Yolo11简介YOLO11系列是YOLO家族中最先进的(SOTA)、最轻量级、最高效的模型,其表现优于其前辈。它由Ultralytics创建,该组织发布了YOLOv8,这是迄今为止最稳定
    的头像 发表于 07-25 15:22 794次阅读
    RK3576 <b class='flag-5'>Yolov11</b>训练部署教程

    【Milk-V Duo S 开发板免费体验】5 - 使用YOLOv11进行目标检测

    引言 前面已经完成了Milk-V Duo S开发板的基本功能测试,今天来尝试一下使用YOLOv11进行目标检测。 TDL-SDK Cvitek 所提供的 TDL(Turnkey Deep
    发表于 07-24 14:57

    【HZ-RK3568开发板免费体验】04 YOLOv11 模型转换为RKNN并在板端部署

    程序自动将其保存为out.png,可以下载到电脑端查看,如下图 至此,YOLOv11的模型转换与部署就结束了,后面再研究视频推理。
    发表于 07-02 14:01

    瑞芯微RK3506(3核A7@1.5GHz+双网口+双CAN-FD)工业开发板—图形用户界面(GUI)开发手册

    本文主要说明Qt的图形用户界面(GUI)开发流程,包括Qt程序自启动配置与案例介绍,旨在帮助开发者完成产品开发与测试。
    的头像 发表于 06-03 14:27 1195次阅读
    瑞芯微RK3506(3核A7@1.5GHz+双网口+双CAN-FD)工业开发板—图形<b class='flag-5'>用户</b><b class='flag-5'>界面</b>(GUI)开发手册

    labview调用yolov8/11目标检测、分割、分类

    labview使用2020版本64位编辑,调用yolov8/11的onnx模型案例。 源码: 通过网盘分享的文件:Labview_cls.zip等4个文件 链接: https
    发表于 04-21 19:37

    【技术案例】Qt 环境部署 - Ubuntu 篇

    什么是QtQt是一个跨平台C++图形用户界面应用程序开发框架,可构建高性能的桌面、移动及Web应用程序
    的头像 发表于 04-16 17:17 1437次阅读
    【技术案例】<b class='flag-5'>Qt</b> 环境部署 - Ubuntu 篇

    RK3576 yolov11-seg训练部署教程

    级的精确目标检测与分割,适用于自动驾驶、医学影像、工业检测等对精度和速度要求苛刻的场景。        本教程针对目标分割算法yolov11 seg的训练和部署到EASY-EAI-Orin-nano(RK3576)进行说明,而数据标注方法可以参考我们往期的文章。
    的头像 发表于 04-16 09:43 1882次阅读
    RK3576 <b class='flag-5'>yolov11</b>-seg训练部署教程

    OrinNano yolov11训练部署教程

    ORinNano yolov11训练部署教程
    的头像 发表于 04-10 15:26 2217次阅读
    OrinNano  <b class='flag-5'>yolov11</b>训练部署教程

    RK3576 Yolov11训练部署教程

    YOLO11 系列是 YOLO 家族中最先进的 (SOTA)、最轻量级、最高效的模型,其表现优于其前辈。它由 Ultralytics 创建,该组织发布了 YOLOv8,这是迄今为止最稳定、使用最广泛的 YOLO 变体。YOLO11
    的头像 发表于 04-03 09:35 1754次阅读
    RK3576 <b class='flag-5'>Yolov11</b>训练部署教程

    Raspberry Pi上使用IR v11及OpenVINO™ 2021.3后不兼容怎么办?

    使用 Google Colab OpenVINO™ 2022.2 将 yolov5 模型转换为 IR v11: !git clone https://github.com/ultralytics
    发表于 03-06 07:14

    【米尔RK3576开发板评测】+项目名称YOLOV5目标检测

    /examples/yolov5/python python yolov5.py --model_path ../model/yolov5s
    发表于 02-15 13:24

    RK3568国产芯教学实验箱:指纹识别实战案例

    )GUI的设计实现:LCD显示界面以及与用户的交互;(3)编辑控制代码;(4)编译程序;(5)运行程序Qt
    的头像 发表于 01-08 19:05 1173次阅读
    RK3568国产芯教学实验箱:指纹识别实战案例

    基于QT开发国产主板终端桌面程序 高效、稳定、跨平台的解决方案

    了开发者们面临的一个重要挑战。本文将介绍如何基于QT框架,开发适用于国产主板的终端桌面程序,并探讨其优势和应用场景。 QT是一个跨平台的C++图形用户
    的头像 发表于 01-08 15:34 1438次阅读