OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4217|回复: 0

[XILINX] 【正点原子FPGA连载】第七章 OV5640摄像头Sobel边缘检测--摘自【正点原子】领航者ZYNQ之HLS开发指南V1.1

[复制链接]

1118

主题

1129

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4671
金钱
4671
注册时间
2019-5-8
在线时间
1224 小时
发表于 2020-8-28 17:16:46 | 显示全部楼层 |阅读模式
本帖最后由 正点原子01 于 2020-8-28 17:16 编辑

1)实验平台:正点原子领航者ZYNQ开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html
4)对正点原子FPGA感兴趣的同学可以加群讨论:905624739 点击加入群聊
5)关注正点原子公众号,获取最新资料更新
1.jpg
1120.png

第七章OV5640摄像头Sobel边缘检测

     边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。在本章我们将通过OV5640摄像头Sobel边缘检测实验,来学习如何使用Vivado HLS工具生成实现Sobel边缘检测算法的IP核,以及在Vivado中对综合结果进行验证的流程。
本章包括以下几个部分:        
1.1        Sobel边缘检测简介
1.2        实验任务
1.3        HLS设计
1.4        IP验证
1.5        下载验证
1.1 Sobel边缘检测简介
    所谓边缘是指其周围像素灰度急剧变化的那些象素的集合,它是图像最基本的特征。边缘存在于目标、背景和区域之间,所以,它是图像分割所依赖的最重要的依据。由于边缘是位置的标志,对灰度的变化不敏感,因此,边缘也是图像匹配的重要的特征。
    边缘检测和区域划分是图像分割的两种不同的方法,二者具有相互补充的特点。在边缘检测中,是提取图像中不连续部分的特征,根据闭合的边缘确定区域。而在区域划分中,是把图像分割成特征相同的区域,区域之间的边界就是边缘。由于边缘检测方法不需要将图像逐个像素地分割,因此更适合大图像的分割。边缘大致可以分为两种,一种是阶跃状边缘,边缘两边像素的灰度值明显不同;另一种为屋顶状边缘,边缘处于灰度值由小到大再到小的变化转折点处。边缘检测的主要工具是边缘检测模板。边缘检测的有很多,典型的有索贝尔算子、普里维特算子、罗伯茨交叉边缘检测等边缘检测技术,在本章设计中采用的是索贝尔算子。
索贝尔算子算法简介:
    索贝尔算子(Sobeloperator)主要用作边缘检测,在技术上,它是一离散性差分算子,用来运算图像亮度函数的灰度之近似值。在图像的任何一点使用此算子,将会产生对应的灰度矢量或是其法矢量。
Sobel卷积因子为:
image002.png

7.1.1 Sobel卷积因子
    该算子包含两组 3x3 的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以 A 代表原始图像, Gx 及 Gy 分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:
image004.png

7.1.2 横向及纵向的图像灰度值计算公式
    图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:
image006.png

7.1.3 像素的灰度值计算公式
通常,为了提高效率 使用不开平方的近似值,但这样做会损失精度,迫不得已的时候可以如下这样子:

image005.png

图 7.1.4 像素灰度值的近似计算公式
如果梯度G大于某一阀值,则认为该点(x,y)为边缘点。
1.2 实验任务
    本节的实验任务是使用VivadoHLS工具设计实现Sobel边缘检测算法的IP核,并在Vivado中对设计出来的IP核进行验证。
1.3 HLS设计
    我们在电脑中的“F:\ZYNQ\High_Level_Synthesis”目录下新建一个名为ov5640_sobel的文件夹,作为本次实验的工程目录。然后打开Vivado HLS工具,创建一个新的工程。设置工程名为“ov5640_sobel”,选择工程路径为刚刚创建的文件夹。需要注意的是,工程名以及路径只能由英文字母、数字和下划线组成,不能包含中文、空格以及其他特殊字符。如下图所示:
image008.jpg

7.3.1 工程配置界面
设置好工程名及路径之后,点击“Next”,进入如下界面设置顶层函数:
image010.jpg

7.3.2 设置顶层函数
    工程创建完成后,在工程面板中的“source”目录上点击右键,然后在打开的列表中选择“New File”新建源文件,在弹出的对话框中输入源文件的名称“ov5640_sobel.cpp”,如图1.3.3所示。源文件默认的保存路径为HLS工程目录,为方便源文件的管理,我们在工程目录下新建一个名为“src”的文件下,将源文件保存在src目录下。
image012.jpg

7.3.3 输入源文件名
我们输入的源文件的后缀名为“.cpp”,即使用C++语言进行设计。这是因为我们要使用Vivado HLS视频库,那么就只能使用C++来进行设计。
“ov5640_sobel.cpp”文件源代码如下:
  1.   #include "ov5640_sobel.h"
  2.   
  3.   voidov5640_sobel(AXI_STREAM&INPUT_STREAM,
  4.                    AXI_STREAM& OUTPUT_STREAM,
  5.                     introws,
  6.                     intcols
  7.                    ){
  8.   
  9.   #pragma HLSINTERFACE axis port=INPUT_STREAM
  10. #pragma HLS INTERFACE axis port=OUTPUT_STREAM
  11. #pragma HLS INTERFACE s_axilite port=rows
  12. #pragma HLS INTERFACE s_axilite port=cols
  13. #pragma HLS INTERFACE ap_ctrl_none port=return
  14. #pragma HLS dataflow

  15.      //hls::mat格式变量
  16.      RGB_IMAGE  img_0(rows,cols);
  17.      GRAY_IMAGE img_1(rows,cols);
  18.     GRAY_IMAGE img_2(rows,cols);
  19.      RGB_IMAGE  img_3(rows,cols);

  20.      //将AXI4 Stream数据转换成hls::mat格式
  21.      hls::AXIvideo2Mat(INPUT_STREAM,img_0);

  22.      //将RGB888格式的彩色数据转换成灰度数据
  23.      hls::CvtColor<HLS_RGB2GRAY,HLS_8UC3,HLS_8UC1>(img_0,img_1);

  24.      //将灰度数据与Sobel算子卷积
  25. 29     hls::Sobel<1,0,3>(img_1,img_2);
  26. 30
  27. 31     //将灰度数据转换成三个通道的灰度图像
  28.      hls::CvtColor<HLS_GRAY2RGB,HLS_8UC1,HLS_8UC3>(img_2,img_3);

  29.      //将hls::mat格式数据转换成AXI4 Stream格式
  30.      hls::Mat2AXIvideo(img_3,OUTPUT_STREAM);
  31. }
复制代码
    本章实验的实验代码与《领航者ZYNQ之HLS开发指南》第5章“OV5640摄像头灰度显示实验”类似,不同之处是本章实验代码增加了一个边缘检测函数“Sobel”。代码的其他部分可以参考《领航者ZYNQ之HLS开发指南》第5章“OV5640摄像头灰度显示实验”。
在代码的第29行调用HLS命名空间中的“Sobel”函数,这个函数在UG902中的介绍如下图所示:
image014.jpg

7.3.4 sobel函数
    图中的“Synopsis”是概要的意思。从图中可以看出Vivado HLS视频库中定义了两个Soebl函数,这个是C++中函数重载的概念,编译器根据函数模板输入参数的不同,选择调用相应的函数。图中的“template”是函数模板的概念,它通过将类型作为参数传递给模板,可使编译器生成该类型的函数。图中        的“XORDER”和“YORDER”这两个参数可以设置采用水平方向或垂直方向的Sobel算子,Vivado HLS只支持“XORDER=1,YORDER=0”(指采用水平方向的Sobel算子)或者“XORDER=0,YORDER=1”(指采用垂直方向的Sobel算子)的设置。在本章实验中我们设置“XORDER=1,YORDER=0”表示采用水平方向的Sobel算子进行X轴方向的边缘检测。图中的“SIZE”表示设置Sobel算子模板的大小,Vivado HLS支持设置Sobel算子的大小为3、5、7。本章实验我们设置Sobel算法的大小为3,表示采用3*3的Sobel算子模板。图中的“BORDERMODE”表示设置边界的类型,由于本章我们没有传入边界类型的参数,所以编译器调用了第二个Sobel函数。图中的“SRC_T”表示输入图像的类型,图中的“DST_T”表示输出图像的类型,这里输入和输出图像都是8位无符号单通道数据类型。图中的“ROWS”和“COLS”表示输入图像像素的行和列,图中的“DROWS”和“DCOLS”表示输出图像像素的行和列。
“ov5640_sobel.h”头文件代码如下:
  1. #ifndef _OV5640_SOBEL_H
  2. #define _OV5640_SOBEL_H

  3. #include "hls_video.h"

  4. #define MAX_HEIGHT 1080    //图像最大高度
  5. #define MAX_WIDTH  1920    //图像最大宽度

  6. #define INPUT_IMAGE     "lena.jpg"
  7. #define OUTPUT_IMAGE    "lena_sobel.jpg"

  8. typedef hls::stream<ap_axiu<24,1,1,1> >    AXI_STREAM;
  9. typedef hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC3>   RGB_IMAGE;
  10. typedef hls::Mat<MAX_HEIGHT,MAX_WIDTH,HLS_8UC1> GRAY_IMAGE;

  11. void ov5640_sobel(AXI_STREAM& INPUT_STREAM,
  12.                    AXI_STREAM& OUTPUT_STREAM,
  13.                    int rows,
  14.                   int cols
  15.                   );

  16. #endif
复制代码
    在代码的第1行和第2行是为了防止头文件的重复定义。在代码的第4行引入了“hls_opencv.h”头文件是为了使用Vivado HLS工具给我们提供的数据类型。在代码的第6行和代码的第7行定义了图像的最大高度和宽度。在代码的第9行定义了输入图像是“lena.jpg”,在代码的第10行定义了输出图像是“lena_sobel.jpg”。在代码的第12行定义了AXI_STREAM格式的数据类型,第一个参数24表示我们采用的数据是24位宽。在代码的第13行和第14行分别定义了“RGB_IMAGE”和“GRAY_IMAGE”格式的数据类型。在代码的第16行“ov5640_sobel”是函数的声明。
    当工程比较复杂的时候,可以进行C代码仿真。C代码仿真的步骤如下:在工程面板中的“Test Bench”目录上点击右键,在打开的列表中选择“New File”新建源文件,然后在弹出的对话框中输入测试文件的名称“ov5640_sobel_tb.cpp”,为方便测试文件的管理我们将测试文件保存在src目录下,如下图所示:
image016.jpg

7.3.5 测试文件目录
“ov5640_sobel_tb.cpp”程序如下所示:
  1.   #include "ov5640_sobel.h"
  2.   #include "hls_opencv.h"
  3.   
  4.   intmain(void)
  5.   {
  6.       //获取图像数据
  7.       IplImage*src = cvLoadImage(INPUT_IMAGE);
  8.       IplImage*dst = cvCreateImage(cvGetSize(src),src->depth, src->nChannels);
  9.   
  10.      //使用HLS库进行处理
  11.      AXI_STREAMsrc_axi, dst_axi;
  12.     IplImage2AXIvideo(src, src_axi);
  13.      ov5640_sobel(src_axi,dst_axi, src->height,src->width);
  14.     AXIvideo2IplImage(dst_axi, dst);

  15.      //保存图像
  16.     cvSaveImage(OUTPUT_IMAGE,dst);

  17.     //显示图像
  18.     cvShowImage(INPUT_IMAGE,src);
  19.      cvShowImage(OUTPUT_IMAGE,dst);

  20.      //等待用户按下键盘上的任一按键
  21.      cv::waitKey(0);

  22. }
复制代码
    在代码的第2行引入了“hls_opencv.h”,这个头文件里面包含了opencv库。在代码的第4行定义了main函数,在代码的第7行调用“cvLoadImage”函数来载入输入图像。在代码的第8行      调用“cvCreateImage”来创建输出图像,参数“cvGetSize(src)”表示创建和输入图像一样大小的输出图像,参数“src->channel”表示创建的输出图像的通道和输入图像一样也是三通道  的。在代码的第11行定义了两个变量“src_axi”和“dst_axi”,这两个变量的数据类型是AXI_STREAM格式。在代码的第12行通过调用IplImage2AXIvideo函数来将opencv中的IplImage格式的图像数据类型转换成AXI4-Stream格式的图像数据流从而可以利用FPGA进行数据处理。在代码的第13行调用“ov5640_sobel”函数来将对图像进行sobel边缘处理。在代码的第14行调用      AXIvideo2IplImage将Sobel边缘处理后的图像转换成opencv可以处理的数据类型。在代码的第17行通过调用cvSaveImage来保存Sobel边缘处理后的图像。在代码的第20行和第21行通过调用cvShowImage来显示原图像和边缘处理后的图像。在代码的第24行通过调用waitKey这个函数来等待用户输入,从而避免程序运行完成,图像一闪而过。
    下面进行C仿真,将“lena.jpg”图像加入到测试平台,在工程面板中的“Test bench”目录上点击右键,然后在打开的列表中选择“New File”新建源文件,为方便测试文件的管理我们将“lena.jpg”保存在src目录下,如下图所示:
image018.jpg

7.3.6 lena图片目录
点击“Run CSimulation”按钮,如下图所示:
image020.jpg

7.3.7 C仿真
上图中左边红框标出来的就是我们加入的输入图像,右边红框即为C仿真按钮。仿真结果如下图所示:
image022.jpg
图 7.3.8 仿真结果
从仿真结果中可以看出我们实现了X轴方向的Sobel边缘检测。
接下来点击工具栏中向右的绿色三角形对C代码进行综合,如下图所示:
image024.jpg

7.3.7 运行C综合
综合完成后,会自动打开综合结果(solution)的报告,综合报告中给出了设计的性能评估、资源评估以及接口等信息。本次实验中,我们重点关注综合工具为我们生成的接口信息,如下图所示:
image026.jpg

7.3.8 接口信息
    从图中可以看出,设计综合出了一个“AXI4-Lite”从接口和两个“AXI4-Stream”接口(一个输入,一个输出)。其中“AX4-Lite”总线接口用于控制视频处理的分辨率,而两个“AXI4-Stream”总线接口分别用于输入待处理的视频以及输出处理之后的视频流。
在综合结果正确的情况下,在工具栏中点击黄色的“田”字按钮,导出RTL。
    在导出RTL结束之后,我们到工程目录所指向的文件夹中可以看到以ZIP压缩文件形式存在的IP核,如下图所示:
image028.jpg

7.3.9 将设计导出成IP
      HLS设计结束之后,我们将在Vivado中对导出的IP核进行验证。
1.4 IP验证
     在IP验证环节,我们会使用Vivado工具的IP集成器将生成的IP核添加到Block Design中,然后完成设计后将程序下载到领航者开发板上进行验证。
用于IP验证的底层硬件可以在《领航者ZYNQ之HLS开发指南》第5章“OV5640 摄像头灰度显示”实验的基础上进行。打开该实验所对应的Vivado工程“ov5640_rgb2gray_ip_test”,将其另存为“ov5640_sobel_ip_test”工程。为了方便工程管理,我们将Vivado工程的目录与HLS工程目录保持一致,如下图所示:
image030.jpg

7.4.1 创建Vivado工程
    在通过“另存为”的方式保存工程之后,还要将原来工程中的IP库(名为ip_repo的文件夹)复制到新的Vivado工程目录下, 然后将HLS设计过程中导出的IP核拷贝到“ip_repo”目录下并解压,解压完成后如下图所示:
image032.jpg

7.4.2 拷贝并解压IP
     在Vivado中重新将当前工程目录下的ip_repo文件夹添加到工程的IP库中,然后将HLS生成的IP核Ov5640_sobel添加到Block Design中,并将其STREAM接口分别连接到Video In to AXI4-Stream模块的video_out接口与VDMA模块的S_AXIS_S2MM接口上。最后点击上图中左上角的“Run Connection Automation”,让工具自动连接该IP核的其他端口,包括时钟、复位以及AXI-Lite从接口,[url=]最终[/url][A1] 完成的设计如下图所示:
image034.jpg

7.4.4 完成后的Block Design
    到这里我们的BlockDesign就设计完成了,在Diagram窗口空白处右击,然后选择“Validate Design”验证设计。验证完成后弹出对话框提示“ValidationSuccessful”表明设计无误,点击“OK”确认。最后按快捷键“Ctrl + S”保存设计。
    接下来在Source窗口中右键点击Block Design设计文件“system.bd”,然后依次执行“Generate Output Products”和“Create HDLWrapper”。
    最后在左侧FlowNavigator导航栏中找到PROGRAM AND DEBUG,点击该选项中的“Generate Bitstream”,对设计进行综合、实现、并生成Bitstream文件。
    在生成 Bitstream 之后,在菜单栏中选择 File > Export > Export hardware 导出硬件,并在弹出的对话框 中,勾选“Include bitstream”。然后在菜单栏选择 File >Launch SDK,启动 SDK 软件。
在Vivado SDK中新建空的应用工程,工程名为“ov5640_sobel_lcd”。
然后找到《领航者ZYNQ之嵌入式开发指南》第二十三章“OV5640 摄像头 LCD 显示”实验的Vivado工程目录,将“21_ov7725_lcd\ov7725_lcd.sdk\ov7725_lcd”目录下的src文件夹拷贝到新建的应用工程目录下。
在SDK中刷新src目录,然后将“main.c”的代码修改为如下所示:
  1.   #include <stdio.h>
  2.   #include <stdlib.h>
  3.   #include <string.h>
  4.   #include "xil_types.h"
  5.   #include "xil_cache.h"
  6.   #include "xparameters.h"
  7.   #include "xgpio.h"
  8.   #include "xaxivdma.h"
  9.   #include "xaxivdma_i.h"
  10. #include "display_ctrl/display_ctrl.h"
  11. #include "vdma_api/vdma_api.h"
  12. #include "emio_sccb_cfg/emio_sccb_cfg.h"
  13. #include "ov5640/ov5640_init.h"
  14. #include "xov5640_sobel.h"

  15. //宏定义
  16. #define BYTES_PIXEL        3                           //像素字节数,RGB888占3个字节
  17. #define FRAME_BUFFER_NUM   3                           //帧缓存个数3
  18. #define DYNCLK_BASEADDR   XPAR_AXI_DYNCLK_0_BASEADDR  //动态时钟基地址
  19. #define VDMA_ID           XPAR_AXIVDMA_0_DEVICE_ID    //VDMA器件ID
  20. #define DISP_VTC_ID       XPAR_VTC_0_DEVICE_ID        //VTC器件ID
  21. //PL端 AXI GPIO 0(lcd_id)器件 ID
  22. #define AXI_GPIO_0_ID     XPAR_AXI_GPIO_0_DEVICE_ID   
  23. //使用AXI GPIO(lcd_id)通道1
  24. #define AXI_GPIO_0_CHANEL  1                           

  25. //全局变量
  26. //frame buffer的起始地址
  27. unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR
  28.                                           + 0x1000000);
  29. XAxiVdma         vdma;
  30. DisplayCtrl      dispCtrl;
  31. XGpio            axi_gpio_inst;   //PL端 AXI GPIO 驱动实例
  32. XOv5640_sobel    sobel_inst;   //PL端XOv5640_sobel驱动实例
  33. VideoMode        vd_mode;
  34. unsigned int lcd_id;

  35. int main(void)
  36. {
  37.       u32 status;
  38.       u16 cmos_h_pixel;   //ov56 DVP 输出水平像素点数
  39.       u16 cmos_v_pixel;   //ov5640 DVP 输出垂直像素点数
  40.       u16 total_h_pixel;  //ov5640 水平总像素大小
  41.       u16 total_v_pixel;  //ov5640 垂直总像素大小

  42.       //获取LCD的ID
  43.       XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_0_ID);
  44.       lcd_id = LTDC_PanelID_Read(&axi_gpio_inst,AXI_GPIO_0_CHANEL);
  45.       xil_printf("lcd_id= %x\n\r",lcd_id);

  46.       //根据获取的LCD的ID号来进行ov5640显示分辨率参数的选择
  47.       switch(lcd_id){
  48.           case 0x4342 :  //4.3寸屏,480*272分辨率
  49.               cmos_h_pixel = 480;
  50.               cmos_v_pixel = 272;
  51.               total_h_pixel = 1800;
  52.               total_v_pixel = 1000;
  53.               break;
  54.           case 0x4384 :  //4.3寸屏,800*480分辨率
  55.               cmos_h_pixel = 800;
  56.               cmos_v_pixel = 480;
  57.               total_h_pixel = 1800;
  58.               total_v_pixel = 1000;
  59.               break;
  60.           case 0x7084 :  //7寸屏,800*480分辨率
  61.               cmos_h_pixel = 800;
  62.               cmos_v_pixel = 480;
  63.               total_h_pixel = 1800;
  64.               total_v_pixel = 1000;
  65.               break;
  66.           case 0x7016 :  //7寸屏,1024*600分辨率
  67.               cmos_h_pixel = 1024;
  68.               cmos_v_pixel = 600;
  69.               total_h_pixel = 2200;
  70.               total_v_pixel = 1000;
  71.               break;
  72.           case 0x1018 :  //10.1寸屏,1280*800分辨率
  73.               cmos_h_pixel = 1280;
  74.               cmos_v_pixel = 800;
  75.               total_h_pixel = 2570;
  76.               total_v_pixel = 980;
  77.               break;
  78.          default :
  79.              cmos_h_pixel = 480;
  80.               cmos_v_pixel = 272;
  81.               total_h_pixel = 1800;
  82.               total_v_pixel = 1000;
  83.               break;
  84.       }

  85.       emio_init();                         //初始化EMIO
  86.       status = ov5640_init( cmos_h_pixel,  //初始化ov5640
  87.                             cmos_v_pixel,
  88.                            total_h_pixel,
  89.                            total_v_pixel);
  90.       if(status == 0)
  91.           xil_printf("OV5640detected successful!\r\n");
  92.       else
  93.           xil_printf("OV5640detected failed!\r\n");

  94.      //根据获取的LCD的ID号来进行video参数的选择
  95.      switch(lcd_id){
  96.          case 0x4342 : vd_mode =VMODE_480x272;  break;  //4.3寸屏,480*272分辨率
  97.          case 0x4384 : vd_mode =VMODE_800x480;  break;  //4.3寸屏,800*480分辨率
  98.          case 0x7084 : vd_mode =VMODE_800x480;  break;  //7寸屏,800*480分辨率
  99.          case 0x7016 : vd_mode =VMODE_1024x600; break;  //7寸屏,1024*600分辨率
  100.          case 0x1018 : vd_mode =VMODE_1280x800; break;  //10.1寸屏,1280*800分辨率
  101.          default : vd_mode = VMODE_800x480; break;
  102.      }

  103.      //初始化灰度转换IP核OV5640_sobel
  104.      XOv5640_sobel_Initialize(&sobel_inst, XPAR_OV5640_SOBEL_0_DEVICE_ID);
  105.      //配置灰度转换IP核OV5640_sobel的行数
  106.      XOv5640_sobel_Set_rows(&sobel_inst, vd_mode.height);
  107.      //配置灰度转换IP核OV5640_sobel的列数
  108.      XOv5640_sobel_Set_cols(&sobel_inst, vd_mode.width);

  109.      //配置VDMA
  110.      run_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,
  111.                              frame_buffer_addr,0,0,BOTH);
  112.      //初始化Display controller
  113.      DisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);
  114.      //设置VideoMode
  115.      DisplaySetMode(&dispCtrl, &vd_mode);
  116.      DisplayStart(&dispCtrl);

  117.      return 0;
  118. }
复制代码
    在代码的第14行引入了“xov5640_sobel.h”头文件,这个头文件是Vivado HLS工具生成的,里面声明了灰度转换IP核的驱动函数。首先在代码的34行定义了边缘检测IP核的驱动实例sobel_inst,该变量会在后面对IP核进行配置时用到。然后在代码的第112行通过“XOv5640_sobel_Initialize()”函数来初始化Vivado HLS生成的边缘检测IP核;在代码的第116行通过传入“vd_mode.height”形参来设置灰度转换IP核的行数,在代码的第114行通过传入“vd_mode.width”形参来设置列数。这些数据类型和函数在“xlcd_rgb_color.h”头文件中均有声明。
1.5 下载验证
    编译完工程之后我们就可以开始下载程序了。将 OV5640 摄像头模块插在领航者 Zynq 开发板的“OLED/CAMERA”插座上,并将 LCD 的排线接头插入开发板上的 LCD 接线座。将下载器一端连电脑,另一端与开发板上的 JTAG 端口连接,连接电源线并打开电源开关。
    在 SDK 软件下方的 SDK Terminal 窗口中点击右上角的加号设置并连接串口。然后下载本次实验硬件设计过程中所生成的 BIT 文件,来对 PL 进行配置。最后下载软件程序,下载完成后在LCD上就可以看到摄像头采集的彩色图像被转换成了X方向的灰度图像,如下图所示:
image036.jpg

7.5.1 Sobel边缘检测



正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 19:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表