python版var_threshold 以及 dyn_threshold算法块

import numpy as np
import cv2
import matplotlib.pyplot as plt
import os, math, time

def dyn_threshold(image, fImage, offset, LightDark):
    '''
    dyn_threshold selects from the input image those regions in which the pixels fulfill a threshold condition. Let g_{o} = g_{OrigImage}, and g_{t} = g_{ThresholdImage}. Then the condition for LightDark = 'light' is:
    For LightDark = 'dark' the condition is:
        g0 < gt - offset
    For LightDark = 'equal' it is:
        g0 >= gt + offset
    Finally, for LightDark = 'not_equal' it is:
        g0 < gt - offset or g0 > gt + offset
    Typically, the threshold images are smoothed versions of the original image
    (e.g., by applying mean_image, binomial_filter, gauss_filter, etc.).
    Then the effect of dyn_threshold is similar to applying threshold to a highpass-filtered version
    of the original image (see highpass_image).

    With dyn_threshold, contours of an object can be extracted, where the objects' size (diameter) is
    determined by the mask size of the lowpass filter and the amplitude of the objects' edges:

    The larger the mask size is chosen, the larger the found regions become.
    As a rule of thumb, the mask size should be about twice the diameter of the objects to be extracted.
    It is important not to set the parameter Offset to zero because in this case too many small regions
    will be found (noise). Values between 5 and 40 are a useful choice. The larger Offset is chosen,
    the smaller the extracted regions become.

    All points of the input image fulfilling the above condition are stored jointly in one region.
    If necessary, the connected components can be obtained by calling connection.

    Attention
    If Offset is chosen from -1 to 1 usually a very noisy region is generated, requiring large storage.
    If Offset is chosen too large (> 60, say) it may happen that no points fulfill the threshold condition
     (i.e., an empty region is returned). If Offset is chosen too small (< -60, say) it may happen that
     all points fulfill the threshold condition (i.e., a full region is returned).
    :param image:
    :param fImage:
    :param offset:
    :param LightDark:
    :return:
    '''
    assert isinstance(image, np.ndarray)
    assert isinstance(fImage, np.ndarray)
    assert len(image.shape) == 2
    assert image.shape == fImage.shape
    assert isinstance(LightDark, str)
    assert ['light', 'dark', 'equal', 'no_equal'].count(str(LightDark))!=0
    h, w = image.shape
    g0 = image.astype(np.float32)
    gt = fImage.astype(np.float32)
    index = ['light', 'dark', 'equal', 'no_equal'].index(LightDark)
    if index ==0 :
        dst = (g0 >= gt + offset) * 1.0
    elif index==1:
        dst = (g0 < gt - offset) * 1.0
    elif index==2:
        dst = (gt + offset >= g0 >= gt - offset) * 1.0
    elif index==3:
        dst = (g0 >= gt + offset or g0 <= gt - offset) * 1.0
    dst*=255.
    return dst
def stdFilter(image, winsize, border=cv2.BORDER_REFLECT):
    '''
    blur(src, ksize[, dst[, anchor[, borderType]]]) -> dst
    .   @brief Blurs an image using the normalized box filter.
    .
    .   The function smooths an image using the kernel:
    .   Σ[(x-mean(x))^2]/n ≈ maximum{ Σ(x^2)/n - Σ[mean(x)^2]/n, 0}^2
    :param image:
    :param winwidth: Shift window width
    :param winheight: Shift window height
    :param border: Image border type
    :return: standard deviation smooth array
    '''
    assert image is not None and len(image.shape) == 2
    assert winsize[0]%2!=0 and winsize[1]%2!=0
    img = image / 255.0
    h = np.ones(winsize)
    n = h.sum()
    x_2 = cv2.filter2D(img**2, -1, h, borderType=border) / n
    mean_x = cv2.filter2D(img, -1, h, borderType= border) / n
    mean_x_2 = mean_x**2
    std = np.sqrt(np.maximum(x_2-mean_x_2, 0))
    dst = std * 255.
    return dst

def var_threshold(image, winsize, StdDevScale, AbsThreshold, LightDark):
    '''
    Threshold an image by local mean and standard deviation analysis.
    :param image:
    :param winsize::
        The size of the filter mask defined by MaskWidth and MaskHeight
        determines the maximum size of the objects to be segmented.
        However, if the mask is chosen too large, objects that are very close might be merged.
    :param StdDevScale::
        The local standard deviation is used as a measure of noise in the image.
        It can be scaled by StdDevScale to reflect the desired sensitivity.
        A higher value means that only pixels that are very different from their surrounding are selected.
        For the parameter StdDevScale values between -1.0 and 1.0 are sensible choices,
        with 0.2 as a suggested value. If the parameter is too high or too low, an empty or full region may be returned.
    :param AbsThreshold::
        In homogeneous areas of an image, the standard deviation is low; thus, the influence of single gray values is high.
        To reduce the sensitivity of the operator in homogeneous areas, it's possible to adjust AbsThreshold.
        Thus, small gray value changes in homogeneous surroundings can be ignored. Note that for negative values of StdDevScale,
        AbsThreshold should also be chosen negative.
    :param LightDark::
        'light' or 'dark' returns all pixels that are lighter or darker than their surrounding, respectively.
        'equal' returns all pixels that are not selected by either option, i.e. the pixels that are relatively equal to their surrounding.
        'not_equal' returns the combined results of 'light' and 'dark', i.e., all pixels that differ from their surrounding.
    :return:
    '''
    assert image is not None and len(image.shape) == 2
    assert isinstance(winsize, tuple)
    assert winsize[0] % 2 != 0 and winsize[1] % 2 != 0
    assert isinstance(LightDark, str)
    assert ['light', 'dark', 'equal', 'no_equal'].count(str(LightDark))!=0
    h,w = image.shape[:2]
    d = stdFilter(image, winsize).astype(np.float32)
    image = image.astype(np.float32)
    stdarray = np.ones_like(image, dtype=np.float32) * StdDevScale
    absarray = np.ones_like(image, dtype=np.float32) * AbsThreshold
    meanarray = cv2.blur(image, winsize, borderType=cv2.BORDER_REFLECT) * 1.0
    if StdDevScale >= 0:
        varray = cv2.max(stdarray*d, absarray)
    else:
        varray = cv2.min(stdarray*d, absarray)
    index = ['light', 'dark', 'equal', 'no_equal'].index(str(LightDark).lower())
    if index==0:
        dst = (image >= meanarray + varray) * 1.0
    elif index==1:
        dst = (image <= meanarray - varray) * 1.0
    elif index==2:
        dst = (meanarray-varray <= image <= meanarray + varray) * 1.0
    elif index==3:
        dst = (image < meanarray-varray or image > meanarray + varray) * 1.0
    dst*=255
    return dst.astype(np.uint8)

path = r'D:\Jay.Lee\Study\imgs\var_test_image.png'
image = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
cv2.imshow('image', image)
cv2.waitKey()
cv2.destroyAllWindows()
t1 = time.time()
thresh = var_threshold(image, (5,5), 0, 12, 'dark')
t2 = time.time()-t1
print('cost time: {}'.format(t2))

t3 = time.time()
mean = cv2.blur(image, (5, 5))
thresh1 = dyn_threshold(image, mean,10, 'dark')
t4 = time.time()-t1
print('cost time: {}'.format(t4))

cv2.imshow('thresh', thresh)
cv2.imshow('thresh1', thresh1)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值