FPGA设计经验之图像处理_基于fpga的数字图像处理-程序员宅基地

技术标签: FPGA项目开发经验分享  fpga  

今天和大侠简单聊一聊基于FPGA的图像处理,之前也和各位大侠聊过相关的图像处理,这里面也超链接了几篇,具体如下:

图像边缘检测算法体验步骤(Photoshop,Matlab)

算法系列:基于 FPGA 的图像边缘检测系统设计(sobel算法)    

FPGA设计中 Verilog HDL实现基本的图像滤波处理仿真   

基于FPGA的类脑计算平台 —PYNQ 集群的无监督图像识别类脑计算系统   

需要的可以参考一下,欢迎一起交流学习。话不多说,上货。

 

 

使用FPGA做图像处理优势最关键的就是:FPGA能进行实时流水线运算,能达到最高的实时性。因此在一些对实时性要求非常高的应用领域,做图像处理基本就只能用FPGA。例如在一些分选设备中图像处理基本上用的都是FPGA,因为在其中相机从看到物料图像到给出执行指令之间的延时大概只有几毫秒,这就要求图像处理必须很快且延时固定,只有FPGA进行的实时流水线运算才能满足这一要求。

所以要了解FPGA进行图像处理的优势就必须理解FPGA所能进行的实时流水线运算和DSP,GPU等进行的图像处理运算有何不同。DSP,GPU,CPU对图像的处理基本是以帧为单位的,从相机采集的图像数据会先存在内存中,然后GPU会读取内存中的图像数据进行处理。假如采集图像的帧率是30帧,那么DSP,GPU要是能在1/30秒内完成一帧图像的处理,那基本上就能算是实时处理。

 

 

FPGA对图像进行实时流水线运算是以行为单位的。FPGA可以直接和图像传感器芯片连接获得图像数据流,如果是RAW格式的则还可以进行差值以获得RGB图像数据。FPGA能进行实时流水线处理的关键是它可以用其内部的Block Ram缓存若干行的图像数据。这个Block Ram可以说是类似于CPU里面的Cache,但Cache不是你能完全控制的,但Block Ram是完全可控的,可以用它实现各种灵活的运算处理。这样FPGA通过缓存若干行图像数据就可以对图像进行实时处理,数据就这样一边流过就一边处理好了,不需要送入DDR缓存了之后再读出来处理。

这样的数据流处理显然是顺序读取数据的,那么也就只能实现那些顺序读取数据的算法,也就是图像处理中那一大类用3x3到NxN的算子进行的滤波、取边缘、膨胀腐蚀等算法。可能大家会觉得这些运算似乎都是最基本的图像处理运算,只是个前端的预处理,似乎用处不大。但问题是只有FPGA做这样的运算才是速度最快效率最高的,比如用CPU做一个取边缘的算法根本就达不到实时。另外别小看了这种NxN算子法,它可以有各种组合和玩法,可以实现分选多种颜色,甚至分辨简单形状等功能。FPGA进行的这种算子法处理是并行流水线算法,其延时是固定的,比如用3x3的算子进行处理其给出结果的延时是两行图像的时间。还有这个算子法和现在卷积神经网络中最前面的卷积层运算是类似的。

FPGA中的Block Ram是重要和稀缺资源,能缓存的图像数据行数是有限的,所以这个NxN的算子中的N不能特别大。当然FPGA也可以接DDR把图像缓存到其中再读出来进行处理,但这种处理模式就和CPU差不多了,达不到最高的实时性。其实有些我们认为需要随机读取数据的图像处理算法也是可以并行流水线化的。

 

 

在密集运算中,耽误时间和消耗功耗的操作往往不是运算本身,而是把数据从内存中搬来搬去。GPU,CPU在进行运算时要把数据从内存中取出来,算好了在放回去。这样内存带宽往往成了运算速度的瓶颈,数据搬运过程中的功耗占的比重也不会小。FPGA则可以通过堆很多计算硬件的方法把要做的运算都展开,然后数据从中流过,完成一个阶段的运算之后就直接流入第二个阶段,不需要把一个计算阶段完成后的数据再送回内存中,再读出来交给下一个阶段的运算。这样就会节省很多时间和功耗。现在用FPGA做图像处理就是这样干的,比如先用一个3x3的算子进行滤波,再用一个3x3的算子进行取边缘,在FPGA流水线算法中,滤波处理完了数据立即就会进行取边缘处理,是不需要像CPU那样存回内存再读出来的。

FPGA进行图像处理的前景还是挺广阔的,越来越多的工业应用场合都要求更高的实时性,而这正是FPGA所适合的。还有机器学习领域,神经网络这种层状的,不需要很随机的读取数据的运算是比较适合用FPGA来做的。不过FPGA不擅长浮点运算,如果能整出不需要浮点运算的神经网络,那么FPGA在这方面的应用将会更大。

前些年用matlab和opencv做图像处理。近一段时间通过FPGA处理摄像头视频数据,有太多感触,复杂的算法先不提及,单是上面文章中提到的一些处理手段及策略,非常受用。

下面就几个方面简单列一些:

 

 

神圣分割线

图像处理系统设计注意点:

1.将算法开发和FPGA实现分离

用软件的图像处理环境可以使用大批量的图像样本进行测试及调试算法,再将算法映射到硬件上,这样大大节省了硬件调试周期。

2.算法的精度

图像处理的算法中,大部分需要采用浮点数运算,而浮点数运算在FPGA中是非常不划算的,因此需要转换成定点数计算,此时会设计到浮点运算转定点运算时精度下降的问题。

3.软件和硬件的合理划分

这里的软件是指DSP、CPU等等,硬件是指FPGA;一般结构规则、计算量大的操作如sobel算子、均值滤波可以采用硬件进行,不规则的动态可变长度循环的底层算法由软件进行。

 

 

神圣分割线

图像处理FPGA 设计基本方法:

1.阵列结构结合流水线处理设计

例如RGB图像,包括三组数据,处理时需要并行三通道后,每个通道进行分别的串行流水处理。

2.缓存设计

帧缓存 行缓存 列对齐

3.资源

分辨率 处理窗口 对资源影响成倍增加

 

 

神圣分割线

基于FPGA设计框架举例:

1、灰度直方图统计

直方图是图像的灰度分布统计的一种表示方法,统计目标图像中各个灰度点的像素个数,很多对于图像的调整算法都是基于此进行的;

如何基于FPGA进行统计呢?

1)由于是统计图像的直方图,所以一定是统计结果会在图像经过之后才能产生,因此需要进行缓存;

缓存一:统计后的结果;

缓存二:经过统计处理器的图像数据,以便后面和直方图做同步处理。

2)图像常常用8位、24位、32位来表示一个像素的灰度值。因此,统计种类分别为2^8=256/2^24=16777216/2^32=4294967296,地址位宽根据此进行选择设定。根据不同的精度选择不同的缓存方式:片内或片外缓存。

3)处理流程:

首先根据当前来的灰度值做为读RAM地址,读出RAM中对应灰度值的的统计值;

第二步将读出结果加一并回写回RAM的当前地址中;

第三步重复操作至当前图像处理结束;

第四步下一幅图像到来之前顺序按灰度值从0到最大的顺序将最终结果读出;

第五步读出最终结果后,将RAM清空。

4)处理细节

定义参数 图像高度IH 图像宽度IW 像素逐行输入,因此以行同步脉冲的上升沿作为统计开始,行同步脉冲作为行统计计数器,行统计计数器达到最大高度时,作为统计结束标志。

 

 

 

2.灰度直方图均衡化处理

1.统计出直方图,获取各个像素灰度累加和;

2.乘以均衡系数:(2^DW-1)/IW*IH(像素最大值/图像的面积)。

 

 

 

3.直方图线性拉伸处理

此节暂时略过,不太精通,后续有时间可以研究再分享一下;

 

 

 

4.线性滤波器

首先需要区分线性和非线性滤波器的区别,区别在于其输出与输入之间是否有唯一且确定的函数传递。

线性滤波器分类:

平滑滤波器:主要包括均值滤波器和高斯滤波器等;

锐化滤波器:主要包括SOBEL算子、LAPLAS算子、梯度运算等。    

滤波器的物理意义主要是响应信号对目标信号响应后的样子,也就是响应函数g(i,j) 滑过整个图像,即对图像做一个卷积处理,就得到了滤波结果。

1)均值滤波器概述

用一个图像区域的各个像素的平均值来代替原图像的各个像素值,主要作用是减小锐度,减小噪声。

均值滤波一般出现在图像处理的预处理步骤,

预处理后,根据噪声来源,例如针对椒盐噪声做中值滤波处理,针对高斯噪声做高斯滤波处理

后续可能继续做边缘提取等复杂操作处理。

2)均值滤波器设计   

设计一个滤波器可以理解成设计一个响应函数g(x,y)=Σi=-rrΣj=-rr I(x+i,y+j)) / (2r+1)2  

数学公式很好理解,就是求一个窗口的所有像素灰度值之后后再除以整个窗口的面积也就是像素点个数,求出平均值;   

均值滤波的方法将数据存储成3x3的矩阵,然后求这个矩阵。在图像上对目标像素给一个模板,   

该模板包括了其周围的临近像素(以目标像素为中心的周围 8 个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。

shift_ram 进行数据矩阵化,将3x3矩阵的中心像素的周围八个点求和,采取了流水线的设计方法,来增加吞吐量,然后再求平均值代替目标像素的值。

 

3)sobel算子

包括X和Y两个方向的两套3X3矩阵,使其分别和图像的X和Y方向进行卷积计算(矩阵的卷积计算即将所有元素做乘加计算),两个方向的卷积结果求平方根计算,计算结果如果大于阈值则等于0xffff,如果小于阈值则等于0,最终输出则是图像的边缘。

参考代码如下:由于算子简单以及有正负区分,因此需要做正值和负值分别计算后再进行相减计算。

//    | -1  0 +1 |//Gx= | -2  0 +2 |//    | -1  0 +1 |////    | -1 -2 -1 |//Gy= |  0  0  0 |//    | +1 +2 +1 |reg [8:0] p_x_data ,p_y_data ;  // x 和 y 的正值之和reg [8:0] n_x_data ,n_y_data ; // x 和 y 的负值之和reg [8:0] gx_data  ,gy_data  ; //最终结果always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin       p_x_data <=0;       n_x_data <=0;       gx_data   <=0;    end    else if(per_href_ff1==1) begin         p_x_data <= p_13 + (p_23<<1) + p_33 ;        n_x_data <= p_11 + (p_12<<1 )+ p_13 ;        gx_data   <= (p_x_data >=n_x_data)? p_x_data - n_x_data : n_x_data - p_x_data ;     end    else begin         p_x_data<=0;         n_x_data<=0;         gx_data <=0;    end  endalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin       p_y_data <=0;       n_y_data <=0;       gy_data   <=0;    end    else if(per_href_ff1==1) begin        p_y_data <= p_11 + (p_12<<1) + p_13 ;        n_y_data <= p_31 + (p_32<<1) + p_33 ;        gy_data   <= (p_y_data >=n_y_data)? p_y_data - n_y_data : n_y_data - p_y_data ;     end    else begin        p_y_data <=0;        n_y_data <=0;        gy_data   <=0;   endend//求平方和,调用ip核开平方reg [16:0] gxy; // Gx 与 Gy 的平方和always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        gxy<=0;    end    else begin        gxy<= gy_data* gy_data + gx_data* gx_data ;    endendwire [8:0] squart_out ; altsquart  u1_altsquart (     //例化开平方的ip核    .radical (gxy),    .q       (squart_out),  //输出的结果    .remainder()                       );//与阈值进行比较reg [15:0] post_y_data_r;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        post_y_data_r<=16'h00;    end    else if(squart_out>=threshold)         post_y_data_r<=16'h00  ;    else         post_y_data_r<=16'hffff  ;    end

 

 

 

5.非线性滤波器 

非线性滤波器通常下是没有特定的转移函数,统计排序滤波器;

中值滤波   

将 3*3 滑动块中的灰度值进行排序,然后用排序的中间值取代 3*3 滑块中心的值。示意图如下图所示。

  

   第一步:将每一行按最大值、中间值、最小值排列;

   第二步:提取出最大值的最小值,中间值的中间值,最小值的最大值;

   第三步:将第二步提取出来的三个数进行排序,中间值即我们要求的中间值。

 

 

 

   6.图像分割

   图像分割是将图像划分成若干个互不相交的小区域的过程,将图像中有意义的特征或应用所需要的特征信息提取出来,最终结果是分割成一些具有某种特征的单元,称为图像的基元。

 

 

神圣分割线

本篇到此结束,后续有时间再更新,欢迎一起交流学习,共同进步!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40310273/article/details/105678708

智能推荐

前端开发之vue-grid-layout的使用和实例-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏34次。vue-grid-layout的使用、实例、遇到的问题和解决方案_vue-grid-layout

Power Apps-上传附件控件_powerapps点击按钮上传附件-程序员宅基地

文章浏览阅读218次。然后连接一个数据源,就会在下面自动产生一个添加附件的组件。把这个控件复制粘贴到页面里,就可以单独使用来上传了。插入一个“编辑”窗体。_powerapps点击按钮上传附件

C++ 面向对象(Object-Oriented)的特征 & 构造函数& 析构函数_"object(cnofd[\"ofdrender\"])十条"-程序员宅基地

文章浏览阅读264次。(1) Abstraction (抽象)(2) Polymorphism (多态)(3) Inheritance (继承)(4) Encapsulation (封装)_"object(cnofd[\"ofdrender\"])十条"

修改node_modules源码,并保存,使用patch-package打补丁,git提交代码后,所有人可以用到修改后的_修改 node_modules-程序员宅基地

文章浏览阅读133次。删除node_modules,重新npm install看是否成功。在 package.json 文件中的 scripts 中加入。修改你的第三方库的bug等。然后目录会多出一个目录文件。_修改 node_modules

【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure-程序员宅基地

文章浏览阅读883次。【代码】【】kali--password:su的 Authentication failure问题,&sudo passwd root输入密码时Sorry, try again._password: su: authentication failure

整理5个优秀的微信小程序开源项目_微信小程序开源模板-程序员宅基地

文章浏览阅读1w次,点赞13次,收藏97次。整理5个优秀的微信小程序开源项目。收集了微信小程序开发过程中会使用到的资料、问题以及第三方组件库。_微信小程序开源模板

随便推点

Centos7最简搭建NFS服务器_centos7 搭建nfs server-程序员宅基地

文章浏览阅读128次。Centos7最简搭建NFS服务器_centos7 搭建nfs server

Springboot整合Mybatis-Plus使用总结(mybatis 坑补充)_mybaitis-plus ruledataobjectattributemapper' and '-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏3次。前言mybatis在持久层框架中还是比较火的,一般项目都是基于ssm。虽然mybatis可以直接在xml中通过SQL语句操作数据库,很是灵活。但正其操作都要通过SQL语句进行,就必须写大量的xml文件,很是麻烦。mybatis-plus就很好的解决了这个问题。..._mybaitis-plus ruledataobjectattributemapper' and 'com.picc.rule.management.d

EECE 1080C / Programming for ECESummer 2022 Laboratory 4: Global Functions Practice_eece1080c-程序员宅基地

文章浏览阅读325次。EECE 1080C / Programming for ECESummer 2022Laboratory 4: Global Functions PracticePlagiarism will not be tolerated:Topics covered:function creation and call statements (emphasis on global functions)Objective:To practice program development b_eece1080c

洛谷p4777 【模板】扩展中国剩余定理-程序员宅基地

文章浏览阅读53次。被同机房早就1年前就学过的东西我现在才学,wtcl。设要求的数为\(x\)。设当前处理到第\(k\)个同余式,设\(M = LCM ^ {k - 1} _ {i - 1}\) ,前\(k - 1\)个的通解就是\(x + i * M\)。那么其实第\(k\)个来说,其实就是求一个\(y\)使得\(x + y * M ≡ a_k(mod b_k)\)转化一下就是\(y * M ...

android 退出应用没有走ondestory方法,[Android基础论]为何Activity退出之后,系统没有调用onDestroy方法?...-程序员宅基地

文章浏览阅读1.3k次。首先,问题是如何出现的?晚上复查代码,发现一个activity没有调用自己的ondestroy方法我表示非常的费解,于是我检查了下代码。发现再finish代码之后接了如下代码finish();System.exit(0);//这就是罪魁祸首为什么这样写会出现问题System.exit(0);////看一下函数的原型public static void exit (int code)//Added ..._android 手动杀死app,activity不执行ondestroy

SylixOS快问快答_select函数 导致堆栈溢出 sylixos-程序员宅基地

文章浏览阅读894次。Q: SylixOS 版权是什么形式, 是否分为<开发版税>和<运行时版税>.A: SylixOS 是开源并免费的操作系统, 支持 BSD/GPL 协议(GPL 版本暂未确定). 没有任何的运行时版税. 您可以用她来做任何 您喜欢做的项目. 也可以修改 SylixOS 的源代码, 不需要支付任何费用. 当然笔者希望您可以将使用 SylixOS 开发的项目 (不需要开源)或对 SylixOS 源码的修改及时告知笔者.需要指出: SylixOS 本身仅是笔者用来提升自己水平而开发的_select函数 导致堆栈溢出 sylixos

推荐文章

热门文章

相关标签