2010-01-12 35 views
12

Tôi có một vòng lặp để chụp ảnh từ một khung hình tốc độ cao ở tốc độ 250 khung hình/giây.Hiển thị hình ảnh trong chuỗi thứ hai, OpenCV?

/** Loop processes 250 video frames per second **/ 
while(1){ 
    AcquireFrame(); 
    DoProcessing(); 
    TakeAction(); 
} 

Đồng thời, tôi muốn người dùng có thể theo dõi những gì đang diễn ra. Người dùng chỉ cần xem hình ảnh ở khoảng 30 khung hình/giây (hoặc ít hơn). Làm cách nào để thiết lập chuỗi thứ hai hiển thị khung hình hiện tại thường xuyên như vậy?

Thread(){ 
    cvShowImage(); 
    Wait(30); /** Wait for 30 ms **/ 
} 

Tôi đang dùng Windows trên máy lõi tứ Intel sử dụng MinGW, gcc và OpenCV 1.1. Các tiêu chí chính là chuỗi hiển thị phải mất ít thời gian nhất từ ​​vòng lặp xử lý chính của tôi càng tốt. Mỗi mili giây đều tính.

Tôi đã thử sử dụng CreateThread() để tạo chủ đề mới với cvShowImage()cvWaitKey() nhưng apparently those functions are not threadsafe.

Tôi đang xem xét sử dụng OpenMP, nhưng một số người là report problems with OpenMP and OpenCV. Tôi cũng đang xem xét cố gắng sử dụng DirectX directDraw vì dường như nó rất nhanh. nhưng nó looks complicated và rõ ràng là có problems using Windows DLL's with MinGw.

Đường nào trong số những con đường này sẽ là nơi tốt nhất để bắt đầu?

+0

Không phải chỉ đủ để sử dụng điều kiện if và biến "đếm" tối đa 250 để hiển thị mọi lần chụp thứ 8 (250/30)? –

+0

Ah vâng. Nhưng nếu bạn làm điều đó, thì toàn bộ chương trình sẽ dừng lại trong khi bạn hiển thị lần chụp thứ 8. Phải mất ~ 10 ms để hiển thị hình ảnh bằng cvShowImage. Lúc đó bạn đã bỏ lỡ một vài khung hình. – AndyL

+0

Bạn có nhận được 250 fps từ máy ảnh không? Nếu bạn có thể cho tôi biết bạn đã làm như thế nào? Điều đó cực kỳ nhanh. – bakalolo

Trả lời

10

Ok. Vì vậy, câu hỏi của tôi xấu hổ cũng là câu trả lời của riêng mình.

Sử dụng CreateThread(), CvShowImage()CvWaitKey() như được mô tả trong câu hỏi của tôi thực sự hoạt động-- trái với một số bài đăng trên web đề xuất khác.

Trong mọi trường hợp, tôi thực hiện một cái gì đó như thế này:

/** Global Variables **/ 
bool DispThreadHasFinished; 
bool MainThreadHasFinished; 
iplImage* myImg; 

/** Main Loop that loops at >100fps **/ 
main() { 
    DispThreadHasFinished = FALSE; 
    MainThreadHasFinished = FALSE; 
    CreateThread(..,..,Thread,..); 

    while(IsTheUserDone()) { 
    myImg=AcquireFrame(); 
    DoProcessing(); 
    TakeAction(); 
    } 
    MainThreadHasFinished = TRUE; 

    while (!DisplayThreadHasFinished) { 
    CvWaitKey(100); 
    } 

    return; 
} 

/** Thread that displays image at ~30fps **/ 
Thread() { 
    while (!MainThreadHasFinished) { 
    cvShowImage(myImg); 
    cvWaitKey(30); 
    } 
DispThreadHasFinished=TRUE; 
return; 
} 

Khi tôi đâu câu hỏi này, mã của tôi đã thất bại vì những lý do không liên quan. Tôi hi vọng cái này giúp được!

4

Vì việc lấy khung không cần sử dụng giao diện người dùng, tôi đã thiết lập chuỗi thứ hai để xử lý việc lấy khung và có chuỗi ban đầu xử lý giao diện người dùng hiển thị khung mẫu. Nếu bạn cố gắng để hiển thị khung hiện đang được nắm lấy, bạn sẽ phải khóa dữ liệu (nói chung là khá chậm). Để tránh điều đó, tôi sẽ hiển thị một khung (hoặc có thể là hai) "đằng sau" một khung hiện đang được chụp, do đó không có tranh chấp giữa việc lấy và hiển thị dữ liệu. Bạn sẽ vẫn phải đảm bảo rằng việc tăng số khung hình hiện tại là an toàn luồng, nhưng điều đó khá đơn giản - sử dụng InterlockedIncrement trong chuỗi bắt giữ.

+0

Tôi đồng ý với giải pháp này - có vẻ như sự phức tạp ở đây là bắt nguồn từ thực tế là việc xử lý đang được thực hiện trên chủ đề chính. Nếu quá trình xử lý được thực hiện trên một chuỗi nền, lưu một tham chiếu, đến hình ảnh cuối cùng, chuỗi ui (hoặc chuỗi công nhân trên ui) có thể lấy hình ảnh cuối cùng ở bất kỳ tốc độ nào bạn chọn. –

0

Tôi rất tiếc, hiện tại tôi không thể cung cấp cho bạn câu trả lời hay hơn, nhưng dường như câu hỏi của bạn không phải về cấu trúc chương trình mà là về công cụ bạn nên sử dụng để thực hiện đa luồng. Đối với điều này tôi sẽ giới thiệu Qt. Tôi đã sử dụng Qt trong một thời gian nhưng bây giờ tôi mới bắt đầu đa luồng.

Dường như với tôi rằng đặt cược tốt nhất của bạn có thể là QReadWriteLock. Điều này cho phép bạn đọc từ một hình ảnh nhưng chủ đề đọc sẽ từ bỏ khóa của nó khi chuỗi ghi đi kèm. Trong trường hợp này, bạn có thể giữ một bản sao của hình ảnh bạn hiển thị lần cuối và hiển thị nó nếu hình ảnh bị khóa để ghi.

Xin lỗi một lần nữa rằng tôi không thể chi tiết hơn nhưng, như tôi đã nói, tôi cũng chỉ tham gia vào vấn đề này. Tôi về cơ bản cố gắng làm điều tương tự mà bạn đang có, nhưng không gần như là nhanh :). Chúc may mắn!

0

Tôi không chắc chắn lý do tại sao điều này xảy ra, nhưng tôi đã thêm một cvWaitKey sau mỗi cvShowImage và hình ảnh được hiển thị đúng cách.

cvShowImage(myImage); 
cvWaitKey(1); 
Các vấn đề liên quan