3

一部のコードを Matlab から Opencv に移行しようとしていますが、勾配関数の正確なレプリカが必要です。cv::Sobel 関数を試しましたが、何らかの理由で、結果の cv::Mat の値が Matlab バージョンの値と同じではありません。さらに計算するには、X と Y の勾配を別々の行列に入れる必要があります。

これを達成できる回避策は素晴らしいでしょう

4

5 に答える 5

6

Sobel はイメージ ピクセルの 2 次導関数しか計算できませんが、これは私たちが望んでいるものではありません。

(f(i+1,j) + f(i-1,j) - 2f(i,j)) / 2

私たちが欲しいのは

(f(i+i,j)-f(i-1,j)) / 2

だから私たちは適用する必要があります

Mat kernelx = (Mat_<float>(1,3)<<-0.5, 0, 0.5);
Mat kernely = (Mat_<float>(3,1)<<-0.5, 0, 0.5);
filter2D(src, fx, -1, kernelx)
filter2D(src, fy, -1, kernely);

Matlab は境界ピクセルを内部ピクセルとは異なる方法で扱います。したがって、上記のコードは境界値で間違っています。BORDER_CONSTANT を使用して境界値を定数で拡張することができますが、残念ながら定数は OpenCV では -1 であり、0 に変更することはできません (これが必要です)。

境界値に関しては、私はそれに対する非常にきちんとした答えを持っていません。手で一次導関数を計算してみてください...

于 2014-02-07T08:34:55.590 に答える
0

Matlab は、内側の行と境界行の勾配を異なる方法で計算します (もちろん列にも同じことが当てはまります)。境界では、単純な前方差gradY(1) = row(2) - row(1)です。内側の行の勾配は、中心差によって計算されますgradY(2) = (row(3) - row(1)) / 2

OpenCV でマトリックス全体に対して単一の畳み込みフィルターを実行するだけでは、同じ結果を達成できないと思います。とともに使用cv::Sobel()ksize = 1、境界線を処理します (手動で、または [ 1 -1 ] フィルターを適用して)。

于 2013-10-08T19:50:21.467 に答える
0

Peiの答えは部分的に正しいです。Matlab は境界線に次の計算を使用します。

G(:,1) = A(:,2) - A(:,1); G(:,N) = A(:,N) - A(:,N-1);

そのため、次の opencv コードを使用してグラデーションを完成させました。

static cv::Mat kernelx = (cv::Mat_<double>(1, 3) << -0.5, 0, 0.5);
static cv::Mat kernely = (cv::Mat_<double>(3, 1) << -0.5, 0, 0.5);
cv::Mat fx, fy;

cv::filter2D(Image, fx, -1, kernelx, cv::Point(-1, -1), 0, cv::BORDER_REPLICATE);
cv::filter2D(Image, fy, -1, kernely, cv::Point(-1, -1), 0, cv::BORDER_REPLICATE);

fx.col(fx.cols - 1) *= 2;
fx.col(0) *= 2;
fy.row(fy.rows - 1) *= 2;
fy.row(0) *= 2;
于 2017-05-23T15:16:59.650 に答える