//首先進行高斯模糊,降噪
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,...