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

    文章

    3788

    浏览量

    81097
  • PID控制器
    +关注

    关注

    2

    文章

    173

    浏览量

    18589
  • python
    +关注

    关注

    56

    文章

    4797

    浏览量

    84752

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

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

收藏 人收藏

    评论

    相关推荐

    在RK3568教学实验箱上实现基于YOLOV5的算法物体识别案例详解

    安装了所有必要的依赖。这通常包括 torch、torchvision 和 opencv-python。 (2)下载预训练模型 YOLOv5 提供了多个预训练模型,可以从官方仓库或相关资源中下载。 (3
    发表于 12-03 14:56

    YOLOv6在LabVIEW中的推理部署(含源码)

    YOLOv6 是美团视觉智能部研发的一款目标检测框架,致力于工业应用。如何使用python进行该模型的部署,官网已经介绍的很清楚了,但是对于如何在LabVIEW中实现该模型的部署,笔者目前还没有看到
    的头像 发表于 11-06 16:07 304次阅读
    <b class='flag-5'>YOLOv</b>6在LabVIEW中的推理部署(含源码)

    国产Cortex-A55实验箱操作案例分享:LED程序开发

    一、实验目的(1)熟悉Qt程序的开发流程。(2)掌握QtCreator的基础开发使用。(3)通过编写Qt程序实现LED控制的显示界面。二、实
    的头像 发表于 11-01 08:10 161次阅读
    国产Cortex-A55实验箱操作案例分享:LED<b class='flag-5'>程序</b>开发

    EtherCAT运动控制器上位机开发之Python+Qt(三):PDO配置与SDO读写

    PC上位机Python+Qt混合编程实现PDO配置与SDO读写
    的头像 发表于 08-21 15:56 1145次阅读
    EtherCAT运动控制器上位机开发之<b class='flag-5'>Python+Qt</b>(三):PDO配置与SDO读写

    嵌入式QT常见开发方式有哪些?

    提供的丰富组件如按钮、文本框、窗口等构建传统的桌面应用风格界面。对于嵌入式设备上的复杂用户界面或者需要高性能响应的应用,Qt Widgets是一个较为常用的选择。 2.
    发表于 08-12 10:05

    EtherCAT运动控制器上位机之Python+Qt(一):链接与单轴运动

    PC上位机Python+Qt混合编程,助力智能制造高效开发。
    的头像 发表于 07-31 09:43 438次阅读
    EtherCAT运动控制器上位机之<b class='flag-5'>Python+Qt</b>(一):链接与单轴运动

    上位机可视化界面编程软件有哪些

    。以下是一些常见的上位机可视化界面编程软件: Qt (跨平台C++框架) 介绍 :Qt是一个跨平台的C++图形用户界面应用
    的头像 发表于 06-06 10:48 2548次阅读

    Qt Group与高通公司合作,简化工业物联网的用户界面开发

    公司于当地时间4月9日宣布,正在合作为工业物联网设备简化高级图形用户界面 (GUI) 的开发和软件质量保证。 Qt Group与高通公司合作,简化工业物联网的用户
    的头像 发表于 04-10 14:12 450次阅读
    <b class='flag-5'>Qt</b> Group与高通公司合作,简化工业物联网的<b class='flag-5'>用户</b><b class='flag-5'>界面</b>开发

    FPGA板子可以跑Qt应用程序

    Qt作为一款跨平台GUI图形界面设计软件,她可以在windows、Linux上运行,没听说过在FPGA的板子上运行Qt程序呢?
    发表于 03-28 23:27

    Qt For OpenHarmony图形化的进展突破

    Qt 适配 OpenHarmony 意义 Qt 是一个 C++ 跨平台开发框架,主要用于开发图形用户界面(Graphical User Interface,GUI)
    的头像 发表于 02-02 14:29 1539次阅读
    <b class='flag-5'>Qt</b> For OpenHarmony图形化的进展突破

    如何使用linux下gdb来调试python程序

    如何使用linux下gdb来调试python程序  在Linux下,可以使用GDB(GNU调试器)来调试Python程序。GDB是一个强大的调试工具,可以帮助开发者诊断和修复
    的头像 发表于 01-31 10:41 2650次阅读

    基于QT5+OpenCV+OpenVINO C++的应用打包过程

    我用QT C++写了一个YOLOv5模型推理演示应用。
    的头像 发表于 01-26 10:17 1326次阅读
    基于<b class='flag-5'>QT</b>5+OpenCV+OpenVINO C++的应用打包过程

    在buildroot创建带qt的根文件系统,宿主机的qt需要在什么位置?

    问题1. 之前使用bsp里的qt,分别编译成arm版的和x86板的,安装路径是/usr/local/Trolltech/qt-4.8.5-x11和/usr/local/Trolltech
    发表于 01-17 08:27

    深入浅出Yolov3和Yolov4

    Yolov3是目标检测Yolo系列非常非常经典的算法,不过很多同学拿到Yolov3或者Yolov4的cfg文件时,并不知道如何直观的可视化查看网络结构。
    的头像 发表于 01-11 10:42 800次阅读
    深入浅出<b class='flag-5'>Yolov</b>3和<b class='flag-5'>Yolov</b>4

    yolov5量化INT8出错怎么处理?

    model_deploy.py --mlir yolov5l.mlir --quantize INT8 --calibration_table yolov5l_cali_table --chip
    发表于 01-10 06:40