【xilinx xfopencv】Vivado_HLS_ov5640_threshold_hdmi(图像二值化)第二部分

写在前面

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

创建项目、添加示例代码和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核验证成功。

工具

  • Vivado HLS 2019.1
  • Vivado 2019.1
  • Xilinx SDK 2019.1
  • 启明星开发板(XC7Z010clg400-1)及配套下载器等
  • 正点原子OV5640摄像头模块
  • 显示屏及HDMI线

Part 1

综合(Synthesis)

代码请参考Part 2,删除与 otsuthreshold 相关的文件,并在xf_threshold_config.h 增加了2行宏定义,如下:

#define THRESH  104
#define MAXVAL 	245

综合报告如下:

【xilinx xfopencv】Vivado_HLS_ov5640_threshold_hdmi(图像二值化)第二部分_第1张图片

Create Block Design

可以另存之前的项目工程,添加IP核等步骤不再赘述。

【xilinx xfopencv】Vivado_HLS_ov5640_threshold_hdmi(图像二值化)第二部分_第2张图片

Launch SDK

main.c 代码如下:


#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;
}
 

【xilinx xfopencv】Vivado_HLS_ov5640_threshold_hdmi(图像二值化)第二部分_第3张图片

实验结果

threshold

Part 2

综合(Synthesis)

代码

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);
}

综合结果

综合报告如下:

【xilinx xfopencv】Vivado_HLS_ov5640_threshold_hdmi(图像二值化)第二部分_第4张图片

总结

对于Part 2 出现的问题,可能自己的功力还不够,继续努力…

你可能感兴趣的:(Vivado_HLS_图像处理,fpga开发,opencv)