bilateral filter using opencv

This is an implementation of bilateral filter using opencv. The bilateral filter's math expression is:


where


so the code is:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <math.h>
#include <stdio.h>

#define HU_MAX(x, y) (x) > (y) ? (x):(y)
#define HU_MIN(x, y) (x) < (y) ? (x):(y)

typedef unsigned char uchar;

void uchar2float(uchar *srcData, int srcW, int srcH, int srcStride,
                    double *dstData, int dstW, int dstH, int dstStride)
{
    uchar *p1 = NULL;
    double *p2 = NULL;

    for(int y = 0; y < srcH; y++)
    {
        p1 = srcData + y * srcStride;
        p2 = dstData + y * dstStride;

        for(int x = 0; x < srcW; x++)
            p2[x] = 1.0f * p1[x] / 255;
    }
}

void init_domain_kernel(double *G, int N, double sigmad)
{
    int N2 = 2 * N + 1;
    int size = N2 * N2;

    assert(G != NULL);

    memset(G, 0, sizeof(double) * size);

    int i, j, i1, j1;

    for(i = 0; i <= N; i++)
    {
        i1 = N2-i-1;

        for(j = 0; j <= N; j++)
        {
            double t = exp((pow(i-N, 2) + pow(j-N, 2)) / (2 * sigmad * sigmad));

            j1 = N2-j-1;

            G[i * N2 + j] = G[i * N2 + j1] = G[i1 * N2 + j] = G[i1 * N2 + j1] = t;
        }
    }
}


void bilateral_filter(uchar *image_data, int width, int height, int stride,
                        int N, double sigmad, double sigmar)
{
    if(N < 1) N = 5;

    if(sigmad <= 0) sigmad = 3;
    if(sigmar <= 0) sigmar = 0.1;

    double *image_data_f = new double[height * width];

    int N2 = 2 * N +1;
    int size = N2 * N2;
    double *G = new double[size];
    int x, y, i, j;

    uchar2float(image_data, width, height, stride,
                image_data_f, width, height, width);

    init_domain_kernel(G, N, sigmad);

    double sigmar2_2 = 2 * sigmar * sigmar;
    
    for(y = 0; y < height; y++)
    {
        int y0 = HU_MAX(y-N, 0);
        int y1 = HU_MIN(y+N, height-1);
        
        for(x = 0; x < width; x++)
        {
            int x0 = HU_MAX(x-N, 0);
            int x1 = HU_MIN(x+N, width-1);
            

            double summ = 0;
            double sumw = 0;
            double g, f, w;

            for(j = y0; j <= y1; j++)
            {
                for(i = x0; i <= x1; i++)
                {
                    g = G[(j-y0) * N2 + (i-x0)];
                    f = image_data_f[j * width + i]  - image_data_f[y * width + x];
                    f = f * f / sigmar2_2;

                    w = exp(- g - f);

                    summ += image_data_f[j * width +i] * w;
                    sumw += w;
                }
            }

            image_data[y * stride + x] = uchar(summ/sumw * 255);
        }
    }

    delete [] G;
    delete [] image_data_f;
}


void merge_image(cv::Mat &img1, cv::Mat &img2, cv::Mat &res)
{
    int cols = img1.cols +  img2.cols;
    int rows = img1.rows > img2.rows ? img1.rows: img2.rows;

    res = cv::Mat(rows, cols, CV_8UC1, cv::Scalar(0));

    assert(img1.type() == res.type());
    assert(img2.type() == res.type());

    cv::Mat left(res, cv::Rect(0, 0, img1.cols, img1.rows));
    cv::Mat right(res, cv::Rect(img1.cols, 0, img2.cols, img2.rows));

    left = left + img1;
    right = right + img2;
}


int main(int argc, char **argv)
{
    if(argc < 2)
    {
        printf("Usage:%s [image]\n", argv[0]);
        return 1;
    }

    cv::Mat img = cv::imread(argv[1], 0);

    if(img.empty())
    {
        printf("Can't open image %s\n", argv[1]);
        return 1;
    }

    cv::Mat dst = img.clone();
    bilateral_filter(dst.data, dst.cols, dst.rows, dst.step, 5, 3, 0.1);

    cv::Mat res;
    
    merge_image(img, dst, res);
    
    cv::imshow("res", res);
    cv::waitKey();


    return 0;
}


see more in : http://www.voidcn.com/article/p-nbzjrykl-bep.html

相关文章
相关标签/搜索