2017-10-12 2 views
0

私は分離可能なソベルフィルタ実装の独自の実装の作成に取り組んでいます。私の関数は入力としてkernelSize、ピクセルY1の勾配Yの水平フィルタ、ピクセルY2の勾配Yの垂直フィルタ、ピクセルX1の勾配Xの水平フィルタ、ピクセルX2の勾配Xの垂直フィルタがあります。分離可能なソベルフィルタの実装openCV C++

X1の入力された[1、0、-1](水平)

X2の入力された[1、2、1](垂直)

Y1の入力である[1 Input Image 出力イメージ:、2、1](水平)

Y2の入力は[1、0 -1](垂直)

void gradientFilter1D(Mat& img, int kernelSize, vector<double> pixelsY1, vector<double> pixelsY2, vector<double> pixelsX1, vector<double> pixelsX2) 
{ 
    int sumMin = INT_MAX, sumMax = INT_MIN; 
    //gradient X 
    vector<vector<int>> pixelsX(img.rows, vector<int>(img.cols, 0)); 
    //gradient Y 
    vector<vector<int>> pixelsY(img.rows, vector<int>(img.cols, 0)); 
    vector<vector<int>> sumArray(img.rows, vector<int>(img.cols, 0)); 

    for (int j = kernelSize/2; j < img.rows - kernelSize/2; j++) 
    { 
     for (int i = kernelSize/2; i < img.cols - kernelSize/2; i++) 
     { 
      double totalX = 0; 
      double totalY = 0; 
      //this is the horizontal multiplication 
      for (int x = -kernelSize/2; x <= kernelSize/2; x++) 
      { 
       totalY += img.at<uchar>(j, i + x) * pixelsY1[x + (kernelSize/2)]; 
       totalX += img.at<uchar>(j, i + x) * pixelsX1[x + (kernelSize/2)]; 
       //cout << int(img.at<uchar>(j, i + x)) << " " << pixelsY1[x + (kernelSize/2)] << endl; 
      } 
      pixelsX[j][i] = totalX; 
      pixelsY[j][i] = totalY;  
     } 
    } 
    for (int j = kernelSize/2; j < img.rows - kernelSize/2; j++) 
    { 
     for (int i = kernelSize/2; i < img.cols - kernelSize/2; i++) 
     { 
      double totalX = 0; 
      double totalY = 0; 
      //this is the vertical multiplication 
      for (int x = -kernelSize/2; x <= kernelSize/2; x++) 
      { 
       totalY += pixelsY[j + x][i] * pixelsY2[x + (kernelSize/2)]; 
       totalX += pixelsX[j + x][i] * pixelsX2[x + (kernelSize/2)]; 
       //cout << int(img.at<uchar>(j, i + x)) << " " << pixelsY1[x + (kernelSize/2)] << endl; 
      } 
      pixelsX[j][i] = totalX; 
      pixelsY[j][i] = totalY; 
     } 
    } 
    for (int j = 0; j < img.rows; j++) 
    { 
     for (int i = 0; i < img.cols; i++) 
     { 
      int sum; 
      sum = sqrt(pow(pixelsX[j][i], 2) + pow(pixelsY[j][i], 2)); 
      sumArray[j][i] = sum; 
      sumMin = sumMin < sum ? sumMin : sum; 
      sumMax = sumMax > sum ? sumMax : sum; 
     } 
    } 
    //normalization 
    for (int j = 0; j < img.rows; j++) 
     for (int i = 0; i < img.cols; i++) 
     { 
      sumArray[j][i] = (sumArray[j][i] - sumMin) * ((255.0 - 0)/(sumMax - sumMin)) + 0; 
      img.at<uchar>(j, i) = sumArray[j][i]; 
     } 
} 

入力画像でありますOutput Image 何が間違っていますか?

答えて

0

分離可能フィルタは、実質的に2回通過するもので計算されます。 (パスはインターリーブすることができますが、垂直フィルタで使用されるすべての値は、水平フィルタによって順番に計算されている必要があります)。コメント//then here I do the vertical multiplicationのすぐ下には、ピクセルXおよびピクセルYへのアクセスがあります分離可能なフィルタの第2パス。 xの負の値でアクセスされた値は以前に計算されており、xの正の値に対する値は水平パスによってまだ計算されていません。

チェックアウトHalide。これは、この種のコードをより簡単に、よりパフォーマンスの高いものにします。

+0

私は正しいと分かっていれば、再びイメージを渡して、垂直の乗算を行いますか? – Vipoon

0

オーケー(のstd ::ベクトルの二重のネスティングが。行くには良い方法ではありません)ので、私のミスは、したがって、この

for (int j = kernelSize/2; j < img.rows - kernelSize/2; j++) 
    { 
     for (int i = kernelSize/2; i < img.cols - kernelSize/2; i++) 
     { 
      double totalX = 0; 
      double totalY = 0; 
      //this is the vertical multiplication 
      for (int x = -kernelSize/2; x <= kernelSize/2; x++) 
      { 
       totalY += pixelsY[j + x][i] * pixelsY2[x + (kernelSize/2)]; 
       totalX += pixelsX[j + x][i] * pixelsX2[x + (kernelSize/2)]; 
       //cout << int(img.at<uchar>(j, i + x)) << " " << pixelsY1[x + (kernelSize/2)] << endl; 
      } 
      pixelsX[j][i] = totalX; <---- I overwrite the old values 
      pixelsY[j][i] = totalY; <--- I overwrite the old values 
     } 
    } 

に実際にいた、pixelsX [J] [i]を= totalXと私が残りのj、iループで計算を終わらせるためには古い値が必要なので、そうではありません。だから、私はベクトルの別のベクトルを作成し、それにtotalXとYをプッシュし、これが私の問題を解決しました。

+0

ああ、ソーベルは2Dコンボリューションのようなものではないことに気がつきました。しかし、同じ問題です。垂直計算の値の半分は水平計算からのもので、半分は元の画像からのものです。修正は、水平計算からそれらをすべて取る私の提案ではなく、オリジナルからすべてを作ることです。 –

関連する問題