各向异性扩散

时间:2015-12-11 16:25:13

标签: c++ opencv image-processing

我已将此Matlab各向异性扩散代码转换为C ++,但我没有得到所需的输出。我得到的只是一个黑色的图像。有人可以检查我的代码并提出任何建议吗?以下是我的代码:

const double lambda = 1 / 7;
const double k = 30;
const int iter = 1;


int ahN[3][3] = { {0, 1, 0}, {0, -1, 0}, {0, 0, 0} };
int ahS[3][3] = { {0, 0, 0}, {0, -1, 0}, {0, 1, 0} };
int ahE[3][3] = { {0, 0, 0}, {0, -1, 1}, {0, 0, 0} };
int ahW[3][3] = { {0, 0, 0}, {1, -1, 0}, {0, 0, 0} };
int ahNE[3][3] = { {0, 0, 1}, {0, -1, 0}, {0, 0, 0} };
int ahSE[3][3] = { {0, 0, 0}, {0, -1, 0}, {0, 0, 1} };
int ahSW[3][3] = { {0, 0, 0}, {0, -1, 0}, {1, 0, 0} };
int ahNW[3][3] = { {1, 0, 0}, {0, -1, 0}, {0, 0, 0} };

Mat hN = Mat(3, 3, CV_32FC1, &ahN);
Mat hS = Mat(3, 3, CV_32FC1, &ahS);
Mat hE = Mat(3, 3, CV_32FC1, &ahE);
Mat hW = Mat(3, 3, CV_32FC1, &ahW);
Mat hNE = Mat(3, 3, CV_32FC1, &ahNE);
Mat hSE = Mat(3, 3, CV_32FC1, &ahSE);
Mat hSW = Mat(3, 3, CV_32FC1, &ahSW);
Mat hNW = Mat(3, 3, CV_32FC1, &ahNW);

void anisotropicDiffusion(Mat &output, int width, int height) {

//mat initialisation
Mat nablaN, nablaS, nablaW, nablaE, nablaNE, nablaSE, nablaSW, nablaNW;
Mat cN, cS, cW, cE, cNE, cSE, cSW, cNW;

//depth of filters
int ddepth = -1;

//center pixel distance
double dx = 1, dy = 1, dd = sqrt(2);
double idxSqr = 1.0 / (dx * dx), idySqr = 1.0 / (dy * dy), iddSqr = 1 / (dd * dd);

for (int i = 0; i < iter; i++) {

    //filters 
    filter2D(output, nablaN, ddepth, hN);
    filter2D(output, nablaS, ddepth, hS);
    filter2D(output, nablaW, ddepth, hW);
    filter2D(output, nablaE, ddepth, hE);
    filter2D(output, nablaNE, ddepth, hNE);
    filter2D(output, nablaSE, ddepth, hSE);
    filter2D(output, nablaSW, ddepth, hSW);
    filter2D(output, nablaNW, ddepth, hNW);

    //exponential flux
    cN = nablaN / k;
    cN.mul(cN);
    cN = 1.0 / (1.0 + cN);
    //exp(-cN, cN);

    cS = nablaS / k;
    cS.mul(cS);
    cS = 1.0 / (1.0 + cS);
    //exp(-cS, cS);

    cW = nablaW / k;
    cW.mul(cW);
    cW = 1.0 / (1.0 + cW);
    //exp(-cW, cW);

    cE = nablaE / k;
    cE.mul(cE);
    cE = 1.0 / (1.0 + cE);
    //exp(-cE, cE);

    cNE = nablaNE / k;
    cNE.mul(cNE);
    cNE = 1.0 / (1.0 + cNE);
    //exp(-cNE, cNE);

    cSE = nablaSE / k;
    cSE.mul(cSE);
    cSE = 1.0 / (1.0 + cSE);
    //exp(-cSE, cSE);

    cSW = nablaSW / k;
    cSW.mul(cSW);
    cSW = 1.0 / (1.0 + cSW);
    //exp(-cSW, cSW);

    cNW = nablaNW / k;
    cNW.mul(cNW);
    cNW = 1.0 / (1.0 + cNW);
    //exp(-cNW, cNW);

    output = output + lambda * (idySqr * cN.mul(nablaN) + idySqr * cS.mul(nablaS) + 
                                idxSqr * cW.mul(nablaW) + idxSqr * cE.mul(nablaE) +
                                iddSqr * cNE.mul(nablaNE) + iddSqr * cSE.mul(nablaSE) +
                                iddSqr * cNW.mul(nablaNW) + iddSqr * cSW.mul(nablaSW));
    }
}

2 个答案:

答案 0 :(得分:1)

看起来你需要分配乘法结果:

Mat C = A.mul(B);

int ahN[3][3] .... 

应该是

float ahN[3][3] ....

答案 1 :(得分:0)

在c#中解决。易于翻译成c ++ 你需要这个变量:

IMAGE [height,width] =存储图像的整数数组

height =以像素为单位的图像高度

width =以像素为单位的图像宽度

/// <summary>Perona & Malik anisotropic difusion filter. (squared formula)</summary>
/// <param name="data">Image data</param>
/// <param name="dt">Heat difusion value. Upper = more rapid convergence.</param>
/// <param name="lambda">The shape of the diffusion coefficient g(), controlling the Perona Malik diffusion g(delta) = 1/((1 +  delta2)  / lambda2). Upper = more blurred image & more noise removed</param>
/// <param name="interations">Determines the maximum number of iteration steps of the filter. Upper = less speed & more noise removed</param>
private void PeronaMalik(int[,] image, double dt, int lambda, int interations)
{
    try
    {
        //test parameters
        if (dt < 0)
            throw new Exception("DT negative value not allowed");
        if (lambda < 0)
            throw new Exception("lambda must be upper of 0");
        if (interations <= 0)
            throw new Exception("Iterations must be upper of 0");

        //Make temp image
        int[,] temp = new int[height, width];
        Array.Copy(image, temp, image.Length);

        //Precalculate tables (for speed up)
        double[] precal = new double[512];
        double lambda2 = lambda * lambda;
        for (int f = 0; f < 512; f++)
        {
            int diff = f - 255;
            precal[f] = -dt * diff * lambda2 / (lambda2 + diff * diff);
        }

        //Apply the filter
        for (int n = 0; n < interations; n++)
        {
            for (int h = 0; h < height; h++)
                for (int w = 0; w < width; w++)
                {
                    int current = temp[h, w];

                    int px = w - 1;
                    int nx = w + 1;
                    int py = h - 1;
                    int ny = h + 1;
                    if (px < 0)
                        px = 0;
                    if (nx >= width)
                        nx = width - 1;
                    if (py < 0)
                        py = 0;
                    if (ny >= height)
                        ny = height - 1;

                    image[h, w] = (int)(precal[255 + current - temp[h, px]] +
                                        precal[255 + current - temp[h, nx]] +
                                        precal[255 + current - temp[py, w]] +
                                        precal[255 + current - temp[ny, w]]) +
                                        temp[h, w];
                }
        }
    }
    catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn PeronaMalik"); }
}

解决方案是等式2.如果你想要方程1(指数),你可以改变预先表格中的ecuation:

precal[f] = -dt * delta * Math.Exp(-(delta * delta / lambda2));