C++ 下 Halcon 与 OpenCV 图像的转换
2023-06-13 09:18:40 时间
Halcon 中的图像数据结构为
HImage
, OpenCV 中的图像为Mat
,使用中经常需要相互转换的情况,本文记录转换方式。
转换规则
halcon、opencv 和 C++图像内存数据处理机制有差异,在进行相互转换的时候需要注意内存数据排列问题,否则可能出现花图或者多出黑边等现象。
- Halcon 的 HImage 和 OpenCV 的 Mat 都是连续存储图像数据的,HImage 存储数据是每个通道的数据存在一起的, Mat 的数据是一个像素点中的多个通道数据连续存在一起的。
- 单通道图像如果位深度一致可以直接复制内存,如果多通道则需要按照图像的存储规则重新整理。
HImage to Mat
8 bit 深度图像
- 当图像为 8 bit 单通道普通图像时,Mat 图像在内存中各个像素连续排列,像素存在的顺序和 HImage 一致,可以直接拷贝内存:
HalconCpp::HTuple pointer;
GetImagePointer1(H_img, &pointer, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
cv_img = cv::Mat::zeros(height, width, CV_8UC1);
memcpy(cv_img.data, (void*)(pointer.L()), size);
- 当图像为多通道图像时,OpenCV 的 Mat 图像内存仍然是连续的,HImage 是多个单通道图像的组合,因此内存组织上有些区别,需要逐个像素整理
HalconCpp::HTuple pointerR, pointerG, pointerB;
HalconCpp::GetImagePointer3(H_img, &pointerR, &pointerG, &pointerB, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
cv_img = cv::Mat::zeros(height, width, CV_8UC3);
uchar* R = (uchar*)(pointerR.L());
uchar* G = (uchar*)(pointerG.L());
uchar* B = (uchar*)(pointerB.L());
for (int i = 0; i < height; ++i)
{
uchar *p = cv_img.ptr<uchar>(i);
for (int j = 0; j < width; ++j)
{
p[3 * j] = B[i * width + j];
p[3 * j + 1] = G[i * width + j];
p[3 * j + 2] = R[i * width + j];
}
}
示例代码
#include<stdio.h>
#include<opencv2/opencv.hpp>
#include"HalconCpp.h"
#include<string>
usingnamespace std;
usingnamespace cv;
usingnamespace HalconCpp;
cv::Mat HImageToMat(HalconCpp::HObject &H_img)
{
cv::Mat cv_img;
HalconCpp::HTuple channels, w, h;
HalconCpp::ConvertImageType(H_img, &H_img, "byte");
HalconCpp::CountChannels(H_img, &channels);
if (channels.I() == 1)
{
HalconCpp::HTuple pointer;
GetImagePointer1(H_img, &pointer, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
cv_img = cv::Mat::zeros(height, width, CV_8UC1);
memcpy(cv_img.data, (void*)(pointer.L()), size);
cout << "Gray" << endl;
}
elseif (channels.I() == 3)
{
HalconCpp::HTuple pointerR, pointerG, pointerB;
HalconCpp::GetImagePointer3(H_img, &pointerR, &pointerG, &pointerB, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
cv_img = cv::Mat::zeros(height, width, CV_8UC3);
uchar* R = (uchar*)(pointerR.L());
uchar* G = (uchar*)(pointerG.L());
uchar* B = (uchar*)(pointerB.L());
for (int i = 0; i < height; ++i)
{
uchar *p = cv_img.ptr<uchar>(i);
for (int j = 0; j < width; ++j)
{
p[3 * j] = B[i * width + j];
p[3 * j + 1] = G[i * width + j];
p[3 * j + 2] = R[i * width + j];
}
}
cout << "RGB" << endl;
}
return cv_img;
}
intmain()
{
string data_path = "1.jpg";
HalconCpp::HImage Image(data_path.c_str()), ImageGray;
Rgb1ToGray(Image, &ImageGray);
Mat cv_img_gray = HImageToMat(ImageGray);
Mat cv_img_rgb = HImageToMat(Image);
return0;
}
其他深度图像
- 当图像深度不为 8 bits 时,Mat 图像为连续的内存,HImage 图像仍为多个通道单独处理内存的情况,内存拷贝时需要注意转换前后的图像的位深度一致
示例代码
#include<stdio.h>
#include<opencv2/opencv.hpp>
#include"HalconCpp.h"
#include<string>
usingnamespace std;
usingnamespace cv;
usingnamespace HalconCpp;
intmain()
{
string data_path = "1.jpg";
HalconCpp::HImage Image(data_path.c_str()), ImageGray;
Rgb1ToGray(Image, &ImageGray);
ConvertImageType(ImageGray, &ImageGray, "int4");
HTuple channels, w, h;
HTuple pointer;
CountChannels(ImageGray, &channels);
GetImagePointer1(ImageGray, &pointer, nullptr, &w, &h);
int width = w.I(), height = h.I();
int size = width * height;
Mat cv_img, cv_res;
cv_img = cv::Mat::zeros(height, width, CV_32S);
memcpy(cv_img.data, (void*)(pointer.L()), size * 4);
cv_img.convertTo(cv_res, CV_8UC1);
return0;
}
Mat to HImage
- 图像转换逻辑和 HImage 转 Mat 是一致的,直接上示例代码
示例代码
#include<stdio.h>
#include<opencv2/opencv.hpp>
#include"HalconCpp.h"
#include<string>
usingnamespace std;
usingnamespace cv;
usingnamespace HalconCpp;
HalconCpp::HObject MatToHImage(cv::Mat& cv_img)
{
HalconCpp::HObject H_img;
if (cv_img.channels() == 1)
{
int height = cv_img.rows, width = cv_img.cols;
int size = height * width;
uchar *temp = new uchar[size];
memcpy(temp, cv_img.data, size);
HalconCpp::GenImage1(&H_img, "byte", width, height, (Hlong)(temp));
delete[] temp;
}
elseif (cv_img.channels() == 3)
{
int height = cv_img.rows, width = cv_img.cols;
int size = height * width;
uchar *B = new uchar[size];
uchar *G = new uchar[size];
uchar *R = new uchar[size];
for (int i = 0; i < height; i++)
{
uchar *p = cv_img.ptr<uchar>(i);
for (int j = 0; j < width; j++)
{
B[i * width + j] = p[3 * j];
G[i * width + j] = p[3 * j + 1];
R[i * width + j] = p[3 * j + 2];
}
}
HalconCpp::GenImage3(&H_img, "byte", width, height, (Hlong)(R), (Hlong)(G), (Hlong)(B));
delete[] R;
delete[] G;
delete[] B;
}
return H_img;
}
intmain()
{
string data_path = "1.jpg";
cv::Mat cv_img = cv::imread(data_path);
HImage H_img_new = MatToHImage(cv_img);
Mat cv_img_gray;
cvtColor(cv_img, cv_img_gray, COLOR_RGB2GRAY);
HImage H_img_gray = MatToHImage(cv_img_gray);
return0;
}
参考资料
相关文章
- C++学习——c++逗号操作符说明(附加全部运算符优先级)
- 在Pycharm的环境下安装OpenCV「建议收藏」
- pycharm中安装opencv_pycharm安装opencv库出错
- win10系统下pycharm2017配置opencv-python3.4.5[通俗易懂]
- opencv之Canny()函数
- 简单人脸识别一之使用opencv+cnn网络实现人脸识别
- OpenCV中的width与widthStep
- opencv 人脸识别 (二)训练和识别
- C++版OpenCV使用神经网络ANN进行mnist手写数字识别[通俗易懂]
- windows环境下的Anaconda安装与OpenCV机器视觉环境搭建[通俗易懂]
- c++获取子类窗口句柄位置_C++中各种获取窗口句柄的方法「建议收藏」
- c++ auto类型_auto C++
- OpenCV-Python学习(3)—— OpenCV 图像色彩空间转换
- C++构造函数的作用_c++什么是构造函数
- openCV._imread opencv
- python使用opencv如何保存图片_OpenCV Python 保存图片
- opencv(4.5.3)-python(十二)--图像阈值处理
- opencv(4.5.3)-python(十七)--图像金字塔
- c++的链表-C++链表
- c++的链表-链表入门(C++)
- 【图像配准】使用OpenCV进行多图配准拼接