在机器视觉应用中,不同的图像处理库和框架常使用不同的数据结构来表示图像。常用的库包括 Qt 的 QImage
、OpenCV 的 cv::Mat
以及 Halcon 的 HObject
。为了在这些库之间实现无缝的数据传递和处理,图像格式的转换成为必不可少的环节。本文将详细介绍如何在 QImage
、cv::Mat
和 HalconCpp::HObject
之间进行相互转换,并提供相应的代码实现。
1. QImage 到 cv::Mat 的转换
QImage
是 Qt 框架中表示图像的类,它支持多种格式(如 RGB32、RGB888、灰度等)。为了将 QImage
转换为 OpenCV 的 cv::Mat
,需要根据 QImage
的格式构建不同类型的 cv::Mat
。代码如下:
cv::Mat QImageToMat(const QImage& image) {switch (image.format()) {case QImage::Format_RGB32: {// 对于 Format_RGB32 格式,QImage 是 RGBA 格式,4 通道cv::Mat mat(image.height(), image.width(), CV_8UC4, const_cast<uchar*>(image.bits()), image.bytesPerLine());return mat.clone(); // 需要深拷贝,防止指针问题}case QImage::Format_RGB888: {// 对于 RGB888 格式,QImage 是 RGB 格式,3 通道cv::Mat mat(image.height(), image.width(), CV_8UC3, const_cast<uchar*>(image.bits()), image.bytesPerLine());return mat.clone(); // 深拷贝}case QImage::Format_Grayscale8: {// 对于 Grayscale8 格式,QImage 是灰度图,1 通道cv::Mat mat(image.height(), image.width(), CV_8UC1, const_cast<uchar*>(image.bits()), image.bytesPerLine());return mat.clone(); // 深拷贝}default:// 如果遇到不支持的格式,输出警告信息qWarning() << "不支持的 QImage 格式!";return cv::Mat();}
}
这段代码通过检测 QImage
的格式,将其正确地转换为相应的 cv::Mat
格式,并进行深拷贝以防止指针问题。
2. cv::Mat 到 QImage 的转换
在很多情况下,OpenCV 的 cv::Mat
是图像处理的核心数据结构。如果需要将 cv::Mat
转换为 QImage
,则需要处理不同的通道数(如单通道灰度图、三通道 BGR 图像、四通道 RGBA 图像等)。以下是转换实现:
QImage MatToQImage(const cv::Mat& mat) {switch (mat.type()) {case CV_8UC1: {// 单通道灰度图return QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Grayscale8).copy(); // 深拷贝}case CV_8UC3: {// 三通道彩色图像,OpenCV 默认是 BGR 格式,需要转换为 RGBreturn QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_RGB888).rgbSwapped().copy(); // 深拷贝}case CV_8UC4: {// 四通道 RGBA 图像return QImage(mat.data, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32).copy(); // 深拷贝}default:qWarning() << "不支持的 cv::Mat 格式!";return QImage();}
}
在这段代码中,如果 cv::Mat
是三通道的 BGR 格式,必须先转换为 RGB 格式。深拷贝是为了避免数据被意外修改或释放。
3. cv::Mat 到 HalconCpp::HObject 的转换
Halcon 是工业机器视觉中广泛使用的库,其 HObject
是处理图像的基础数据结构。将 cv::Mat
转换为 HObject
时,需要分别处理单通道灰度图和三通道彩色图(需要从 BGR 转换为 RGB)。代码如下:
HalconCpp::HObject MatToHObject(const cv::Mat& mat) {HalconCpp::HObject hImage;if (mat.type() == CV_8UC1) {// 单通道灰度图像HalconCpp::GenImage1(&hImage, "byte", mat.cols, mat.rows, (Hlong)mat.data);} else if (mat.type() == CV_8UC3) {// 三通道彩色图像,OpenCV 中是 BGR 格式,需转换为 RGB 格式cv::Mat rgbMat;cv::cvtColor(mat, rgbMat, cv::COLOR_BGR2RGB);HalconCpp::GenImageInterleaved(&hImage, (Hlong)rgbMat.data, "rgb", rgbMat.cols, rgbMat.rows, -1, "byte", 0, 0, 0, 0, -1, 0);} else {qWarning() << "不支持的 cv::Mat 格式转换为 HalconCpp::HObject!";}return hImage;
}
通过此方法,我们可以将 OpenCV 的 cv::Mat
格式转化为 Halcon 的 HObject
,并且保证彩色图像的通道顺序正确。
4. HalconCpp::HObject 到 cv::Mat 的转换
将 HObject
转换为 cv::Mat
也涉及到通道数的处理。以下是相应的代码:
cv::Mat HObjectToMat(const HalconCpp::HObject& hImage) {HTuple hChannels;HalconCpp::CountChannels(hImage, &hChannels);if (hChannels[0].I() == 1) {HTuple hWidth, hHeight;HalconCpp::GetImageSize(hImage, &hWidth, &hHeight);cv::Mat mat(hHeight.I(), hWidth.I(), CV_8UC1);HalconCpp::GetImagePointer1(hImage, nullptr, nullptr, &hWidth, &hHeight);memcpy(mat.data, (void*)hImage.GetDataPointer(), mat.total());return mat;} else if (hChannels[0].I() == 3) {HTuple hWidth, hHeight;HalconCpp::GetImageSize(hImage, &hWidth, &hHeight);cv::Mat mat(hHeight.I(), hWidth.I(), CV_8UC3);HalconCpp::GetImagePointer3(hImage, nullptr, nullptr, nullptr, &hWidth, &hHeight);memcpy(mat.data, (void*)hImage.GetDataPointer(), mat.total() * 3);cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR);return mat;} else {qWarning() << "不支持的 HObject 格式转换为 cv::Mat!";return cv::Mat();}
}
此方法通过 Halcon
提供的 API 获取图像的指针,并将数据复制到 cv::Mat
对象中。对于彩色图像,需要将 RGB 格式转换为 OpenCV 的 BGR 格式。
结论
本文介绍了如何在 Qt 的 QImage
、OpenCV 的 cv::Mat
和 Halcon 的 HObject
之间进行相互转换,这在图像处理和机器视觉应用中尤为重要。通过这些转换方法,不同库之间的图像处理功能可以被集成到同一个应用程序中,从而实现更强大的图像处理能力。