软件版本:VIVADO2017.4
操作系统:WIN10 64bit
硬件平台:适用米联客 ZYNQ系列开发板
米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!
3.1 概述
通过前面的学习,我们已经基本熟悉了HLS的开发流程,那么在HLS上进行算法开发,算法实现综合后我们需要对算法的正确性进行验证,那么我们如何得到我们想要的视频图像数据流,对算法模块进行测试呢?
本章介绍了3种HLS仿真中最常用的获取仿真数据流的方法,并对图像、视频数据流以及外部摄像头调用进行了验证。在接下来的算法设计中,我们就即将用到本章介绍的这3种方法,对设计的功能进行仿真,掌握好这一章的内容以便完成接下来的算法设计。
3.2 图片数据的获取
当我们进行前期算法验证的时候,需要读取图片进行仿真,那么关键的一步就是如何加载图片进行测试,在HLS中比较基础的两种加载图片的方法如下:
第一种,通过cvLoadImage函数加载图片
cvLoadImage函数
格式:
通过cvLoadImage函数加载图片格式如下
IplImage* src = cvLoadImage(INPUT_IMAGE);
cvShowImage("src",src);
函数原型:
IplImage* cvLoadImage(const char*filename,int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR));
filename :要被读入的文件的文件名(包括后缀);
iscolor:指定读入图像的颜色和深度;
指定的颜色可以将输入的图片转为3信道(CV_LOAD_IMAGE_COLOR),单信道(CV_LOAD_IMAGE_GRAYSCALE),或者保持不变(CV_LOAD_IMAGE_ANYCOLOR)。
使用方法:
cvLoadImage函数使用方法有下面几种
cvLoadImage( filename, -1 ); 默认读取图像的原通道数
cvLoadImage( filename, 0 ); 强制转化读取图像为灰度图
cvLoadImage( filename, 1 ); 读取彩色图
示例
我们在这里演示一个通过cvLoadImage函数读取图片显示的例子,源码及结果如下图:
IplImage* src = cvLoadImage(INPUT_IMAGE);
IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);//获取原始图像大小
AXI_STREAM src_axi;
IplImage2AXIvideo(src, src_axi);
AXIvideo2IplImage(src_axi, dst);
cvSaveImage(OUTPUT_IMAGE, dst);
cvShowImage( "result_1080p",dst);
第二种,通过imread函数读取图片
imread函数
格式:通过imread函数读取图片,格式如下
Mat src_rgb = imread(INPUT_IMAGE);
IplImage src = src_rgb;
cvShowImage("src",&src);
函数原型:
在官方文档中查到imread函数原型如下:
CV_EXPORTS_W Mat imread( const string& filename, int flags=1 );
参数1:const string&类型的filename,填我们需要载入的图片路径名。
参数2:int类型的flags,为载入标识,它指定一个加载图像的颜色类型。
可以看到它自带缺省值1.所以有时候这个参数在调用时我们可以忽略,在看了下面的讲解之后,我们就会发现,如果在调用时忽略这个参数,就表示载入三通道的彩色图像。通过转到定义,我们可以在highgui_c.h(192-204行)中发现这个枚举的定义是这样的:
enum
{
/* 8bit, color or not */
CV_LOAD_IMAGE_UNCHANGED =-1,
/* 8bit, gray */
CV_LOAD_IMAGE_GRAYSCALE =0,
/* ?, color */
CV_LOAD_IMAGE_COLOR =1,
/* any depth, ? */
CV_LOAD_IMAGE_ANYDEPTH =2,
/* ?, any color */
CV_LOAD_IMAGE_ANYCOLOR =4
};
示例:
我们通过imread函数读取一副图片并且灰度显示的代码如下:
Mat src_rgb = imread(INPUT_IMAGE,CV_LOAD_IMAGE_GRAYSCALE);//加载图片并灰度显示
IplImage src = src_rgb;
cvSaveImage(OUTPUT_IMAGE, &src);
cvShowImage("src",&src);
3.3 视频流文件的载入
cvCaptureFromAVI函数
格式:cvCaptureFromAVI("AVI文件名称");
功能:函数进行视频文件的载入,用来播放AVI文件视频;
定义:在highgui_c.h文件可以看到有如下定义:
#define cvCaptureFromFile cvCreateFileCapture
#define cvCaptureFromAVI cvCaptureFromFile
说明:所以用cvCaptureFromAVI()跟cvCaptureFromFile(),cvCreateFileCapture()都是一样的作用;文件的类型不一定必须是AVI格式,只要文件符合OpenCV支持的格式就能播放。
cvGrabFrame函数
格式:int cvGrabFrame(CvCapture结构体);
功能:将capture抓下來的相片放在OpenCV中;其与cvQueryFrame()是相同的步骤;
cvGrabFrame()返回值为0或1;0是失败,1是成功。
cvRetrieveFrame函数
格式:cvRetrieveFrame(CvCapture结构);
功能:从OpenCV快取中得到Frame,并配置给IplImage结构体;其中:
cvQueryFrame()=cvGrabFrame()+cvRetrieveFrame().
示例
我们通过一个实例让大家理解这几个函数的使用
IplImage *frame;
CvCapture *capture = cvCaptureFromAVI("1.avi");//获取视频数据
cvNamedWindow("AVI player",0);
while(true)
{
if(cvGrabFrame(capture))
{
frame = cvRetrieveFrame(capture);
cvShowImage("AVI player",frame);
if(cvWaitKey(10)>=0) break;
}
}
通过运行仿真,我们截取的视频画面如下:
3.4 外部摄像头的调用
cvCaptureFromCAM函数
格式:CvCapture*cvCaptureFromCAM( int index );
参数:index,要使用的摄像头索引。
cvReleaseCapture函数
功能:释放(cvCaptureFromCAM)这个结构,使用函数cvReleaseCapture。
cvWriteFrame函数
功能:要将视频写入文件中,使用cvWriteFrame写入一帧到一个视频文件中
格式:int cvWriteFrame( CvVideoWriter* writer, const IplImage* image );
示例:
通过摄像头捕获视频数据的关键代码如下,并且通过调用外部USB摄像头成功采集到视频数据,为后期算法验证提供了测试依据。
IplImage *frame;
CvCapture *capture = cvCaptureFromCAM(1);//捕获摄像头数据0--笔记本自带摄像头 1--外部摄像头
3.5 工程创建与验证
上面介绍完了仿真数据流的获取方法之后,接下来我们创建一个工程对其进行验证。
Step1:打开Vivado HLS开发工具,单击Creat New Project创建一个新工程,设置好工程路径和工程名,一直点击Next按照默认设置。
Step2:出现如下图所示界面,时钟周期Clock Period按照默认10ns,Uncertaintly和Solution Name均按照默认设置,点击红色圆圈部分选择芯片类型,然后点击OK。
MZ7XA-7020、MZXB开发板型号选择设置
MZ7XA -7010、MZ7XA -MINI7010开发板型号选择设置
Step3:点击Finish,出现如下界面。右单击Source,选择New file,添加一个设计源文件。
Step4:与上一章不同的是,本章只要进行仿真,因此直接单击Test Bench,添加一个名为Test.cpp的测试文件,并添加如下程序。
#include "hls_opencv.h" #include "top.h" #include "opencv_top.h"
using namespace cv;
#define INPUT_IMAGE "test_1080p.bmp" #define OUTPUT_IMAGE "result_1080p.bmp"
int main (int argc, char** argv) { //方法1 cvLoadImage函数加载图片 IplImage* src = cvLoadImage(INPUT_IMAGE); IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);//获取原始图像大小
AXI_STREAM src_axi, dst_axi; IplImage2AXIvideo(src, src_axi); //image_filter(src_axi, dst_axi, src->height, src->width); AXIvideo2IplImage(src_axi, dst);
cvSaveImage(OUTPUT_IMAGE, dst); cvShowImage( "result_1080p",dst); cvReleaseImage(&src);
cvWaitKey();
/* //方法2 cvLoadImage函数加载图片 Mat src_rgb = imread(INPUT_IMAGE,CV_LOAD_IMAGE_GRAYSCALE);//加载图片并灰度显示
IplImage src = src_rgb; cvSaveImage(OUTPUT_IMAGE, &src); cvShowImage("src",&src); waitKey(0); return 0; */
/* //读取视频文件 IplImage *frame; CvCapture *capture = cvCaptureFromAVI("1.avi");//获取视频数据 cvNamedWindow("AVI player",0); while(true) { if(cvGrabFrame(capture)) { frame = cvRetrieveFrame(capture); cvShowImage("AVI player",frame); if(cvWaitKey(10)>=0) break; } else { break; } } cvReleaseCapture(&capture); cvDestroyWindow("AVI player");
return 0; */ /* //摄像头操作 IplImage *frame; CvCapture *capture = cvCaptureFromCAM(1);//捕获摄像头数据0--笔记本自带摄像头 1--外部摄像头 cvNamedWindow("AVI player",0); while(true) { if(cvGrabFrame(capture)) { frame = cvRetrieveFrame(capture);
cvShowImage("AVI player",frame); if(cvWaitKey(10)>=0) break; } else { break;//没有采集到视频数据退出 } } cvReleaseCapture(&capture); cvDestroyWindow("AVI player");
return 0; */ } |
在这个程序中,我们把前3节的程序都写到了同一个函数当中,在程序中已经给出了注释,在仿真过程中可以将不必要的代码通过注释的方法屏蔽,分别对这三个部分进行测试。
Step5:将要测试的文件添加进Test Bench中(文件在我们提供的源程序文件夹中的image文件夹中可以找到),添加方法是选中Test Bench右单击然后选择Add File命令。
AVI视频显示
摄像头显示(可以使用笔记本的内置摄像头,或者外置USB摄像头进行测试,下图是使用外置摄像头进行测试)