Sobel 原理介紹
索貝爾算子(Sobel operator)主要用作邊緣檢測,在技術(shù)上,它是一離散性差分算子,用來運(yùn)算圖像亮度函數(shù)的灰度之近似值。在圖像的任何一點(diǎn)使用此算子,將會(huì)產(chǎn)生對應(yīng)的灰度矢量或是其法矢量Sobel 卷積因子為:
該算子包含兩組 3x3 的矩陣,分別為橫向及縱向,將之與圖像作平面卷積,即可分別得出橫向及縱向的亮度差分近似值。如果以 A 代表原始圖像,Gx 及 Gy 分別代表經(jīng)橫向及縱向邊緣檢測的圖像灰度值,其公式如下:
具體計(jì)算如下:
Gx = (-1)*f(x-1, y-1) + 0*f(x,y-1) + 1*f(x+1,y-1)
+(-2)*f(x-1,y) + 0*f(x,y)+2*f(x+1,y)
+(-1)*f(x-1,y+1) + 0*f(x,y+1) + 1*f(x+1,y+1)
= [f(x+1,y-1)+2*f(x+1,y)+f(x+1,y+1)]-[f(x-1,y-1)+2*f(x-1,y)+f(x-1,y+1)]
Gy =1* f(x-1, y-1) + 2*f(x,y-1)+ 1*f(x+1,y-1)
+0*f(x-1,y) 0*f(x,y) + 0*f(x+1,y)
+(-1)*f(x-1,y+1) + (-2)*f(x,y+1) + (-1)*f(x+1, y+1)
= [f(x-1,y-1)+2f(x,y-1)+f(x+1,y-1)]-[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)]
其中 f(a,b), 表示圖像(a,b)點(diǎn)的灰度值;
圖像的每一個(gè)像素的橫向及縱向灰度值通過以下公式結(jié)合,來計(jì)算該點(diǎn)灰度的大?。?/p>
通常,為了提高效率 使用不開平方的近似值
Sobel 算子根據(jù)像素點(diǎn)上下、左右鄰點(diǎn)灰度加權(quán)差,在邊緣處達(dá)到極值這一現(xiàn)象檢測邊緣。對噪聲具有平滑作用,提供較為精確的邊緣方向信息,邊緣定位精度不夠高。當(dāng)對精度要求不是很高時(shí),是一種較為常用的邊緣檢測方法。
Sobel 算子在 HLS 上的實(shí)現(xiàn)
工程創(chuàng)建
Step1:打開Vivado HLS開發(fā)工具,單擊Creat New Project創(chuàng)建一個(gè)新工程,設(shè)置好工程路徑和工程名,一直點(diǎn)擊 Next 按照默認(rèn)設(shè)置
Step2:出現(xiàn)如下圖所示界面,時(shí)鐘周期Clock Period按照默認(rèn)10ns,Uncertaintly和Solution Name均按照默認(rèn)設(shè)置,點(diǎn)擊紅色箭頭部分選擇芯片類型,然后點(diǎn)擊 OK。
點(diǎn)擊Finish,出現(xiàn)如下界面
Step4:右單擊Source選項(xiàng),選擇New File,創(chuàng)建一個(gè)名為Top.cpp的文件。(一定要加cpp后綴)
Step5:打開剛剛新建的cpp文件,進(jìn)入編輯狀態(tài),輸入以下代碼
Top.cpp代碼
#include "top.h"
void hls_sobel(AXI_STREAM& INPUT_STREAM, AXI_STREAM&
OUTPUT_STREAM, int rows, int cols)
{
//Create AXI streaming interfaces for the core
#pragma HLS INTERFACE axis port=INPUT_STREAM
#pragma HLS INTERFACE axis port=OUTPUT_STREAM
#pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata="- bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata="-bus_bundle CONTROL_BUS"
#pragma HLS INTERFACE ap_stable port=rows
#pragma HLS INTERFACE ap_stable port=cols
RGB_IMAGE img_0(rows, cols);
RGB_IMAGE img_1(rows, cols);
RGB_IMAGE img_2(rows, cols);
RGB_IMAGE img_3(rows, cols);
RGB_IMAGE img_4(rows, cols);
RGB_IMAGE img_5(rows, cols);
RGB_PIXEL pix(50, 50, 50);
#pragma HLS dataflow
hls::AXIvideo2Mat(INPUT_STREAM, img_0);
hls::Sobel<1,0,3>(img_0, img_1);
hls::SubS(img_1, pix, img_2);
hls::Scale(img_2, img_3, 2, 0);
hls::Erode(img_3, img_4);
hls::Dilate(img_4, img_5);
hls::Mat2AXIvideo(img_5, OUTPUT_STREAM)
}
Step6:再在Source中添加一個(gè)名為Top.h的庫函數(shù),并添加如下程序:
Top.h代碼
#ifndefTOP_H
#defineTOP_H
#include "hls_video.h"
// maximum image size
#define MAX_WIDTH 512
#define MAX_HEIGHT 512
// I/O Image Settings
#define INPUT_IMAGE "lena.jpg"
#define OUTPUT_IMAGE "result.jpg"
#define OUTPUT_IMAGE_GOLDEN "result_golden.jpg"
// typedef video library core structures
typedef hls::stream
typedef hls::Scalar<3, unsigned char> RGB_PIXEL;
typedef hls::MatRGB_IMAGE;
// top level function for HW synthesis
void hls_sobel(AXI_STREAM& src_axi, AXI_STREAM& dst_axi, int rows, int cols);
#endif
Step7:在Test Bench中,用同樣的方法添加一個(gè)名為Test.cpp的測試程序。添加如下代碼:
Test.cpp代碼
#include "top.h"
#include "opencv_top.h"
using namespace std;
using namespace cv;
int main (int argc, char** argv)
{
//獲取圖像數(shù)據(jù)
IplImage* src = cvLoadImage(INPUT_IMAGE);
IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
//使用HLS庫進(jìn)行處理
AXI_STREAM src_axi, dst_axi;
IplImage2AXIvideo(src, src_axi);
hls_sobel(src_axi, dst_axi, src->height, src->width);
AXIvideo2IplImage(dst_axi, dst);
cvSaveImage(OUTPUT_IMAGE,dst);
cvShowImage("hls_dst", dst);
//使用OPENCV庫進(jìn)行處理
opencv_image_filter(src, dst);
cvShowImage("cv_dst", dst);
cvSaveImage(OUTPUT_IMAGE_GOLDEN,dst);
waitKey(0);
//釋放內(nèi)存
cvReleaseImage(&src);
cvReleaseImage(&dst);
}
Step8:用同樣的方法,再在Test Bench中創(chuàng)建一個(gè)opencv_top.cpp和opencv_top.h文件,添加如下程序:
Opencv_top.cpp代碼
#include "opencv_top.h"
#include "top.h"
void opencv_image_filter(IplImage* src, IplImage* dst)
{
IplImage* tmp = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
cvCopy(src, tmp);
cv::Mat)tmp, (cv::Mat)dst, -1, 1, 0);
cvSubS(dst, cvScalar(50,50,50), tmp);
cvScale(tmp, dst, 2, 0);
cvErode(dst, tmp);
cvDilate(tmp, dst);
cvReleaseImage(&tmp);
}
void sw_image_filter(IplImage* src, IplImage* dst)
{
AXI_STREAM src_axi, dst_axi;
IplImage2AXIvideo(src, src_axi);
hls_sobel(src_axi, dst_axi, src->height, src->width);
AXIvideo2IplImage(dst_axi, dst);
}
opencv_top.h代碼
#ifndefOPENCV_TOP_H___ #define ___OPENCV_TOP_H
#include "hls_opencv.h"
void opencv_image_filter(IplImage* src, IplImage* dst);
void sw_image_filter(IplImage* src, IplImage* dst);
#endif
Step7:在Test Bench中添加一張名為lena.jpg的測試圖片
接下來對工程進(jìn)行編譯和仿真。
Step1:單擊Project-Project settings或直接單擊快捷按鈕。
Step2:選擇Synthesis選項(xiàng),然后點(diǎn)擊Browse..指定一個(gè)頂層函數(shù),選定hls_sobel為頂層函數(shù),
單擊開始綜合
在協(xié)議類型里面我們可以看到我們主要使用了三種協(xié)議,分別是axis、ap_stable和ap_ctrl_hs三種,這些協(xié)議的詳細(xì)解釋我們均可以在官方手冊ug902中找到,其中ap_ctrl_hs的時(shí)序操作如下圖所示,說簡單點(diǎn)就是復(fù)位完成等待ap_start信號(hào)開始進(jìn)行操作
綜合完畢,我們對代碼進(jìn)行仿真測試,單擊開始仿真
仿真結(jié)果如下,與通過OPENCV實(shí)現(xiàn)的Sobel檢測結(jié)果基本一致。
審核編輯:湯梓紅
-
算子
+關(guān)注
關(guān)注
0文章
16瀏覽量
7347 -
HLS
+關(guān)注
關(guān)注
1文章
133瀏覽量
24839 -
sobel
+關(guān)注
關(guān)注
0文章
12瀏覽量
8060
原文標(biāo)題:Sobel 算子在 HLS 上的實(shí)現(xiàn)
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評(píng)論請先 登錄
基于 DSP5509 進(jìn)行數(shù)字圖像處理中 Sobel 算子邊緣檢測的硬件連接電路圖
基于FPGA的Sobel邊緣檢測的實(shí)現(xiàn)
Labview圖像處理——邊緣檢測
基于GFO算子的圖像增強(qiáng)算法如何去實(shí)現(xiàn)?
邊緣檢測的幾種微分算子
EdgeBoard中神經(jīng)網(wǎng)絡(luò)算子在FPGA中的實(shí)現(xiàn)方法是什么?
迅為iTOP-RK3568開發(fā)板Sobel 算子邊緣檢測
拉普拉斯算子的FPGA實(shí)現(xiàn)方法

LOG算子在FPGA中的實(shí)現(xiàn)

Vivado HLS在Zedboard中的Sobel濾波算法實(shí)現(xiàn)步驟教程

Laplacian算子的FPGA實(shí)現(xiàn)方法

淺述Sobel算子在HLS上的實(shí)現(xiàn)教程

評(píng)論