sobel運算元進行邊緣檢測

2021-09-25 12:59:31 字數 3354 閱讀 5609

//首先進行高斯模糊,降噪

mat gauimage;

gaussianblur(srcimage, gauimage, size(3, 3), 0, 0, 4);

原圖如下:

//將轉換成灰度圖

mat grayimage;

cvtcolor(gauimage, grayimage, color_bgr2gray);

//進行x和y方向的soble運算元

mat xgrand, ygrand;

sobel(grayimage, xgrand, cv_16s, 1, 0, 3);

convertscaleabs(xgrand, xgrand);

sobel(grayimage, ygrand, cv_16s, 0, 1, 3);

convertscaleabs(ygrand, ygrand);

下面詳細講述一下x和y方向導數怎麼求解。

對於一元連續函式的導數,我們直接通過公式求導就可以;對於多元連續函式的導數,我們需要求各個方向的偏導。但是對於儲存在計算機中的影象來說,計算機只能夠處理離散的畫素值,不能夠使用公式求解導數,因此只能夠使用導數的定義來求解x和y方向的導數。比如求解x方向的導數:dx = i(i + 1) - i(i);求解y方向的導數:dx = i(j + 1) - i(j),某點的導數 = 該點x(y)方向的下乙個畫素值 - 該點的畫素值,就可以得到該點x或者y方向的導數。

值得注意的是,因為sobel函式在求x或者y方向的導數時,使用的核是不一樣的,得到的導數可能小於0,或者大於255,因此為了保護細節,最好選用16位(cv_16s)的輸出影象的深度,並且呼叫convertscaleabs(輸出影象為8位),將所得結果盡可能的保護下來。

方法一:使用線性混合的方法進行疊加

//進行線性混合疊加

方法二:使用近似的方法,將x和y方向的導數進行相加

mat dst = mat :: zeros( xgrand.size(), ygrand.type());

//將x和y的梯度直接相加

這個方法消耗的時間較長,消耗了0.1s左右的時間,但是執行結果顯而易見,獲得了更多的細節和邊緣。

方法三:根據勾股定理求出近似梯度

根據向量的加法,如果要求得影象整體的梯度,就要求x和y向量加法的模,也就是x和y構成的直角三角形的斜邊。

具體**如下:

//使用勾股定理獲得更多的細節

這個方法消耗的時間比方法二消耗的時間略長一些,但是效果和方法二相差不多。因此,從時間方面考慮,完全可以使用第二種方法代替第三種方法。 

最終所有**如下:

#include #include #include using namespace cv;

int main(int argc, char ** ar**)

imshow("原影象", srcimage);

//首先進行高斯模糊,降噪

mat gauimage;

gaussianblur(srcimage, gauimage, size(3, 3), 0, 0, 4);

//將轉換成灰度圖

mat grayimage;

cvtcolor(gauimage, grayimage, color_bgr2gray);

imshow("灰度圖", grayimage);

//進行x和y方向的soble運算元

mat xgrand, ygrand;

sobel(grayimage, xgrand, cv_16s, 1, 0, 3);

convertscaleabs(xgrand, xgrand);

sobel(grayimage, ygrand, cv_16s, 0, 1, 3);

convertscaleabs(ygrand, ygrand);

//進行疊加

float t1 = gettickcount();

mat dst = mat :: zeros( xgrand.size(), ygrand.type());

//使用線性混合的方法

//addweighted(xgrand, 0.5, ygrand, 0.5, 0, dst, -1);

將x和y的梯度直接相加

//int colsimage = srcimage.cols;

//int rowsimage = srcimage.rows;

//for (int row = 0; row < rowsimage; row++)

//}//使用勾股定理獲得更多的細節

int colsimage = srcimage.cols;

int rowsimage = srcimage.rows;

for (int row = 0; row < rowsimage; row++)

} float timeconsume = (gettickcount() - t1) / gettickfrequency();

printf("線性混合疊加消耗的時間是:%f\n", timeconsume);

imshow("最終影象", dst);

邊緣檢測 Sobel運算元

依賴opencv來做一些資料結構和顯示的工作,但主要的計算法部分是自己實現的。後面爭取依次給出常見的集中邊緣提取的演算法實現。下次補上原理推到說明。sobel.cpp 定義控制台應用程式的入口點。include stdafx.h include cv.h include highgui.h incl...

邊緣檢測之Sobel檢測運算元

在討論邊緣運算元之前,首先給出一些術語的定義 1 邊緣 灰度或結構等資訊的突變處,邊緣是乙個區域的結束,也是另乙個區域的開始,利用該特徵可以分割影象。2 邊緣點 影象中具有座標 x,y 且處在強度顯著變化的位置上的點。3 邊緣段 對應於邊緣點座標 x,y 及其方位 邊緣的方位可能是梯度角。二 sob...

Opencv學習 邊緣檢測(sobel運算元)

sobel運算元是乙個主要用於邊緣檢測的離散微分運算元。它結合了高斯平滑和微分求導,用來計算灰度函式的近似梯度。void sobel inputarray src,outputarray dst,int ddepth,int dx,int dy,int ksize 3,double scale 1,...