文章目錄
- 簡述:Sobel Scharr Laplacian
- Sobel算子
- Scharr算子
- Laplacian 算子
- 1. Sobel()
- DEMO
- 效果
- 2.Scharr()
- DEMO
- 效果
- 3. Laplacian()
- DEMO
- 效果
- 縮放,絕對值,轉換為無符號的8位型別 convertScaleAbs
- Depth combinations
簡述:Sobel Scharr Laplacian
Sobel算子是高斯平滑加微分運算的聯合運算,因此它更抗噪聲,你可以指定要采用的導數方向,垂直或水平(分別通過引數yorder和xorder),你還可以通過引數ksize指定內核的大小,如果ksize = -1,則使用3x3 Scharr濾波器,比3x3 Sobel濾波器具有更好的結果,
Sobel算子
k
e
r
n
e
l
=
[
?
1
0
1
?
2
0
2
?
1
0
1
]
kernel = \left[ \begin{matrix} -1 & 0 & 1 \\-2 & 0 & 2 \\ -1 & 0 & 1 \end{matrix} \right]
kernel=????1?2?1?000?121????
k
e
r
n
e
l
=
[
?
1
?
2
?
1
0
0
0
1
2
1
]
kernel = \left[ \begin{matrix} -1 & -2 & -1 \\0 & 0 & 0 \\ 1 & 2 & 1 \end{matrix} \right]
kernel=????101??202??101????
Scharr算子
k
e
r
n
e
l
=
[
?
3
0
3
?
10
0
10
?
3
0
3
]
kernel = \left[ \begin{matrix} -3 & 0 & 3 \\-10 & 0 & 10 \\ -3 & 0 & 3 \end{matrix} \right]
kernel=????3?10?3?000?3103????
k
e
r
n
e
l
=
[
?
3
?
10
?
3
0
0
0
3
10
3
]
kernel = \left[ \begin{matrix} -3 & -10 & -3 \\0 & 0 & 0 \\ 3 & 10 & 3\end{matrix} \right]
kernel=????303??10010??303????
和Sobel算子相比,scharr算子臨近像素的權重更大,所以精確度更高,能計算出更小的梯度變化
Laplacian 算子
如果ksize > 1 (ksize必須為正奇數) ,該函式通過Sobel算子計算出影像X方向和Y方向的二階導數,將兩個方向的導數求和得到Laplacian算子:
Δ
s
r
c
=
?
2
s
r
c
?
x
2
+
?
2
s
r
c
?
y
2
Δsrc=\frac{?^{2}src}{?x^{2}} + \frac{?^{2}src}{?y^{2}}
Δsrc=?x2?2src?+?y2?2src?
如果ksize = 1,則使用以下內核用于過濾:
k e r n e l = [ 0 1 0 1 ? 4 1 0 1 0 ] kernel=\left[ \begin{matrix} 0 & 1 & 0 \\1 & -4 & 1 \\ 0 & 1 & 0 \end{matrix} \right] kernel=???010?1?41?010????
1. Sobel()
注意:當輸出資料型別為cv::CV_8U時有一個小問題,黑色到白色的過渡被視為正斜率(具有正值),而白色到黑色的過渡被視為負斜率(具有負值),因此,將資料轉換為CV_8U時,所有負斜率均??設為零,簡而言之,就是會錯過這一邊緣資訊,如果要檢測兩個邊緣,更好的選擇是將輸出資料型別保留為更高的形式,例如cv::CV_16S,cv::CV_64F等,取其絕對值,然后轉換回cv::CV_8U,
CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize = 3,
double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
/*Sobel算子將高斯平滑和微分相結合,因此結果或多或少具有抗噪性,
通常,使用(xorder = 1,yorder = 0,ksize = 3)或(xorder = 0,yorder = 1,ksize = 3)來對x求導或對y求導,
第一種情況對應于一個內核:
-1 0 1
-2 0 2
-1 0 1
第二種情況對應于以下內核:
-1 -2 -1
0 0 0
1 2 1
@param src //輸入影像,
@param dst //輸出與src相同大小和相同通道數的影像,
@param ddepth //輸出影像深度,請參見 Depth combinations;對于8位輸入影像,將導致截斷的導數,
@param dx //導數x的階數
@para dy //導數y的階數,
@param ksize //擴展的Sobel內核的大小;它必須是1、3、5或7,
@param scale //計算出的導數值的可選比例因子;默認情況下,不應用縮放(有關詳細資訊,請參見#getDerivKernels),
@param delta //在將結果存盤在dst中之前將其添加到結果中的可選delta值,
@param borderType //像素外推方法,請參見#BorderTypes*/
DEMO
int main() {
cv::namedWindow("src", 0);
cv::namedWindow("dst", 0);
cv::Mat src = cv::imread("./img/test1.jpg", 1);
cv::Mat dst, dst_x, dst_y;
cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
cv::Sobel(src, dst_x, CV_16S, 1, 0, 3);
cv::Sobel(src, dst_y, CV_16S, 0, 1, 3);
cv::convertScaleAbs(dst_x, dst_x);
cv::convertScaleAbs(dst_y, dst_y);
cv::addWeighted(dst_x, 0.5, dst_y, 0.5, 0, dst);
cv::imshow("dst_x", dst_x);
cv::imshow("dst_y", dst_y);
cv::imshow("src", src);
cv::imshow("dst", dst);
cv::waitKey(0);
}
效果
原圖:

x方向邊緣檢測:

y方向邊緣檢測:

x和y方向邊緣檢測:

2.Scharr()
CV_EXPORTS_W void Scharr( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
@param src //輸入影像,
@param dst //輸出與src相同大小和相同通道數的影像,
@param ddepth //輸出影像深度,請參閱 Depth combinations
@param dx //導數x的階數
@para dy //導數y的階數,
@param scale //計算得出的導數值的可選比例因子; 默認情況下,不應用縮放(有關詳細資訊,請參見#getDerivKernels),
@param delta //在將結果存盤到dst之前將其添加到結果中的可選增量值,
@param borderType //像素外推方法,請參見#BorderTypes
DEMO
int main() {
cv::namedWindow("src", 0);
cv::namedWindow("dst", 0);
cv::Mat src = cv::imread("./img/test1.jpg", 1);
cv::Mat dst, dst_x, dst_y;
cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
cv::Scharr(src, dst_x, CV_16S, 1, 0, 3);
cv::Scharr(src, dst_y, CV_16S, 0, 1, 3);
cv::convertScaleAbs(dst_x, dst_x);
cv::convertScaleAbs(dst_y, dst_y);
cv::addWeighted(dst_x, 0.5, dst_y, 0.5, 0, dst);
cv::imshow("dst_x", dst_x);
cv::imshow("dst_y", dst_y);
cv::imshow("src", src);
cv::imshow("dst", dst);
cv::waitKey(0);
}
效果
原圖:

x反向邊緣檢測:

y方向邊緣檢測:

x和y方向邊緣檢測:

3. Laplacian()
注意:Laplacian算子具有各方向同性的特點,能夠對任意方向的邊緣進行提取,具有無方向性的優點,因此使用Laplacian算子提取邊緣不需要分別檢測X方向的邊緣和Y方向的邊緣,只需要一次邊緣檢測即可,Laplacian算子是一種二階導數算子,對噪聲比較敏感,因此常需要配合高斯濾波一起使用,
CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth,
int ksize = 1, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
/*
@param src //源影像,
@param dst //與src具有相同大小和相同通道數的目標影像,
@param ddepth //所需目標影像的深度,
@param ksize //用于計算二階導數濾波器的孔徑大小, 有關詳細資訊,請參見#getDerivKernels, 大小必須為正數和奇數,
@param scale //計算的Laplacian值的可選比例因子, 默認情況下,不應用縮放, 有關詳細資訊,請參見#getDerivKernels,
@param delta //在將結果存盤到dst之前將其添加到結果中的可選增量值,
@param borderType //像素外推方法,請參見#BorderTypes
*/
DEMO
int main() {
cv::namedWindow("src", 0);
cv::namedWindow("dst", 0);
cv::Mat src = cv::imread("./img/test1.jpg", 1);
cv::Mat dst, dst_x, dst_y, src_gs;
cv::cvtColor(src, src, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(src, src_gs, cv::Size(3, 3), 5, 0); //高斯濾波
cv::Laplacian(src_gs, dst, CV_16S, 1, 3);
cv::convertScaleAbs(dst, dst);
cv::imshow("src", src);
cv::imshow("dst", dst);
cv::waitKey(0);
cv::imwrite("./img/dst.jpg", dst);
cv::imwrite("./img/src.jpg", src);
}
效果
原圖:

結果:

縮放,絕對值,轉換為無符號的8位型別 convertScaleAbs
/*函式convertScaleAbs按順序執行三個操作:縮放,絕對值,轉換為無符號的8位型別*/
CV_EXPORTS_W void convertScaleAbs(InputArray src, OutputArray dst,
double alpha = 1, double beta = 0);
Depth combinations
| Input depth (src.depth()) | Output depth (ddepth) |
|---|---|
| CV_8U | -1/CV_16S/CV_32F/CV_64F |
| CV_16U/CV_16S | -1/CV_32F/CV_64F |
| CV_32F | -1/CV_32F/CV_64F |
| CV_64F | -1/CV_64F |
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/229405.html
標籤:AI
