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

Qt中基于QCamera的摄像头流红圈绘制问题求助

嘿,作为Qt新手能搞定摄像头流已经超棒了!我给你梳理几个关键步骤,帮你实现圆圈标记的效果,一步步来:

1. 先捕获摄像头的每一帧图像

你之前用QCamera+QCameraViewfinder只是显示流,但要做识别和标记,得先拿到每一帧的图像数据。Qt的QVideoProbe是干这个的绝佳工具:

  • 先创建一个QVideoProbe实例,绑定到你的摄像头对象上,监听帧数据:

    QVideoProbe *frameProbe = new QVideoProbe(this);
    if (frameProbe->setSource(yourCameraInstance)) {
        // 绑定帧捕获的槽函数
        connect(frameProbe, &QVideoProbe::videoFrameProbed, this, &YourMainWindow::onNewVideoFrame);
    }
    
  • 在槽函数里,把QVideoFrame转换成QImage(方便后续处理和绘制):

    void YourMainWindow::onNewVideoFrame(const QVideoFrame &frame) {
        QVideoFrame readableFrame = frame;
        // 先映射帧到内存,才能读取数据
        if (!readableFrame.map(QAbstractVideoBuffer::ReadOnly)) {
            return;
        }
        // 转换成QImage,注意格式匹配
        QImage frameImage(readableFrame.bits(), 
                         readableFrame.width(), 
                         readableFrame.height(),
                         QVideoFrame::imageFormatFromPixelFormat(readableFrame.pixelFormat()));
        readableFrame.unmap();
    
        // 拿到图像后,就可以去识别圆圈并标记了
        markDetectedCircles(frameImage);
    }
    

2. 识别图像中的圆圈(用OpenCV最省心)

Qt本身没有内置的圆圈识别算法,最成熟的方案是配合OpenCV的霍夫圆变换,新手友好且效果稳定:

  • 先把QImage转换成OpenCV的cv::Mat,做预处理(降噪、转灰度),然后调用霍夫圆检测:
    #include <opencv2/opencv.hpp>
    
    void YourMainWindow::markDetectedCircles(QImage &inputImage) {
        // QImage转OpenCV Mat(注意QImage是RGB,OpenCV默认是BGR)
        cv::Mat cvImage(cv::Size(inputImage.width(), inputImage.height()), 
                       CV_8UC3, 
                       inputImage.bits(), 
                       inputImage.bytesPerLine());
        cv::cvtColor(cvImage, cvImage, cv::COLOR_RGB2BGR);
    
        // 预处理:转灰度+高斯模糊,减少噪声干扰
        cv::Mat grayImage;
        cv::cvtColor(cvImage, grayImage, cv::COLOR_BGR2GRAY);
        cv::GaussianBlur(grayImage, grayImage, cv::Size(9, 9), 2, 2);
    
        // 霍夫圆检测,参数可以根据你的场景调整
        std::vector<cv::Vec3f> detectedCircles;
        cv::HoughCircles(grayImage, detectedCircles, cv::HOUGH_GRADIENT,
                        1,                  // 累加器分辨率
                        grayImage.rows / 8, // 圆心之间的最小距离
                        200,                // Canny边缘检测的高阈值
                        100,                // 累加器阈值(越小识别越多)
                        0, 0);              // 最小/最大半径
    
        // 给识别到的圆圈画红色标记
        for (size_t i = 0; i < detectedCircles.size(); ++i) {
            cv::Point circleCenter(cvRound(detectedCircles[i][0]), cvRound(detectedCircles[i][1]));
            int circleRadius = cvRound(detectedCircles[i][2]);
            // 画红色圆心(实心)
            cv::circle(cvImage, circleCenter, 3, cv::Scalar(0, 0, 255), -1);
            // 画红色圆轮廓(粗线)
            cv::circle(cvImage, circleCenter, circleRadius, cv::Scalar(0, 0, 255), 3);
        }
    
        // 把标记后的Mat转回QImage
        cv::cvtColor(cvImage, cvImage, cv::COLOR_BGR2RGB);
        QImage markedImage(cvImage.data, cvImage.cols, cvImage.rows, cvImage.step, QImage::Format_RGB888);
        // 拷贝一份避免内存指针失效
        inputImage = markedImage.copy();
    
        // 最后把标记后的图像显示出来
        updateDisplay(inputImage);
    }
    

3. 显示带标记的图像

你之前用QCameraViewfinder显示原始流,现在换成QLabel或者自定义QWidget来显示处理后的图像就好:

void YourMainWindow::updateDisplay(const QImage &image) {
    // 把图像缩放到标签尺寸,保持比例
    ui->displayLabel->setPixmap(QPixmap::fromImage(image.scaled(ui->displayLabel->size(), Qt::KeepAspectRatio)));
}

4. 一些新手注意点

  • 如果用OpenCV,记得在Qt项目的.pro文件里配置链接:
    INCLUDEPATH += /你的OpenCV路径/include
    LIBS += -L/你的OpenCV路径/lib -lopencv_core -lopencv_imgproc -lopencv_highgui
    
  • 帧处理可能会卡顿,要是识别速度跟不上帧率,把识别+绘制的逻辑放到子线程里,别阻塞UI线程。
  • QVideoFrame的格式可能有差异,如果转换QImage失败,可以试试强制用QImage::Format_ARGB32格式手动转换。

内容的提问来源于stack exchange,提问作者Nghia Bui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:13:53