大津法---OTSU算法

OPENCV的二值化操作中,有一种“大津阈值处理”的方法,使用函数cvThreshold(image,image2,0,255,CV_THRESH_OTSU) 实现,该函数就会使用大律法OTSU得到的全局自适应阈值来进行二值化图片,而参数中的threshold不再起作用。
OTSU算法
OTSU算法也称最大类间差法,有时也称之为大津算法,由大津于1979年提出,被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
设灰度图像灰度级是L,则灰度范围为[0,L-1],利用OTSU算法计算图像的最佳阈值为:
t = Max[w0(t) * (u0(t) - u)^2 + w1(t) * (u1(t) - u)^2)]
其中的变量说明:当分割的阈值为t时,w0为背景比例,u0为背景均值,w1为前景比例,u1为前景均值,u为整幅图像的均值。
使以上表达式值最大的t,即为分割图像的最佳阈值。
以下是一段在OpenCV中实现的C语言程序,即一个使用OTSU算法提取图像阈值的函数,输入参数为一个图像指针,返回分割该图像的最佳阈值。
其中的变量说明:当分割的阈值为t时
w0为背景像素点占整幅图像的比例
u0为w0平均灰度
w1为前景像素点占整幅图像的比例
u1为w1平均灰度
u为整幅图像的平均灰度
公式:g = w0*pow((u-u0),2) + w1*pow((u-u1),2)

int MyAutoFocusDll::otsuThreshold(IplImage *frame)
{
const int GrayScale = 256;
int width = frame->width;
int height = frame->height;
int pixelCount[GrayScale];
float pixelPro[GrayScale];
int i, j, pixelSum = width * height, threshold = 0;
uchar* data = (uchar*)frame->imageData; //指向像素数据的指针
for(i = 0; i < GrayScale; i++)
{
pixelCount[i] = 0;
pixelPro[i] = 0;
}

//统计灰度级中每个像素在整幅图像中的个数
for(i = 0; i < height; i++)
{
for(j = 0;j < width;j++)
{
pixelCount[(int)data[i * width + j]]++; //将像素值作为计数数组的下标
}
}

//计算每个像素在整幅图像中的比例
float maxPro = 0.0;
int kk=0;
for(i = 0; i < GrayScale; i++)
{
pixelPro[i] = (float)pixelCount[i] / pixelSum;
if( pixelPro[i] > maxPro )
{
maxPro = pixelPro[i];
kk = i;
}
}

//遍历灰度级[0,255]
float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
for(i = 0; i < GrayScale; i++) // i作为阈值
{
w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;
for(j = 0; j < GrayScale; j++)
{
if(j <= i) //背景部分
{
w0 += pixelPro[j];
u0tmp += j * pixelPro[j];
}
else //前景部分
{
w1 += pixelPro[j];
u1tmp += j * pixelPro[j];
}
}
u0 = u0tmp / w0;
u1 = u1tmp / w1;
u = u0tmp + u1tmp;
deltaTmp = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);
if(deltaTmp > deltaMax)
{
deltaMax = deltaTmp;
threshold = i;
}
}

return threshold;
}

### 使用 Sentinel-1 数据结合大津 (Otsu) 实现图像分割 Sentinel-1 是一种合成孔径雷达 (SAR) 卫星,其数据具有穿透云层的能力,在洪水监测、土地覆盖变化分析等领域有广泛应用。通过 Google Earth Engine (GEE),可以高效处理大规模遥感数据并实现自动化分析。 #### 1. 数据预处理 在 GEE 中加载 Sentinel-1 数据前,需对其进行一系列预处理操作以减少噪声干扰并增强信号质量。以下是常见的预处理步骤: - **去噪**: 对原始 SAR 图像应用 Lee 滤波器或其他滤波算法降低斑点噪声的影响。 - **辐射校正**: 调整回波强度以补偿地形起伏带来的影响。 - **几何校正**: 将 SAR 图像投影至地理坐标系中以便后续分析。 代码示例如下: ```javascript // 加载 Sentinel-1 GRD 数据集合 var sentinel1 = ee.ImageCollection('COPERNICUS/S1_GRD') .filterDate('2023-01-01', '2023-12-31') // 时间范围筛选 .filterBounds(geometry); // 地理范围筛选 // 应用 Lee 滤波器去除噪声 function applyLeeFilter(image) { var bandVH = image.select('VH'); // 提取 VH 波段 var mean = bandVH.reduceNeighborhood({ reducer: ee.Reducer.mean(), kernel: ee.Kernel.circle(3), // 定义窗口大小 }); return image.addBands(mean.rename('VH_mean')); // 添加平滑后的波段 } var filteredImages = sentinel1.map(applyLeeFilter); ``` #### 2. 计算 NDVI 或其他指数(可选) 虽然 Sentinel-1 不提供光谱信息,但在某些情况下可以通过与其他光学传感器(如 Sentinel-2)联合使用计算归一化差异水体指数 (NDWI)[^2] 来辅助分类过程。如果仅依赖于 SAR 数据,则可以直接跳过此部分。 #### 3. 大津 (Otsu) 阈值分割 大津是一种自动确定最佳全局阈值的方,适用于二值化问题。它基于直方图统计寻找能够最大化类间方差的分界点作为最终阈值。 具体实现如下所示: ```javascript // 获取单张影像用于演示目的 var singleImage = filteredImages.first(); // 提取感兴趣波段(此处假设为 VH 均值) var vhBand = singleImage.select('VH_mean'); // 执行 Otsu 自动阈值得到掩膜 var otsuThreshold = ee.Number(ee.Algorithms.If( vhBand.reduceRegion({ reducer: ee.Reducer.percentile([99]), // 初始估计最大值 geometry: geometry, scale: 10, // 分辨率设置 maxPixels: 1e13 // 最大像素数限制 }).values().get(0), vhBand.reduceRegion({ reducer: ee.Reducer.histogram(), // 构建灰度直方图 geometry: geometry, scale: 10, maxPixels: 1e13 }).get('histogram'), function(histogram){ var counts = ee.Array(ee.Dictionary(histogram).get('hist')); var means = ee.Array(ee.Dictionary(histogram).get('bucketMeans')); var size = means.length().get([0]); var total = counts.reduce(ee.Reducer.sum(), [0]).get([0]); var sum = means.multiply(counts).reduce(ee.Reducer.sum(), [0]).get([0]); var mean = sum.divide(total); var indices = ee.List.sequence(1, size); var betweenSum = indices.map(function(i){ var aCounts = counts.slice(0, 0, i); var aCount = aCounts.reduce(ee.Reducer.sum(), [0]).get([0]); var bCount = total.subtract(aCount); var aMeans = means.slice(0, 0, i); var aMean = aMeans.multiply(aCounts).reduce(ee.Reducer.sum(), [0]).get([0]).divide(aCount); var bMean = sum.subtract(aCount.multiply(aMean)).divide(bCount); return aCount.multiply(bCount).multiply(aMean.subtract(bMean).pow(2)); }); return betweenSum.indexOf(betweenSum.sort().reverse().get([0])); } )); // 创建二值掩码 var thresholded = vhBand.gt(otsuThreshold); // 显示结果 Map.addLayer(thresholded.selfMask(), {palette: ['blue']}, 'Flood Area'); ``` 以上脚本实现了从 Sentinel-1 数据提取目标区域的过程,并采用大津完成阈值划分[^1]。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值