Forever忠
技术员
技术员
  • 最后登录2020-09-19
  • 发帖数29
  • 金币191枚
  • 贡献勋章0枚
阅读:66回复:3

分享相机buffer、HObject、QImage的转换问题

楼主#
更多 发布于:2020-09-16 15:45
      最近项目在开发取图和显示模块,因为我用的QT+Halcon,所以需要将相机Buffer转换成Hobject处理,然后Hobject需要转换成QImage,QImage转换成QPixmap进行显示
      图像内存转换的资料网上很多,但是我发现大多数人都忽略了一个图像对齐的问题,对齐其实就是图像宽度是4的整数倍

1、相机Buffer出来的内存一般是不考虑对齐的,我用过的AVI Basler 海康 大华都是这样
2、HObject也是不要考虑对齐的,所有相机buffer转hobject就很简单,黑白图像为例:
HalconCpp::GenImage1(&testHobject, "byte", width, height,(Hlong)((uint8_t*)buffer))


3、QImage则需要考虑对齐,所以HObject转QImage需要考虑两种情况,这里黑白图像我考虑了不对齐情况,彩色的我暂时没写不对其情况,你可以参考写:
QImage GrubImage::Hobject2QImage(const HalconCpp::HObject& hoImage) {
    QImage             image;
    HalconCpp::HObject hobject;
    HalconCpp::HTuple  nchannels, type;
    HalconCpp::HTuple  ptrR, ptrG, ptrB;
    HalconCpp::HTuple  width, height;
  
    HalconCpp::ConvertImageType(hoImage, &hobject, "byte");
    HalconCpp::CountChannels(hobject, &nchannels);
    if (3 == nchannels) {
        uchar *dataR, *dataG, *dataB;
        HalconCpp::GetImagePointer3(hobject, &ptrR, &ptrG, &ptrB, &type, &width, &height);
        dataR = (unsigned char*)(ptrR[0].L());
        dataG = (unsigned char*)(ptrG[0].L());
        dataB = (unsigned char*)(ptrB[0].L());
  
        int    bytesperline = (width * 8 * 3 + 31) / 32 * 4;
        int    bytecount    = bytesperline * height;
        uchar* data8        = new uchar[bytecount];
        int    lineheadid, pixid;
        for (int i = 0; i < height; i++) {
            lineheadid = bytesperline * i;
            for (int j = 0; j < width; j++) {
                pixid            = lineheadid + j * 3;
                data8[pixid]     = dataR[width * i + j];
                data8[pixid + 1] = dataG[width * i + j];
                data8[pixid + 2] = dataB[width * i + j];
            }
        }
        image = QImage(data8, width, height, QImage::Format_RGB888);
    } else if (1 == nchannels) {
        uchar* data;
        HalconCpp::GetImagePointer1(hobject, &ptrR, &type, &width, &height);
  
        int pad       = ((width * nchannels) % 4 == 0) ? 0 : 4 - ((width * nchannels) % 4);
        int widthStep = width * nchannels + pad;
        if (width != widthStep) {
            data = new uchar[height.I() * widthStep];
            for (int y = 0; y < height; ++y) {
                memcpy(data + widthStep * y, (unsigned char*)(ptrR[0].L()) + width.I() * y, width.I());
            }
            QImage imageTemp = QImage(data, width, height, widthStep, QImage::Format_Indexed8);
            image            = imageTemp.copy();
            delete[] data;
        } else {
            data  = (unsigned char*)(ptrR[0].L());
            image = QImage(data, width, height, QImage::Format_Indexed8);
        }
    }
  
    return image;
}


喜欢0

最新打赏:0人

Forever忠
技术员
技术员
  • 最后登录2020-09-19
  • 发帖数29
  • 金币191枚
  • 贡献勋章0枚
沙发#
发布于:2020-09-16 15:50
这里分享一下问题总结:
1、当你看到你的图像显示错位,首先考虑是不是内存拷贝错位,然后考虑是否图像对齐问题
2、当你看到你的图像花屏、黑屏、有一半图像,跟踪一下你的显示图像的变量生命周期,看是否从采用了浅拷贝策略,导致在图像显示刷新过程中,原始图像地址数据更改
3、显示图像死机,看你的指针是否变成野指针,看你是否有内存泄漏,valgrand工具查看
ydl890406
技术员
技术员
  • 最后登录2020-09-18
  • 发帖数48
  • 金币197枚
  • 贡献勋章0枚
  • 社区居民
板凳#
发布于:2020-09-16 23:14
目前还没遇到过这种错位情况,感谢分享经验,先记下
gt785976799
技术员
技术员
  • 最后登录2020-09-19
  • 发帖数315
  • 金币934枚
  • 贡献勋章0枚
  • 社区居民
  • 忠实会员
地板#
发布于:2020-09-17 13:19
目前还没遇到过这种错位情况,感谢分享经验,先记下
游客

返回顶部
支付

欢迎打赏,请选择打赏金额

  • 1元
  • 6元
  • 10元
  • 66元
  • 100元

支付即代表同意《本站支付协议》 有疑问请联系客服