【博文连载】Sobel边缘检测算法的HDL实现

FPGA中针对以上矩阵进行算法移植。由于直接计算会因为负值而得到错误的结果,用补码表示比较繁琐,需要用到unsigned 以及signed类型,不适合FPGA的运算。

cnblog有真oo无双的代码,通过并形乘法、并行相加、平方根来使用,采用各种IP相当的复杂,虽然实现了补码、负数,但看得我都蒙了。为何要把简单的问题复杂化:

http://www.cnblogs.com/oomusou/archive/2008/08/25/verilog_sobel_edge_detector.html

为此Bingo发愤图强(不过oo的博文真的有很好的参考性)!!!!

前面Sobel算子的实现,为了实现FPGA的加速运算,发挥并行流水线的特性,可以划分为4个步骤,解析与实现分别如下:

  1. 计算计算Gx与Gy与模板每行的乘积

  2. 求得3*3模板运算后的Gx、Gy

    为了便于阅读理解,这里(1)与(2),Bingo在同一个always中描述了,但实际上耗费了2个时钟。Gx(Gx_data)与Gy(Gy_data)的计算分别如下:

//-------------------------------------------

//Sobel Parameter

//         Gx                  Gy               Pixel

// [   -1  0   +1  ]   [   +1  +2   +1 ]     [   P11  P12   P13 ]

// [   -2  0   +2  ]   [   0   0    0  ]     [   P21  P22   P23 ]

// [   -1  0   +1  ]   [   -1  -2   -1 ]     [   P31  P32   P33 ]

//Caculate horizontal Grade with |abs|

//Step 1.1

reg   [9:0]   Gx_temp1;   //postive result

reg   [9:0]   Gx_temp2;   //negetive result

reg   [9:0]   Gx_data;    //Horizontal grade data

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

Gx_temp1 <= 0;

Gx_temp2 <= 0;

Gx_data <= 0;

end

else

begin

Gx_temp1 <= matrix_p13 + (matrix_p23 << 1) + matrix_p33;    //postive result

Gx_temp2 <= matrix_p11 + (matrix_p21 << 1) + matrix_p31;    //negetive result

Gx_data <= (Gx_temp1 >= Gx_temp2) ? Gx_temp1 - Gx_temp2 : Gx_temp2 - Gx_temp1;

end

end

//---------------------------------------

//Caculate vertical Grade with |abs|

//Step 1.2

reg   [9:0]   Gy_temp1;   //postive result

reg   [9:0]   Gy_temp2;   //negetive result

reg   [9:0]   Gy_data;    //Vertical grade data

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

Gy_temp1 <= 0;

Gy_temp2 <= 0;

Gy_data <= 0;

end

else

begin

Gy_temp1 <= matrix_p11 + (matrix_p12 << 1) + matrix_p13;    //postive result

Gy_temp2 <= matrix_p31 + (matrix_p32 << 1) + matrix_p33;    //negetive result

Gy_data <= (Gy_temp1 >= Gy_temp2) ? Gy_temp1 - Gy_temp2 : Gy_temp2 - Gy_temp1;

end

end

具体的实现方式请自行分析代码,Bingo认为这是极简单的……

(3)求得Gx^2+Gy^2的结果,及Gx与Gy的平方和

这一步直接通过HDL中乘法器的描述来实现,综合时会自动布线为片内乘法器,如下:

//---------------------------------------

//Caculate the square of distance = (Gx^2 + Gy^2)

//Step 3

reg   [20:0]  Gxy_square;

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

Gxy_square <= 0;

else

Gxy_square <= Gx_data * Gx_data + Gy_data * Gy_data;

end

(4)求得Gx^2+Gy^2的平方根

当年Bingo在第一次遇到这个的时候差点崩溃,不过有幸看过无双oo的博文,才知道强大的Altera竟然在LPM中提供了平方根的IP,如下所示:

ALTSQRT的使用非常简单,坦白的说Bingo从来没看到DT。以下直接给出SQRT的例化,从而得到平方根,如下:

//---------------------------------------

//Caculate the distance of P5 = (Gx^2 + Gy^2)^0.5

//Step 4

wire  [10:0]  Dim;

SQRT  u_SQRT

(

.radical    (Gxy_square),

.q          (Dim),

.remainder  ()

);

(5)根据外部输入阀值,判断并实现边缘的检测

简单的判断Dim的大小而已,大于阀值,视为有效,赋1;反之则赋0。这里的Sobel_Threshold由外部输入,暂且认为是60吧。。。

//---------------------------------------

//Compare and get the Sobel_data

//Step 5

reg   post_img_Bit_r;

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

post_img_Bit_r <= 1'b0; //Default None

else if(Dim >= Sobel_Threshold)

post_img_Bit_r <= 1'b1; //Edge Flag

else

post_img_Bit_r <= 1'b0; //Not Edge

end

前面从(1)-(5)中,总共消耗了5个时钟,因此最后对行场、像素有效时钟进行5个clock的偏移,如下:

//------------------------------------------

//lag 5 clocks signal sync

reg   [4:0]   per_frame_vsync_r;

reg   [4:0]   per_frame_href_r;

always@(posedge clk or negedge rst_n)

begin

if(!rst_n)

begin

per_frame_vsync_r <= 0;

per_frame_href_r <= 0;

end

else

begin

per_frame_vsync_r   <=  {per_frame_vsync_r[3:0],    matrix_frame_vsync};

per_frame_href_r    <=  {per_frame_href_r[3:0],     matrix_frame_href};

end

end

assign    post_frame_vsync    =   per_frame_vsync_r[4];

assign    post_frame_href     =   per_frame_href_r[4];

assign    post_img_Bit        =   post_frame_href ? post_img_Bit_r : 1'b0;

这样,便完成了Sobel边缘检测算法的移植。工程目录sim文件夹下包含了VIP的Modelsim工程,波形仿真如下(新架构没有*_clken):

最后,在Video_Image_Processor中例化VIP_Sobel_Edge_Detector模块,并且在Video_Image_Processor信号列表中修改输出与阀值输入,相关如下:

output              post_img_Bit,       //Processed Image Bit flag outout(1: Value, 0:inValid)

//user interface

input       [7:0]   Sobel_Threshold     //Sobel Threshold for image edge detect

);

//--------------------------------------

//Image edge detector with Sobel.

VIP_Sobel_Edge_Detector

#(

.IMG_HDISP  (IMG_HDISP),    //640*480

.IMG_VDISP  (IMG_VDISP)

)

u_VIP_Sobel_Edge_Detector

(

//global clock

.clk                    (clk),               //cmos video pixel clock

.rst_n                  (rst_n),                //global reset

//Image data prepred to be processd

.per_frame_vsync        (per_frame_vsync),      //Prepared Image data vsync valid signal

.per_frame_href         (per_frame_href),       //Prepared Image data href vaild  signal

.per_img_Y              (per_img_Y),            //Prepared Image brightness input

//Image data has been processd

.post_frame_vsync       (post_frame_vsync),     //Processed Image data vsync valid signal

.post_frame_href        (post_frame_href),      //Processed Image data href vaild  signal

.post_img_Bit           (post_img_Bit),         //Processed Image Bit flag outout(1: Value, 0:inValid)

//User interface

.Sobel_Threshold        (Sobel_Threshold)                   //Sobel Threshold for image edge detect

);

endmodule

VIP的例化从略。全编译,下载sof文件,如下图所示,为Sobel_Threshold=60下的边缘检测图(VGA 和USB一样哦)。

 

(0)

相关推荐

  • 制作抖音卡点视频?Python来帮你~

    第一时间获取 Python 技术干货! 阅读文本大概需要 10 分钟. 1 目 标 场 景 玩抖音的朋友都应该知道,最近「卡点视频」简直不要太火.抖音上很多大神也出了剪辑各种卡点视频的教程. 实际上, ...

  • Chromium网页渲染调度器(Scheduler)实现分析 vsync信号

    在采用线程化渲染方式渲染网页时,Chromium依赖一个调度器协调Main线程和Compositor线程的执行,同时也通过这个调度器决定它们什么时候该执行什么操作.调度器将Main线程和Composi ...

  • 短视频篇 | Python 带你进行短视频二次创作

    第一时间获取 Python 技术干货! 阅读文本大概需要 10 分钟. 1 目 标 场 景 无论是抖音还是快手等视频平台,一旦一个视频火了后,很多 UP 主都会争先抢后去模仿拍摄或剪辑,然后上传到平台 ...

  • 【博文连载】边缘检测算法介绍

    所谓边缘是指其周围像素灰度急剧变化的那些象素的集合,它是图像最基本的特征.边缘存在于目标.背景和区域之间,所以,它是图像分割所依赖的最重要的依据.由于边缘是位置的标志,对灰度的变化不敏感,,因此,边缘 ...

  • 【博文连载】动态Sobel阀值的HDL实现

    完美是没有极限的,前面我们已经实现了固定阀值下,图像的边缘检测结果.不过如何能手动输入,或者控制阀值的大小,那其实更完美一点点. 既然我们能够在努力一点点,为何要放弃??? OK,Bingo这里打算教 ...

  • 【博文连载】中值滤波算法的介绍

    言归正传,我们先挑一个相对最简单的滤波算法(其实均值滤波更简单,但是它对边缘的保持太差,那就稍微努力点用中值滤波吧).进行中值滤波不仅可以去除孤点噪声,而且可以保持图像的边缘特性,不会使图像产生显著的 ...

  • 【博文连载】【VGA+USB】灰度图像的均值滤波算法实现

    图像处理算法可以在RGB域处理,也可以在灰度域处理,牛逼的还可以在Bayer处理.但是大部分目标识别.跟踪.检测等图像处理算法,都是灰度域处理的,因为灰度除了没有色度,以及包含了基本图像处理所需的信息 ...

  • 什么是 Canny 边缘检测算法?

    重磅干货,第一时间送达 一.简介 Canny 边缘检测器是一种多步算法,用于检测任何输入图像的边缘.它涉及在检测图像边缘时要遵循的以下步骤. 1. 使用高斯滤波器去除输入图像中的噪声. 2.计算高斯滤 ...

  • 边缘检测算法6.-Paillou边缘检测

    在 OpenCV扩展模块里面,有一个算法: paillou定义的 边缘检测 查资料,了解是 1997年 Paillou 提出来的 改进 SAR图像的 边缘检测方法. 论文在这个地方:https://i ...

  • 边缘检测算法2.-自定义差分算子

    边缘检测,根据原理,只要是计算像素差异,都能产生边缘检测效果. 我根据一些 实际情况,定义一种很简单的差分算子: 计算 核 Width x Height 的最大值 pMax 和最小值 pMin 计算 ...

  • 边缘检测算法4.-教你动手实现kirsch和robinson算子

    还有很多 边缘检测算子,在OpenCV中没有实现代码. 所以,我们得掌握看懂算法,然后扩展 算法得能力. 比如,我已知的一些 边缘检测核心: Kirsch 8方向算子 Robinson 8方向算子 这 ...

  • 【博文连载】Median_Filter均值滤波算法的实现

    ChinaAET<电子应用技术>出版过一篇值得参考的<基于FPGA的实时中值滤波器的硬件实现>,该文采用FPGA+SRAM实现了实时中值滤波,思维值得参考(当然Bingo认为实 ...