图像均值滤波的几个方法,以及时间比较

baoli,暴力方法:
jifen, 积分图方法:c++ vector
jifen point, 积分图指针方法:不使用vector,速度有提升

col,列积分: 图像边缘未过滤
col2,列积分:图像边缘过滤方法同积分图方法

opencv, opencv的boxFilter方法

 运行时间

// filter_im.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <cstdlib>
#include<opencv2\opencv.hpp>  // 导入opencv

using namespace std;
using namespace cv;
typedef unsigned char uchar;
#define PIXEL(frame, W, x, y) (frame+(y)*3*(W)+(x)*3)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define Clip(a,min,max) ((a)<(min)?(min):((a)>(max)?(max):(a)))
//暴力
int filter_box_v(uint8_t r[], uint8_t r_filter[], int radiu, int height, int width) {

    //float* r_filter = (float*)malloc(HEIGHT * WIDTH * sizeof(float));
    //if (r_filter != NULL) {
    //	memset(r_filter, 0, HEIGHT * WIDTH * sizeof(float));
    //}
    //else {
    //	printf("error happend !! ");
    //	return -1;
    //}
    int cnt = (2 * radiu + 1) * (2 * radiu + 1);

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int ave = 0;
            for (int id = -radiu; id <= radiu; id++) {
                for (int jd = -radiu; jd <= radiu; jd++) {
                    int ii = i + id;
                    int jj = j + jd;
                    if (ii < 0) ii = 0;
                    if (ii >= height) ii = height - 1;
                    if (jj < 0) jj = 0;
                    if (jj >= width) jj = width - 1;
                    ave += r[ii * width + jj];

                }
            }
            r_filter[i * width + j] = (uint8_t)(ave / cnt);
            //if (i % 40 == 0 && j % 40 == 0) {
            //    printf("%d,%d,%d,%d   ", ave, cnt, ave / cnt, r[i + width + j]);
            //    //printf("%d,%d,%d,%d   ", rr, rr1, cc, cc1);
            //}
        }
        //if (i % 40 == 0) {
        //    printf("\n");
        //}
    }
    return 1;
}

int filter_box_fast(uint8_t r[], uint8_t r_filter[], int radiu, int height, int width) {

    int x, y;
    uint8_t* p_add, * p_del, * p_res;

    long long sum;
    long long sum_col[1001];


    int N = 2 * radiu + 1;
    int c = (1 << 23) / (N * N);

    memset(sum_col, 0, sizeof(long long) * width);
    //前N行的列积分
    for (y = 0, p_add = r; y < N; y++)
    {
        for (x = 0; x < width; x++)
        {
            sum_col[x] += *(p_add++);
        }
    }

    //滤波
    for (y = radiu, p_res = r_filter + y * width, p_del = r; y < height - radiu; y++)
    {
        sum = 0;
        for (x = 0; x < N; x++)//N 列
        {
            sum += sum_col[x];
        }

        p_res += radiu;
        for (x = radiu; x < width - radiu; x++) {
            *(p_res++) = (sum*c)>>23;//sum / (N * N);
            sum -= sum_col[x - radiu];
            sum += sum_col[x + radiu + 1];
        }

        p_res += radiu;
        //更新 sum_col
        for (x = 0; x < width; x++) {
            sum_col[x] -= *(p_del++);
            sum_col[x] += *(p_add++);
        }
    }
    return 1;
}
int filter_box_fast2(uint8_t r[], uint8_t r_filter[], int radiu, int height, int width) {

    int x, y;
    uint8_t* p_add, * p_del, * p_res;

    long long sum;
    long long sum_col[1001];


    int N = 2 * radiu + 1;
    int c = (1 << 23) / (N * N);

    memset(sum_col, 0, sizeof(long long) * width);
    //前radiu+1 行的列积分
    for (y = 0, p_add = r; y < radiu+1; y++)
    {
        for (x = 0; x < width; x++)
        {
            sum_col[x] += *(p_add++);
        }
    }

    //滤波
#define Ra (0)
    int rr, cc, rr1, cc1, cnt;
    for (y = Ra, p_res = r_filter + y * width, p_del = r; y < height - Ra; y++)
    {
        sum = 0;
        for (x = 0; x < radiu+1; x++)//N 列
        {
            sum += sum_col[x];
        }

        p_res += Ra;
        for (x = Ra; x < width - Ra; x++) {
            rr = Max(0, y - radiu);
            cc = Max(0, x - radiu);
            rr1 = Min(height-1, y + radiu);
            cc1 = Min(width-1, x + radiu);
            cnt = (rr1 - rr + 1) * (cc1 - cc + 1);


            *(p_res++) = sum / cnt;// (sum * c) >> 23;//sum / (N * N);
            if(x - radiu >= 0)
                sum -= sum_col[x - radiu];
            if(x + radiu + 1 < width)
                sum += sum_col[x + radiu + 1];
        }

        p_res += Ra;
        //更新 sum_col
        for (x = 0; x < width; x++) {
            if(y >= radiu)
                sum_col[x] -= *(p_del++);
            if(y + radiu + 1 < height)
                sum_col[x] += *(p_add++);
        }
    }
    return 1;
}
int filter_box_v2(uint8_t r[], uint8_t r_filter[], int radiu, int height, int width) {
    //for (int i = 0; i < height; i+=40) {
    //    for (int j = 0; j < width; j+=40) {
   //         printf("%d ",r[i * width + j]);
     //   }
    //    printf("\n");
    //}
    //intergate

    //printf("sum:\n\n");
    vector<vector<long long>> sumv(height+1, vector<long long> (width+1, 0));

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            sumv[i+1][j+1] = -sumv[i][j]+ sumv[i+1][j] + sumv[i][j+1] + r[i*width+j];
        }
    }


    int sumt = 0;

    int rr, cc, rr1, cc1, cnt;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            rr = max(1,i - radiu);
            cc = max(1,j - radiu);
            rr1 = min(height, i + radiu);
            cc1 = min(width, j + radiu);
            cnt = (rr1 - rr + 1) * (cc1 - cc + 1);
            sumt = (int)(sumv[rr1][cc1]  - sumv[rr1][cc - 1] - sumv[rr - 1][cc1] + sumv[rr - 1][cc - 1]);

            r_filter[i * width + j] = (uint8_t)(sumt / cnt);
        }

    }
    return 1;
}
int filter_box_v3(uint8_t r[], uint8_t r_filter[], int radiu, int height, int width) {

    long long* sumv =( long long* )malloc(801*801*sizeof(long long));
    //vector<vector<long long>> sumv(height + 1, vector<long long>(width + 1, 0));
    memset(sumv, 0, sizeof(sumv));
    int pos;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            pos = i * width + j;
            sumv[pos+width+1] = -sumv[pos] + sumv[pos+width] + sumv[pos + 1] + r[pos];
        }
    }


    int sumt = 0;

    int rr, cc, rr1, cc1, cnt;

    int pos1, pos2, pos3, pos4;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            rr = max(1, i - radiu);
            cc = max(1, j - radiu);
            rr1 = min(height, i + radiu);
            cc1 = min(width, j + radiu);
            cnt = (rr1 - rr + 1) * (cc1 - cc + 1);
            
            pos1 = rr1 * width + cc1;
            pos2 = rr1 * width + cc - 1;
            pos3 = (rr - 1) * width + cc1;
            pos4 = (rr - 1) * width + cc - 1;
            sumt = (int)(sumv[pos1] - sumv[pos2] - sumv[pos3] + sumv[pos4]);

            r_filter[i * width + j] = (uint8_t)(sumt / cnt);
        }

    }

    free(sumv);
    return 1;
}
int get_data(cv::Mat& im, float* r, float* g, float* b, int height, int width) {
    assert(height == im.rows);
    assert(width == im.cols);
    assert(3 == im.channels());

    const int num = height * width;
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            int pos = i * width + j;
            uint8_t* p = PIXEL(im.data, width, j, i);
            r[i * width + j] = p[2] / 255.0f;
            g[i * width + j] = p[1] / 255.0f;
            b[i * width + j] = p[0] / 255.0f;
            //printf("ddd: %d, %d, %d", p[2], p[1], p[0]);
        }
    }
    return 1;
}

/*
void filter_by_sum(int* sum_img, int height, int width, int M, int N, uint8_t* im_filter) {
    int* py1, * py2;
    uint8_t* im_res;
    int halfx, halfy;
    int x, y, x1, y1;
    int sum, c;

    //init
    //M, N is filter len,should be odd
    
}
*/
int main()
{
    //d
    std::cout << "Hello World!\n";
    Mat image;  //

    
    //image = imread("D:\\MedData\\dark_mask\\002.jpg");  // 以绝对地址导入图片,图片路径是自己设置的
    image = imread("D:\\dataset\\wang\\ccm\\2022-06-21-15-08-20_raw_gamma3.png");

    int width = 800;
    int height = 800;
    cv::Size dsize = cv::Size(height, width);
    cv::Mat img;
    cv::resize(image, img, dsize, 0, 0, cv::INTER_AREA);


    if (img.empty())  // 判断是否导入图片
    {
        cout << "请确认图片正确位置!" << endl;
        return -1;  // 返回-1
    }
    namedWindow("test", WINDOW_NORMAL);  // 创建一个常规窗口
    
    imshow("test", img);  // 展示图片
    waitKey(0);  // 获取键盘按键响应
    cv::imwrite("im_00.png", img);
    Mat img2;
    img.copyTo(img2);



    clock_t start_time;
    clock_t finish_time;
    float program_time;

    int radiu = 9;

    
    
    Mat rgb[3], rgb2[3];
    split(img, rgb);
    split(img2, rgb2);
    printf("%p,%p  ", rgb[0].data, rgb2[0].data);

    uint8_t* b = rgb[0].data;
    uint8_t* g = rgb[1].data;
    uint8_t* r = rgb[2].data;

    uint8_t* b2 = rgb2[0].data;
    uint8_t* g2 = rgb2[1].data;
    uint8_t* r2 = rgb2[2].data;
    //for (int i = 0; i < height; i+=40) {
   //     for (int j = 0; j < width; j+=40){
   //         printf("%d  ", r[i*width+j]);
   //     }
   //     printf("\n");
  //  }
   // printf("\n");

   
    start_time = clock();
    filter_box_v(r, r2, radiu, height, width);
    filter_box_v(g, g2, radiu, height, width);
    filter_box_v(b, b2, radiu, height, width);

    finish_time = clock();
    program_time = (float)(finish_time - start_time) / CLOCKS_PER_SEC;
    printf("Program complete time baoli:  %f\n", program_time);

    merge(rgb2, 3, img2);
    imshow("baoli", img2);  // 展示图片
    waitKey(0);
    cv::imwrite("im_baoli.png", img2);



    img.copyTo(img2);
    start_time = clock();
    filter_box_v2(r, r2, radiu, height, width);
    filter_box_v2(g, g2, radiu, height, width);
    filter_box_v2(b, b2, radiu, height, width);

    finish_time = clock();
    program_time = (float)(finish_time - start_time) / CLOCKS_PER_SEC;
    printf("Program complete time jifen:  %f\n", program_time);

    merge(rgb2, 3, img2);
    imshow("jifen", img2);  // 展示图片
    waitKey(0);
    cv::imwrite("im_jifen.png", img2);
    //Mat img3(height, width, CV_32FC3, 1/255.0);
    //Mat img4(height, width, CV_32FC3, 1/255.0);
    //img.convertTo(img3, CV_32FC3);
    //img2.convertTo(img4, CV_32FC3);

    img.copyTo(img2);
    start_time = clock();
    boxFilter(img, img2, 8, Size(29,29));
    //filter_box_v(img3.data, img4.data, width, height, radius);
    finish_time = clock();
    program_time = (float)(finish_time - start_time) / CLOCKS_PER_SEC;
    printf("Program complete time opencv:  %f\n", program_time);

    imshow("opencv", img2);  // 展示图片
    waitKey(0);  // 获取键盘按键响应
    cv::imwrite("im_opencv.png", img2);

    
    //col
    img.copyTo(img2);
    start_time = clock();
    filter_box_fast(r, r2, radiu, height, width);
    filter_box_fast(g, g2, radiu, height, width);
    filter_box_fast(b, b2, radiu, height, width);

    finish_time = clock();
    program_time = (float)(finish_time - start_time) / CLOCKS_PER_SEC;
    printf("Program complete time col jifen:  %f\n", program_time);

    merge(rgb2, 3, img2);
    imshow("col", img2);  // 展示图片
    waitKey(0);
    cv::imwrite("im_col.png", img2);
    //col2
    img.copyTo(img2);
    start_time = clock();
    filter_box_fast2(r, r2, radiu, height, width);
    filter_box_fast2(g, g2, radiu, height, width);
    filter_box_fast2(b, b2, radiu, height, width);

    finish_time = clock();
    program_time = (float)(finish_time - start_time) / CLOCKS_PER_SEC;
    printf("Program complete time col2 jifen:  %f\n", program_time);

    merge(rgb2, 3, img2);
    imshow("col2", img2);  // 展示图片
    waitKey(0);
    cv::imwrite("im_col2.png", img2);


    img.copyTo(img2);
    start_time = clock();
    filter_box_v3(r, r2, radiu, height, width);
    filter_box_v3(g, g2, radiu, height, width);
    filter_box_v3(b, b2, radiu, height, width);

    finish_time = clock();
    program_time = (float)(finish_time - start_time) / CLOCKS_PER_SEC;
    printf("Program complete time jifenpoint:  %f\n", program_time);

    merge(rgb2, 3, img2);
    imshow("jifenpoint", img2);  // 展示图片
    waitKey(0);
    cv::imwrite("im_jifenpoint.png", img2);
    //imshow("test3", img2);  // 展示图片
    //waitKey(0);  // 获取键盘按键响应
    destroyAllWindows();  // 销毁所有窗口


}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值