【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

后续还会更新…

  • 30
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Xilinx HLS(High-Level Synthesis,高级综合)是一种将高级语言(如C/C++)代码转化为硬件描述语言(如VHDL或Verilog)的工具。它可以帮助开发者将算法设计转换为FPGA硬件的实现。 直方图均衡(Histogram Equalization)是一种用于图像增强的方法,通过调整图像亮度分布,从而增加图像的对比度和细节。在图像处理中,直方图是描述图像中每个像素灰度级别出现频率的统计图。直方图均衡通过将图像的直方图拉伸到整个灰度级范围来提高图像质量。 在使用Xilinx HLS进行直方图均衡的时候,可以通过以下步骤实现: 1. 首先,将图像数据加载到FPGA的内存中,将其存储为数组的形式。 2. 编写C/C++代码来实现直方图均衡算法。这个算法将对图像进行处理,使其灰度级分布更加均匀。 3. 使用Xilinx HLS将C/C++代码转化为硬件描述语言(如VHDL或Verilog),生成对应的硬件描述文件。 4. 进行硬件级综合和优化,将生成的硬件描述文件综合为具体的硬件电路。 5. 将综合后的电路下载到FPGA芯片中运行。 通过以上步骤,利用Xilinx HLS进行直方图均衡的算法加速,可以在FPGA上实现高效的图像增强功能。同时,使用Xilinx HLS进行开发开发者可以更加便捷地实现算法设计与硬件实现之间的转换。这样的方法可以提高图像处理的速度和效果,适用于各种需要进行即时图像处理的应用场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值