opencv过滤器在多维Mat上

时间:2013-12-30 08:54:19

标签: c++ opencv

我想将以下代码传输到c ++:

gaussFilter = fspecial('gaussian', 2*neighSize+1, 0.5*neighSize);
pointFeature = imfilter(pointFeature, gaussFilter, 'symmetric');

其中pointFeature是[height,width,24]数组。

我尝试使用filter2D,但它只支持2D数组。

所以我想知道opencv中是否有可以过滤多维数组的函数?

2 个答案:

答案 0 :(得分:1)

您可以使用可分离的内核过滤器进行任意定义过滤。

答案 1 :(得分:1)

如果您使用的是OpenCV,可以尝试使用3维MatND:

void Smooth3DHist(cv::MatND &hist, const int& kernDimension)
{

    assert(hist.dims == 3);
    int x_size  = hist.size[0];
    int y_size  = hist.size[1];
    int z_size  = hist.size[2];
    int xy_size = x_size*y_size;

    cv::Mat kernal = cv::getGaussianKernel(kernDimension, -1, CV_32F);

    // Filter XY dimensions for every Z
    for (int z = 0; z < z_size; z++)
    {
        float *ind = (float*)hist.data + z * xy_size; // sub-matrix pointer
        cv::Mat subMatrix(2, hist.size, CV_32F, ind);
        cv::sepFilter2D(subMatrix, subMatrix, CV_32F, kernal.t(), kernal, Point(-1,-1), 0.0, cv::BORDER_REPLICATE);
    }

    // Filter Z dimension
    float* kernGauss = (float *)kernal.data;
    unsigned kernSize = kernal.total();
    int kernMargin = (kernSize - 1)/2;
    float* lineBuffer = new float[z_size + 2*kernMargin];
    for (int y = 0; y < y_size; y++)
    {
        for (int x = 0; x < x_size; x++)
        {
            // Copy along Z dimension into a line buffer
            float* z_ptr = (float*)hist.data + y * x_size + x;//same as hist.ptr<float>(0, y, x)
            for (int z = 0; z < z_size; z++, z_ptr += xy_size)
            {
                lineBuffer[z + kernMargin] = *z_ptr;
            }

            // Replicate borders
            for (int m = 0; m < kernMargin; m++)
            {
                lineBuffer[m] = lineBuffer[kernMargin];// replicate left side
                lineBuffer[z_size + 2*kernMargin - 1 - m] = lineBuffer[kernMargin + z_size - 1];//replicate right side
            }

            // Filter line buffer 1D - convolution
            z_ptr = (float*)hist.data + y * x_size + x;
            for (int z = 0; z < z_size; z++, z_ptr += xy_size)
            {
                *z_ptr = 0.0f;
                for (unsigned k = 0; k < kernSize; k++)
                {
                    *z_ptr += lineBuffer[z+k]*kernGauss[k];
                }
            }
        }
    }
    delete [] lineBuffer;

}