QImage/cv::Mat/HObject的图像格式互相转换

710 阅读1分钟

QImage/cv::Mat互相转换

QImage ImgChange::cvMat2QImage(const Mat &mat) // Mat 改成 QImage
{
    if (mat.type() == CV_8UC1) // 单通道
    {
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        image.setColorCount(256); // 灰度级数256
        for (int i = 0; i < 256; i++)
        {
            image.setColor(i, qRgb(i, i, i));
        }
        uchar *pSrc = mat.data; // 复制mat数据
        for (int row = 0; row < mat.rows; row++)
        {
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc, mat.cols);
            pSrc += mat.step;
        }
        return image;
    }

    else if (mat.type() == CV_8UC3) // 3通道
    {
        const uchar *pSrc = (const uchar *)mat.data;                             // 复制像素
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888); // R, G, B 对应 0,1,2
        return image.rgbSwapped();                                               // rgbSwapped是为了显示效果色彩好一些。
    }
    else if (mat.type() == CV_8UC4)
    {
        const uchar *pSrc = (const uchar *)mat.data;                             // 复制像素
                                                                                 // Create QImage with same dimensions as input Mat
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32); // B,G,R,A 对应 0,1,2,3
        return image.copy();
    }
    else
    {
        return QImage();
    }
}

Mat ImgChange::QImage2cvMat(const QImage &image) // QImage改成Mat
{
    Mat mat;
    switch (image.format())
    {
    case QImage::Format_ARGB32:
    case QImage::Format_RGB32:
    case QImage::Format_ARGB32_Premultiplied:
        mat = Mat(image.height(), image.width(), CV_8UC4, (void *)image.constBits(), image.bytesPerLine());
        break;
    case QImage::Format_RGB888:
        mat = Mat(image.height(), image.width(), CV_8UC3, (void *)image.constBits(), image.bytesPerLine());
        cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);
        break;
    case QImage::Format_Indexed8:
        mat = Mat(image.height(), image.width(), CV_8UC1, (void *)image.constBits(), image.bytesPerLine());
        break;
    }
    return mat;
}

 

cv::Mat与HObject的互相转换

HalconCpp::HObject CImagePreprocessing::Mat2HObject(const cv::Mat &image) //OpenCV的cv::Mat和Halcon的HObject类型互相转换
{
    HalconCpp::HObject Hobj = HalconCpp::HObject();
    int height = image.rows;
    int width = image.cols;
    if (height <= 0 || width <= 0)
    {
        return Hobj;
    }

    if (height > m_iH || width > m_iW) //如果新图像大于原图像,就得重新分配内存
    {
        _destroyTempBuf();
        _createTempBuf(height, width);
        m_iH = height;
        m_iW = width;
    }

    if (image.type() == CV_8UC3)
    {
        vector<cv::Mat> imgchannel;
        cv::split(image, imgchannel);
        cv::Mat imgB = imgchannel[0];
        cv::Mat imgG = imgchannel[1];
        cv::Mat imgR = imgchannel[2];

        for (int i = 0; i < height; i++)
        {
            memcpy(m_pDataR + width * i, imgR.data + imgR.step * i, width);
            memcpy(m_pDataG + width * i, imgG.data + imgG.step * i, width);
            memcpy(m_pDataB + width * i, imgB.data + imgB.step * i, width);
        }

        GenImage3(&Hobj, "byte", width, height, (Hlong)m_pDataR, (Hlong)m_pDataG, (Hlong)m_pDataB);
    }
    else if (image.type() == CV_8UC1)
    {
        for (int i = 0; i < height; i++)
        {
            memcpy(m_pData8 + width * i, image.data + image.step * i, width);
        }

        GenImage1(&Hobj, "byte", width, height, (Hlong)m_pData8);
    }

    return Hobj;
}

cv::Mat CImagePreprocessing::HObject2Mat(const HalconCpp::HObject &Hobj) //Halcon中的HObject类型转OpenCV中的cv::Mat类型
{
    HalconCpp::HTuple htCh = HalconCpp::HTuple();
    HalconCpp::HTuple hv_Length;
    HalconCpp::HTuple cType;
    cv::Mat Image;
    HalconCpp::HObject ho_img;
    ConvertImageType(Hobj, &ho_img, "byte");
    CountChannels(ho_img, &htCh);
    TupleLength(htCh, &hv_Length);
    if (hv_Length.L() == 0)
    {
        return Image;
    }

    HalconCpp::HTuple width;
    HalconCpp::HTuple height;
    int W = 0, H = 0;

    if (htCh[0].I() == 1)
    {
        HalconCpp::HTuple ptr;
        GetImagePointer1(ho_img, &ptr, &cType, &width, &height);
        W = (int)width;
        H = (int)height;
        BYTE *p = (BYTE *)ptr[0].L();      //必须是L(),不能是I()
        Image = cv::Mat(H, W, CV_8UC1, p); //单通道
                                           //或者
                                           //Image.create(H, W, CV_8UC1);
                                           //memcpy(Image.data, p, W * H * sizeof(BYTE));
    }
    else if (htCh[0].I() == 3)
    {
        HalconCpp::HTuple ptrR, ptrG, ptrB;
        GetImagePointer3(ho_img, &ptrR, &ptrG, &ptrB, &cType, &width, &height);
        W = (int)width;
        H = (int)height;
        Image.create(H, W, CV_8UC3); //三通道
        vector<cv::Mat> vecM(3);
        vecM[2].create(H, W, CV_8UC1);
        vecM[1].create(H, W, CV_8UC1);
        vecM[0].create(H, W, CV_8UC1);
        uchar *pr = (uchar *)ptrR[0].L();
        uchar *pg = (uchar *)ptrG[0].L();
        uchar *pb = (uchar *)ptrB[0].L();
        memcpy(vecM[2].data, pr, W * H); //Mat以bgr格式输出
        memcpy(vecM[1].data, pg, W * H);
        memcpy(vecM[0].data, pb, W * H);
        cv::merge(vecM, Image);
    }

    return Image;
}

 

Halcon HImage 与 Qt QImage 的相互转换

参考文献

blog.csdn.net/liyuanbhu/a…

www.ihalcon.com/read-15719.…

QImage CUtil::HObject2QImage(const HalconCpp::HObject &Hobj) //Halcon中的HObject类型转QImage类型
{
    HalconCpp::HTuple htCh = HalconCpp::HTuple();
    HalconCpp::HTuple hv_Length;
    HalconCpp::HTuple cType;
    QImage Image;
    HalconCpp::HObject ho_img;
    ConvertImageType(Hobj, &ho_img, "byte");
    CountChannels(ho_img, &htCh);
    TupleLength(htCh, &hv_Length);
    if (hv_Length.L() == 0)
    {
        return Image;
    }

    HalconCpp::HTuple width;
    HalconCpp::HTuple height;
    int W = 0, H = 0;

    if (htCh[0].I() == 1)
    {
        HalconCpp::HTuple ptr;
        GetImagePointer1(ho_img, &ptr, &cType, &width, &height);
        W = (int)width;
        H = (int)height;
        BYTE *p = (BYTE *)ptr[0].L(); //必须是L(),不能是I()

        //Set buf data
        QImage tmp = QImage(W, H, QImage::Format_Indexed8);
        Image = tmp.copy();
        memcpy(Image.bits(), p, W * H); //单通道

        //Set the color table (used to translate colour indexes to qRgb values)
        QVector<QRgb> vtColorTable;
        for (int k = 0; k < 256; ++k)
        {
            vtColorTable.push_back(qRgb(k, k, k));
        }

        Image.setColorTable(vtColorTable);
    }
    else if (htCh[0].I() == 3)
    {
        HalconCpp::HTuple ptrR, ptrG, ptrB;
        GetImagePointer3(ho_img, &ptrR, &ptrG, &ptrB, &cType, &width, &height);
        W = (int)width;
        H = (int)height;
        uchar *pr = (uchar *)ptrR[0].L(); //三通道
        uchar *pg = (uchar *)ptrG[0].L();
        uchar *pb = (uchar *)ptrB[0].L();

        QImage tmp = QImage(W, H, QImage::Format_RGB888);
        Image = tmp.copy();

#if 0 //该方法行不通
        for (int row = 0; row < height; row++)
        {
            QRgb *line = reinterpret_cast<QRgb *>(Image.scanLine(row));
            for (int col = 0; col < width; col++)
            {
                line[col] = qRgb(*pr++, *pg++, *pb++);
            }
        }
#else //该方法可行
        int bytesPerLine = W * 3;
        int lineHeadId = 0;
        int pixId = 0;
        BYTE *data24 = Image.bits();

        for (int i = 0; i < H; i++)
        {
            lineHeadId = bytesPerLine * i;
            for (int k = 0; k < W; k++)
            {
                pixId = lineHeadId + k * 3;
                data24[pixId + 0] = pr[W * i + k];
                data24[pixId + 1] = pg[W * i + k];
                data24[pixId + 2] = pb[W * i + k];
            }
        }
#endif
    }

    return Image;
}