2016-06-17 17 views
0

出力ピクセルの可能な最大値または最小値を所定の範囲で制限する画像フィルタリング用の「適応型」畳み込みを実装しようとしています。私はこれを行うことを可能にするopencvの機能を発見していないので、私は私が探しているものを達成するために自分自身を書きました。 (おそらく別のライブラリはありますか?)唯一の問題は、この関数は約0.9秒かかりますが、cv :: filter2Dが画像をフィルタリングするのにかかる時間は約0.005秒(同じカーネルで)です。誰も私の方法をスピードアップできる方法を知っていますか?畳み込み関数を高速化するC++

私のカーネルに関するいくつかのコメント:9x9カスタムシャープニングフィルタであり、カーネルは分離できません。分離可能にするためにフィルターを再設計しようとしましたが、目的の結果が得られません。何かご意見は?以下は、私は私のコードに使用する機能は次のとおりです。

Mat& adaptive_convolution(Mat& img) 
{ 

    fstream in("kernel.txt"); 
    string line; 

    float v[9][9]; 
    int i = 0, k = 0; 

    while (getline(in, line)) 
    { 
     float value; 
     int k = 0; 
     stringstream ss(line); 

     while (ss >> value) 
     { 
      v[i][k] = value; 
      ++k; 
     } 
     ++i; 
    } 


    clock_t init, end; 
    double minVal; 
    double maxVal; 
    Point minLoc; 
    Point maxLoc; 

    int pad_fact = 4; 
    int top, left, bottom, right; 

    Mat new_image = img; 
    top = pad_fact; bottom = pad_fact; 
    left = pad_fact; right = pad_fact; 

    copyMakeBorder(img, new_image, top, bottom, left, right, BORDER_CONSTANT, 0); 

    minMaxLoc(img, &minVal, &maxVal, &minLoc, &maxLoc); 
    new_image/2^8; 
    init = clock(); 
    double temp = 0; 

    for (int i = pad_fact; i < img.rows + pad_fact; i++) 
    { 
     for (int j = pad_fact; j < img.cols + pad_fact; j++) 
     { 
      for (int ii = -pad_fact; ii <= pad_fact; ii++) 
      { 
       for (int jj = -pad_fact; jj <= pad_fact; jj++) 
       { 
        //temp = double(v[ii + 2*pad_fact][jj + 2*pad_fact]); 
        temp = temp + double(v[ii + pad_fact][jj + pad_fact] * float(new_image.at<uchar>(i - jj, j - ii))); 
        //temp = double(new_image.at<uchar>(i - jj, j - ii)); 
       } 
      } 
      if (temp > maxVal) 
      { 
       temp = maxVal; 
      } 
      else 
      { 
       if (temp < minVal) 
       { 
        temp = minVal; 
       } 
      } 
      new_image.at<uchar>(i, j) = temp; 
      temp = 0; 
     } 
    } 



    img = new_image; 
    end = clock(); 
    cout << float(end - init)/1000 << endl; 
    return img; 
} 

EDIT:

私はNumbaを使用して約0.2秒に使用していますPythonスクリプトで畳み込みをスピードアップすることができました。私はまだC++を使ってこの種の改善を見なければなりません。私はopencvを使って助けていますか?

import numba as nb 
import numpy as np 

@nb.autojit 
def custom_convolve(image,kernel,pad_fact): 
    pad_fact = int(pad_fact) 
    filt_im = np.zeros(image.shape) 
    rows = image.shape[0] 
    columns = image.shape[1] 
    glob_max = np.max(image) 
    glob_min = np.min(image) 

    for x in range(pad_fact,columns-pad_fact,1): 
     for y in range(pad_fact,rows-pad_fact,1): 
      pix_sum = 0 
      for k in range(-pad_fact,pad_fact,1): 
       for j in range(-pad_fact,pad_fact,1): 
        pix_sum = pix_sum + kernel[k+pad_fact,j+pad_fact]*image[y-j,x-k] 

      if pix_sum > glob_max: 
       pix_sum = glob_max 
      elif pix_sum < glob_min: 
       pix_sum = glob_min 

      filt_im[y,x] = pix_sum 
    return filt_im 
+0

計算 'new_image.at (i、j)'を並列化することは可能ですか? – AndyG

+0

最も外側のループに "parallel_for_"を使用するのは意味がありますか?私は、parallel_for_ループ内の引数を読み込みからどのように記述するかについては正確にはわかりません。また、特定のC++ライブラリを使用してループを並列化するさまざまな方法があることも確認しています。特にどの方法をお勧めしますか? – RMatt

+0

なぜ畳み込みの後に値*をクランプできないのですか? – beaker

答えて

0

基本OpenCVの実装は、2つのプロセスadditon等128ビット変数を使用して並列を可能SSE functionを使用しているのほとんど。フィルタカーネルはseparableであり、次のように構成することができる場合、別のトリックである:

K = D * D」

* convolutation演算子を表し、Dは、例えばベクターであります[1 2 1]、Kは最終カーネルです。画像Aのフィルタリングを画像Bに置き換えることができます。

B = A * K;

B = A * D(*)(* D) 'と

ここで(*)は、画素ごとの乗算を示し、転置記号 '転置画像すなわちを表します'。

+0

私の元の投稿から、私のカーネルは分離できません。私はSSEの機能を見ていきます。 – RMatt

関連する問題