opencv學習之路(2)、讀取視頻,讀取攝像頭


  一、介紹

視頻讀取本質上就是讀取圖像,因為視頻是由一幀一幀圖像組成的。1秒24幀基本就能流暢的讀取視頻了。 
①讀取視頻有兩種方法: 
A. VideoCapture cap; 
cap.open(“1.avi”); 
B. VideoCapture cap(“1.avi”);


②循環顯示每一幀: 
while(1) 

Mat frame; //定義Mat變量,用來存儲每一幀 
cap>>frame; //讀取當前幀方法一 
//cap.read(frame); //讀取當前幀方法二 
imshow(“視頻顯示”, frame); //顯示一幀畫面 
waitKey(30); //延時30ms 
}

  二、讀取視頻示例程序

 1 #include<opencv2/opencv.hpp>
 2 using namespace cv;
 3 
 4 void main(){
 5     VideoCapture cap;
 6     cap.open("E://2.avi"); //打開視頻,以上兩句等價於VideoCapture cap("E://2.avi");
 7 
 8     //cap.open("http://www.laganiere.name/bike.avi");//也可以直接從網頁中獲取圖片,前提是網頁有視頻,以及網速夠快
 9     if(!cap.isOpened())//如果視頻不能正常打開則返回
10         return;
11     Mat frame;
12     while(1)
13     {
14         cap>>frame;//等價於cap.read(frame);
15         if(frame.empty())//如果某幀為空則退出循環
16             break;
17         imshow("video", frame);
18         waitKey(20);//每幀延時20毫秒
19     }
20     cap.release();//釋放資源
21 }

  三、讀取視頻說明

  1. 打開的視頻可以是本地視頻如: 
    VideoCapture cap(“1.avi”); 
    也可以是網絡視頻如: 
    VideoCapture cap(“http://www.laganiere.name/bike.avi“);
  2. 讀取視頻一定要加異常判斷 
    A.打開視頻失敗(各種原因) 
    B. 取幀失敗異常(程序結尾判斷) 
    ex1: 
    if(!cap.isOpened()) //檢查打開是否成功 
    return; 
    ex2: 
    cap>>frame; 
    if(!frame.empty()) //判斷當前 幀是否為空 

    imshow(“video”, frame); 
    waitKey(30); 

    else break;

  四、獲取指定視頻類的相關參數信息

 1 #include<opencv2/opencv.hpp>
 2 #include<iostream>
 3 using namespace cv;
 4 using namespace std;
 5 
 6 void main(){
 7     VideoCapture cap;
 8     cap.open("E:\\2.avi"); //打開視頻,等價於   VideoCapture cap("E://2.avi");
 9 
10     if(!cap.isOpened())
11         return;
12 
13     int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);  //幀寬度
14     int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //幀高度
15     int frameRate = cap.get(CV_CAP_PROP_FPS);  //幀率 x frames/s
16     int totalFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); //總幀數
17 
18     cout<<"視頻寬度="<<width<<endl;
19     cout<<"視頻高度="<<height<<endl;
20     cout<<"視頻總幀數="<<totalFrames<<endl;
21     cout<<"幀率="<<frameRate<<endl;
22 
23     Mat frame;
24     while(1)
25     {
26         cap>>frame;//等價於cap.read(frame);
27         if(frame.empty())
28             break;
29         imshow("video", frame);
30         if(waitKey(20)>0)
31             break;
32     }
33     cap.release();
34 }

  五、讀取攝像頭

讀取攝像頭和讀取視頻大同小異,主要是這句代碼有些許不同。 
VideoCapture cap; 
cap.open(0); 
讀取視頻時可以傳入視頻路徑,而讀取攝像頭傳入的是index索引號。


注: 
1)如果默認筆記本/台式機只有一個USB攝像頭,Index=0; 如果有2個,一般Index為0和1,根據具體情況區分,攝像頭接入和斷開會改變Index值 
2)如果接入2個以上,但只想用指定的一個,可以在設備管理器中禁用其他,同時Index設置為0 

3)因為開啟攝像頭后一直在進行讀取,所以需要用waitKey()返回值判斷退出預覽 
imshow(“video”, frame); 
if(waitKey(30)>0)//無按鍵按下返回-1,按鍵按下時退出 
break; 
也可以指定按鍵退出: 
if(waitKey(30)==27) //Esc鍵退出,ESC的ASCLL碼為27 
break;

  六、讀取攝像頭后加入簡單處理效果

如果只是讀取攝像頭不進行處理的話,那毫無意義,現在以canny邊緣檢測以及顏色空間轉換為目標進行處理。

 1 #include<opencv2/opencv.hpp>
 2 using namespace cv;
 3 
 4 void main(){
 5     VideoCapture cap;
 6     cap.open(0); //打開攝像頭
 7 
 8     if(!cap.isOpened())
 9         return;
10 
11     Mat frame;
12     while(1)
13     {
14         cap>>frame;//等價於cap.read(frame);
15         Canny(frame, frame, 30, 100);//canny邊緣檢測,去掉這一行就是純粹的讀取攝像頭了
16         //cvtColor(frame, frame, CV_BGR2HSV);//BGR空間轉為HSV顏色空間,注意,兩者不能同時對同一張圖片(在此為frame)進行處理,否則報錯
17         if(frame.empty())
18             break;
19         imshow("video", frame);
20         if(waitKey(20)>0)//按下任意鍵退出攝像頭  因電腦環境而異,有的電腦可能會出現一閃而過的情況
21             break;
22     }
23     cap.release();
24     destroyAllWindows();//關閉所有窗口
25 }

針對第20行代碼:最開始電腦配置的opencv2.x版本,上述代碼打開攝像頭沒有問題;后來使用opencv3.x版本,重新編譯了contrib包,發現攝像頭打開后一閃而過。

原因是 waitkey() 如果不按鍵的時候是返回 oxff,oxff無符號時是255,有符號時是-1。windows vs 的環境默認了這個為非符號數 即255,而opencv的有些配置環境中是-1。

解決方案:把原始代碼中循環讀取幀的

if (waitKey(20)>=0)  break;

改為

if (waitKey(20) != 255)  break;

或者把waitkey的返回值用有符號數去讀取。

uchar c=waitkey(20);  if(c!=255)  break;

  七、寫入視頻

  1、介紹

①VideoWriter: OpenCV提供VideoWriter類寫視頻文件,類的構造函數可以指定文件名、播放幀率、幀尺寸、是否創建彩色視頻。 

②兩種寫入幀方法: 
1 ) writer.write(frame); 
2)writer >>frame(這里的箭頭方向應該相反,不知道為什么箭頭不能向←); 
③注意事項: 
1)寫入視頻前需安裝對應的編解碼器 
2)生成視頻是否支持彩色應與構造函數設置一致 
3)生成視頻尺寸需與讀取視頻尺寸一致

  2、代碼示例

 1 #include<opencv2/opencv.hpp>
 2 #include<iostream>
 3 using namespace cv;
 4 using namespace std;
 5 
 6 void main(){
 7     VideoCapture cap;
 8     cap.open("E://2.avi");
 9     Size size0=Size(cap.get(CV_CAP_PROP_FRAME_WIDTH),cap.get(CV_CAP_PROP_FRAME_HEIGHT));
10     VideoWriter writer("E://out.avi",-1,cap.get(CV_CAP_PROP_FPS),size0,false);
11 
12     if(!cap.isOpened())
13         return;
14 
15     Mat frame;
16     while(1)
17     {
18         cap>>frame;
19         Canny(frame,frame,30,100);
20         if(frame.empty())
21             break;
22         writer<<frame;//等同於writer.write(frame);
23         imshow("video", frame);
24         if(waitKey(10)>0)
25             break;
26     }
27     cout<<"write end!";
28     cap.release();
29     destroyAllWindows();
30 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM