繁体   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