搜索
bottom↓
回复: 0

【正点原子FPGA连载】第四十六章基于OV5640的二值化实验

[复制链接]

出0入234汤圆

发表于 2020-12-10 10:47:16 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2021-1-23 15:31 编辑

1)实验平台:正点原子达芬奇FPGA开发板
2)  章节摘自【正点原子】达芬奇之FPGA开发指南
3)购买链接:https://detail.tmall.com/item.htm?id=624335496505
4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz_dafenqi.html
5)正点原子官方B站:https://space.bilibili.com/394620890
6)对正点原子FPGA感兴趣的同学可以加群讨论:
905624739 点击加入: QQ群头像.png

100846rel79a9p4uelap24.jpg

100846f1ce1fg14zbg0va4.png

第四十六章基于OV5640的二值化实验



在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,还能凸显出目标的轮廓。图像二值化在计算机视觉、图像分割以及人工智能等方面有着广泛应用。在本章节将进行基于OV5640的二值化实验。
本章包括以下几个部分:
4646.1简介
46.2实验任务
46.3硬件设计
46.4程序设计
46.5下载验证

46.1简介
图像二值化(Image Binarization)就是将图像上的像素点的灰度值设置为最大(白色)或最小(黑色),也就是将整个图像呈现出明显的黑白效果的过程。这里以8bit表示的灰度图像为例(灰度值的范围为0~255),二值化就是通过选取适当的阈值,与图像中的256个亮度等级进行比较。亮度高于阈值的像素点设置为白色(255),低于阈值的像素点设置为黑色(0),从而明显地反映出图像的整体和局部特征。
在数字图像处理中,二值图像占有非常重要的地位,特别是在实时的图像处理中,通过二值图像来构成的系统有很多。要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样有利于在对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值用255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。
实现二值化有两种方法,一种是手动指定一个阈值,通过阈值来进行二值化处理;另一种是一个自适应阈值二值化方法(OTSU算法和Kittle算法等)。使用第一种方法计算量小速度快,但在处理不同图像时颜色分布差别很大;使用第二种方法适用性强,能直接观测出图像的轮廓,但计算相对更复杂。本章节实验将使用第一种方法来实现图像的二值化。
如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用制定阈值的方法,可以得到比较有效的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阈值选取技术来分割该图像。
46.2实验任务
本节实验任务是在达芬奇开发板上使用OV5640摄像头采集RGB565数据,将数据转化成Ycbcr格式,然后进行灰度二值化,并通过HDMI显示。
46.3硬件设计
本章节中硬件设计与“OV5640摄像头HDMI显示实验”完全相同,此处不再赘述。
46.4程序设计
根据实验任务,首先设计如图 46.4.1所示的系统框图,本章实验的系统框架延续了“OV5640摄像头HDMI灰度显示实验”的整体架构。本次实验包括以下模块:时钟模块、图像分辨率设置模块、DDR控制器模块、摄像头驱动模块、图像处理模块和HDMI顶层模块。其中时钟模块、DDR控制器模块、HDMI顶层模块、图像分辨率设置模块和摄像头驱动模块没有做任何修改,这些模块在“OV5640摄像头HDMI显示实验”中已经说明过,这里不再详述,本次实验只对图像处理模块做了修改。
OV5640的二值化实验系统框图如下图所示:
基于OV5640的二值化实验1359.png

图 46.4.1 顶层系统框图

由上图可知,时钟模块(clk_wiz_0)为HDMI顶层模块、DDR控制模块以及OV5640驱动模块提供驱动时钟。OV5640驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后将采集到的数据写入图像处理模块。图像处理模块将摄像头数据进行处理后存入DDR控制模块。顶层模块从DDR控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在DDR3和传感器都初始化完成之后才开始输出数据的,避免了在DDR3初始化过程中向里面写入数据。
顶层模块的原理图如下图所示:
基于OV5640的二值化实验1683.png

图 46.4.2 顶层模块原理图

FPGA顶层模块(ov5640_hdmi_img_binarization)例化了以下五个模块:时钟模块(clk_wiz_0)、OV5640驱动模块(ov5640_dri)、图像处理模块(vip)、DDR控制模块(ddr3_top)和HDMI顶层模块(hdmi_top)。     
时钟模块(clk_wiz_0):时钟模块通过调用MMCM IP核实现,共输出4个时钟,频率分别为200Mhz(DDR3参考时钟)、50Mhz时钟、65Mhz时钟和325M时钟(HDMI像素时钟的5倍频)。200Mhz时钟作为DDR控制模块的参考时钟,由MIG IP核产生的ui_clk(本次设计为100Mhz)作为DDR控制模块的驱动时钟,50Mhz时钟作为OV5640驱动模块驱动时钟,65Mhz时钟和325M时钟(HDMI像素时钟的5倍频)负责驱动HDMI顶层模块。
OV5640驱动模块(ov5640_dri):OV5640驱动模块负责驱动OV5640 SCCB接口总线,将像素时钟驱动下的传感器输出的场同步信号、行同步信号以及8位数据转换成DDR读写控制模块的写使能信号和16位写数据信号,完成对OV5640传感器图像的采集。
图像处理模块(vip):对采集后的图像数据进行处理,并将处理后的数据存入DDR控制模块。
DDR控制模块(ddr3_top):DDR读写控制器模块负责驱动DDR片外存储器,缓存图像传感器输出的图像数据。该模块将MIG IP核复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。
有关DDR控制模块的详细介绍请大家参考“OV7725摄像头RGB-LCD显示实验”章节。
HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供显示器参数、场同步信号和数据请求信号。关HDMI顶层模块的详细介绍请大家参考“OV5640摄像头HDMI显示实验”章节。
VIP模块框图如下图所示:

基于OV5640的二值化实验2603.png

图 46.4.3 vip模块框图

vip模块例化了RGB转YCbCr模块(rgb2ycbcr)、中值滤波模块(vip_gray_median_jilter)和二值化模块(binarization)。RGB转YCbCr模块负责将摄像头采集的RGB565格式数据到转换为YUV格式的数据。中值滤波模块负责将YUV格式的视频图像进行中值滤波后输出。二值化模块负责将中值滤波后的视频图像进行二值化处理再输出。有关RGB转YCbCr模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。有关中值滤波模块的详细介绍请大家参考“基于OV5640的中值滤波实验”章节。
vip模块原理图如下图所示:
基于OV5640的二值化实验2950.png

图 46.4.4 vip模块原理图

如上图所示,摄像头采集到16位rgb565输入vip模块,经过“rgb2ycbcr”模块转化为8位的yuv444数据,然后在将转化后的灰度数据(img_y)作为“vip_gray_median_filter”模块的输入,对灰度进行中值滤波处理,再将中值滤波后的数据输入进二值化模块,对数据进行二值化处理,最后输出经过二值化处理后的灰度数据“monoc”。
图像处理模块负责图像数据的格式转换,代码如下:
  1. 1  module vip(
  2. 2      //module clock
  3. 3      input           clk            ,   // 时钟信号
  4. 4      input           rst_n          ,   // 复位信号(低有效)
  5. 5  
  6. 6      //图像处理前的数据接口
  7. 7      input           pre_frame_vsync,   
  8. 8      input           pre_frame_hsync,
  9. 9      input           pre_frame_de   ,
  10. 10     input    [15:0] pre_rgb        ,
  11. 11     input    [10:0] xpos           ,
  12. 12     input    [10:0] ypos           ,
  13. 13
  14. 14     //图像处理后的数据接口
  15. 15     output          post_frame_vsync,  // 场同步信号
  16. 16     output          post_frame_hsync,  // 行同步信号
  17. 17     output          post_frame_de   ,  // 数据输入使能
  18. 18     output   [15:0] post_rgb           // RGB565颜色数据
  19. 19
  20. 20
  21. 21 );
  22. 22
  23. 23 //wire define
  24. 24 wire   [ 7:0]         img_y;
  25. 25 wire   [ 7:0]         post_img_y;
  26. 26 wire   [15:0]         post_rgb;
  27. 27 wire                  post_frame_vsync;
  28. 28 wire                  post_frame_hsync;
  29. 29 wire                  post_frame_de;
  30. 30 wire                  pe_frame_vsync;
  31. 31 wire                  pe_frame_href;
  32. 32 wire                  pe_frame_clken;
  33. 33 wire                  ycbcr_vsync;
  34. 34 wire                  ycbcr_hsync;
  35. 35 wire                  ycbcr_de;
  36. 36 wire                  monoc;
  37. 37 //*****************************************************
  38. 38 //**                    main code
  39. 39 //*****************************************************
  40. 40
  41. 41 assign  post_rgb = {16{monoc}};
  42. 42
  43. 43 //RGB转YCbCr模块
  44. 44 rgb2ycbcr u_rgb2ycbcr(
  45. 45     //module clock
  46. 46     .clk             (clk    ),            // 时钟信号
  47. 47     .rst_n           (rst_n  ),            // 复位信号(低有效)
  48. 48     //图像处理前的数据接口
  49. 49     .pre_frame_vsync (pre_frame_vsync),    // vsync信号
  50. 50     .pre_frame_hsync (pre_frame_hsync),    // href信号
  51. 51     .pre_frame_de    (pre_frame_de   ),    // data enable信号
  52. 52     .img_red         (pre_rgb[15:11] ),
  53. 53     .img_green       (pre_rgb[10:5 ] ),
  54. 54     .img_blue        (pre_rgb[ 4:0 ] ),
  55. 55     //图像处理后的数据接口
  56. 56     .post_frame_vsync(pe_frame_vsync),     // vsync信号
  57. 57     .post_frame_hsync(pe_frame_href),      // href信号
  58. 58     .post_frame_de   (pe_frame_clken),     // data enable信号
  59. 59     .img_y           (img_y),              //灰度数据
  60. 60     .img_cb          (),
  61. 61     .img_cr          ()
  62. 62 );
  63. 63
  64. 64 //灰度图中值滤波
  65. 65 vip_gray_median_filter u_ vip_gray_median_filter (
  66. 66     .clk    (clk),   
  67. 67     .rst_n  (rst_n),
  68. 68     
  69. 69     //预处理图像数据
  70. 70     .pe_frame_vsync (pe_frame_vsync),      // vsync信号
  71. 71     .pe_frame_href  (pe_frame_href),       // href信号
  72. 72     .pe_frame_clken (pe_frame_clken),      // data enable信号
  73. 73     .pe_img_y       (img_y),               
  74. 74                                            
  75. 75     //处理后的图像数据                     
  76. 76     .pos_frame_vsync (ycbcr_vsync),        // vsync信号
  77. 77     .pos_frame_href  (ycbcr_hsync),        // href信号
  78. 78     .pos_frame_clken (ycbcr_de),           // data enable信号
  79. 79     .pos_img_y       (post_img_y)          //中值滤波后的灰度数据
  80. 80 );
  81. 81
  82. 82 //二值化模块
  83. 83 binarization  u_binarization(
  84. 84     .clk         (clk),
  85. 85     .rst_n       (rst_n),
  86. 86     //图像处理前的数据接口     
  87. 87     .ycbcr_vsync (ycbcr_vsync),
  88. 88     .ycbcr_hsync (ycbcr_hsync),
  89. 89     .ycbcr_de    (ycbcr_de),
  90. 90     .luminance   (post_img_y),
  91. 91     //图像处理后的数据接口     
  92. 92     .post_vsync  (post_frame_vsync),
  93. 93     .post_hsync  (post_frame_hsync),
  94. 94     .post_de     (post_frame_de),
  95. 95     .monoc       (monoc)                   //二值化后的数据
  96. 96 );
  97. 97 endmodule
复制代码

代码的第37行表示对二值化后的1bit灰度数据进行位拼接,形成16bit的RGB565格式的数据输出。
代码的第39行至58行是对灰度转换模块的例化,在该模块以摄像头采集的16位RGB565红、绿、蓝三原色数据作为输入数据,通过算法实现RGB到YCbCr的转换,并输出8位灰度数据,并输出数据输出使能信号。有关RGB转YCbCr模块的详细介绍请大家参考“OV5640摄像头HDMI灰度显示实验”章节。
代码的第61行至75行是对中值滤波模块的例化,该模块负责将YUV格式的视频图像进行中值滤波后输出。有关中值滤波模块的详细介绍请大家参考“基于OV5640的中值滤波实验”章节。
代码的第83行至96行是对二值化模块的例化,该模块主要是根据设定阈值,将图像化分为黑白两种颜色。
中值滤波模块和灰度转换模块在前面的章节已经讲解过,本次实验不在讲述。本次实验重点讲解二值化模块,下面是二值化模块的代码。
  1. 1  module binarization(
  2. 2      //module clock
  3. 3      input               clk             ,   // 时钟信号
  4. 4      input               rst_n           ,   // 复位信号(低有效)
  5. 5  
  6. 6      //图像处理前的数据接口
  7. 7      input               ycbcr_vsync     ,   // vsync信号
  8. 8      input               ycbcr_hsync     ,   // hsync信号
  9. 9      input               ycbcr_de        ,   // data enable信号
  10. 10     input   [7:0]       luminance       ,
  11. 11
  12. 12     //图像处理后的数据接口
  13. 13     output              post_vsync      ,   // vsync信号
  14. 14     output              post_hsync      ,   // hsync信号
  15. 15     output              post_de         ,   // data enable信号
  16. 16     output   reg        monoc               // monochrome(1=白,0=黑)
  17. 17 );
  18. 18
  19. 19 //reg define
  20. 20 reg    ycbcr_vsync_d;
  21. 21 reg    ycbcr_hsync_d;
  22. 22 reg    ycbcr_de_d   ;
  23. 23
  24. 24 //*****************************************************
  25. 25 //**                    main code
  26. 26 //*****************************************************
  27. 27
  28. 28 assign  post_vsync = ycbcr_vsync_d  ;
  29. 29 assign  post_hsync = ycbcr_hsync_d  ;
  30. 30 assign  post_de    = ycbcr_de_d     ;
  31. 31
  32. 32 //二值化
  33. 33 always @(posedge clk or negedge rst_n) begin
  34. 34     if(!rst_n)
  35. 35         monoc <= 1'b0;
  36. 36     else if(luminance > 8'd64)  //阈值
  37. 37         monoc <= 1'b1;
  38. 38     else
  39. 39         monoc <= 1'b0;
  40. 40 end
  41. 41
  42. 42 //延时1拍以同步时钟信号
  43. 43 always@(posedge clk or negedge rst_n) begin
  44. 44     if(!rst_n) begin
  45. 45         ycbcr_vsync_d <= 1'd0;
  46. 46         ycbcr_hsync_d <= 1'd0;
  47. 47         ycbcr_de_d    <= 1'd0;
  48. 48     end
  49. 49     else begin
  50. 50         ycbcr_vsync_d <= ycbcr_vsync;
  51. 51         ycbcr_hsync_d <= ycbcr_hsync;
  52. 52         ycbcr_de_d    <= ycbcr_de   ;
  53. 53     end
  54. 54 end
  55. 55
  56. 56 endmodule
复制代码

二值化的主要原理就是,给出一个设定的阈值,将灰度值与该阈值比较,若灰度值大于该阈值则monoc为1,若小于阈值,则monoc为0,如代码第33到40行。理论上阈值可以是0到255中的任意值,但阈值过大,会提取多余的部分;而阈值过小,又会丢失所需的部分,因此阈值选取就是一个很重要的步骤。
在代码第43到54行,通过寄存操作对gray_vsync、gray_clken等信号作了一个时钟周期的延迟。这是因为在进行二值判定时消耗了一个时钟,因此相应的同步信号也要延迟一个时钟周期,以实现与数据的同步。
46.5下载验证
编译完工程之后就可以开始下载程序了。将OV5640摄像头模块插在达芬奇开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI_B插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,下载完成后观察HDMI显示器显示的二值化后的图案。如下图所示:

基于OV5640的二值化实验9077.png

图 46.5.1HDMI实时显示二值化图像

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 18:31

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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