摘要: 通過調用 magnitude
/ phase
/ cartToPolar
, 分別實現梯度幅值/角度的單獨計算和同時計算, 並輸出/顯示. 需要說明的是, 示例函數可適用於三通道圖像, 但計算三通道圖像的梯度意義不大, 這裏限定爲單通道.
計算圖像差分
參考來源: OpenCV Tutorials: Sobel Derivatives
Sobel 算子
- Sobel算子是高斯平滑和微分操作的結合體, 能夠更好的抗噪;
- 使用擴展的Sobel算子可以計算一階,二階, 三階或混合圖像的差分;
- x 方向指的是 Horizontal changes
- y 方向指的是 Vertical changes
Scharr 算子
- Sobel 算子計算的差分的近似值. 當
ksize=3
時, 可能產生較明顯的誤差; - Scharr 算子是Sobel算子的優化. OpenCV中只能使用
ksize=3
, 速度一致, 但結果更準確.
差分顯示
void imshowDifferentiation(Mat img)
{
assert(img.channels() == 1);
Mat dx, dy, value;
Sobel(img, dx, CV_32F, 1, 0, 3);
Sobel(img, dy, CV_32F, 0, 1, 3);
magnitude(dx, dy, value);
// 顯示差分圖像, 包含負值, 需要轉換尺度
convertScaleAbs(dx, dx);
imshow("dx", dx);
convertScaleAbs(dy, dy);
imshow("dy", dy);
}
計算梯度幅值
- 一般認爲, 梯度即爲梯度的幅值大小, 但爲了避免歧義, 這裏統稱
梯度幅值
,梯度方向角
- 計算公式如下:
- 代碼示例:
void calculateGradientValue(Mat img)
{
assert(img.channels() == 1);
Mat dx, dy, value;
Sobel(img, dx, CV_32F, 1, 0, 3);
Sobel(img, dy, CV_32F, 0, 1, 3);
magnitude(dx, dy, value);
// 顯示梯度幅值圖像
value.convertTo(value, CV_8U, 1);
imshow("magnitude", value);
}
計算梯度方向角
- 計算公式如下:
- 代碼示例:
void calculateGradienAngle(Mat img)
{
assert(img.channels() == 1);
Mat dx, dy, angle;
Sobel(img, dx, CV_32F, 1, 0, 3);
Sobel(img, dy, CV_32F, 0, 1, 3);
// 計算梯度角度(弧度制)
phase(dx, dy, angle);
cout << "梯度方向角(弧度制): " << angle(Rect(0, 0, 10, 1)) << endl;
// 計算梯度角度(角度制)
phase(dx, dy, angle, true);
cout << "梯度方向角(角度制): " << angle(Rect(0, 0, 10, 1)) << endl;
}
同時計算梯度幅值和方向角
void calculateGradient(Mat img)
{
assert(img.channels() == 1);
Mat dx, dy, value, angle;
Sobel(img, dx, CV_32F, 1, 0, 3);
Sobel(img, dy, CV_32F, 0, 1, 3);
// 計算梯度幅值和角度(弧度制)
cartToPolar(dx, dy, value, angle);
cout << "梯度方向角(弧度制): " << angle(Rect(0, 0, 10, 1)) << endl;
// 計算梯度幅值和角度(角度制)
cartToPolar(dx, dy, value, angle, true);
cout << "梯度方向角(角度制): " << angle(Rect(0, 0, 10, 1)) << endl;
// 顯示梯度幅值圖像
value.convertTo(value, CV_32F, 1. / 255);
imshow("cartToPolar", value);
}
HOG特徵
限於篇幅,請訪問 https://blog.csdn.net/Augurlee/article/details/105034336