[视觉实战案例]Qt下BYTE、QImage、HObject、Mat等图像格式的转换和图像显示方法

一、图像格式间相互转换

1.BYTE转QImage、HObject和Mat

Balser下相机图像数据转换成QImage、Mat、HObject

    QImage Qimg;
    Mat cvImg;
    HObject hvImg;
    //格式转换
    m_formatConverter.Convert(pylonImage, ptrGrabResult);
    uchar * din = (uchar *)(pylonImage.GetBuffer()); //数据指针
    //单通道Momo
    if(IsMono(pylonImage.GetPixelType()))
    {
        qDebug()<<"黑白图像";
        Qimg = QImage(din, ptrGrabResult->GetWidth(), ptrGrabResult->GetHeight(), QImage::Format_Indexed8);
        cvImg = Mat(ptrGrabResult->GetHeight(),ptrGrabResult->GetWidth(),CV_8UC1,din).clone();
        GenImage1Extern(&hvImg,"byte",(HTuple)ptrGrabResult->GetWidth(),(HTuple)ptrGrabResult->GetHeight(),(long)din,NULL); //Mono
    }
    else
    {
        //此处可以根据相机的格式获取特定格式的彩色图像
        if(IsRGB(pylonImage.GetPixelType()))
        {
            Qimg = QImage(din, ptrGrabResult->GetWidth(), ptrGrabResult->GetHeight(), QImage::Format_RGB888);
            cvImg = Mat(ptrGrabResult->GetHeight(),ptrGrabResult->GetWidth(),CV_8UC3,din).clone();
            GenImageInterleaved (&hvImg,(long)din, "rgb", (HTuple)ptrGrabResult->GetWidth(),(HTuple)ptrGrabResult->GetHeight(), 0, "byte", 0, 0, 0, 0, 8, 0);
        }
    }

2.QImage、HObject和Mat的相互转换

QImage转HObject
HObject Widget::QImage2HObject(QImage qimage)
{
    HObject hv_image;
    int width = qimage.width();
    int height = qimage.height();
    QImage::Format format = qimage.format();
    if(format == QImage::Format_RGB32 ||
            format == QImage::Format_ARGB32 ||
            format == QImage::Format_ARGB32_Premultiplied)
    {
        GenImageInterleaved(&hv_image,(Hlong)qimage.bits(),"bgrx",qimage.width(),qimage.height(),0,"byte",width, height, 0, 0, 8, 0);
    }
    else if(format == QImage::Format_RGB888)
    {
        GenImageInterleaved(&hv_image,(Hlong)qimage.bits(),"bgr",qimage.width(),qimage.height(),0,"byte",width, height, 0, 0, 8, 0);
    }
    else if(format == QImage::Format_Grayscale8 || format == QImage::Format_Indexed8)
    {
        GenImage1(&hv_image,"byte", width, height, (Hlong)qimage.bits());
    }
    return hv_image;
}
HObject转QImage
void HObjectToQImage(HObject hv_image, QImage &qimage)
{
    HTuple hChannels,htype,hpointer;
    HTuple width=0;
    HTuple height=0;
    ConvertImageType(hv_image,&hv_image,"byte");//将图片转化成byte类型
    CountChannels(hv_image,&hChannels);       //判断图像通道数

    if(hChannels[0].I()==1)//单通道图
    {
        unsigned char *ptr;
        GetImagePointer1(hv_image,&hpointer,&htype,&width,&height);
        ptr=(unsigned char *)hpointer[0].L();
        qimage= QImage(ptr,width,height,QImage::Format_Indexed8);
    }
    else if(hChannels[0].I()==3)//三通道图
    {
        unsigned char *ptr3;
        HObject ho_ImageInterleaved;

        rgb3_to_interleaved(hv_image, &ho_ImageInterleaved);
        GetImagePointer1(ho_ImageInterleaved, &hpointer, &htype, &width, &height);

        ptr3=(unsigned char *)hpointer[0].L();
        qimage= QImage(ptr3,width/3,height,width,QImage::Format_RGB888);
    }
}
void rgb3_to_interleaved (HObject ho_ImageRGB, HObject *ho_ImageInterleaved)
{
    // Local iconic variables
    HObject  ho_ImageAffineTrans, ho_ImageRed, ho_ImageGreen;
    HObject  ho_ImageBlue, ho_RegionGrid, ho_RegionMoved, ho_RegionClipped;

    // Local control variables
    HTuple  hv_PointerRed, hv_PointerGreen, hv_PointerBlue;
    HTuple  hv_Type, hv_Width, hv_Height, hv_HomMat2DIdentity;
    HTuple  hv_HomMat2DScale;

    GetImagePointer3(ho_ImageRGB, &hv_PointerRed, &hv_PointerGreen, &hv_PointerBlue,
                     &hv_Type, &hv_Width, &hv_Height);
    GenImageConst(&(*ho_ImageInterleaved), "byte", hv_Width*3, hv_Height);
    //
    HomMat2dIdentity(&hv_HomMat2DIdentity);
    HomMat2dScale(hv_HomMat2DIdentity, 1, 3, 0, 0, &hv_HomMat2DScale);
    AffineTransImageSize(ho_ImageRGB, &ho_ImageAffineTrans, hv_HomMat2DScale, "constant",
                         hv_Width*3, hv_Height);
    //
    Decompose3(ho_ImageAffineTrans, &ho_ImageRed, &ho_ImageGreen, &ho_ImageBlue);
    GenGridRegion(&ho_RegionGrid, 2*hv_Height, 3, "lines", hv_Width*3, hv_Height+1);
    MoveRegion(ho_RegionGrid, &ho_RegionMoved, -1, 0);
    ClipRegion(ho_RegionMoved, &ho_RegionClipped, 0, 0, hv_Height-1, (3*hv_Width)-1);

    ReduceDomain(ho_ImageRed, ho_RegionClipped, &ho_ImageRed);
    MoveRegion(ho_RegionGrid, &ho_RegionMoved, -1, 1);
    ClipRegion(ho_RegionMoved, &ho_RegionClipped, 0, 0, hv_Height-1, (3*hv_Width)-1);
    ReduceDomain(ho_ImageGreen, ho_RegionClipped, &ho_ImageGreen);
    MoveRegion(ho_RegionGrid, &ho_RegionMoved, -1, 2);
    ClipRegion(ho_RegionMoved, &ho_RegionClipped, 0, 0, hv_Height-1, (3*hv_Width)-1);
    ReduceDomain(ho_ImageBlue, ho_RegionClipped, &ho_ImageBlue);
    OverpaintGray((*ho_ImageInterleaved), ho_ImageRed);
    OverpaintGray((*ho_ImageInterleaved), ho_ImageGreen);
    OverpaintGray((*ho_ImageInterleaved), ho_ImageBlue);
    return;
}
HObject和Mat互转
using namespace cv;
using namespace Halcon;

//HObject转Mat
Mat HObject2Mat(HObject Hobj)
{
    HTuple htCh = HTuple();
    HString cType;
    cv::Mat Image;
    ConvertImageType(Hobj,&Hobj,"byte");
    CountChannels(Hobj,&htch);
    Hlong wid = 0;
    Hlong hgt = 0;
    if(htch[0].I() == 1)
    {
        HImage hImg(Hobj);
        void *ptr = hImg.GetImagePointer1(&cType,&wid,&hgt);
        int W = wid;
        int H = hgt;
        Image.create(H,W,CV_8UC1);
        unsigned char *pdata = static_case(ptr);
        memcpy(Image.data,pdata,W*H);
     }
     else if (htch[0].I()  == 3)
     {
        void *Rptr;
        void *Gptr;
        void *Bptr;
        HImage hImg(Hobj);
        hImg.GetImagePointer3(&Rptr,&Gptr,&Bptr,&cType,&wid,&hgt);
        int W = wid;
        int H = hgt;
        Image.create(H,W,CV_8UC3);
        vector VecM(3);
        VecM[0].create(H,W,CV_8UC1);
        VecM[1].create(H,W,CV_8UC1);
        VecM[2].create(H,W,CV_8UC1);
        unsigned char *R = (unsigned char *)Rptr;
        unsigned char *G = (unsigned char *)Gptr;
        unsigned char *B = (unsigned char *)Bptr;
        memcpy(VecM[2].data,R,W*H);
        memcpy(VecM[1].data,G,W*H);
        memcpy(VecM[0].data,B,W*H);
        cv::merge(VecM,Image);
     }
     return Image;
}
//Mat转Hobject
Hobject Mat2Hobject(Mat& image)
{
    Hobject Hobj = Hobject();
    int hgt = image.rows;
    int wid = image.cols;
    int i;
    if (image.type() == CV_8UC3)
    {
        vector imgchannel;
        split(image, imgchannel);
        Mat imgB = imgchannel[0];
        Mat imgG = imgchannel[1];
        Mat imgR = imgchannel[2];
        uchar* dataR = new uchar[hgt*wid];
        uchar* dataG = new uchar[hgt*wid];
        uchar* dataB = new uchar[hgt*wid];
        for (i = 0; i < hgt; i++)
        {
            memcpy(dataR + wid*i, imgR.data + imgR.step*i, wid);
            memcpy(dataG + wid*i, imgG.data + imgG.step*i, wid);
            memcpy(dataB + wid*i, imgB.data + imgB.step*i, wid);
        }
        gen_image3(&Hobj, "byte", wid, hgt, (Hlong)dataR, (Hlong)dataG, (Hlong)dataB);
        delete[]dataR;
        delete[]dataG;
        delete[]dataB;
        dataR = NULL;
        dataG = NULL;
        dataB = NULL;
    }
    else if (image.type() == CV_8UC1)
    {
        uchar* data = new uchar[hgt*wid];
        for (i = 0; i < hgt; i++)
            memcpy(data + wid*i, image.data + image.step*i, wid);
        gen_image1(&Hobj, "byte", wid, hgt, (Hlong)data);
        delete[] data;
        data = NULL;
    }
    return Hobj;
}
Mat转QImage
QImage cvMat2QImage(const cv::Mat &mat)
{
    switch ( mat.type() )
    {
    // 8-bit  4 channel
    case CV_8UC4:
    {
        QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast(mat.step), QImage::Format_RGB32 );
        return image;
    }

    // 8-bit  3 channel
    case CV_8UC3:
    {
        QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast(mat.step), QImage::Format_RGB888 );
        return image.rgbSwapped();
    }

    // 8-bit  1 channel
    case CV_8UC1:
    {
        static QVector  sColorTable;
        // only create our color table once
        if ( sColorTable.isEmpty() )
        {
            sColorTable.resize( 256 );
            for ( int i = 0; i < 256; ++i )
            {
                sColorTable[i] = qRgb( i, i, i );
            }
        }
        QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast(mat.step), QImage::Format_Indexed8 );
        image.setColorTable( sColorTable );
        return image;
    }
    default:
        qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels());
        qWarning() << "cvMatToQImage - cv::Mat image type not handled in switch:" << mat.type();
        break;
    }
    return QImage();
}
QImage转Mat
Mat QImage2Mat(QImage image)
{
    Mat cvMat;
    qDebug()<

二、图像显示方法

目前图像显示使用三种方法,第一种是QImage显示在Qlabel上,第二种方法是使用QGraphicsView来显示QImage,第三种方法是将Halcon的窗口贴在QLabel上,在Halcon的窗口上显示图像。

1.QLabel显示QPixmap图像

    qDebug()<<"显示图像";
    QPixmap m_pix = QPixmap::fromImage(img);
    m_pix = m_pix.scaled(ui->lbl_PicShow->size(), Qt::KeepAspectRatio);
    ui->lbl_PicShow->setPixmap(m_pix);

2.QGraphicsView显示QPixmap

首先用QGraphics View控件,创建QGraphicsScene背景和QGraphicsPixmapItem组件

    m_scene = new QGraphicsScene();
    ImageItem = new QGraphicsPixmapItem();
    ImageItem->setFlag(QGraphicsItem::ItemIsMovable,false);
    m_scene->addItem(ImageItem);
    ui->PicShow->setScene(m_scene);

    QPixmap m_pix = QPixmap::fromImage(Qimg);
    m_pix = m_pix.scaled(ui->PicShow->size(), Qt::KeepAspectRatio);
    ImageItem->setPixmap(m_pix);

3.Halcon窗口显示HObject图像

首先要在控件上创建Halcon窗口句柄

    OpenWindow(0,0,ui->PicShow->width(),ui->PicShow->height(),m_hLabelID,"visible","",&m_hHalconID);
    GetImageSize(CurTestImg,&hv_Width,&hv_Height);
    SetPart(m_hHalconID, 0, 0, hv_Height-1, hv_Width-1);
    dispOnWindow(CurTestImg,m_hHalconID);

总结

目前图像格式主要是QImage,主要用于Qt的显示和图像操作,HObject是Halcon的格式,图像处理要使用Halcon算法库的,要将图像转成HObject后进行图像处理运算,Mat是OpenCV的图像格式,调用OpenCV的图像算法库,要转换成对应的Mat格式。显示方法上第二种具有图层的概念,可以针对需要对显示的图像和文字进行拖动隐藏等操作。

你可能感兴趣的:(qthalconopencv)