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

不调用QImage::scaled()在QML渲染QImage时程序崩溃问题求助

崩溃原因排查及修复方案

核心崩溃原因

  • 绘制时硬编码的源矩形越界访问
    你在paint方法中固定了源矩形为800x550,当你不调用scaled时,原始QImage的分辨率小于800x550的情况下,drawImage会尝试访问图像实际范围外的内存地址,直接触发越界崩溃。
  • OpenCV转QImage的浅拷贝导致野指针
    常规的Mat转QImage实现会直接复用cv::Mat的底层数据缓冲区,不会做深拷贝:
    1. 你构造cv::Mat时直接引用了外部缓冲区m_pBufForSaveImage
    2. 当你调用scaled时,返回的是全新的深拷贝QImage,不再依赖原缓冲区
    3. 不调用scaled时,QImage仍然绑定原cv::Mat的缓冲区,一旦采集线程更新/释放了m_pBufForSaveImage,渲染线程读取QImage时就会访问野指针崩溃
  • 线程安全问题
    摄像头采集逻辑通常运行在子线程,你直接在子线程调用单例的setM_Image修改UI相关属性,没有做跨线程同步,也可能触发内存访问冲突。

修复方案

1. 修正绘制逻辑的源矩形

修改paint方法,动态获取当前QImage的尺寸作为源矩形范围,不要硬编码固定尺寸:

void MyImage::paint(QPainter *painter)
{
   QRectF target(0.0, 0.0, 800.0, 550.0);
   // 动态获取图像实际尺寸作为源区域
   QRectF source(0.0, 0.0, m_Image.width(), m_Image.height());
   painter->setRenderHint(QPainter::Antialiasing, true);
   painter->drawImage(target, this->m_Image, source);
}

2. 转换QImage时强制深拷贝

Mat转QImage后调用copy()方法,让QImage持有独立的数据缓冲区,不依赖原始采集缓冲区:

QImage Qimag = MatImageToQt(image).copy(); // 强制深拷贝
// 不需要scaled时直接传入即可
// Qimag = Qimag.scaled(image.cols*0.33,image.rows*0.27,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
MyImage *myimg = MyImage::instance();
myimg->setM_Image(Qimag);

3. 优化跨线程数据传递

不要在子线程直接调用UI对象的方法,改用信号槽传递QImage,Qt会自动处理隐式共享的线程安全。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:45:03