METOCO 2024-06-21 00:09 采纳率: 0%
浏览 28
已结题

cv::resize不同线程时间不同

CameraThread::CameraThread(int id, QSemaphore* semaphore, QMutex* resultMutex, bool* hasDefect, CameraWidget* camerawidget, std::atomic<bool>& state_run, std::atomic<bool>& state_collect, QObject* parent) : QThread(parent), id_(id), semaphore_(semaphore), resultMutex_(resultMutex), hasDefect_(hasDefect), camerawidget_(camerawidget), state_run_(state_run), state_collect_(state_collect){} 
void CameraThread::run() { 
  pen.setColor(QColor(0, 0, 0)); 
  font.setPixelSize(32); 
  DCSP_CORE *yoloDetector = new DCSP_CORE; // 设置图像的保存路径 
  loadModelParams(); // 加载模型参数 
  DCSP_INIT_PARAM params{model_path, YOLO_ORIGIN_V8, {640, 640}, currentModelParam.ConfidenceThreshold, currentModelParam.iouThreshold, true}; 
  yoloDetector->CreateSession(params); 
  while (state_run_) { 
      cv::Mat image = camerawidget_->convertImage(); 
      QTime afterconvertImageTime = QTime::currentTime(); 
      qDebug() << "camera id : "<<QString(id_)<<"after convertImage : " << afterconvertImageTime; // 模型检测 
      bool hasdefect = detectDefect(image, yoloDetector,currentModelParam.minArea, detectionArea); 
      QTime afterdetectDefect = QTime::currentTime(); qDebug() << "after detectDefect : " << afterdetectDefect;
 }
CameraThread::detectDefect(cv::Mat& img, DCSP_CORE *&p, float minArea, const cv::Rect& detectionArea) 
{ 
  std::vector<DCSP_RESULT> res; // 使用传入的 DCSP_CORE 对象的 RunSession 方法对图像进行检测,并将结果存储在 res 中 
  p->RunSession(img, res); 
  ..
}
char *DCSP_CORE::RunSession(cv::Mat &iImg, std::vector<DCSP_RESULT> &oResult) 
{
  #ifdef benchmark clock_t starttime_1 = clock(); 
  #endif // benchmark char *Ret = RET_OK; 
  cv::Mat processedImg; PostProcess(iImg, imgSize, processedImg); 
  float *blob = new float [processedImg.total() * 3]; 
  BlobFromImage(processedImg, blob); 
  std::vector<int64_t> inputNodeDims = {1, 3, imgSize.at(0), imgSize.at(1)}; 
  TensorProcess(starttime_1, iImg, blob, inputNodeDims, oResult); 
  ..
}
char *PostProcess(cv::Mat &iImg, std::vector<int> iImgSize, cv::Mat &oImg) 
{ 
  clock_t time_1= clock(); 
  qDebug()<<"time_1: "<<time_1; 
  cv::Size imageSize = iImg.size(); qDebug() << "Image size (width x height):" << imageSize.width << "x" << imageSize.height; 
  clock_t time_2= clock(); 
  qDebug()<<"time_2: "<<time_2; 
  cv::resize(iImg, oImg, cv::Size(iImgSize.at(0), iImgSize.at(1))); 
  clock_t time_3= clock(); 
  qDebug()<<"time_3: "<<time_3; 
  return RET_OK; 
}

我有三个相同上述的线程(图像、启动时间等都基本一样),但最后的打印信息如下:

camera id : "\u0001" after convertImage : QTime("22:01:50.869")
camera id : "\u0000" after convertImage : QTime("22:01:50.869")
camera id : "\u0002" after convertImage : QTime("22:01:50.869") 
time_1 : 47744 
time_1 : 47744 
time_1 : 47744
Image size (width x height): 1280 x 1024 
Image size (width x height): 1280 x 1024 
Image size (width x height): 1280 x 1024 
time_2 : 47744 
time_2 : 47744 
time_2 : 47744 
time_3 : 47772  
[DCSP_ONNX(CUDA)]: 37.00ms pre-process, 23.00ms inference, 10.00ms post-process. 
after detectDefect : QTime("22:01:50.942") 
time_3 : 47858  
time_3 : 47859 
[DCSP_ONNX(CUDA)]: 131.00ms pre-process, 47.00ms inference, 15.00ms post-process. 
after detectDefect : QTime("22:01:51.063")
[DCSP_ONNX(CUDA)]: 132.00ms pre-process, 50.00ms inference, 14.00ms post-process. 
after detectDefect : QTime("22:01:51.066")

描述:我设置了三个上述相同的线程,获取的图像基本相同,线程启动时间、输入参数也完全相同。但pre-process时间却差别很大。经过调试,是函数char *PostProcess()时间出现了差别,可以看到上述打印信息,time_1 和time_2的时间差别不大,但是time_3(也就是在cv::resize之后),出现了差别,第一个time_3 要比后面两个time_3 快 100多ms,但是后面两个time_3 却相差差不多。 (目的:想缩短 pre-process的时间,使三个线程的时间基本和第一个 37ms一样了)

  • 写回答

16条回答 默认 最新

  • 专家-皆知 2024-06-21 00:10
    关注

    参考免费微信小程序:皆我百晓生 作答,经由专家-皆知整理回复,如问题解决,望采纳;如仍有疑问,请评论回复。

    从你提供的代码和描述来看,问题可能出现在 cv::resize 函数的执行时间上。cv::resize 是一个相对耗时的操作,尤其是在处理大尺寸图像时。不同线程间 cv::resize 的执行时间差异可能是由于多线程环境下的资源争用、CPU调度或其他线程间的竞争条件导致的。

    以下是一些可能的解决方案:

    1. 优化图像尺寸:如果可能,尝试减少图像的原始尺寸或调整目标尺寸,以减少 cv::resize 的计算负担。

    2. 使用多线程:如果 cv::resize 是瓶颈,可以考虑使用 OpenCV 的并行版本,例如 cv::parallel_resize(如果可用),这可以利用多核CPU的优势。

    3. 调整线程优先级:在某些情况下,调整线程的优先级可以改善线程的调度和执行。

    4. 资源分配:确保每个线程都有充足的资源进行操作,例如,通过限制每个线程的CPU亲和性,确保它们不会相互干扰。

    5. 分析和优化:使用性能分析工具来确定 PostProcess 函数中的其他可能的瓶颈。

    6. 图像缓存:如果图像尺寸较大,考虑在内存中缓存处理后的图像,避免重复处理相同的图像。

    7. 同步机制:如果线程间的同步是导致延迟的原因,考虑优化或调整同步机制。

    8. 硬件加速:如果可用,使用GPU加速图像处理操作。

    下面是一个使用 cv::parallel_for_ 进行多线程处理的示例代码:

    void PostProcess(cv::Mat &iImg, std::vector<int> iImgSize, cv::Mat &oImg)
    {
        clock_t time_1= clock();
        qDebug()<<"time_1: "<<time_1;
        cv::Size imageSize = iImg.size();
        qDebug() << "Image size (width x height):" << imageSize.width << "x" << imageSize.height;
        clock_t time_2= clock();
        qDebug()<<"time_2: "<<time_2;
    
        // 分割图像为小块,以便并行处理
        const int block_width = 128; // 可以根据实际情况调整块大小
        cv::parallel_for_(cv::Range(0, iImg.rows), [&](const cv::Range &rowRange) {
            for (int y = rowRange.start; y < rowRange.end; y += block_width) {
                for (int x = 0; x < iImg.cols; x += block_width) {
                    // 计算块的边界
                    int endX = std::min(x + block_width, iImg.cols);
                    int endY = std::min(y + block_width, iImg.rows);
                    cv::Mat block = iImg(cv::Rect(x, y, endX - x, endY - y));
                    cv::Mat resizedBlock;
                    // 调整块的大小
                    cv::resize(block, resizedBlock, cv::Size(iImgSize.at(0), iImgSize.at(1)));
                    // 将处理后的块放回原图像中
                    oImg(cv::Rect(x, y, endX - x, endY - y)) = resizedBlock;
                }
            }
        });
    
        clock_t time_3= clock();
        qDebug()<<"time_3: "<<time_3;
    }
    

    请注意,这个代码只是一个示例,实际使用时需要根据你的具体情况进行调整。希望这些建议能帮助你解决问题。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月23日
  • 创建了问题 6月21日

悬赏问题

  • ¥15 skynet MySQL ProtocolBuffers
  • ¥15 Boost库编译出错。
  • ¥15 使用docker安装chemex后无法启动
  • ¥15 关于#vue.js#的问题:word excel和ppt预览问题语言-javascript)
  • ¥15 Apache显示系统错误3该如何解决?
  • ¥30 uniapp小程序苹果手机加载gif图片不显示动效?
  • ¥20 js怎么实现跨域问题
  • ¥15 C++dll二次开发,C#调用
  • ¥15 请教,如何使用C#加载本地摄像头进行逐帧推流
  • ¥15 Python easyocr无法顺利执行,如何解决?