opencv+python3图像增强之Sauvola二值化

       sauvola是一种考虑局部均值亮度的图像二值化方法, 以局部均值为基准在根据标准差做些微调.算法实现上一般用积分图方法来实现的.

步骤1 计算区域像素积分和和积分平方和

步骤2 计算标准差,标准差的计算方法为: std = sqrt((sqdiff - diff*diff / area) / (area - 1))

步骤3 sauvola二值化算法的阈值为T = mean*(1 + k*((std / 128) - 1)).

python代码如下:

def integral(img):
    '''
    计算图像的积分和平方积分
    :param img:Mat--- 输入待处理图像
    :return:integral_sum, integral_sqrt_sum:Mat--- 积分图和平方积分图
    '''
    integral_sum=np.zeros((img.shape[0],img.shape[1]),dtype=np.int32)
    integral_sqrt_sum=np.zeros((img.shape[0],img.shape[1]),dtype=np.int32)

    rows,cols=img.shape
    for r in range(rows):
        sum=0
        sqrt_sum=0
        for c in range(cols):
            sum+=img[r][c]
            sqrt_sum+=math.sqrt(img[r][c])

            if r==0:
                integral_sum[r][c]=sum
                integral_sqrt_sum[r][c]=sqrt_sum
            else:
                integral_sum[r][c]=sum+integral_sum[r-1][c]
                integral_sqrt_sum[r][c]=sqrt_sum+integral_sqrt_sum[r-1][c]

    return integral_sum, integral_sqrt_sum

def sauvola(img,k=0.1,kernerl=(31,31)):
    '''
    sauvola阈值法。
    根据当前像素点邻域内的灰度均值与标准方差来动态计算该像素点的阈值
    :param img:Mat--- 输入待处理图像
    :param k:float---修正参数,一般0<k<1
    :param kernerl:set---窗口大小
    :return:img:Mat---阈值处理后的图像
    '''
    if kernerl[0]%2!=1 or kernerl[1]%2!=1:
        raise ValueError('kernerl元组中的值必须为奇数,'
                         '请检查kernerl[0] or kernerl[1]是否为奇数!!!')

    # 计算积分图和积分平方和图
    integral_sum,integral_sqrt_sum=integral(img)
    # integral_sum, integral_sqrt_sum = cv2.integral2(img)
    # integral_sum=integral_sum[1:integral_sum.shape[0],1:integral_sum.shape[1]]
    # integral_sqrt_sum=integral_sqrt_sum[1:integral_sqrt_sum.shape[0],1:integral_sqrt_sum.shape[1]]

    #创建图像
    rows,cols=img.shape
    diff=np.zeros((rows,cols),np.float32)
    sqrt_diff=np.zeros((rows,cols),np.float32)
    mean=np.zeros((rows,cols),np.float32)
    threshold=np.zeros((rows,cols),np.float32)
    std=np.zeros((rows,cols),np.float32)

    whalf=kernerl[0]>>1#计算领域类半径的一半

    for row in range(rows):
        print('第{}行处理中...'.format(row))
        for col in range(cols):
            xmin=max(0,row-whalf)
            ymin=max(0,col-whalf)
            xmax=min(rows-1,row+whalf)
            ymax=min(cols-1,col+whalf)

            area=(xmax-xmin+1)*(ymax-ymin+1)
            if area<=0:
                sys.exit(1)

            if xmin==0 and ymin==0:
                diff[row,col]=integral_sum[xmax,ymax]
                sqrt_diff[row,col]=integral_sqrt_sum[xmax,ymax]
            elif xmin>0 and ymin==0:
                diff[row, col] = integral_sum[xmax, ymax]-integral_sum[xmin-1,ymax]
                sqrt_diff[row, col] = integral_sqrt_sum[xmax, ymax]-integral_sqrt_sum[xmin-1, ymax]
            elif xmin==0 and ymin>0:
                diff[row, col] = integral_sum[xmax, ymax] - integral_sum[xmax, ymax-1]
                sqrt_diff[row, col] = integral_sqrt_sum[xmax, ymax] - integral_sqrt_sum[xmax, ymax-1]
            else:
                diagsum=integral_sum[xmax, ymax]+integral_sum[xmin-1, ymin-1]
                idiagsum=integral_sum[xmax, ymin-1]+integral_sum[xmin-1, ymax]
                diff[row,col]=diagsum-idiagsum

                sqdiagsum=integral_sqrt_sum[xmax, ymax]+integral_sqrt_sum[xmin-1, ymin-1]
                sqidiagsum=integral_sqrt_sum[xmax, ymin-1]+integral_sqrt_sum[xmin-1, ymax]
                sqrt_diff[row,col]=sqdiagsum-sqidiagsum

            mean[row,col]=diff[row, col]/area
            std[row,col]=math.sqrt((sqrt_diff[row,col]-math.sqrt(diff[row,col])/area)/(area-1))
            threshold[row,col]=mean[row,col]*(1+k*((std[row,col]/128)-1))

            if img[row,col]<threshold[row,col]:
                img[row,col]=0
            else:
                img[row,col]=255

    return img

原图:

Sauvola二值化后:

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在使用OpenCV进行灰度图像二值化时,可以使用以下函数进行操作: ```python import cv2 # 读取图像 img = cv2.imread('image.jpg', 0) # 以灰度模式读取图像 # 应用全局阈值二值化 _, img_bin = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 显示二值化后的图像 cv2.imshow('Binary Image', img_bin) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在上述代码中,`cv2.threshold()`函数用于将灰度图像进行二值化处理。其中,`img`是输入的灰度图像,`127`是设定的阈值,`255`是二值化后的最大值,`cv2.THRESH_BINARY`表示使用二进制阈值化方法。函数返回两个值,第一个值是阈值,第二个值是二值化后的图像。最后,使用`cv2.imshow()`函数显示二值化后的图像。 请注意,上述代码中的`image.jpg`是示例图像的文件名,你需要根据实际情况修改为你要处理的图像文件名。 #### 引用[.reference_title] - *1* [OpenCV python(四)图像预处理:二值化 && 滤波操作](https://blog.csdn.net/xztli/article/details/126175975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Python - OpenCV 图像二值化处理](https://blog.csdn.net/bugang4663/article/details/109589177)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Python-opencv 灰度直方图+图像二值化](https://blog.csdn.net/weixin_43909400/article/details/123378690)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值