使用 SDL 在 C 语言中设置 Sauvola 阈值

Sauvola thresholding in C using SDL

提问人:ImDaronned 提问时间:11/2/2023 最后编辑:genpfaultImDaronned 更新时间:11/2/2023 访问量:78

问:

我尝试使用局部阈值和 sauvola 算法对图像进行二值化。

我按照以下步骤操作:

  1. 遍历图像中的所有像素
  2. 计算局部均值 (μ(x, y))
  3. 计算局部标准差 (σ(x, y))
  4. 计算局部阈值 [使用此 T(x, y) = μ(x, y) * (1 + k * ((σ(x, y) / R) - 1))]
  5. 像素二值化

这是我的代码:

float average_neighbors(SDL_Surface* surface, int x, int y, int w, int h) {
    float sum = 0.;
    int count = 0;

    int min_dimension = (w < h) ? w : h;
    int size;

    if (min_dimension < 1250)
        size = 1;
    else
        size = 2;

    for (int i = -size; i <= size; i++) {
        for (int j = -size; j <= size; j++) {
            int nX = x+i, nY = y+j;

            if (nX >= 0 && nX < w && nY >= 0 && nY < h) {
                Uint32 pixel = get_pixel(surface, nX, nY);
                Uint8 pixel_color = pixel & 0xFF;
                sum += pixel_color;
                count++;
            }

        }
    }

    return sum/count;
}

float std_deviation(SDL_Surface* surface, int x, int y, float av) {
    float sum = 0.;
    int count = 0;

    for (int i = y -2; i <= y +2; i++) {
        //printf("i: %i\n", i);
        for (int j = x -2; j <= x +2; j++) {
            //printf("j: %i\n", j);
            Uint8 pixel = get_pixel(surface, j, i) & 0xFF;
            sum += (pixel - av) * (pixel - av);
            count ++;
        }
    }
    return sqrt(sum / count);
}

int dynamic_range(SDL_Surface* surface, int w, int h) {
    int min = 255;
    int max = 0;

    for (int x = 0; x < w; x++) {
        for (int y = 0; y < h; y++) {
            Uint8 color = get_pixel(surface, x, y) & 0xFF;

            if (color < min)
                min = color;
            if (color > max)
                max = color; 
        }
    }

    return max - min;
}

SDL_Surface* binarize_image(SDL_Surface* surface) {
    int w = surface->w;
    int h = surface->h;

    float k = 0.2;
    int R = dynamic_range(surface, w, h);

    SDL_Surface* res = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);


    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            float av = average_neighbors(surface, x, y, w, h);
            //printf("av: %f\n", av);
            float deviation = std_deviation(surface, x, y, av);
            //printf("dv: %f\n", deviation);

            float pixel = (float)(get_pixel(surface, x, y) & 0xFF);

            float sauvola_t = av * (1 + k * (deviation / R - 1));

            if (pixel > sauvola_t) {
                Uint32 nPixel = SDL_MapRGB(res->format, 255, 255, 255);
                put_pixel(res, x, y, nPixel); 
            }
            else {
                Uint32 nPixel = SDL_MapRGB(res->format, 0, 0, 0);
                put_pixel(res, x, y, nPixel); 
            }

        }
    }
    
    free_surface(surface);
    return res;
}

功能get_pixel和put_pixel正在工作。

我的函数结果在这里

我不明白我做错了什么。

当我调试时,我似乎是正确的:去泡

关于如何去做的任何想法?

c SDL 图像 自适应阈值

评论


答: 暂无答案