图像处理_Ostu算法(大律法、最大类间方差法)

一、算法简述

       Otsu算法是一种用于二值化最佳阈值的选取方法。基本原理是根据阈值T将图像中的像素点分为C1和C2两类,不断的调整阈值T之后若此时两类之间存在最大的类间方差,那么此阈值即是最佳阈值。

二、算法理论

  1、基础公式

      w_{1}=\sum_{i=0}^{k} p_{i}=w(k)                                                     (1)

      w_{2} = \sum_{i=k+1}^{L-1} p_{i} = 1-w(k)                                            (2)

     m_{1} = \sum_{i=0}^{k} \frac{ip_{i}}{w_{1}} = \frac{m(k)}{w(k)}                                                   (3)

    m_{2} = \sum_{i=k+1}^{L-1} \frac{ip_{i}}{w_{2}} = \frac{m-m(k)}{1-w(k)}                                         (4)

    m = \sum_{i=0}^{L-1} ip_{i}                                                                      (5)

    \sigma ^{2} = w_{1}(m_{1}-m)^{2} + w_{2}(m_{2}-m)^{2}                              (6)

    m = w_{1}m_{1} + w_{2}m_{2}                                                         (7)

    w_{1} + w_{2} = 1                                                                     (8)

2、Otsu算法公式推导(为了减少计算量,所以对(6)式进行化简)

    利用(7)、(8)可将(6)化简成:

   \sigma ^{2} = w_{1}w_{2}(m_{1}-m_{2})^{2}                                                     (9)

   利用(3)、(4)可将(9)化简成:

   \sigma ^{2} = \frac{[mw(k)-m_{1}]^{2}}{w(k)[1-w(k)]}                                                        (10) 

  不断更改阈值T,,再利用(1)、(2)、(3)、(5)计算出(10)中的相关值计算出(10)中的最大方差值时,阈值T即为   最佳。

三、算法实现(2020.2.4)

  1、matlab实现

clear all
PI = imread('E:\Image_Processing\Image_Repo\拉力表.jpg');
subplot(1,2,1),imshow(PI);
T = graythresh(PI);
PO = im2bw(PI,T);
subplot(1,2,2),imshow(PO);

  2、python实现

# -*- coding: utf-8 -*-
import sys
import numpy as np
import cv2
import math
#计算图像灰度直方图
def calcGrayHist(image):
    #灰度图像矩阵的宽高
    rows,cols = image.shape
    #存储灰度直方图
    grayHist = np.zeros([1,256],np.uint32)
    for r in range(rows):
        for c in range(cols):
            grayHist[0][image[r][c]] +=1
    return grayHist         
def ostu(image):
    rows,cols = image.shape
    #计算图像的灰度直方图
    grayHist = calcGrayHist(image)
    #归一化灰度直方图
    uniformGrayHist = grayHist/float(rows*cols)
    #计算零阶累积矩和一阶累积矩
    zeroCumuMoment = np.zeros([1,256],np.float32)
    oneCumuMoment = np.zeros([1,256],np.float32)
    for k in range(256):
        if k == 0:
            zeroCumuMoment[0][k] = uniformGrayHist[0][0]
            oneCumuMoment[0][k] = (k+1)*uniformGrayHist[0][0]
        else:
            zeroCumuMoment[0][k] = zeroCumuMoment[0][k-1] + uniformGrayHist[0][k]
            oneCumuMoment[0][k] = oneCumuMoment[0][k-1] + k*uniformGrayHist[0][k]
    #计算类间方差  
    variance = np.zeros([1,256],np.float32)
    for k in range(255):
        if zeroCumuMoment[0][k] == 0:
            variance[0][k] = 0
        else:
            variance[0][k] = math.pow(oneCumuMoment[0][255]*zeroCumuMoment[0][k] - oneCumuMoment[0][k],2)/(zeroCumuMoment[0][k]*(1.0-zeroCumuMoment[0][k]))
    #找到阈值
    threshLoc = np.where(variance[0][0:255] == np.max(variance[0][0:255]))
    thresh = threshLoc[0]
    #阈值处理
    threshold = np.copy(image)
    threshold[threshold > thresh] = 255
    threshold[threshold <= thresh] = 0
    return threshold
#主函数
if __name__ =="__main__":
    image = cv2.imread('E:\Image_Processing\Image_Repo\pull_Meter.jpg',cv2.IMREAD_COLOR)
    #显示原图
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    cv2.imshow("image",image)
    #阈值算法
    ostu_threshold = ostu(image)
    #显示阈值处理的结果
    cv2.imshow("ostu_threshold",ostu_threshold)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

  3、c++实现

四、后记:本文主要是本人在学习过程中的一些学习记录和心得,欢迎大家评论交流纠正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值