我有一类函数‘检测器’,它在给定一段视频、一个空间尺度参数和一个时间尺度参数的情况下,检测一些兴趣点.我编写了一个‘MultiscaleDetector’函数,它基本上接受一个空间尺度参数列表和一个‘探测器’函数作为参数,并 for each 尺度执行给定的探测器系数.

下面是它们的外观:

def GaborDetector(v, sigma, tau, threshold, num_points):
    """
    Gabor Detector
    
    Keyword arguments:
    video -- input video (y_len, x_len, frames)
    sigma -- Gaussian kernel space standard deviation
    tau -- Gaussian kernel time standard deviation
    kappa -- Gabor response threshold
    """
    # setup video
    video = v.copy()
    video = video.astype(float)/video.max()
    video = video_smoothen_space(video, sigma)
    # first define a linspace of width -2tau to 2tau
    time = np.linspace(-2*tau, 2*tau, int(4*tau+1))
    omega = 4/tau
    # define the gabor filters
    h_ev = np.exp(-time**2/(2*tau**2)) * np.cos(2*np.pi*omega*time)
    h_od = np.exp(-time**2/(2*tau**2)) * np.sin(2*np.pi*omega*time)
    # normalize the L1 norm
    h_ev /= np.linalg.norm(h_ev, ord=1)
    h_od /= np.linalg.norm(h_od, ord=1)
    # compute the response
    response = (scp.convolve1d(video, h_ev, axis=2) ** 2) + (scp.convolve1d(video, h_od, axis=2) ** 2)
    points = interest_points(response, num=num_points, threshold=threshold, scale=sigma)
    return points
def MultiscaleDetector(detector, video, sigmas, tau, num_points):
    """
    Multiscale Detector

    Executes a detector at multiple scales. Detector has to be a function that
    takes a video as input, along with other parameters, and returns a list of interest points.

    
    Keyword arguments:
    detector -- function that returns interest points
    video -- input video (y_len, x_len, frames)
    sigmas -- list of scales
    """
    
    # for every scale, compute the response
    points = []
    for sigm in sigmas:
        found = detector(video, sigm, tau)
        points.append(found)

    # filter the points, currently irrelevant

正如您可能已经注意到的,在"GborDetector"函数内部进行了一些繁重的计算,这仅取决于时间参数.因此,"MultiscaleDetector"函数在每次调用中都不必要地重新计算这些变量.

为了避免重构代码,我想出了一个我希望是一个很好的技巧,但我认为这将是徒劳的:

def MultiscaleDetector(detector, video, sigmas, tau, num_points):
    """
    Multiscale Detector

    Executes a detector at multiple scales. Detector has to be a function that
    takes a video as input, along with other parameters, and returns a list of interest points.

    
    Keyword arguments:
    detector -- function that returns interest points
    video -- input video (y_len, x_len, frames)
    sigmas -- list of scales
    """
    
    optimization_trick = lambda s_param: detector(video, s_param, tau)
    # for every scale, compute the response
    points = []
    for sigm in sigmas:
        found = optimization_trick(sigm)
        points.append(found)

    # filter the points, currently irrelevant

我希望只依赖tau的变量将以某种方式"存储"在"OPTIMIZATION_TICK"中,从而避免被重新计算.然而,当我对不同的实现进行计时时,差异大约是0.02秒,"优化"函数的速度更快.

编辑:

实际发生的呼叫如下所示:

# read the video
video = read_video(video_name, num_frames, 0)
# get the interest points
detector = lambda v, s, t: GaborDetector(v, s, t, 0.3, 500)
scales = [3*(1.1)**i for i in range(6)]
start = time.time()
points = MultiscaleDetector(detector, video, scales, 1.5, 500)
end = time.time()
print("Time: {}".format(end-start))

我try 将我想要避免的所有变量放在一个不同的函数中,如下所示:

def GaborDetectorTrial(v, sigma, tau, threshold, num_points):
    """
    Gabor Detector
    
    Keyword arguments:
    video -- input video (y_len, x_len, frames)
    sigma -- Gaussian kernel space standard deviation
    tau -- Gaussian kernel time standard deviation
    kappa -- Gabor response threshold
    """
    @lru_cache(maxsize=None)
    def time_function(tau):
        time = np.linspace(-2*tau, 2*tau, int(4*tau+1))
        omega = 4/tau
        # define the gabor filters
        h_ev = np.exp(-time**2/(2*tau**2)) * np.cos(2*np.pi*omega*time)
        h_od = np.exp(-time**2/(2*tau**2)) * np.sin(2*np.pi*omega*time)
        # normalize the L1 norm
        h_ev /= np.linalg.norm(h_ev, ord=1)
        h_od /= np.linalg.norm(h_od, ord=1)
        return h_ev, h_od
    # setup video
    video = v.copy()
    video = video.astype(float)/video.max()
    video = video_smoothen_space(video, sigma)
    # compute the response
    h_ev, h_od = time_function(tau)
    response = (scp.convolve1d(video, h_ev, axis=2) ** 2) + (scp.convolve1d(video, h_od, axis=2) ** 2)
    points = interest_points(response, num=num_points, threshold=threshold, scale=sigma)
    return points

我想避免重新计算的变量是h_ev和h_od.执行时间基本相同(实际上慢了一些毫秒).

推荐答案

你就不能分成多个功能吗?

示例:

def time_function(tau): #To compute hev and hod
        time = np.linspace(-2*tau, 2*tau, int(4*tau+1))
        omega = 4/tau
        # define the gabor filters
        h_ev = np.exp(-time**2/(2*tau**2)) * np.cos(2*np.pi*omega*time)
        h_od = np.exp(-time**2/(2*tau**2)) * np.sin(2*np.pi*omega*time)
        # normalize the L1 norm
        h_ev /= np.linalg.norm(h_ev, ord=1)
        h_od /= np.linalg.norm(h_od, ord=1)
        return h_ev, h_od

然后

# read the video
video = read_video(video_name, num_frames, 0)
# get the interest points
custom_tau = {}

scales = [3*(1.1)**i for i in range(6)]
start = time.time()
for i in range(0,10): # for loop cause otherwise you call GaborDetector only once so the question is not revelant
    #Insert logic here because for your question to be revelant Tau must not always be the same
    if tau not in custom_tau.keys(): # Logic to "cache" hev and hod for the same tau value
        hev, hod = time_function(tau)
        custom_tau[tau] = (hev, hod)
    else:
        hev, hod = custom_tau[tau]
    gabor = GaborDetector(v, s, t, hev, hod, 0.3, 500)
    points = MultiscaleDetector(gabor, video, scales, 1.5, 500)
end = time.time()
print("Time: {}".format(end-start))

最后,将GarborCollector更改为不重新计算时间

def GaborDetectorTrial(v, sigma, tau,hev, hod, threshold, num_points):

    video = v.copy()
    video = video.astype(float)/video.max()
    video = video_smoothen_space(video, sigma)
    response = (scp.convolve1d(video, h_ev, axis=2) ** 2) + (scp.convolve1d(video, h_od, axis=2) ** 2)
    points = interest_points(response, num=num_points, threshold=threshold, scale=sigma)
    return points

在这段代码中,您所做的是(通过一个字典)对hev和hod进行"缓存",因此,如果您已经为给定的"tau"计算了它,那么您将在字典中查找结果,否则您将计算它并将其放入字典中.

我不得不推断和猜测您的代码将如何工作,因为在您给出的情况下,he_v和ho_d永远不会重新计算,因为您只调用garbor一次

Python相关问答推荐

如何从FDaGrid实例中删除某些函数?

将numpy数组存储在原始二进制文件中

如何访问所有文件,例如环境变量

将输入管道传输到正在运行的Python脚本中

加速Python循环

使用@ guardlasses. guardlass和注释的Python继承

ODE集成中如何终止solve_ivp的无限运行

如何在Pyplot表中舍入值

如何排除prefecture_related中查询集为空的实例?

通过追加列表以极向聚合

如何按row_id/row_number过滤数据帧

Python pint将1/华氏度转换为1/摄氏度°°

pandas:在操作pandora之后将pandora列转换为int

如何将一组组合框重置回无 Select tkinter?

如何在验证文本列表时使正则表达式无序?

你能把函数的返回类型用作其他地方的类型吗?'

使用np.fft.fft2和cv2.dft重现相位谱.为什么结果并不相似呢?

替换包含Python DataFrame中的值的<;

如何在Quarto中的标题页之前创建序言页

如何从一个维基页面中抓取和存储多个表格?