有没有办法在python 3.7中手动清除ram?

时间:2019-07-06 04:51:59

标签: python ram

我正在尝试制作一个程序,该程序删除视频中的背景,以便仅显示前景。它适用于短片,但长片则成倍地减慢速度,并开始使用越来越多的内存,从而使程序崩溃。

我尝试删除for循环中使用的变量,如下面的代码所示。

def video_generator(name_of_video, video, cap, number_of_frames):
    check, frame = cap.read()
    A = np.array([])
    a = np.array([])

    if cap.isOpened():
        width = int(cap.get(3))
        height = int(cap.get(4))

    dims = (height, width)

    while cap.isOpened():
        check, frame = cap.read()

        if check:
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY).flatten()
            A = np.append(A, gray)
            a = np.append(a, 'row')
            image = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
        else:
            break   

    B = np.resize(A, (number_of_frames, width * height))

    U, S, V = decomposition.randomized_svd(B, 2)
    background = U @ np.diag(S) @ V

    foreground = ([])

    def generate_frames(B, background):
        for i in range(number_of_frames):
            foreground = np.reshape(B[i] - background[i], dims)
            frame = plt.imshow(foreground, cmap = 'gray')
            plt.savefig('D:/Python_Programs/BR_SVD/Frames/' + name_of_video + '/file_' + str(i + x * number_of_frames).zfill(2) + '.png')   

            del frame
            del foreground
            gc.collect()

    generate_frames(B, background)  

if number_of_frames_initial <= 200:
    cap = cv2.VideoCapture(video)
    video_generator(name_of_video, video_initial, cap_initial, number_of_frames_initial)

else:
    number_of_videos = int(number_of_frames_initial/200 + 1)
    time_of_videos = duration/number_of_videos

    for x in range (number_of_videos):

        subprocess.call ([
            'ffmpeg', '-i', video_initial, '-ss', str(time_of_videos * x), '-t', str(time_of_videos), 'D:/Python_Programs/BR_SVD/Temp_Videos/video_%02d.mp4' % x])

        video = 'D:/Python_Programs/BR_SVD/Temp_Videos/video_%02d.mp4' % x
        cap = cv2.VideoCapture(video)
        number_of_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        video_generator(name_of_video, video, cap, number_of_frames)

        del B
        del background
        gc.collect()

2 个答案:

答案 0 :(得分:0)

关于Python如何进行垃圾回收(除了源代码本身),没有确切的资源,但是这3个链接应该给你一个很好的主意。

更新

来源实际上很有帮助。从中获得多少取决于您对C的理解程度,但是注释实际上非常有帮助。跳到collect()函数,注释会很好地解释该过程(尽管在技术上非常严格)。

答案 1 :(得分:0)

作为对您的顶级问题的解答:明确del指向对象的最后一个引用并调用gc.collect()是手动清除Python拥有的RAM的最接近的方法,而这两个都不是通常是必需的。当函数退出时(就像每个本地名称都是del ed一样),函数的局部变量会自动清除,并且默认情况下,循环GC会每隔几百个分配运行一次,通常这很好,除非您有大量的对象参与循环。除此之外,一般规则是显式调用清理方法(或更好的方法是,在可用时使用with语句)以确保资源被及时释放,并且引用的保留时间不要超过您的需要(如果您愿意,保持全局list并保持append的状态,因为您要求永久保留这些东西,所以任何GC都无法拯救您。

有关具体建议:

我相信您在使用cap.release()对象时应该在其上调用VideoCapture;在range(number_of_videos)上的每个循环中都保留一个开放可能会占用相当长的一段时间。从理论上讲,文档声称析构函数为您调用release,但是最好明确地调用它,以确保确定,特别是因为引用循环出奇的容易触发,并且可能导致延迟(或者写得不好或使用Python的情况) 2个扩展模块,完全阻止)您期望的清理。

您反复打给np.append的电话也会使您放慢速度; np.append创建输入的副本并追加到输入中,这将以Schlemiel the Painter's algorithm的形式出现;每个新框架最终都会复制之前的所有数据以及新数据,并且先前的数据会不断增长。我建议保持A / a为您调用list的普通Python .append,并仅在末尾重新组合一次,以避免内存复制的二次增长

我还要注意,您的del Bdel background毫无意义;它们仅存在于video_generator的范围内,并且您正在尝试del处于全局范围内(无论如何,在清理它们之后,并且从从不/ em>存在)。通常不需要显式的del名称;当函数退出时(假设不存在其他引用),将清理本地人,因此您尝试在不需要时执行运行时的工作。