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 的相互转换
参考文献
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;
}