日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

opencv sobel导数

發布時間:2025/4/16 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv sobel导数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 如何使用OpenCV函數?Sobel?對圖像求導。
  • 如何使用OpenCV函數?Scharr?更準確地計算??核的導數。

原理

Note

?

以下內容來自于Bradski和Kaehler的大作:?Learning OpenCV?.

  • 上面兩節我們已經學習了卷積操作。一個最重要的卷積運算就是導數的計算(或者近似計算).

  • 為什么對圖像進行求導是重要的呢? 假設我們需要檢測圖像中的?邊緣?,如下圖:

    你可以看到在?邊緣?,相素值顯著的?改變?了。表示這一?改變?的一個方法是使用?導數?。 梯度值的大變預示著圖像中內容的顯著變化。

  • 用更加形象的圖像來解釋,假設我們有一張一維圖形。下圖中灰度值的”躍升”表示邊緣的存在:

  • 使用一階微分求導我們可以更加清晰的看到邊緣”躍升”的存在(這里顯示為高峰值)

  • 從上例中我們可以推論檢測邊緣可以通過定位梯度值大于鄰域的相素的方法找到(或者推廣到大于一個閥值).

  • 更加詳細的解釋,請參考Bradski 和 Kaehler的?Learning OpenCV?。

  • Sobel算子

  • Sobel 算子是一個離散微分算子 (discrete differentiation operator)。 它用來計算圖像灰度函數的近似梯度。
  • Sobel 算子結合了高斯平滑和微分求導。
  • 計算

    假設被作用圖像為?:

  • 在兩個方向求導:

  • 水平變化: 將??與一個奇數大小的內核??進行卷積。比如,當內核大小為3時,??的計算結果為:

  • 垂直變化: 將:math:I?與一個奇數大小的內核??進行卷積。比如,當內核大小為3時,??的計算結果為:

  • 在圖像的每一點,結合以上兩個結果求出近似?梯度:

    有時也用下面更簡單公式代替:

  • Note

    當內核大小為??時, 以上Sobel內核可能產生比較明顯的誤差(畢竟,Sobel算子只是求取了導數的近似值)。 為解決這一問題,OpenCV提供了?Scharr?函數,但該函數僅作用于大小為3的內核。該函數的運算與Sobel函數一樣快,但結果卻更加精確,其內核為:

    關于(?Scharr?)的更多信息請參考OpenCV文檔。在下面的示例代碼中,你會發現在?Sobel?函數調用的上面有被注釋掉的?Scharr?函數調用。 反注釋Scharr調用 (當然也要相應的注釋掉Sobel調用),看看該函數是如何工作的。

    源碼

  • 本程序做什么?
    • 使用?Sobel算子?產生的輸出圖像上,檢測到的亮起的?邊緣?相素散布在更暗的背景中。
  • 下面是本教程的源碼,你也可以從?here?下載
  • #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <stdlib.h> #include <stdio.h>using namespace cv;/** @function main */ int main( int argc, char** argv ) {Mat src, src_gray;Mat grad;char* window_name = "Sobel Demo - Simple Edge Detector";int scale = 1;int delta = 0;int ddepth = CV_16S;int c;/// 裝載圖像src = imread( argv[1] );if( !src.data ){ return -1; }GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );/// 轉換為灰度圖cvtColor( src, src_gray, CV_RGB2GRAY );/// 創建顯示窗口namedWindow( window_name, CV_WINDOW_AUTOSIZE );/// 創建 grad_x 和 grad_y 矩陣Mat grad_x, grad_y;Mat abs_grad_x, abs_grad_y;/// 求 X方向梯度//Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );convertScaleAbs( grad_x, abs_grad_x );/// 求Y方向梯度//Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT );Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );convertScaleAbs( grad_y, abs_grad_y );/// 合并梯度(近似)addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );imshow( window_name, grad );waitKey(0);return 0;}

    解釋

  • 首先申明變量:

    Mat src, src_gray; Mat grad; char* window_name = "Sobel Demo - Simple Edge Detector"; int scale = 1; int delta = 0; int ddepth = CV_16S;
  • 裝載原圖像?src:

    src = imread( argv[1] );if( !src.data ) { return -1; }
  • 第一步對原圖像使用?GaussianBlur?降噪 ( 內核大小 = 3 )

    GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
  • 將降噪后的圖像轉換為灰度圖:

    cvtColor( src, src_gray, CV_RGB2GRAY );
  • 第二步,在?x?和?y?方向分別”求導“。 為此,我們使用函數?Sobel?:

    Mat grad_x, grad_y; Mat abs_grad_x, abs_grad_y;/// 求 X方向梯度 Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); /// 求 Y方向梯度 Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );

    該函數接受了以下參數:

    • src_gray: 在本例中為輸入圖像,元素類型?CV_8U
    • grad_x/grad_y: 輸出圖像.
    • ddepth: 輸出圖像的深度,設定為?CV_16S?避免外溢。
    • x_order:?x?方向求導的階數。
    • y_order:?y?方向求導的階數。
    • scale,?delta?和?BORDER_DEFAULT: 使用默認值

    注意為了在?x?方向求導我們使用:??,?. 采用同樣方法在?y?方向求導。

  • 將中間結果轉換到?CV_8U:

    convertScaleAbs( grad_x, abs_grad_x ); convertScaleAbs( grad_y, abs_grad_y );
  • 將兩個方向的梯度相加來求取近似?梯度?(注意這里沒有準確的計算,但是對我們來講已經足夠了)。

    addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
  • 最后,顯示結果:

    imshow( window_name, grad );
  • 結果

  • 這里是將Sobel算子作用于?lena.jpg?的結果:

  • 總結

    以上是生活随笔為你收集整理的opencv sobel导数的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。