【HLS图像处理】HLS平台实现双目相机立体校正(二)

在之前的文章里【HLS图像处理】HLS平台实现双目相机立体校正(一)大致描述了怎么使用HLS库函数简单实现一个图像校正IP核,但是这种方案有一个问题,就是会占用比较多的硬件DSP资源用于实时计算图像映射关系。本次使用另一种常见的图像校正方案:将图像校正映射表提前计算并保存,图像校正时实时读取,以节省DSP资源。

获取映射表

获取映射表之前需要进行双目标定获取相机参数,具体操作步骤参考上一篇文章。
这里使用OpenCV库中的stereoRectify函数配合initUndistortRectifyMap函数进行图像映射表的计算,函数中各类参数矩阵含义在此不做解释,具体代码如下。代码最后将计算得到的四个映射表矩阵保存至xml文件。

int main(void)
{
	cv::Mat cameraMatrix1 = (cv::Mat_<double>(3, 3) << 591.02482981, -0.26160718, 347.10028729, 0.0, 594.53920305, 211.70964625, 0.0, 0.0, 1.0);
	cv::Mat cameraMatrix2 = (cv::Mat_<double>(3, 3) << 597.91014066, -0.06403916, 337.37116277, 0.0, 602.74968283, 216.70548617, 0.0, 0.0, 1.0);
	cv::Mat distCoeffs1 = (cv::Mat_<double>(5, 1) << 0.04620326, 0.00084191, -0.00056648, -0.00420301, -0.20072713);
	cv::Mat distCoeffs2 = (cv::Mat_<double>(5, 1) << 0.06399693, -0.06656621, 0.00105274, -0.00153776, -0.16573330);
	cv::Size imageSize(640, 480);
	cv::Mat R = (cv::Mat_<double>(3, 3) << 0.99992918, -0.00770894, 0.00906646, 0.00777881, 0.99994012, -0.00769691, -0.00900658, 0.00776689, 0.99992928);
	cv::Mat T = (cv::Mat_<double>(3, 1) << -150.65606533, -1.03590462, 2.47469780);
	cv::Mat Left_Mapx(640, 480, CV_32FC1);
	cv::Mat Left_Mapy(640, 480, CV_32FC1);
	cv::Mat Right_Mapx(640, 480, CV_32FC1);
	cv::Mat Right_Mapy(640, 480, CV_32FC1);
	cv::Mat R1, R2, P1, P2, Q;

	cv::stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q);

	cv::initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R1, P1, imageSize, CV_32FC1, Left_Mapx, Left_Mapy);
	cv::initUndistortRectifyMap(cameraMatrix2, distCoeffs2, R2, P2, imageSize, CV_32FC1, Right_Mapx, Right_Mapy);

	cv::FileStorage fw("Left_Map.xml", cv::FileStorage::WRITE);
	fw << "Left_Mapx" << Left_Mapx;
	fw << "Left_Mapy" << Left_Mapy;
	fw << "Right_Mapx" << Right_Mapx;
	fw << "Right_Mapy" << Right_Mapy;
	fw.release();

	return 0;
}

映射表处理保存

将一幅图像的完整映射表写入FPGA/ZYNQ的BRAM中以供随时读取肯定是不现实的,这里需要先将映射表以文件的形式保存到SD卡上,在系统初始化时将其读入DDR存储空间,再由图像校正IP核进行访问读取。
使用Matlab读取xml文件并将映射表转换为bin文件保存,代码如下。

clear all;

doc = xmlread("Left_Map.xml");

left_mapx = doc.getElementsByTagName('Left_Mapx');
rows = str2double(left_mapx.item(0).getElementsByTagName('rows').item(0).getTextContent());
cols = str2double(left_mapx.item(0).getElementsByTagName('cols').item(0).getTextContent());
data_node = left_mapx.item(0).getElementsByTagName('data').item(0);
data_str = char(data_node.getTextContent());
data_arr = sscanf(data_str, '%e');
Left_Mapx = single(reshape(data_arr, [cols, rows])');

left_mapy = doc.getElementsByTagName('Left_Mapy');
rows = str2double(left_mapy.item(0).getElementsByTagName('rows').item(0).getTextContent());
cols = str2double(left_mapy.item(0).getElementsByTagName('cols').item(0).getTextContent());
data_node = left_mapy.item(0).getElementsByTagName('data').item(0);
data_str = char(data_node.getTextContent());
data_arr = sscanf(data_str, '%e');
Left_Mapy = single(reshape(data_arr, [cols, rows])');

for i = 1:rows
    for j = 1:cols
        Left_Mapx_data(i, j) = typecast(Left_Mapx(i, j), 'uint32');
        Left_Mapy_data(i, j) = typecast(Left_Mapy(i, j), 'uint32');
    end
end

fileID = fopen('Left_Mapx.bin','wb');
fwrite(fileID, Left_Mapx_data', 'uint32');
fclose(fileID);

fileID = fopen('Left_Mapy.bin','wb');
fwrite(fileID, Left_Mapy_data', 'uint32');
fclose(fileID);

最好可以使用WinHEX之类的软件对保存的bin文件进行检查,确保数据正确。
在这里插入图片描述

图像校正IP

在HLS平台使用remap函数即可完成图像校正IP设计,不过与之前的设计不同的是,这里添加了两个AXI接口用于映射表数据的读取。

#define HEIGHT 480
#define WIDTH  640

typedef hls::stream< ap_axiu<8,1,1,1> > AXIS_GRAY;
typedef xf::cv::Mat<XF_8UC1, HEIGHT, WIDTH, XF_NPPC1, 0> GRAY_IMAGE;
typedef xf::cv::Mat<XF_32FC1, HEIGHT, WIDTH, XF_NPPC1, 0> MAP_IMAGE;

void Image_Correct(AXIS_GRAY &Video_Input, AXIS_GRAY &Video_Output, ap_uint<32>* Mapx, ap_uint<32>* Mapy)
{
	#pragma HLS INTERFACE axis port = Video_Input
	#pragma HLS INTERFACE axis port = Video_Output
	#pragma HLS INTERFACE m_axi depth=307200 port=Mapx offset=slave bundle=Mapx_data
	#pragma HLS INTERFACE m_axi depth=307200 port=Mapy offset=slave bundle=Mapy_data
	#pragma HLS INTERFACE s_axilite port = return

	GRAY_IMAGE Image_Input, Image_Output;
	MAP_IMAGE Image_Mapx, Image_Mapy;

	#pragma HLS DATAFLOW

	xf::cv::AXIvideo2xfMat(Video_Input, Image_Input);

	xf::cv::Array2xfMat(Mapx, Image_Mapx, WIDTH);
	xf::cv::Array2xfMat(Mapy, Image_Mapy, WIDTH);

	xf::cv::remap<16, XF_INTERPOLATION_BILINEAR, XF_8UC1, XF_32FC1, XF_8UC1, HEIGHT, WIDTH, XF_NPPC1, false, 0, 0, 0, 0>
	(Image_Input, Image_Output, Image_Mapx, Image_Mapy);

	xf::cv::xfMat2AXIvideo(Image_Output, Video_Output);
}

软硬件部署编程

生成IP核导出到Vivado后,根据自己的实际用途进行部署即可。最后在软件端的代码大致流程如下。
SD卡系统初始化->读取bin文件->初始化图像校正IP核->设置映射表地址->启动图像校正IP核

void Image_Correct_Init(void)
{
	SD_SYS_Init();
	Map_bin_read(Lx, Left_Mapx, &fil);
	Map_bin_read(Ly, Left_Mapy, &fil);
	Map_bin_read(Rx, Right_Mapx, &fil);
	Map_bin_read(Ry, Right_Mapy, &fil);

	XImage_correct_Initialize(&xcorrect_0, XPAR_IMAGE_CORRECT_0_DEVICE_ID);
	XImage_correct_Set_Mapx(&xcorrect_0, (u64)Left_Mapx);
	XImage_correct_Set_Mapy(&xcorrect_0, (u64)Left_Mapy);
	XImage_correct_EnableAutoRestart(&xcorrect_0);

	XImage_correct_Initialize(&xcorrect_1, XPAR_IMAGE_CORRECT_1_DEVICE_ID);
	XImage_correct_Set_Mapx(&xcorrect_1, (u64)Right_Mapx);
	XImage_correct_Set_Mapy(&xcorrect_1, (u64)Right_Mapy);
	XImage_correct_EnableAutoRestart(&xcorrect_1);

	XImage_correct_Start(&xcorrect_1);
	XImage_correct_Start(&xcorrect_0);
}

总结

最后实际上板测试所得到的实验现象与上一种方法完全一致,而且在本项目中成功节省了将近100多个硬件DSP,达到预期效果。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Vivado HLS 是 Xilinx 公司推出的一款高级综合工具,可以将 C/C++ 等高级语言代码转换为硬件描述语言 VHDL/Verilog,从而实现硬件加速。在图像处理领域,使用 Vivado HLS 可以将图像处理算法实现为硬件电路,提高算法运行速度和功耗效率。 以下是 Vivado HLS图像处理中的基本应用: 1. 图像滤波:图像滤波是图像处理中的基本操作,可以去除噪声、增强图像细节等。常用的滤波算法有均值滤波、中值滤波、高斯滤波等。使用 Vivado HLS 可以将这些算法实现为硬件电路,加速图像滤波操作。 2. 图像变换:图像变换是将图像从一个空间域转换到另一个空间域的操作,如傅里叶变换、小波变换等。这些变换算法需要大量的计算,使用 Vivado HLS 可以将其实现为硬件电路,提高计算速度。 3. 图像分割:图像分割是将图像分成多个区域的操作,常用的算法有阈值分割、边缘检测等。使用 Vivado HLS 可以将这些算法实现为硬件电路,提高图像分割速度。 4. 特征提取:图像特征提取是从图像中提取出特定的特征,如角点、边缘等。常用的特征提取算法有Harris角点检测、SIFT算法等。使用 Vivado HLS 可以将这些算法实现为硬件电路,提高特征提取速度。 总之,Vivado HLS图像处理领域中有着广泛的应用,可以加速图像处理算法的运行,提高系统性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值