Python+OpenCV基于OTSU算法的局部二值化算法(失败品)

大津法(otsu算法)是基于全局的阈值分割算法,极易受到光照不均的干扰,使图像前景像素与背景像素分割不合理,达不到预期效果,故需要采用局部阈值分割的方法,本文采用以每列为局部,将每列进行一次otsu算法,求出列阈值,以此类推,直至遍历完所有的列。

代码如下:

import cv2 as cv
import numpy as np

# 转灰
def rgb2gray(img):
    h=img.shape[0]
    w=img.shape[1]
    img1=np.zeros((h,w),np.uint8)
    for i in range(h):
        for j in range(w):
            img1[i,j]=0.144*img[i,j,0]+0.587*img[i,j,1]+0.299*img[i,j,1]
    return img1

# 二值化
def otsu(img):
    h=img.shape[0]
    w=img.shape[1]
    otsuimg=np.zeros((h,w),np.uint8)
    for i in range(w):   # 遍历列
        sigma=threshold=0   # 定义类间方差和最终阈值
        histogram=np.zeros(256,np.int32)   # 初始化各灰度级个数统计
        probability=np.zeros(256,np.float32)   # 初始化各灰度级概率分布
        for j in range (h):   # 遍历行,进行otsu算法
            s=img[j,i]
            histogram[s]+=1   # 统计灰度级中每个像素在整幅图像中的个数
        for k in range (256):
            probability[k]=histogram[k]/h   # 统计每个灰度级占图像中的分布
        for p in range (255):
            w0 = w1 = 0   # 定义前景像素点和背景像素点灰度级占图像中的分布
            fgs = bgs = 0   # 定义前景像素点灰度级总和and背景像素点灰度级总和
            for q in range (256):
                if q<=p:   # 当前i为分割阈值
                    w0+=probability[q]   # 前景像素点占整幅图像的比例累加
                    fgs+=q*probability[q]   # 前景像素点的平均灰度
                else:
                    w1+=probability[q]   # 背景像素点占整幅图像的比例累加
                    bgs+=q*probability[q]   # 背景像素点的平均灰度
            u0=fgs/w0
            u1=bgs/w1
            g=w0*w1*(u0-u1)**2   # 类间方差
            if g>=sigma:
                sigma=g
                threshold=p
        for j in range (h):   # 对某列的每一行进行二值化
            if img[j,i]>threshold:
                otsuimg[j,i]=255
            else:
                otsuimg[j,i]=0
    return otsuimg

image = cv.imread("D:/Testdata/a.png")
grayimage = rgb2gray(image)
otsuimage = otsu(grayimage)
cv.imshow("image", image)
cv.imshow("otsuimage", otsuimage)
cv.waitKey(0)
cv.destroyAllWindows()

实验结果:
原图
局部二值化图
为检验二值化效果,与otsu算法实验结果比较:
otsu算法图片
比较发现,这种基于otsu算法的局部二值化算法效果并不明显,所以算是一个失败品吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值