【xilinx xfopencv】Vivado_HLS_ov5640_rgb2gray_hdmi 第一部分


写在前面

本人是参考赛灵思官方文档、正点原子教程和网上相关内容,所有参考、转载会标明出处,希望文章对大家有所帮助,感谢各位!

目的

使用 Vivado HLS 实现一个图像处理的 IP 核,该 IP 核能利用 xfopencv 将 OV5640 摄像头产生的 RGB 彩色图像转换成灰度图像,在 Vivado 中对 IP 核进行验证。因为上海疫情,购买不到LCD屏,最后通过 HDMI 实时显示。


工具

1.Vivado HLS 2019.1
2.xfopencv-2019.1_release.zip

一、创建项目

打开 Vivado HLS 2019.1,创建项目 ov5640_rgb2gray。创建好之后,在项目文件夹的根目录下添加一个 src 文件夹。

在这里插入图片描述


二、步骤

1.下载xfopencv库

在 GitHub 上下载 https://github.com/Xilinx/xfopencv

在这里插入图片描述


2.引入xfopencv库

下载之后,解压在 Xilinx 文件下。

在这里插入图片描述


3.参考示例代码

如下图所示,打开文件,里面是示例的模板和代码,虽然文件较多,但这是官方固定的代码架构,代码内容不难,可以顺便学习别人的编程风格。

重点:一定要按照这个示例来,否则进行 Synthesis 的时候可能会报错,目前还不清楚原因。

在这里插入图片描述
报错的报告如下图所示

在这里插入图片描述


4.代码

下图是本人依照示例编写的该项目代码架构

在这里插入图片描述
4.1 xf_headers.h
本人查询了相关的文章,简单的对一些代码进行解释,不一定正确,仅供参考。

#ifndef _XF_HEADERS_H_
#define _XF_HEADERS_H_

/*与C环境相关的头文件*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/*与HLS相关的头文件,需要包含HLS的include的path*/
#include "ap_int.h"
#include "hls_stream.h"
/*针对SDSCC*/
#if __SDSCC__
#undef __ARM_NEON__
#undef __ARM_NEON
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#define __ARM_NEON__
#define __ARM_NEON
#else

//在CSIM中的tb中包含的H文件
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#endif

#if __SDSCC__
#include "sds_lib.h"
#define TIME_STAMP_INIT  unsigned int clock_start, clock_end;  clock_start = sds_clock_counter();
#define TIME_STAMP  { clock_end = sds_clock_counter(); printf("elapsed time %lu \n", clock_end-clock_start); clock_start = sds_clock_counter();  }
#endif
/*在CSIM中的tb中包含的H文件*/
#include "common/xf_sw_utils.h"
#include "common/xf_axi.h"

#endif//_XF_HEADERS_H_

4.2 xf_config_params.h
xf_config_params.h 头文件中的内容似乎可以和 xf_rgb2gray_config.h 合并,但是本人先留下来了。

/* Optimization type */

#define RO  0 // Resource Optimized (8-pixel implementation)
#define NO  1 // Normal Operation (1-pixel implementation)

4.3 xf_rgb2gray_config.h
配置相关参数等的头文件,重要!

#ifndef _XF_RGB2GRAY_CONFIG_H_
#define _XF_RGB2GRAY_CONFIG_H_

/*与HLS相关的头文件,需要包含HLS的include的path*/
#include "hls_stream.h"
#include "ap_int.h"
/*与xfopencv相关的头文件*/
#include "common/xf_common.h"
#include "common/xf_utility.h"
#include "common/xf_infra.h"
/*与图像处理相关的头文件*/
#include "imgproc/xf_cvt_color.hpp"
#include "imgproc/xf_cvt_color_1.hpp"
//#include "imgproc/xf_rgb2hsv.hpp"
//#include "imgproc/xf_bgr2hsv.hpp"
// Has to be set when synthesizing

#include "xf_config_params.h"

/* config width and height */
#define WIDTH 	1024
#define HEIGHT	800

#if NO
#define NPC1 XF_NPPC1
#else
#define NPC1 XF_NPPC8
#endif
/*声明主函数*/
void ov5640_rgb2gray(hls::stream< ap_axiu<24,1,1,1> >& _src,hls::stream< ap_axiu<24,1,1,1> >& _dst,int height,int width);

#endif // _XF_RGB2GRAY_CONFIG_H_

4.4 xf_rgb2gray_accel.cpp
cvtcolor_rgb2gray 函数,核心的内置函数,重要!

#include "xf_rgb2gray_config.h"
void cvtcolor_rgb2gray(xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> &imgInput,xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> &imgOutput )
	{
		xf::rgb2gray<XF_8UC3,XF_8UC1, HEIGHT, WIDTH, NPC1>(imgInput, imgOutput);
	}
void cvtcolor_gray2rgb(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> &imgInput,xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> &imgOutput )
	{
		xf::gray2rgb<XF_8UC1,XF_8UC3, HEIGHT, WIDTH, NPC1>(imgInput, imgOutput);
	}

4.5 ov5640_rgb2gray.cpp
主函数 Top Function,定义变量,调用函数等等。

#include "xf_rgb2gray_config.h"

typedef hls::stream< ap_axiu<24,1,1,1> > AXI_STREAM_24;

void cvtcolor_rgb2gray(xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> &imgInput,xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> &imgOutput);
void cvtcolor_gray2rgb(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> &imgInput,xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> &imgOutput);
void ov5640_rgb2gray(AXI_STREAM_24& _src,AXI_STREAM_24& _dst,int height,int width)
{
#pragma HLS INTERFACE axis register both  port=_src
#pragma HLS INTERFACE axis register both  port=_dst

	 xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> imgInput1(height,width);
	 xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> imgGray(height,width);
	 xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> imgOutput1(height,width);

#pragma HLS stream variable=imgInput1.data dim=1 depth=1
#pragma HLS stream variable=imgGray.data dim=1 depth=1
#pragma HLS stream variable=imgOutput1.data dim=1 depth=1
#pragma HLS dataflow

	xf::AXIvideo2xfMat(_src, imgInput1);

	cvtcolor_rgb2gray(imgInput1,imgGray);
	cvtcolor_gray2rgb(imgGray,imgOutput1);

	xf::xfMat2AXIvideo(imgOutput1, _dst);

}

4.6
在进行综合之前,强烈建议调试和测试。


#include "xf_headers.h"
#include "xf_rgb2gray_config.h"

int main(int argc, char** argv){
		uint16_t img_width;
		uint16_t img_height;

		cv::Mat inputimg1, inputimg;
		cv::Mat error_img0;

	cv::Mat outputimg,ocv_outputimg;
	inputimg1 = cv::imread(argv[1], 1);
	if(!inputimg1.data)
	{
		return -1;
	}
	cv::cvtColor(inputimg1,inputimg,CV_BGR2RGB);
	outputimg.create(inputimg.rows, inputimg.cols, CV_8UC1);
	static xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> imgInput(inputimg.rows,inputimg.cols);
	static xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> imgOutput(outputimg.rows,outputimg.cols);

	imgInput.copyTo((unsigned short int*)inputimg.data);

	#if __SDSCC__
		hw_ctr.start();
	#endif
		cvtcolor_rgb2gray(imgInput,imgOutput);
	#if __SDSCC__
		hw_ctr.stop();
		uint64_t hw_cycles = hw_ctr.avg_cpu_cycles();
	#endif

	outputimg.data = imgOutput.copyFrom();

	//OpenCV reference
	cv::cvtColor(inputimg,ocv_outputimg,CV_RGB2GRAY,1);
	cv::imwrite("ocv_out.jpg",ocv_outputimg);
	cv::imwrite("hls_out.jpg",outputimg);
	absdiff(outputimg,ocv_outputimg,error_img0);

	/* ## *************************************************************** ##*/
	return 0;

}

5.设置

在Xilinx官方文档ug1233中介绍了相关配置。另外,进行测试的时候,可以在 testbench 中引入库中 example 下 data 文件夹中图片。
在这里插入图片描述
Synthesis 设置

在这里插入图片描述Simulation设置

在这里插入图片描述


6.结果

1.C-Sim 结果

在这里插入图片描述

在该项目文件目录下可以查看结果

在这里插入图片描述
在这里插入图片描述

2.Synthesis 成功后,会弹出report ,含有接口等信息。

在这里插入图片描述在这里插入图片描述

问题

小问题

  1. Include 后面的引号问题引起重视,中英文下的引号需要注意。

  2. 头文件中要声明使用到的函数。

  3. 配置的时候粗心,本来2个下划线,写成3个,导致了如下图的error。
    在这里插入图片描述
    在这里插入图片描述

Synthesis 过程中产生的问题

  1. cvtcolor_bgr2gray sythesis issue
    参考了GitHub上的文章解决了。
    参考该链接解决下图所示error https://github.com/Xilinx/xfopencv/issues/82
    在这里插入图片描述

  2. 待解决的警告:
    希望有解决方案的大佬评论留言,感激不尽。
    D:/Xilinx/xfopencv/include\imgproc/xf_cvt_color.hpp:2171:57: warning: default template arguments for a function template are a C++11 extension [-Wc++11-extensions]
    template <int SRC_T, int DST_T, int ROWS, int COLS, int NPC=1>
    ^ ~

总结

个人理解:之所以用 FPGA 进行图像处理,第一是因为FPGA并行计算和硬件加速的特点可以获得更快的响应。第二是因为有利于减少产品研发时间,快速形成产品,比如车牌识别,目标跟踪等。
Xilinx OpenCV 是一个为 FPGA 高级合成(HLS)优化的模板库,允许以与使用 OpenCV 库相同的方式轻松创建图像处理渠道。
推荐一篇文章,介绍 Xilinx OpenCV ,并且给每段代码进行了解释,值得收藏一看。
Introduction to Xilinx OpenCV

自己不怎么写文章,也有很多不会的地方(如3 和4.2),可能写的不好,欢迎批评、指正和交流。
第二部分 已经更新

https://blog.csdn.net/m0_49474265/article/details/124511504

后续还会更新…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值