一、waitkey函數是什麼
waitkey函數是openCV庫中一個非常重要的函數,它的主要作用是等待用戶按下某個鍵,同時它還會返回該按鍵的ASCII碼值。在圖像處理的過程中,waitkey函數通常用來實現按鍵控制,比如實現按Esc鍵退出程序。
int waitKey(int delay)
二、waitkey函數的調用方法
waitkey函數的調用非常簡單,只需要將想要等待的時間以毫秒為單位作為參數傳遞給該函數即可。如果在等待過程中用戶沒有按下任何鍵,waitkey函數會在超時後返回-1。
例如:
char key = 0;
while(key != 27) // 27是ASCII碼中的Esc鍵
{
Mat frame;
cap >> frame; // 讀取一幀圖像
imshow("video", frame); // 在窗口中顯示該幀圖像
key = waitKey(30); // 等待30毫秒,如果用戶按下任意鍵則返回該鍵的ASCII碼值
}
三、waitkey函數的注意事項
1、waitkey函數的參數設置
在使用waitkey函數時,其參數delay需要進行合理設置。如果參數設置的過大,則程序在等待用戶按下鍵盤時會卡死,無法進行下一步操作,而如果參數設置的過小,則程序會非常佔用系統資源。一般來說,建議將參數設置在20~50之間。
2、waitkey函數與imshow函數的配合使用
在使用waitkey函數時,通常會與imshow函數一起使用。在imshow函數中,需要為窗口命名,因為waitkey函數會等待用戶在該窗口中進行按鍵操作。同時,需要注意的是,在建立窗口後,必須在waitkey函數之後再使用imshow函數,否則imshow函數無法正常工作。
例如:
namedWindow("video", CV_WINDOW_NORMAL); // 建立一個名為"video"的窗口
while(key != 27) // 27是ASCII碼中的Esc鍵
{
Mat frame;
cap >> frame; // 讀取一幀圖像
key = waitKey(30); // 等待30毫秒,如果用戶按下任意鍵則返回該鍵的ASCII碼值
imshow("video", frame); // 在窗口中顯示該幀圖像
}
destroyWindow("video"); // 銷毀窗口
3、waitkey函數與多線程的配合使用
在進行圖像處理時,可能需要使用多線程來提高程序的運行效率。如果在多個線程中同時使用waitkey函數,可能會導致程序無法正常運行,因為waitkey函數只能在主線程中使用。
解決辦法是將waitkey函數從子線程中移出,改為在主線程中進行調用。在子線程中,如果需要進行按鍵操作,則通常使用消息循環來實現。具體實現方法可以參考以下代碼:
void captureThread()
{
while (true)
{
if (!bStop)
{
Mat frame;
cap >> frame; // 讀取一幀圖像
imshow("video", frame); // 在窗口中顯示該幀圖像
}
int c = waitKey(1);
if ((char)c == 27)
break;
}
}
四、waitkey函數的實例
1、實現按Esc鍵退出程序
int main()
{
VideoCapture cap(0); // 打開攝像頭
if (!cap.isOpened()) // 如果攝像頭未正常打開,則結束程序
return -1;
namedWindow("video", CV_WINDOW_NORMAL); // 建立一個名為"video"的窗口
char key = 0;
while(key != 27) // 27是ASCII碼中的Esc鍵
{
Mat frame;
cap >> frame; // 讀取一幀圖像
imshow("video", frame); // 在窗口中顯示該幀圖像
key = waitKey(30); // 等待30毫秒,如果用戶按下任意鍵則返回該鍵的ASCII碼值
}
destroyWindow("video"); // 銷毀窗口
return 0;
}
2、實現按下s鍵保存當前幀圖像
int main()
{
VideoCapture cap(0); // 打開攝像頭
if (!cap.isOpened()) // 如果攝像頭未正常打開,則結束程序
return -1;
namedWindow("video", CV_WINDOW_NORMAL); // 建立一個名為"video"的窗口
char key = 0;
int count = 0; // 用於保存圖像的計數器
while(key != 27) // 27是ASCII碼中的Esc鍵
{
Mat frame;
cap >> frame; // 讀取一幀圖像
imshow("video", frame); // 在窗口中顯示該幀圖像
key = waitKey(30); // 等待30毫秒,如果用戶按下任意鍵則返回該鍵的ASCII碼值
if (key == 's') // 如果用戶按下s鍵,則保存當前幀圖像
{
String savePath = format("./image/frame_%d.jpg", count++);
imwrite(savePath, frame);
cout << "Save image " << savePath << " successfully!" << endl;
}
}
destroyWindow("video"); // 銷毀窗口
return 0;
}
3、實現通過按下數字鍵來切換視頻流
int main()
{
vector files; // 用於存儲視頻流文件名的向量
files.push_back("./video/video1.mp4");
files.push_back("./video/video2.mp4");
files.push_back("./video/video3.mp4");
int index = 0; // 當前視頻流的索引
VideoCapture cap(files[index]); // 打開第一個視頻流
if (!cap.isOpened()) // 如果視頻流未正常打開,則結束程序
return -1;
namedWindow("video", CV_WINDOW_NORMAL); // 建立一個名為"video"的窗口
char key = 0;
while(key != 27) // 27是ASCII碼中的Esc鍵
{
Mat frame;
cap >> frame; // 讀取一幀圖像
imshow("video", frame); // 在窗口中顯示該幀圖像
key = waitKey(30); // 等待30毫秒,如果用戶按下任意鍵則返回該鍵的ASCII碼值
if (key >= '1' && key <= '3') // 如果用戶按下數字鍵,則切換到對應的視頻流
{
index = key - '1';
cap.release(); // 釋放當前視頻流
cap.open(files[index]); // 打開新的視頻流
}
}
destroyWindow("video"); // 銷毀窗口
return 0;
}
4、實現打開多個攝像頭並顯示在不同的窗口中
int main()
{
VideoCapture cap1(0); // 打開第一個攝像頭
if (!cap1.isOpened()) // 如果攝像頭未正常打開,則結束程序
return -1;
VideoCapture cap2(1); // 打開第二個攝像頭
if (!cap2.isOpened()) // 如果攝像頭未正常打開,則結束程序
return -1;
namedWindow("video1", CV_WINDOW_NORMAL); // 建立一個名為"video1"的窗口
namedWindow("video2", CV_WINDOW_NORMAL); // 建立一個名為"video2"的窗口
char key = 0;
while(key != 27) // 27是ASCII碼中的Esc鍵
{
Mat frame1, frame2;
cap1 >> frame1; // 讀取第一個攝像頭的一幀圖像
cap2 >> frame2; // 讀取第二個攝像頭的一幀圖像
imshow("video1", frame1); // 在"video1"窗口中顯示第一個攝像頭的幀圖像
imshow("video2", frame2); // 在"video2"窗口中顯示第二個攝像頭的幀圖像
key = waitKey(30); // 等待30毫秒,如果用戶按下任意鍵則返回該鍵的ASCII碼值
}
destroyWindow("video1"); // 銷毀"video1"窗口
destroyWindow("video2"); // 銷毀"video2"窗口
return 0;
}
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/196447.html
微信掃一掃
支付寶掃一掃