You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

YOLOv8+Streamlit图像检测项目遇ModuleNotFoundError及运行错误求助

YOLOv8目标检测+Streamlit Web应用报错问题

我在Visual Studio Code中基于YOLOv8实现目标检测,并通过Streamlit搭建Web应用,遇到以下问题:

  • 运行1_YOLO_for_image.py时,执行from yolo_predictions import YOLO_Pred语句出现ModuleNotFoundError: No module named 'yolo_predictions'错误,尽管已将yolo_predictions.py放在同一目录
  • 启动Streamlit时也出现异常

yolo_predictions.py代码

#!/usr/bin/env python
# coding: utf-8

import cv2
import numpy as np
import os
import yaml
from yaml.loader import SafeLoader


class YOLO_Pred():
    def __init__(self,onnx_model,data_yaml):
        #加载YAML配置
        with open(data_yaml,mode='r') as f:
            data_yaml = yaml.load(f,Loader=SafeLoader)

        self.labels = data_yaml['names']
        self.nc = data_yaml['nc']

        #加载YOLO模型
        self.yolo = cv2.dnn.readNetFromONNX(onnx_model)
        self.yolo.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
        self.yolo.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)

    def predictions(self,image):
        
        row, col, d = image.shape
        #从图像获取YOLO预测结果
        #步骤1:将图像转换为方形数组
        max_rc = max(row,col)
        input_image = np.zeros((max_rc,max_rc,3),dtype=np.uint8)
        input_image [0:row,0:col] = image
        #步骤2:从方形数组获取预测结果
        INPUT_WH_YOLO = 640
        blob = cv2.dnn.blobFromImage(input_image,1/255,(INPUT_WH_YOLO,INPUT_WH_YOLO),swapRB=True,crop=False)
        self.yolo.setInput(blob)
        preds = self.yolo.forward() #YOLO的检测/预测结果


        #非极大值抑制(NMS)
        #步骤1:根据置信度(0.4)和概率得分(0.8)过滤检测结果
        detections = preds[0]
        boxes = []
        confidences = []
        classes = []

        #输入图像的宽高
        image_w, image_h = input_image.shape[:2]
        x_factor = image_w/INPUT_WH_YOLO
        y_factor = image_h/INPUT_WH_YOLO

        for i in range (len(detections)):
            row = detections[i]
            confidence = row[4] #检测到目标的置信度
            if confidence > 0.4:
                class_score = row[5:].max() #各类别中的最大概率
                class_id = row[5:].argmax() #最大概率对应的类别索引

                if class_score > 0.8:
                    cx, cy, w, h = row[0:4]
                    #从四个值构造边界框
                    left = int((cx - 0.5*w)*x_factor)
                    top = int((cy - 0.5*w)*y_factor)
                    width = int(w*x_factor)
                    height = int(h*y_factor)

                    box = np.array([left,top,width,height])

                    #将值添加到列表中
                    confidences.append(confidence)
                    boxes.append(box)
                    classes.append(class_id)

        #整理数据格式
        boxes_np = np.array(boxes).tolist()
        confidences_np = np.array(confidences).tolist()

        #执行NMS
        index = np.array(cv2.dnn.NMSBoxes(boxes_np,confidences_np,0.25,0.45)).flatten()
        #绘制边界框
        aa=0
        bb=0
        cc=0 
        my_array=[]  
        for ind in index:
            #提取边界框
            x,y,w,h = boxes_np[ind]
            bb_conf = int(confidences_np[ind]*100)
            classes_id = classes[ind]
            class_name = self.labels[classes_id]
            colors = self.generate_colors(classes_id)
            text = f'{class_name}: {bb_conf}%'

            if(class_name=='retak diagonal'):
                aa+=1
            if(class_name=='retak vertikal'):
                bb+=1
            if(class_name=='retak horizontal'):
                cc+=1

            cv2.rectangle(image,(x,y),(x+w,y+h),colors,2)
            cv2.rectangle(image,(x,y-10),(x+w,y),colors,-1)

            cv2.putText(image,text,(x,y-10),cv2.FONT_HERSHEY_PLAIN,0.7,(0,0,0),1)

        my_array=[aa,bb,cc]
        return image,my_array
    
    def generate_colors(self,ID):
        np.random.seed(10)
        colors = np.random.randint(100,255,size=(self.nc,3)).tolist()
        return tuple(colors[ID])

1_YOLO_for_image.py代码

import streamlit as st
from yolo_predictions import YOLO_Pred
from PIL import Image
import numpy as np

st.set_page_config(page_title="YOLO目标检测",
                   layout='wide',
                    page_icon='./images/object.png' )

st.title('欢迎来到裂缝检测系统(图像版)')
st.write('请上传图像以获取检测结果')

with st.spinner('模型加载中,请稍候'):
    yolo = YOLO_Pred(onnx_model='./models/bestie.onnx',
                    data_yaml='./models/configp.yaml')
    ##st.balloons()


def upload_image():
    #上传图像
    image_file = st.file_uploader(label='上传图像')
    if image_file is not None:
        size_mb = image_file.size/(1024**2)
        file_details={"文件名":image_file.name,
                    "文件类型":image_file.type,
                    "文件大小":"{:,.2f} MB".format(size_mb)}
        ##st.json(file_details)
        #验证文件类型
        if file_details['文件类型'] in ('image/png','image/jpeg'):
            st.success('有效的图像文件类型(png或jpeg)')
            return {"文件":image_file, 
                    "详情":file_details}
        else:
            st.error('无效的图像文件类型')
            st.error('仅支持上传png、jpg、jpeg格式')
            return None
        
def main():
    object = upload_image()

    if object:
        prediction = False
        image_obj = Image.open(object['文件']).convert('RGB')
        

        col1 , col2 = st.columns(2)

        with col1:
            st.info('图像预览')
            st.image(image_obj)

        with col2:
            st.subheader('查看文件详情')
            st.json(object['详情'])
            button = st.button('使用YOLO进行检测')
            if button:
                with st.spinner("""
                    正在检测图像中的目标,请稍候
                                """):
                #将图像对象转换为数组
                    image_array = np.array(image_obj)
                    pred_img= yolo.predictionss(image_array)
                    pred_img_obj = Image.fromarray(pred_img)

                    prediction = True

        if prediction:
            st.subheader("检测结果图像")
            st.caption("目标检测完成")
            st.image(pred_img_obj)
            st.write('实时目标检测结果:')
           # st.write('斜向裂缝 =' +str(my_array[0]))
          #  st.write('竖向裂缝 =' +str(my_array[1]))
          #  st.write('横向裂缝 =' +str(my_array[2])) 
            #for object_class, count in detected_objects.items():
            #    st.write(f'{object_class}: {count}')
            
        
if __name__ == "__main__":
    main()

问题解决建议

针对ModuleNotFoundError错误

  1. 确认文件结构:确保yolo_predictions.py和1_YOLO_for_image.py在同一根目录下,无嵌套子文件夹差异。
  2. 强制添加路径:在1_YOLO_for_image.py开头加入以下代码,将当前目录加入Python搜索路径:
    import sys
    from pathlib import Path
    sys.path.append(str(Path(__file__).parent))
    
  3. 检查虚拟环境:若使用虚拟环境,确认激活了正确环境,且文件目录被环境识别。
  4. VS Code工作区设置:确保VS Code打开的工作区根目录为两个文件所在文件夹,避免解释器路径错误。

针对Streamlit启动异常

  1. 修复方法名拼写错误:代码中yolo.predictionss(image_array)多了一个s,正确调用应为:
    pred_img, my_array = yolo.predictions(image_array)
    
    同时取消后续裂缝计数打印代码的注释,即可正常显示各类裂缝数量。
  2. 验证依赖完整性:执行以下命令安装/更新所有依赖库:
    pip install streamlit opencv-python numpy pyyaml pillow
    
  3. 检查模型路径:确认./models/bestie.onnx和./models/configp.yaml文件存在,路径无误。
  4. 正确启动命令:在终端进入代码所在目录,执行:
    streamlit run 1_YOLO_for_image.py
    

内容的提问来源于stack exchange,提问作者Dewi Cantika Herfieda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:21:01