大津法二值化的理解和C#代码

大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大
     ω0=N0/ M×N (1)
原理:

对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。

假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:
 
      ω1=N1/ M×N (2)
      N0+N1=M×N (3)
      ω0+ω1=1    (4)
      μ=ω0*μ0+ω1*μ1 (5)
      g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)
将式(5)代入式(6),得到等价公式:
      g=ω0ω1(μ0-μ1)^2    (7) 这就是类间方差
采用遍历的方法得到使类间方差g最大的阈值T,即为所求。
C#代码
/大津法/
/*最大类间方差法是由日本学者大进展之于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。
* 它是按图像的灰度特性,将图像分成背景和目标两部分。背景和目标之间的类间方差越大,说明构成图像的两部分
* 的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小。因此,使类间方差最大的分
* 割意味着错分概率最小。对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图
* 像的比例记为\omega_0 ,,其平均灰度\mu_0;背景像素点数占整幅图像的比例为\omega_1,其平均灰度为\mu_1。
* 图像的总平均灰度记为\mu,类间方差记为g。假设图像的背景较暗,并且图像的大小为M*N,图像中像素的灰度值小
* 于阈值T的像素个数记作N_0,像素灰度大于阈值T的像素个数记作N_1,则有:*/
public static int GetOSTUThreshold(int[] HistGram)
{
int X, Y, Amount = 0;
int PixelBack = 0, PixelFore = 0, PixelIntegralBack = 0, PixelIntegralFore = 0, PixelIntegral = 0;
double OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma; // 类间方差;
int MinValue, MaxValue;
int Threshold = 0;

        for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;//获取最小灰度的值
        for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ;//获取最大灰度的值
        if (MaxValue == MinValue) 
            return MaxValue;          // 图像中只有一个颜色             
        if (MinValue + 1 == MaxValue) 
            return MinValue;      // 图像中只有二个颜色

        for (Y = MinValue; Y <= MaxValue; Y++)
        {
            Amount += HistGram[Y];        //  像素总数
        }

        PixelIntegral = 0;
        for (Y = MinValue; Y <= MaxValue; Y++)
        {
            PixelIntegral += HistGram[Y] * Y;//灰度值总数
        }
        SigmaB = -1;
        for (Y = MinValue; Y < MaxValue; Y++)
        {
            PixelBack = PixelBack + HistGram[Y];    //前景像素点数
            PixelFore = Amount - PixelBack;         //背景像素点数
            OmegaBack = (double)PixelBack / Amount;//前景像素百分比
            OmegaFore = (double)PixelFore / Amount;//背景像素百分比
            PixelIntegralBack += HistGram[Y] * Y;  //前景灰度值
            PixelIntegralFore = PixelIntegral - PixelIntegralBack;//背景灰度值
            MicroBack = (double)PixelIntegralBack / PixelBack;//前景灰度百分比
            MicroFore = (double)PixelIntegralFore / PixelFore;//背景灰度百分比
            Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore);//g
            if (Sigma > SigmaB)//遍历最大的类间方差g
            {
                SigmaB = Sigma;
                Threshold = Y;
            }
        }
        return Threshold;
    }
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大津法(Otsu's Method)是一种图像二值化算法,它是一种自适应阈值选择方法。以下是使用C语言实现大津法二值化代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int i, j, t, w, total; double u1, u2, w1, w2, var, max_var; unsigned char *img, *out; FILE *fp_in, *fp_out; // 打开输入图像文件 if ((fp_in = fopen("input.bmp", "rb")) == NULL) { printf("Cannot open file: input.bmp\n"); exit(1); } // 读取图像数据 fseek(fp_in, 54, SEEK_SET); img = (unsigned char*) malloc(512 * 512 * sizeof(unsigned char)); fread(img, sizeof(unsigned char), 512 * 512, fp_in); // 关闭输入图像文件 fclose(fp_in); // 分配输出图像内存 out = (unsigned char*) malloc(512 * 512 * sizeof(unsigned char)); // 计算灰度直方图 int hist[256] = {0}; for (i = 0; i < 512 * 512; i++) { hist[img[i]]++; } // 计算总像素数 total = 512 * 512; // 初始化最大方差 max_var = -1; // 寻找最佳阈值 for (t = 0; t < 256; t++) { // 计算背景和前景的像素数和像素值的总和 w1 = w2 = u1 = u2 = 0; for (i = 0; i < 256; i++) { if (i <= t) { w1 += hist[i]; u1 += i * hist[i]; } else { w2 += hist[i]; u2 += i * hist[i]; } } // 计算背景和前景的平均像素值 u1 /= w1; u2 /= w2; // 计算类间方差 var = w1 * w2 * pow(u1 - u2, 2); // 更新最大方差和最佳阈值 if (var > max_var) { max_var = var; w = t; } } // 二值化图像 for (i = 0; i < 512 * 512; i++) { out[i] = (img[i] <= w) ? 0 : 255; } // 打开输出图像文件 if ((fp_out = fopen("output.bmp", "wb")) == NULL) { printf("Cannot create file: output.bmp\n"); exit(1); } // 写入输出图像文件头 unsigned char header[54] = { 0x42, 0x4d, 0x36, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; fwrite(header, sizeof(unsigned char), 54, fp_out); // 写入输出图像数据 fwrite(out, sizeof(unsigned char), 512 * 512, fp_out); // 关闭输出图像文件 fclose(fp_out); // 释放内存 free(img); free(out); return 0; } ``` 注意:此代码仅适用于位深度为8位的BMP图像,且文件头为54字节。在实际使用中需要根据具体情况进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值