otsu算法_大津二值化算法OTSU的理解

otsu 大津算法原理

otsu 大津算法是一种图像二值化算法,作用是确定将图像分成黑白两个部分的阈值。

将图像背景和前景分成黑白两类很好理解,但是如何确定背景和前景的二值化界限(阈值)呢?

对于不同的图像,这个阈值可能不同,这就需要有一种算法来根据图像的信息自适应地确定这个阈值。

首先,需要将图像转换成灰度图像,255个灰度等级。

可以将图像理解成255个图层,每一层分布了不同的像素,这些像素垂直叠加合成了一张完整的灰度图。

我们的目的就是找到一个合适的灰度值,大于这个值的我们将它称之为背景(灰度值越大像素越黑),小于这个值的我们将它称之为前景(灰度值越小像素越白)。

怎么确定这个值就是我们想要的值呢?

这里引入方差的概念,方差越大,相关性越低,黑白越分明。

将每一个灰度值上下之间的像素的方差求出来,找到方差最大的那个灰度值,那个就是我们想要的二值化分隔阈值。

先定义几个符号代表的意义:

h:图像的宽度

w:图像的高度(h*w 得到图像的像素数量)

t :灰度阈值(我们要求的值,大于这个值的像素我们将它的灰度设置为255,小于的设置为0)

n0:小于阈值的像素,前景

n1:大于等于阈值的像素,背景

n0 + n1 == h * w

w0:前景像素数量占总像素数量的比例

w0 = n0 / (h * w)

w1:背景像素数量占总像素数量的比例

w1 = n1 / (h * w)

w0 + w1 == 1

u0:前景平均灰度

u0 = n0灰度累加和 / n0

u1:背景平均灰度

u1 = n1灰度累加和 / n1

u:平均灰度

u = (n0灰度累加和 + n1灰度累加和) / (h * w) 根据上面的关系

u = w0 * u0 + w1 * u1

g:类间方差(那个灰度的g最大,哪个灰度就是需要的阈值t)

g = w0 * (u0 - u)^2 + w1 * (u1 - u)^2

根据上面的关系,可以推出:(这个一步一步推导就可以得到)

g = w0 * w1 * (u0 - u1) ^ 2

然后,遍历每一个灰度值,找到这个灰度值对应的 g

找到最大的 g 对应的 t

import cv2
import numpy as np


# Gray scale
def BGR2GRAY(img):
   b = img[:, :, 0].copy()
   g = img[:, :, 1].copy()
   r = img[:, :, 2].copy()

   # Gray scale
   out = 0.2126 * r + 0.7152 * g + 0.0722 * b
   out = out.astype(np.uint8)

   return out

# Otsu Binarization
def otsu_binarization(img, th=128):
   max_sigma = 0
   max_t = 0

   # determine threshold
   for _t in range(1, 255):
      v0 = out[np.where(out < _t)]
      m0 = np.mean(v0) if len(v0) > 0 else 0.
      w0 = len(v0) / (H * W)
      v1 = out[np.where(out >= _t)]
      m1 = np.mean(v1) if len(v1) > 0 else 0.
      w1 = len(v1) / (H * W)
      sigma = w0 * w1 * ((m0 - m1) ** 2)
      if sigma > max_sigma:
         max_sigma = sigma
         max_t = _t

   # Binarization
   print("threshold >>", max_t)
   th = max_t
   out[out < th] = 0
   out[out >= th] = 255

   return out


# Read image
img = cv2.imread("imori.jpg").astype(np.float32)
H, W, C =img.shape


# Grayscale
out = BGR2GRAY(img)

# Otsu's binarization
out = otsu_binarization(out)

# Save result
cv2.imwrite("out.jpg", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值