2013-09-23 240 views
28

Tôi là người mới bắt đầu trong OpenCV. Tôi muốn thực hiện một số xử lý hình ảnh trên các khung hình của video đang được tải lên máy chủ của tôi. Tôi chỉ muốn đọc các khung hình có sẵn và viết chúng trong một thư mục. Và chờ một phần khác của video được tải lên và ghi các khung hình vào thư mục. Và tôi nên chờ cho mỗi khung hình được tải lên hoàn toàn rồi ghi nó vào một tập tin.Cách xử lý hình ảnh của video, khung theo khung hình trong phát video bằng cách sử dụng python Opencv

Bạn có thể cho tôi biết cách tôi có thể làm điều đó với OpenCV (Python) không?

Chỉnh sửa 1: Tôi đã viết mã này để quay video từ tệp, trong khi dữ liệu mới đang được thêm vào cuối tệp. Nói cách khác, tệp out.mp4 không phải là video hoàn chỉnh và một chương trình khác đang viết khung mới lên đó. Những gì tôi sẽ làm là, chờ đợi cho các chương trình khác để viết khung hình mới sau đó đọc chúng và hiển thị chúng.

Đây là mã của tôi:

import cv2 
cap = cv2.VideoCapture("./out.mp4") 

while True: 
    if cap.grab(): 
     flag, frame = cap.retrieve() 
     if not flag: 
      continue 
     else: 
      cv2.imshow('video', frame) 
    if cv2.waitKey(10) == 27: 
     break 

Vì vậy, vấn đề là cap.grab() gọi! khi không có khung, nó sẽ trả lại False! Và nó sẽ không chụp khung nữa, ngay cả khi tôi chờ đợi một thời gian dài.

+0

Vui lòng thêm mô tả chi tiết hơn. 'một số xử lý hình ảnh trên khung' trong khi tải lên hoặc sau? 'khung có sẵn' ở đâu và chúng có sẵn như thế nào? 'Đợi phần khác của video' chỉ cần thêm? ... –

+0

@RobertCaspary cảm ơn bạn đã bình luận của bạn. 'một số xử lý hình ảnh trên khung hình': chỉ cần giả định rằng tôi muốn viết khung thành một tệp trong một thư mục. 'các khung có sẵn': giả sử rằng video có 100 khung hình, nhưng chỉ 40 khung hình được tải lên, vì vậy các khung có sẵn là 40 khung hình đầu tiên. Và cho đến nay, tôi đã lưu chúng vào các tập tin trong một thư mục cụ thể. 'Đợi phần khác của video': đợi khung hình thứ 41 được tải lên rồi lưu nó vào một tệp khác, sau đó là khung hình thứ 42, v.v. Có rõ không? – Mehran

Trả lời

37

Sau khi đọc tài liệu về VideoCapture. Tôi đã tìm ra rằng bạn có thể cho biết VideoCapture, khung nào được xử lý vào lần tới chúng tôi gọi là VideoCapture.read() (hoặc VideoCapture.grab()).

Vấn đề là khi bạn muốn read() một khung chưa sẵn sàng, đối tượng VideoCapture bị kẹt trên khung đó và không bao giờ tiếp tục. Vì vậy, bạn phải ép buộc nó bắt đầu lại từ khung trước đó.

Đây là mã

import cv2 

cap = cv2.VideoCapture("./out.mp4") 
while not cap.isOpened(): 
    cap = cv2.VideoCapture("./out.mp4") 
    cv2.waitKey(1000) 
    print "Wait for the header" 

pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) 
while True: 
    flag, frame = cap.read() 
    if flag: 
     # The frame is ready and already captured 
     cv2.imshow('video', frame) 
     pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) 
     print str(pos_frame)+" frames" 
    else: 
     # The next frame is not ready, so we try to read it again 
     cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1) 
     print "frame is not ready" 
     # It is better to wait for a while for the next frame to be ready 
     cv2.waitKey(1000) 

    if cv2.waitKey(10) == 27: 
     break 
    if cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT): 
     # If the number of captured frames is equal to the total number of frames, 
     # we stop 
     break 
+0

Công trình này hoạt động, nhưng tại một số điểm ngẫu nhiên, các khung dừng dừng trong khi luồng đầu vào vẫn tiếp tục. Một cái gì đó vẫn bị treo ở đây – Gulzar

7

Trong tài liệu của OpenCV, có example để nhận khung hình video theo khung. Nó được viết bằng C++ nhưng rất dễ dàng để chuyển ví dụ sang python - bạn có thể tìm kiếm từng tài liệu fumction để xem cách gọi chúng trong python.

#include "opencv2/opencv.hpp" 

using namespace cv; 

int main(int, char**) 
{ 
    VideoCapture cap(0); // open the default camera 
    if(!cap.isOpened()) // check if we succeeded 
     return -1; 

    Mat edges; 
    namedWindow("edges",1); 
    for(;;) 
    { 
     Mat frame; 
     cap >> frame; // get a new frame from camera 
     cvtColor(frame, edges, CV_BGR2GRAY); 
     GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); 
     Canny(edges, edges, 0, 30, 3); 
     imshow("edges", edges); 
     if(waitKey(30) >= 0) break; 
    } 
    // the camera will be deinitialized automatically in VideoCapture destructor 
    return 0; 
} 
+0

Cảm ơn bạn rất nhiều vì câu trả lời của bạn. Tôi đã làm điều này trong python. Nhưng vấn đề là, khi bạn gọi cap >> frame; nó không chờ khung hình hoàn toàn sẵn sàng! Vì vậy, nếu khung không sẵn sàng, sau đó nó sẽ trả về null. Và sau đó, nó không chụp bất kỳ khung hình nào khác. Nó có ý nghĩa không? – Mehran

+2

@Mehran bạn sẽ rất nhẹ nhàng để chia sẻ phiên bản python? – user2239318

1

Đây là cách tôi sẽ bắt đầu để giải quyết này:

  1. Tạo một nhà văn video:

    import cv2.cv as cv 
    videowriter = cv.CreateVideoWriter(filename, fourcc, fps, frameSize) 
    

    Check here for valid parameters

  2. Vòng để lấy [1] và viết các khung:

    cv.WriteFrame(videowriter, frame) 
    

    WriteFrame doc

[1] zenpoy đã chỉ theo hướng đúng. Bạn chỉ cần biết rằng bạn có thể truy xuất hình ảnh từ webcam hoặc tệp :-)

Hy vọng rằng tôi đã hiểu đúng yêu cầu.

9

sử dụng này -

import cv2 
cap = cv2.VideoCapture('path of video file') 
count = 0 
while cap.isOpened(): 
    ret,frame = cap.read() 
    cv2.imshow('window-name',frame) 
    cv2.imwrite("frame%d.jpg" % count, frame) 
    count = count + 1 
    if cv2.waitKey(10) & 0xFF == ord('q'): 
     break 


cap.release() 
cap.destroyAllWindows() 
+0

Tôi tin rằng dòng cuối cùng của bạn nên là: 'cv2.destroyAllWindows()' –

6

Theo các bản cập nhật mới nhất cho OpenCV 3.0 trở lên, bạn cần phải thay đổi định danh tài sản như sau trong mã bởi Mehran:

cv2.cv.CV_CAP_PROP_POS_FRAMES 

to

cv2.CAP_PROP_POS_FRAMES 

và áp dụng tương tự cho cv2.CAP_PROP_POS_FRAME_COUNT.

Hy vọng điều đó sẽ hữu ích.

+0

Điều này không trả lời câu hỏi. – JohnAllen

+0

@srihegde Cảm ơn thông tin của bạn – Mehran

+0

Bao gồm một liên kết đến thông tin thêm sẽ được đánh giá cao. – Richard

0

Giải pháp duy nhất tôi tìm thấy là không đặt chỉ mục thành khung trước và chờ (sau đó OpenCV ngừng đọc khung hình), nhưng để khởi tạo lại lần chụp. Vì vậy, có vẻ như sau:

cap = cv2.VideoCapture(camera_url) 
while True: 
    ret, frame = cap.read() 

    if not ret: 
     cap = cv.VideoCapture(camera_url) 
     continue 

    # do your processing here 

Và nó hoạt động hoàn hảo!

+0

Giải pháp tốt. Nhưng, chi phí của việc tái khởi động Capture là gì? chúng ta cần phải chắc chắn rằng việc phá hủy đối tượng và tạo ra nó không làm giảm hiệu năng. – Mehran

+0

Nó không làm giảm hiệu suất - nó giảm vài khung hình. Không có lugging hoặc một cái gì đó tương tự, vì vậy điều này làm việc cho chúng tôi. –

+0

Giải pháp này hoạt động khi luồng (trong trường hợp này là Camera) luôn bắt đầu từ khung hiện tại. Trong trường hợp của tôi, tệp đang được tải lên máy chủ và được lưu vào out.mp4. Vì vậy, nếu tôi reinitialize quay video, nó sẽ bắt đầu từ khung đầu tiên của video không phải là khung có sẵn cuối cùng. – Mehran