Qt图像处理技术一:对QImage图片美颜,使用双指数滤波

一、效果图

Qt图像处理技术一:对QImage图片美颜,使用双指数滤波_第1张图片

二、demo源码地址(除了磨皮还有一些基本的滤镜)

如果你觉得有用的话,期待你的小星星
实战应用项目:
github :https://github.com/dependon/simple-image-filter //纯qt图像处理项目

三、接口代码

img参数是原始图像,返回的是处理后的图像

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
QImage QImageAPI::QImageD_RunBEEPSHorizontalVertical(const QImage &img, double spatialDecay, double photometricStandardDeviation)
{

    QImage imgCopy = QImage(img);

    double c = -0.5 / (photometricStandardDeviation * photometricStandardDeviation); //-1/2 *光度标准偏差的平方
    double mu = spatialDecay / (2 - spatialDecay);

    double *exptable = new double[256];
    double *g_table = new double[256];
    for (int i = 0; i <= 255; i++) {
        exptable[i] = (1 - spatialDecay) * exp(c * i * i);
        g_table[i] = mu * i;
    }
    int width = img.width();
    int height = img.height();
    int length = width * height;
    double *data2Red = new double[length];
    double *data2Green = new double[length];
    double *data2Blue = new double[length];

    int i = 0;

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            QRgb rgb = imgCopy.pixel(x, y);
            data2Red[i] = qRed(rgb);
            data2Green[i] = qGreen(rgb);
            data2Blue[i] = qBlue(rgb);
            i++;
        }
    }


    double *gRed = new double[length];
    double *pRed = new double[length];
    double *rRed = new double[length];

    double *gGreen = new double[length];
    double *pGreen = new double[length];
    double *rGreen = new double[length];

    double *gBlue = new double[length];
    double *pBlue = new double[length];
    double *rBlue = new double[length];
    memcpy(pRed, data2Red, sizeof(double) * length);
    memcpy(rRed, data2Red, sizeof(double) * length);

    memcpy(pGreen, data2Green, sizeof(double) * length);
    memcpy(rGreen, data2Green, sizeof(double) * length);

    memcpy(pBlue, data2Blue, sizeof(double) * length);
    memcpy(rBlue, data2Blue, sizeof(double) * length);


    double rho0 = 1.0 / (2 - spatialDecay);
    for (int k2 = 0; k2 < height; ++k2) {
        int startIndex = k2 * width;
        double mu = 0.0;
        for (int k = startIndex + 1, K = startIndex + width; k < K; ++k) {
            int div0Red = fabs(pRed[k] - pRed[k - 1]);
            mu = exptable[div0Red];
            pRed[k] = pRed[k - 1] * mu + pRed[k] * (1.0 - mu);//公式1

            int div0Green = fabs(pGreen[k] - pGreen[k - 1]);
            mu = exptable[div0Green];
            pGreen[k] = pGreen[k - 1] * mu + pGreen[k] * (1.0 - mu);//公式1

            int div0Blue = fabs(pBlue[k] - pBlue[k - 1]);
            mu = exptable[div0Blue];
            pBlue[k] = pBlue[k - 1] * mu + pBlue[k] * (1.0 - mu);//公式1

        }

        for (int k = startIndex + width - 2; startIndex <= k; --k) {
            int div0Red = fabs(rRed[k] - rRed[k + 1]);
            double mu = exptable[div0Red];
            rRed[k] = rRed[k + 1] * mu + rRed[k] * (1.0 - mu);//公式3

            int div0Green = fabs(rGreen[k] - rGreen[k + 1]);
            mu = exptable[div0Green];
            rGreen[k] = rGreen[k + 1] * mu + rGreen[k] * (1.0 - mu);//公式3

            int div0Blue = fabs(rBlue[k] - rBlue[k + 1]);
            mu = exptable[div0Blue];
            rBlue[k] = rBlue[k + 1] * mu + rBlue[k] * (1.0 - mu);//公式3
        }
        for (int k = startIndex, K = startIndex + width; k < K; k++) {
            rRed[k] = (rRed[k] + pRed[k]) * rho0 - g_table[(int)data2Red[k]];
            rGreen[k] = (rGreen[k] + pGreen[k]) * rho0 - g_table[(int)data2Green[k]];
            rBlue[k] = (rBlue[k] + pBlue[k]) * rho0 - g_table[(int)data2Blue[k]];
        }
    }

    int m = 0;
    for (int k2 = 0; k2 < height; k2++) {
        int n = k2;
        for (int k1 = 0; k1 < width; k1++) {
            gRed[n] = rRed[m];
            gGreen[n] = rGreen[m];
            gBlue[n] = rBlue[m];
            m++;
            n += height;
        }
    }

    memcpy(pRed, gRed, sizeof(double) * height * width);
    memcpy(rRed, gRed, sizeof(double) * height * width);

    memcpy(pGreen, gGreen, sizeof(double) * height * width);
    memcpy(rGreen, gGreen, sizeof(double) * height * width);

    memcpy(pBlue, gBlue, sizeof(double) * height * width);
    memcpy(rBlue, gBlue, sizeof(double) * height * width);

    for (int k1 = 0; k1 < width; ++k1) {
        int startIndex = k1 * height;
        double mu = 0.0;
        for (int k = startIndex + 1, K = startIndex + height; k < K; ++k) {
            int div0Red = fabs(pRed[k] - pRed[k - 1]);
            mu = exptable[div0Red];
            pRed[k] = pRed[k - 1] * mu + pRed[k] * (1.0 - mu);

            int div0Green = fabs(pGreen[k] - pGreen[k - 1]);
            mu = exptable[div0Green];
            pGreen[k] = pGreen[k - 1] * mu + pGreen[k] * (1.0 - mu);

            int div0Blue = fabs(pBlue[k] - pBlue[k - 1]);
            mu = exptable[div0Blue];
            pBlue[k] = pBlue[k - 1] * mu + pBlue[k] * (1.0 - mu);
        }
        for (int k = startIndex + height - 2; startIndex <= k; --k) {
            int div0Red = fabs(rRed[k] - rRed[k + 1]);
            mu = exptable[div0Red];
            rRed[k] = rRed[k + 1] * mu + rRed[k] * (1.0 - mu);

            int div0Green = fabs(rGreen[k] - rGreen[k + 1]);
            mu = exptable[div0Green];
            rGreen[k] = rGreen[k + 1] * mu + rGreen[k] * (1.0 - mu);

            int div0Blue = fabs(rBlue[k] - rBlue[k + 1]);
            mu = exptable[div0Blue];
            rBlue[k] = rBlue[k + 1] * mu + rBlue[k] * (1.0 - mu);
        }
    }

    double init_gain_mu = spatialDecay / (2 - spatialDecay);
    for (int k = 0; k < length; ++k) {
        rRed[k] = (rRed[k] + pRed[k]) * rho0 - gRed[k] * init_gain_mu;

        rGreen[k] = (rGreen[k] + pGreen[k]) * rho0 - gGreen[k] * init_gain_mu;

        rBlue[k] = (rBlue[k] + pBlue[k]) * rho0 - gBlue[k] * init_gain_mu;

    }

    m = 0;
    for (int k1 = 0; k1 < width; ++k1) {
        int n = k1;
        for (int k2 = 0; k2 < height; ++k2) {

            data2Red[n] = rRed[m];
            data2Green[n] = rGreen[m];
            data2Blue[n] = rBlue[m];
            imgCopy.setPixel(k1, k2, qRgb(data2Red[n], data2Green[n], data2Blue[n]));
            m++;
            n += width;
        }
    }
    delete []data2Red;
    data2Red = nullptr;
    delete []data2Green ;
    data2Green = nullptr;
    delete []data2Blue;
    data2Blue = nullptr;

    delete []pRed;
    pRed = nullptr;
    delete []rRed;
    rRed = nullptr;
    delete []gRed;
    gRed = nullptr;

    delete []pGreen;
    pGreen = nullptr;
    delete []rGreen;
    rGreen = nullptr;
    delete []gGreen;
    gGreen = nullptr;

    delete []pBlue;
    pBlue = nullptr;
    delete []rBlue;
    rBlue = nullptr;
    delete []gBlue;
    gBlue = nullptr;

    delete []exptable;
    exptable = nullptr;
    delete []g_table;
    g_table = nullptr;


    return imgCopy;
}

四、原始代码(上面接口是根据原始代码修改的)

//原始代码 
    static void RunBEEPSVerticalHorizontal(double *data,int width,int height,double spatialDecay,double *exp_table,double *g_table)
    {
        int length0=height*width;
        double* g= new double[length0];
        int m = 0;
        for (int k2 = 0;k2<height;++k2)
        {
            int n = k2;
            for (int k1 = 0;k1<width;++k1)
            {
                g[n]=data[m++];
                n += height;
            }
        }
        double*p = new double[length0];
        double*r = new double[length0];
        memcpy(p, g, sizeof(double) * length0);
        memcpy(r, g, sizeof(double) * length0);
        for (int k1 = 0;k1<width; ++k1)
        {
            int startIndex=k1 * height;
            double mu = 0.0;
            for (int k=startIndex+1,K =startIndex+height;k<K;++k)
            {
                int div0=fabs(p[k]-p[k-1]);
                mu =exp_table[div0];
                p[k] = p[k - 1] * mu + p[k] * (1.0 - mu);//文献中的公式1,这里做了一下修改,效果影响不大
            }
            for (int k =startIndex+height-2;startIndex <= k;--k)
            {
                int div0=fabs(r[k]-r[k+1]);
                mu =exp_table[div0];
                r[k] = r[k+1] * mu + r[k] * (1.0-mu) ;//文献公式3
            }
        }
        double rho0=1.0/(2-spatialDecay);
        for (int k = 0;k <length0;++k)
        {
            r[k]= (r[k]+p[k])*rho0-g_table[(int)g[k]];
        }
        m = 0;
        for (int k1=0;k1<width;++k1)
        {
            int n = k1;
            for (int k2 =0;k2<height;++k2)
            {
                data[n] = r[m++];
                n += width;
            }
        }

        memcpy(p,data, sizeof(double) * length0);
        memcpy(r,data, sizeof(double) * length0);
        for (int k2 = 0; k2<height;++k2)
        {
            int startIndex=k2 * width;
            double mu = 0.0;
            for (int k=startIndex+1, K=startIndex+width;k<K;++k)
            {
                int div0=fabs(p[k]-p[k-1]);
                mu =exp_table[div0];
                p[k] = p[k - 1] * mu + p[k] * (1.0 - mu);
            }
            for (int k=startIndex+width-2;startIndex<=k;--k)
            {
                int div0=fabs(r[k]-r[k+1]);
                mu =exp_table[div0];
                r[k] = r[k + 1] * mu + r[k] * (1.0 - mu) ;
            }
        }

        double init_gain_mu=spatialDecay/(2-spatialDecay);
        for (int k = 0; k <length0; k++)
        {
            data[k]=(p[k]+r[k])*rho0-data[k]*init_gain_mu;//文献中的公式5
        }
        delete[] p;
        delete[] r;
        delete[] g;
    }

四、公式原理

The first recursion is progressive. Letting x[k] be the current sample of an input sequence x at location k ∈ Z,were cursively compute the elements of an auxiliary sequence ϕ as:在这里插入图片描述
where:
在这里插入图片描述
The second recursion is regressive and very similar to thefirst one, except for a reversal of the order in which the indices are traversed. We recursively compute a second auxiliary sequence φ as:在这里插入图片描述

where:
在这里插入图片描述
We complete our algorithm by merging the resulting progressive sequence ϕ and regressive sequence φ to produce the samples of the output sequence y as:在这里插入图片描述
在这里我们主要使用到了上面的公式1和公式3,并在关键代码使用里面有所标注。

联系我

[email protected]
有问必答,期待点赞,github星星

你可能感兴趣的:(qt,C++,qt图像处理,图像处理,qt,c++)