使用积分图像进行自适应阈值二值化

import cv2 as cv
import numpy as np


def adaptive_threshold(gray: np.ndarray, whs: int = None, sub_threshold: float = 0.15):
    """
    基于积分图像的自适应阈值二值化算法

    :param gray:            输入的灰度图像
    :param whs:             滑动窗口的半宽高(默认为图像宽度的1/10)
    :param sub_threshold:   自定义子阈值,需要通过实验对比确定
    :return:                二值化图像
    """

    # 计算积分图像
    integral_image = cv.integral(gray, cv.CV_32F)
    # 创建滑动窗口
    height = gray.shape[0]
    width = gray.shape[1]
    window_half_size = int(width / 10) if whs is None else whs
    binary = np.zeros((height, width), dtype=np.uint8)
    # 开始二值化
    for j in range(height):
        for i in range(width):
            # 定义滑动窗口的角点
            x1 = i - window_half_size
            x2 = i + window_half_size
            y1 = j - window_half_size
            y2 = j + window_half_size
            # 检查滑动窗口的边界
            x1 = 0 if x1 < 0 else x1
            y1 = 0 if y1 < 0 else y1
            x2 = width - 1 if x2 > width else x2
            y2 = height - 1 if y2 > height else y2
            count = (x2 - x1) * (y2 - y1)
            # \mbox{I}_W=\mbox{I}(x_2,y_2)-\mbox{I}(x_1-1,y_2)-\mbox{I}(x_2,y_1-1)+\mbox{I}(x_1-1,y_1-1)
            summed = integral_image[y2, x2] - integral_image[y1, x2] - integral_image[y2, x1] + integral_image[y1, x1]
            binary[j, i] = 0 if int(gray[j, i] * count) < int(summed * (1.0 - sub_threshold)) else 255
    return binary
posted @ 2022-08-01 10:34  BNTU  阅读(183)  评论(0编辑  收藏  举报