本文最后更新于:2023年12月5日 下午

之前介绍了 OpenCV 的 remap 函数,Halcon 中也有类似函数 MapImage,本文介绍 MapImage,并将 OpenCV 的 remap 转换为 MapImage。

map_image

  • 函数使用
1
map_image(Image, Map : ImageMapped : : )
  • 其中:
    • Image: 需要被映射修改的图像
    • Map: 映射矩阵
    • ImageMapped: 映射结果
  • 可以看到核心在于 Map 矩阵如何定义和使用。
  • Map 为和原始图像一样大小的 5 通道图像,第一个通道格式为 32 bits 深度int4 类型,表示的是每个需要被映射的图像像素位置对应的原始图像像素编号

这是一张宽度 3072 的图像的映射示例,每个像素的值表示的是原始图像的像素编号

  • Map 的第2-5个通道的格式为 16 bits 的 uint2 类型,表示的是插值四个像素的占比,第一个通道指向的是四个相邻像素中左上角的一个
  • 后四个通道指向的分别是四个比例:

  • uint2 表示比例的思路是四个数的和是 65535(可能会有1-2的误差),根据数值占 65535 的比例来决定四个像素的插值比例
  • 每个通道的图像都看起来挺神奇的,这里展示一张示例图像

remap -> map_image

  • OpenCV 的 remap 需要两个 map 作为输入,可以在 C++ 中将这两个 map 转为 halcon 的 map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

Mat map1, map2, R;
initUndistortRectifyMap(cameraMatrix, distCoeffs, R, newcameramatrix, imageSize, CV_32FC1, map1, map2);

Mat main_map, sub_map2, sub_map3, sub_map4, sub_map5;
main_map = main_map.zeros(imageSize, CV_32S);
sub_map2 = sub_map2.zeros(imageSize, CV_16U);
sub_map3 = sub_map3.zeros(imageSize, CV_16U);
sub_map4 = sub_map4.zeros(imageSize, CV_16U);
sub_map5 = sub_map5.zeros(imageSize, CV_16U);

float x_value, y_value;
float x_diff, y_diff;
int x_temp, y_temp;

for (int row(0); row < imageSize.height; row++) {
for (int col(0); col < imageSize.width; col++) {
x_value = map1.at<float>(row, col);
y_value = map2.at<float>(row, col);

x_temp = floor(x_value);
y_temp = floor(y_value);

if (x_value < 0 or y_value < 0)
{
main_map.at<int32_t>(row, col) = 0;
sub_map2.at<uint16_t>(row, col) = 0;
sub_map3.at<uint16_t>(row, col) = 0;
sub_map4.at<uint16_t>(row, col) = 0;
sub_map5.at<uint16_t>(row, col) = 0;
}
else
{
x_diff = x_value - x_temp;
y_diff = y_value - y_temp;

main_map.at<int32_t>(row, col) = y_temp * imageSize.width + x_temp;
sub_map2.at<uint16_t>(row, col) = (1 - x_diff) * (1 - y_diff) * 65535;
sub_map3.at<uint16_t>(row, col) = x_diff * (1 - y_diff) * 65535;
sub_map4.at<uint16_t>(row, col) = (1 - x_diff) * y_diff * 65535;
sub_map5.at<uint16_t>(row, col) = x_diff * y_diff * 65535;
}
}
}

HalconCpp::HImage main_data, sub_map_data2, sub_map_data3, sub_map_data4, sub_map_data5;
int height1 = main_map.rows, width1 = main_map.cols;
int size = height1 * width1;

uchar *temp = new uchar[size * 4];

memcpy(temp, main_map.data, size * 4);
HalconCpp::GenImage1(&main_data, "int4", imageSize.width, imageSize.height, (Hlong)(temp));

memcpy(temp, sub_map2.data, size * 2);
HalconCpp::GenImage1(&sub_map_data2, "uint2", imageSize.width, imageSize.height, (Hlong)(temp));

memcpy(temp, sub_map3.data, size * 2);
HalconCpp::GenImage1(&sub_map_data3, "uint2", imageSize.width, imageSize.height, (Hlong)(temp));

memcpy(temp, sub_map4.data, size * 2);
HalconCpp::GenImage1(&sub_map_data4, "uint2", imageSize.width, imageSize.height, (Hlong)(temp));

memcpy(temp, sub_map5.data, size * 2);
HalconCpp::GenImage1(&sub_map_data5, "uint2", imageSize.width, imageSize.height, (Hlong)(temp));
delete[] temp;

HalconCpp::HImage map_h, map_res_h;
Compose5(main_data, sub_map_data2, sub_map_data3, sub_map_data4, sub_map_data5, &map_h);

MapImage(ImageGray, map_h, &map_res_h);

参考资料



文章链接:
https://www.zywvvd.com/notes/coding/halcon/halcon-mapimage/halcon-mapimage/


“觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”

微信二维码

微信支付

支付宝二维码

支付宝支付

Halcon MapImage 复刻 remap
https://www.zywvvd.com/notes/coding/halcon/halcon-mapimage/halcon-mapimage/
作者
Yiwei Zhang
发布于
2022年12月28日
许可协议