Cách biết tổng số Frame trong tệp có cv2 trong python


80

Cách biết tổng số Frame trong một tệp (.avi) thông qua Python bằng cách sử dụng mô-đun cv mở.

Nếu có thể, tất cả thông tin (độ phân giải, khung hình / giây, thời lượng, v.v.) mà chúng tôi có thể nhận được về một tệp video thông qua việc này.

Câu trả lời:


120

Với phiên bản OpenCV mới hơn (tôi sử dụng 3.1.0), nó hoạt động như sau:

import cv2

cap = cv2.VideoCapture("video.mp4")
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print( length )

Và tương tự cho các thuộc tính video khác cv2.CAP_PROP_*


3
đối tượng 'mô-đun' không có thuộc tính 'CAP_PROP_FRAME_COUNT'
john ktejik

1
Bạn có chắc mình đang sử dụng OpenCV phiên bản 3+ không? Tôi vừa thử nghiệm với phiên bản 3.3.1 và vẫn hoạt động.
phev8

Bất kỳ ý tưởng nào về độ phức tạp của cap.get()?

Tôi đã thử nghiệm nó ngay bây giờ, đối với tôi, nó cũng hoạt động với các tệp video .avi. Hiện tại, tôi đang sử dụng phiên bản 4.0.1-dev trên máy tính Ubuntu 18.04. Bạn có chắc chắn, tệp video của bạn không bị hỏng?
phev 8

Hoặc như một số người bình luận khác ở đây gợi ý về điều đó, nó phụ thuộc vào những gì có trong vùng chứa avi của bạn ... Rõ ràng, đôi khi nó không có sẵn - bạn có thể thử sử dụng một số bộ mã hóa khác cho tệp video của mình.
phev 8

40
import cv2

cap = cv2.VideoCapture(fn)

if not cap.isOpened(): 
    print "could not open :",fn
    return

length = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
width  = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT))
fps    = cap.get(cv2.cv.CV_CAP_PROP_FPS)

xem ở đây để biết thêm thông tin.

Ngoài ra, tất cả đều có muối, không phải tất cả các đạo cụ đó đều là bắt buộc, một số có thể không có sẵn với codec chụp / video của bạn


1
CAP_PROP_FRAME_COUNT đang cho 0 giá trị, Đây là nhập mã cv2 # - - coding: utf-8 - - filename = "test.avi" cap = cv2.VideoCapture (filename) fps = cap.get (cv2.cv.CV_CAP_PROP_FPS) print 'fps =' + str (fps) Frames = cap.get (cv2.cv.CV_CAP_PROP_FRAME_COUNT) print 'Frames =' + str (Frames) Bạn có thể cho biết tôi đang làm sai ở đâu không.
Niraj

bạn có thể không làm gì sai. một lần nữa, avi chỉ là một vùng chứa, có thể có bất kỳ thứ gì trong đó và một số codec không hỗ trợ truy vấn các thuộc tính nhất định.
berak

Xin chào berak, Xin lỗi vì đã phát lại muộn, bạn có thể vui lòng cho tôi gợi ý thêm về điều này được không.
Niraj

14

Đây là cách nó hoạt động với Python 3.6.5 (trên Anaconda) và OpenCV 3.4.2. [Lưu ý]: Bạn cần bỏ "CV_" khỏi "CV_CAP_PROP_xx" cho bất kỳ thuộc tính nào như được cung cấp trên trang web OpenCV chính thức .

import cv2
cap = cv2.VideoCapture("video.mp4")
property_id = int(cv2.CAP_PROP_FRAME_COUNT) 
length = int(cv2.VideoCapture.get(cap, property_id))
print( length )

2
Điều đó thật tuyệt! Bạn cũng có thể truy xuất bằng cách sử dụnglength = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
Scratch'N'Purr

10

Có hai phương pháp để xác định số khung hình trong tệp video

  • Phương pháp # 1: Sử dụng các thuộc tính OpenCV tích hợp sẵn để truy cập thông tin meta tệp video nhanh và hiệu quả nhưng không chính xác
  • Phương pháp # 2: Lặp lại thủ công từng khung hình trong tệp video với bộ đếm chậm và không hiệu quả nhưng chính xác

Phương pháp # 1 nhanh chóng và dựa vào chức năng thuộc tính video của OpenCV, chức năng này gần như xác định ngay lập tức số lượng khung hình trong tệp video. Tuy nhiên, có một sự đánh đổi về độ chính xác vì nó phụ thuộc vào phiên bản OpenCV và codec video của bạn. Mặt khác, việc đếm thủ công từng khung hình sẽ chính xác 100% mặc dù nó sẽ chậm hơn đáng kể. Đây là một hàm cố gắng thực hiện Phương pháp số 1 theo mặc định, nếu không thành công, nó sẽ tự động sử dụng Phương pháp số 2

def frame_count(video_path, manual=False):
    def manual_count(handler):
        frames = 0
        while True:
            status, frame = handler.read()
            if not status:
                break
            frames += 1
        return frames 

    cap = cv2.VideoCapture(video_path)
    # Slow, inefficient but 100% accurate method 
    if manual:
        frames = manual_count(cap)
    # Fast, efficient but inaccurate method
    else:
        try:
            frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        except:
            frames = manual_count(cap)
    cap.release()
    return frames

Điểm chuẩn

if __name__ == '__main__':
    import timeit
    import cv2

    start = timeit.default_timer()
    print('frames:', frame_count('fedex.mp4', manual=False))
    print(timeit.default_timer() - start, '(s)')

    start = timeit.default_timer()
    print('frames:', frame_count('fedex.mp4', manual=True))
    print(timeit.default_timer() - start, '(s)')

Phương pháp số 1 kết quả

frames: 3671
0.018054921 (s)

Phương pháp số 2 kết quả

frames: 3521
9.447095287 (s)

Lưu ý rằng hai phương pháp khác nhau 150 khung hình và Phương pháp số 2 chậm hơn đáng kể so với Phương pháp số 1 . Do đó, nếu bạn cần tốc độ nhưng sẵn sàng hy sinh độ chính xác, hãy sử dụng Phương pháp số 1. Trong tình huống bạn ổn với độ trễ nhưng cần số khung hình chính xác, hãy sử dụng Phương pháp số 2


4

Một giải pháp khác mà không phụ thuộc vào các trình nhận lỗi đôi khi CV_CAP_PROPlà xem toàn bộ tệp video của bạn trong một vòng lặp

  • Tăng biến bộ đếm khung hình mỗi khi gặp khung hình hợp lệ và dừng khi khung không hợp lệ xuất hiện (cuối tệp video).
  • Việc thu thập thông tin về độ phân giải phức tạp hơn vì một số codec hỗ trợ độ phân giải thay đổi (tương tự như VBR trong các tệp âm thanh trong đó tốc độ bit không phải là hằng số mà thay vào đó bao gồm một số phạm vi được xác định trước).

    • độ phân giải không đổi - bạn chỉ cần khung hình đầu tiên để xác định độ phân giải của toàn bộ tệp video trong trường hợp này, do đó, không cần xem toàn bộ video
    • độ phân giải thay đổi - bạn cần lấy độ phân giải của từng khung hình (chiều rộng và chiều cao) và tính toán trung bình để có được độ phân giải trung bình của video
  • FPS có thể được tính toán tuy nhiên ở đây bạn gặp phải vấn đề tương tự như với độ phân giải - hằng số (CFR) so với biến (VFR). Đây là một vấn đề liên quan đến luồng đột biến omho. Cá nhân tôi sẽ sử dụng một bộ đếm khung hình, bộ đếm này tăng lên sau mỗi khung hình hợp lệ trong khi ở khoảng thời gian 1 giây, một bộ đếm thời gian (chạy trong luồng nền) sẽ kích hoạt lưu giá trị của bộ đếm hiện tại và sau đó đặt lại nó. Bạn có thể lưu trữ các giá trị trong một danh sách để tính toán tốc độ khung hình trung bình / không đổi ở cuối khi bạn cũng sẽ biết tổng số khung hình mà video có.

Nhược điểm của cách làm khá đơn giản này là bạn phải duyệt qua toàn bộ tệp, điều này - trong trường hợp nó dài vài giờ - chắc chắn sẽ bị người dùng chú ý. Trong trường hợp này, bạn có thể thông minh về nó và làm điều đó trong quy trình nền trong khi cho phép người dùng làm việc khác trong khi ứng dụng của bạn đang thu thập thông tin này về tệp video đã tải.

Ưu điểm là bất kể bạn có tệp video nào miễn là OpenCV có thể đọc từ nó, bạn sẽ nhận được kết quả khá chính xác không giống như kết quả CV_CAP_PROPcó thể có hoặc không hoạt động như bạn mong đợi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.