python视频关键帧提取

来自:https://github.com/amanwalia92/KeyFramesExtraction

有三个参数:videopath:视频路径    dir:生成的图片保存路径    len_window:帧数

# -*- coding: utf-8 -*-

import cv2
import operator
import numpy as np
import matplotlib.pyplot as plt
import sys
from scipy.signal import argrelextrema

print(sys.executable)
#Setting fixed threshold criteria
USE_THRESH = False
#fixed threshold value
THRESH = 0.6
#Setting fixed threshold criteria
USE_TOP_ORDER = False
#Setting local maxima criteria
USE_LOCAL_MAXIMA = True
#Number of top sorted frames
NUM_TOP_FRAMES = 20

#Video path of the source file
videopath = 'video.mp4'
#Directory to store the processed frames
dir = './'
#smoothing window size
len_window = int(10)


def smooth(x, window_len=13, window='hanning'):
    """smooth the data using a window with requested size.
    
    This method is based on the convolution of a scaled window with the signal.
    The signal is prepared by introducing reflected copies of the signal 
    (with the window size) in both ends so that transient parts are minimized
    in the begining and end part of the output signal.
    
    input:
        x: the input signal 
        window_len: the dimension of the smoothing window
        window: the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
            flat window will produce a moving average smoothing.

    output:
        the smoothed signal
        
    example:

    import numpy as np    
    t = np.linspace(-2,2,0.1)
    x = np.sin(t)+np.random.randn(len(t))*0.1
    y = smooth(x)
    
    see also: 
    
    numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
    scipy.signal.lfilter
 
    TODO: the window parameter could be the window itself if an array instead of a string   
    """
    print(len(x), window_len)
    # if x.ndim != 1:
    #     raise ValueError, "smooth only accepts 1 dimension arrays."
    #
    # if x.size < window_len:
    #     raise ValueError, "Input vector needs to be bigger than window size."
    #
    # if window_len < 3:
    #     return x
    #
    # if not window in ['flat', 'hanning', 'hamming', 'bartlett', 'blackman']:
    #     raise ValueError, "Window is on of 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'"

    s = np.r_[2 * x[0] - x[window_len:1:-1],
              x, 2 * x[-1] - x[-1:-window_len:-1]]
    #print(len(s))

    if window == 'flat':  # moving average
        w = np.ones(window_len, 'd')
    else:
        w = getattr(np, window)(window_len)
    y = np.convolve(w / w.sum(), s, mode='same')
    return y[window_len - 1:-window_len + 1]

#Class to hold information about each frame


class Frame:
    def __init__(self, id, frame, value):
        self.id = id
        self.frame = frame
        self.value = value

    def __lt__(self, other):
        if self.id == other.id:
            return self.id < other.id
        return self.id < other.id

    def __gt__(self, other):
        return other.__lt__(self)

    def __eq__(self, other):
        return self.id == other.id and self.id == other.id

    def __ne__(self, other):
        return not self.__eq__(other)


def rel_change(a, b):
   x = (b - a) / max(a, b)
   print(x)
   return x


print("Video :" + videopath)
print("Frame Directory: " + dir)


cap = cv2.VideoCapture(str(videopath))


curr_frame = None
prev_frame = None

frame_diffs = []
frames = []
ret, frame = cap.read()
i = 1

while(ret):
    luv = cv2.cvtColor(frame, cv2.COLOR_BGR2LUV)
    curr_frame = luv
    if curr_frame is not None and prev_frame is not None:
        #logic here
        diff = cv2.absdiff(curr_frame, prev_frame)
        count = np.sum(diff)
        frame_diffs.append(count)
        frame = Frame(i, frame, count)
        frames.append(frame)
    prev_frame = curr_frame
    i = i + 1
    ret, frame = cap.read()
"""
    cv2.imshow('frame',luv)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
"""
cap.release()
#cv2.destroyAllWindows()

if USE_TOP_ORDER:
    # sort the list in descending order
    frames.sort(key=operator.attrgetter("value"), reverse=True)
    for keyframe in frames[:NUM_TOP_FRAMES]:
        name = "frame_" + str(keyframe.id) + ".jpg"
        cv2.imwrite(dir + "/" + name, keyframe.frame)

if USE_THRESH:
    print("Using Threshold")
    for i in range(1, len(frames)):
        if (rel_change(np.float(frames[i - 1].value), np.float(frames[i].value)) >= THRESH):
            #print("prev_frame:"+str(frames[i-1].value)+"  curr_frame:"+str(frames[i].value))
            name = "frame_" + str(frames[i].id) + ".jpg"
            cv2.imwrite(dir + "/" + name, frames[i].frame)


if USE_LOCAL_MAXIMA:
    print("Using Local Maxima")
    diff_array = np.array(frame_diffs)
    sm_diff_array = smooth(diff_array, len_window)
    frame_indexes = np.asarray(argrelextrema(sm_diff_array, np.greater))[0]
    for i in frame_indexes:
        name = "frame_" + str(frames[i - 1].id) + ".jpg"
        #print(dir+name)
        cv2.imwrite(dir + name, frames[i - 1].frame)


plt.figure(figsize=(40, 20))
plt.locator_params(numticks=100)
plt.stem(sm_diff_array)
plt.savefig(dir + 'plot.png')

 

### 回答1: 可以使用 OpenCV 库来完成视频关键帧提取。 下面是一个简单的例子: ``` import cv2 # 打开视频文件 video = cv2.VideoCapture("video.mp4") # 设置帧率 fps = video.get(cv2.CAP_PROP_FPS) # 设置帧数 frame_count = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) # 每隔几帧提取一帧关键帧 interval = int(fps * 2) # 储存关键帧 frames = [] # 循环读取每一帧 for i in range(frame_count): ret, frame = video.read() if not ret: break if i % interval == 0: frames.append(frame) # 保存关键帧 for i, frame in enumerate(frames): cv2.imwrite("frame_{}.jpg".format(i), frame) # 释放视频文件 video.release() ``` 在这个例子中,我们使用 OpenCV 读取视频文件,然后从每隔 `interval` 帧提取一帧关键帧。最后,我们把关键帧保存为图像文件。 ### 回答2: 视频关键帧提取是一种常见的视频处理任务,Python可以使用OpenCV库来实现。下面是一个使用Python完成视频关键帧提取的简单步骤: 1. 首先,我们需要导入OpenCV库:`import cv2` 2. 然后,读取视频文件:`video = cv2.VideoCapture('video.mp4')`,其中'video.mp4'是视频文件的路径和文件名。 3. 接下来,我们需要确定关键帧的间隔。关键帧越少,提取速度越快,但可能会错过一些重要的变化。在这里,我们将设置关键帧间隔为10:`interval = 10` 4. 然后,我们需要计算视频的总帧数:`total_frames = video.get(cv2.CAP_PROP_FRAME_COUNT)` 5. 之后,我们可以开始提取关键帧。我们可以遍历视频的每一帧,然后将关键帧保存到一个列表中。下面是一个示例代码: ``` keyframes = [] for frame_num in range(0, int(total_frames), interval): video.set(cv2.CAP_PROP_POS_FRAMES, frame_num) ret, frame = video.read() if ret: keyframes.append(frame) ``` 在上面的代码中,我们首先使用`video.set(cv2.CAP_PROP_POS_FRAMES, frame_num)`将视频的当前帧设置为我们要读取关键帧。然后,使用`video.read()`读取当前帧,并检查返回值`ret`来确保读取成功。如果读取成功,将当前帧存储到关键帧列表中。 6. 最后,我们可以将关键帧保存到磁盘上,以备后续使用。例如,将关键帧保存到一个名为'keyframes'的文件夹中,文件名格式为'frame_{frame_num}.jpg': ``` for i, frame in enumerate(keyframes): cv2.imwrite(f'keyframes/frame_{i}.jpg', frame) ``` 上述代码中,`cv2.imwrite()`函数用于保存关键帧到磁盘,文件名使用了格式化字符串以嵌入帧号。 这样,我们就完成了使用Python提取视频关键帧的过程。通过调整关键帧的间隔,您可以在提取速度和精度之间进行权衡。请注意,上述过程仅提供了基本的关键帧提取示例,实际应用中可能需要进行参数调整和算法优化以获得更好的结果。 ### 回答3: 视频关键帧提取是指从视频序列中提取出具有重要内容的帧。Python是一种功能强大的编程语言,可以使用其提供的各种库和工具来完成视频关键帧提取任务。 首先,我们需要导入所需的Python库。其中,OpenCV是一个常用的计算机视觉库,提供了处理图像和视频的函数和工具。 接下来,我们需要使用OpenCV读取视频文件,并逐帧处理。通过调用视频的帧率(FPS)信息,可以设置提取关键帧的间隔,例如每秒提取一帧。 然后,我们可以使用OpenCV的函数来进行关键帧提取。一种常用的方法是使用帧间差分法(Frame Difference)来判断帧与帧之间的差异。具体而言,我们可以比较连续两帧之间的像素差异,将差异超过某个阈值的帧标记为关键帧。 在计算每个帧的差异时,可以使用灰度转换等方法将彩色图像转换为灰度图像,以降低计算复杂度和提高效率。 最后,我们可以将提取出的关键帧保存为图像文件,或者在需要的时候进行处理和使用。 综上所述,使用Python可以很方便地完成视频关键帧提取。通过利用OpenCV等库和工具,我们可以从视频流中提取出具有重要内容的关键帧,并进一步进行处理和使用。
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值