本人是参考赛灵思官方文档核例程、网上相关教程和内容,所有参考、转载会标明出处,希望文章对大家有所帮助,感谢各位!
创建项目、添加示例代码和Project Settings等操作请参考本人其他文章,链接:https://blog.csdn.net/m0_49474265/article/details/123759085
使用到AXI,需要修改 xf_headers.h 和 xf_config_params.h 文件,可参考下载的xfopencv库里的HLS_Use_Model,或者参考本人的文章,链接:https://blog.csdn.net/m0_49474265/article/details/124106562
使用 Vivado HLS 实现一个图像处理的 IP 核,该 IP 核能利用 xfopencv 将 OV5640 摄像头产生的 RGB 彩色图像转换成灰度图像,进一步利用大津法实现二值化图像,并在 Vivado 中对 IP 核进行验证,最后通过 HDMI 实时显示。
在第一部分已经完成仿真的部分,第二部分主要完成HLS综合、IP核的导出与验证。自己在实验的过程中,在文章下面 Part 2 想使用threshold 函数调用 otsuthreshold 函数生成的阈值进行二值化,虽然仿真验证通过,但是IP核验证并未成功,目前正在找原因。Part 1 为直接利用threshold 函数进行二值化处理(thresh=104,maxval=245),IP核验证成功。
代码请参考Part 2,删除与 otsuthreshold 相关的文件,并在xf_threshold_config.h 增加了2行宏定义,如下:
#define THRESH 104
#define MAXVAL 245
综合报告如下:
可以另存之前的项目工程,添加IP核等步骤不再赘述。
#include
#include
#include
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "display_ctrl_hdmi/display_ctrl.h"
#include "vdma_api/vdma_api.h"
#include "emio_sccb_cfg/emio_sccb_cfg.h"
#include "ov5640/ov5640_init.h"
#include "xotsuthreshold_ip_accel.h"//****需要修改 by Du****改成IP核的名字
//宏定义
#define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR //动态时钟基地址
#define VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID //VDMA器件ID
#define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID //VTC器件ID
//全局变量
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR
+ 0x1000000);
XAxiVdma vdma;
DisplayCtrl dispCtrl;
VideoMode vd_mode;
XOtsuthreshold_ip_accel otsuthreshold_ip_accel_inst;//***需要修改 by Du****
int main(void)
{
u32 status;
u16 cmos_h_pixel; //ov5640 DVP 输出水平像素点数
u16 cmos_v_pixel; //ov5640 DVP 输出垂直像素点数
u16 total_h_pixel; //ov5640 水平总像素大小
u16 total_v_pixel; //ov5640 垂直总像素大小
cmos_h_pixel = 1280; //设置OV5640输出分辨率为1280*720
cmos_v_pixel = 720;
total_h_pixel = 2570;
total_v_pixel = 980;
emio_init(); //初始化EMIO
status = ov5640_init( cmos_h_pixel, //初始化ov5640
cmos_v_pixel,
total_h_pixel,
total_v_pixel);
if(status == 0)
xil_printf("OV5640 detected successful!\r\n");
else
xil_printf("OV5640 detected failed!\r\n");
vd_mode = VMODE_1280x720;
//
XOtsuthreshold_ip_accel_Initialize(&otsuthreshold_ip_accel_inst, XPAR_XOTSUTHRESHOLD_IP_ACCEL_0_DEVICE_ID);//****需要修改 by Du****ip核名称改大写
//配置的行数
XOtsuthreshold_ip_accel_Set_height(&otsuthreshold_ip_accel_inst, vd_mode.height);
//配置的列数
XOtsuthreshold_ip_accel_Set_width(&otsuthreshold_ip_accel_inst, vd_mode.width);
//配置VDMA
run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,
frame_buffer_addr,0,0,BOTH);
//初始化Display controller
DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
//设置VideoMode
DisplaySetMode(&dispCtrl, &vd_mode);
DisplayStart(&dispCtrl);
return 0;
}
threshold
otsuthreshold_ip_accel 代码如下:
#include "xf_threshold_config.h"
#include "xf_otsuthreshold_config.h"
#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 otsuthreshold_accel(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPPC> &imgInput, unsigned char &Otsuval);
void threshold_accel(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> &_src,xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> &_dst,unsigned char thresh,unsigned char maxval);
void otsuthreshold_ip_accel(hls::stream< ap_axiu<24,1,1,1> >& _src,hls::stream< ap_axiu<24,1,1,1> >& _dst,int height,int width,uint8_t maxval)
{
#pragma HLS INTERFACE axis register both port=_src
#pragma HLS INTERFACE axis register both port=_dst
#pragma HLS INTERFACE s_axilite port=height
#pragma HLS INTERFACE s_axilite port=width
#pragma HLS INTERFACE s_axilite port=maxval
#pragma HLS INTERFACE ap_ctrl_none port=return
uint8_t Otsuval;
xf::Mat<XF_8UC3, HEIGHT, WIDTH, NPC1> imgInput1(height,width);
xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> imgGrayIn(height,width);
xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPC1> imgGrayOut(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=imgGrayIn.data dim=1 depth=1
#pragma HLS stream variable=imgGrayOut.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,imgGrayIn);
otsuthreshold_accel(imgGrayIn,Otsuval);
threshold_accel(imgGrayIn,imgGrayOut,Otsuval,MAXVAL);
cvtcolor_gray2rgb(imgGrayOut,imgOutput1);
xf::xfMat2AXIvideo(imgOutput1, _dst);
}
xf_config_params.h 代码如下:
/* set the optimisation type*/
#define NO 1 // Normal Operation
#define RO 0 // Resource Optimized
/* set the type of thresholding*/
#define THRESH_TYPE XF_THRESHOLD_TYPE_BINARY
//added parts by du
// Set Conversion type
#define RGB2GRAY 0
#define GRAY2RGB 0
xf_headers.h 代码如下:
#ifndef _XF_HEADERS_H_
#define _XF_HEADERS_H_
#include
#include
//added parts by du
#include
#include "ap_int.h"
#include "hls_stream.h"
#if __SDSCC__
#undef __ARM_NEON__
#undef __ARM_NEON
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#define __ARM_NEON__
#define __ARM_NEON
#else
#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
#include "common/xf_sw_utils.h"
//added parts by du
#include "common/xf_axi.h"
#endif//_XF_HEADERS_H_
xf_threshold_config.h 代码如下:
#ifndef _XF_THRESHOLD_CONFIG_H_
#define _XF_THRESHOLD_CONFIG_H_
#include "hls_stream.h"
#include "ap_int.h"
#include "common/xf_common.h"
#include "common/xf_utility.h"
#include "imgproc/xf_threshold.hpp"
#include "xf_config_params.h"
typedef ap_uint<8> ap_uint8_t;
typedef ap_uint<64> ap_uint64_t;
//modified part by du
//config width and height
#define WIDTH 1024
#define HEIGHT 800
#define MAXVAL 200
#if RO
#define NPIX XF_NPPC8
#endif
#if NO
#define NPIX XF_NPPC1
#endif
void threshold_accel(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> &_src,xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> &_dst,unsigned char thresh,unsigned char maxval);
#endif // end of _XF_THRESHOLD_CONFIG_H_
xf_otsuthreshold_config.h 代码如下:
#ifndef _XF_OTSUTHRESHOLD_CONFIG_H_
#define _XF_OTSUTHRESHOLD_CONFIG_H_
#include "ap_int.h"
#include "hls_stream.h"
#include "common/xf_common.h"
#include "common/xf_utility.h"
#include "common/xf_infra.h"//added part by du
#include "imgproc/xf_otsuthreshold.hpp"
#include "xf_config_params.h"
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
//added part by du
typedef unsigned char uint8_t;//Unsigned char means unsigned, representing a range of 0~255(0~2^8-1)
//modified part by du
//config width and height
#define WIDTH 1024
#define HEIGHT 800
#if NO
#define NPPC XF_NPPC1
#define IN_TYPE ap_uint<8>
#define NPC1 0
#endif
#if RO
#define NPPC XF_NPPC8
#define IN_TYPE ap_uint<64>
#define NPC1 3
#endif
void otsuthreshold_accel(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPPC> &imgInput, unsigned char &Otsuval);
void otsuthreshold_ip_accel(hls::stream< ap_axiu<24,1,1,1> >& _src,hls::stream< ap_axiu<24,1,1,1> >& _dst,int height,int width,uint8_t maxval);
#endif
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
//modified part by du
//config width and height
#define WIDTH 1024
#define HEIGHT 800
/*xf_config_params.h头文件针对下面的设置*/
#include "xf_config_params.h"
#if NO
#define NPC1 XF_NPPC1
#else
#define NPC1 XF_NPPC8
#endif
//void cvtcolor_rgb2gray(xf::Mat &imgInput,xf::Mat &imgOutput);
//void cvtcolor_gray2rgb(xf::Mat &imgInput,xf::Mat &imgOutput);
//modified part by du
//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_
其余代码如下:
//xf_otsuthreshold_accel.cpp
#include "xf_otsuthreshold_config.h"
void otsuthreshold_accel(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPPC> &imgInput, unsigned char &Otsuval)
{
xf::OtsuThreshold<XF_8UC1, HEIGHT, WIDTH, NPPC>(imgInput, Otsuval);
}
//xf_rgb2gray_accel.cpp
#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);
}
//xf_threshold_accel.cpp
#include "xf_threshold_config.h"
void threshold_accel(xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> &_src,xf::Mat<XF_8UC1, HEIGHT, WIDTH, NPIX> &_dst,unsigned char thresh,unsigned char maxval)
{
xf::Threshold<THRESH_TYPE,XF_8UC1,HEIGHT, WIDTH,NPIX>(_src, _dst,thresh,maxval);
}
综合报告如下:
对于Part 2 出现的问题,可能自己的功力还不够,继续努力…