簡體   English   中英

加快卷積函數C ++

[英]Speed up Convolution Function C++

我正在嘗試為圖像過濾實現“自適應”卷積,將輸出像素的最大或最小可能值限制為預定范圍。 我沒有在opencv中找到任何允許執行此操作的函數,因此我編寫了自己的函數來實現我想要的功能。 (也許有一個不同的庫嗎?)唯一的問題是此功能大約需要0.9秒,而cv :: filter2D過濾圖像所需的時間大約是0.005秒(兩者都具有相同的內核)。 有誰知道我如何加快我的方法?

關於我的內核的幾點評論:這是一個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;
}

編輯:

我使用Numba可以將我正在使用的python腳本中的卷積加速到大約0.2秒。 我仍然需要看到使用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

大多數基本的OpenCV實現都使用SSE功能 ,該功能允許使用128位變量並行添加兩個進程。 另一個技巧是過濾器內核是否可分離並且可以組成如下:

K = D * D'

其中*表示卷積運算符,D是向量,例如[1 2 1],而K是最終核。 比您可以將圖像A的過濾替換為圖像B:

B = A * K;

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

此處(*)表示像素相乘,A'表示轉置圖像,即'轉置符號。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM