OpenCV初體驗

OpenCV提供了一些實用工具來讀取從視頻流到攝像機畫面的各種各樣的圖像格式,這些工具都是HighGUI的一部分。下面幾個小例子可以讓初學者提前體驗一下OpenCV的功能。

1. 打開一張圖像並且將其顯示在屏幕上

#include "stdafx.h"
#include <opencv2/opencv.hpp>


int main( int argc, char** argv )
{
	// 載入圖像
	cv::Mat img = cv::imread("C:\\Users\\Bello\\Desktop\\test.jpg", -1);
	// 檢查圖像是否真的被載入,如果沒有返回-1,結束程序
	if ( img.empty() ) return -1;
	// 由High GUI模塊提供,會將一個名稱賦給窗口,未來High GUI的和這個窗口的交互函數將由這個名稱來指定要與哪個窗口交互。
	// 第二個參數說明了Windows的特性,這個可以設置爲0(默認),也可設爲cv::WINDOW_AUTOSIZE,窗口會在圖像載入的時候
        // 自動縮放以適應圖像的真實大小,也可能由用戶自行調整。
	cv::namedWindow("Example1", cv::WINDOW_AUTOSIZE );
	// 將圖像數據顯示爲圖像,將建一個窗口(若不存在,會自動調用cv::namedWindow()新建窗口)。
	cv::imshow( "Example1", img );
	// 系統暫停並且等待鍵盤事件。
	// 如果傳入了一個大於0的參數,它將會等待等同於該參數的毫秒數時間,然後繼續執行程序。
	// 如果參數被設置爲0或一個負數,程序將會無限等待知道有鍵被按下。
	cv::waitKey( 1000 );
	// 關閉窗口並釋放掉相關聯的內存空間
	cv::destroyWindow("Example1");
    return 0;
}

2. 播放視頻文件

#include "stdafx.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


int main()
{
	cv::namedWindow( "Example3", cv::WINDOW_AUTOSIZE );
	// 視頻讀取結構
	cv::VideoCapture cap;
	// 視頻讀取結構通過傳入字符串打開文件,這個字符串指示了想要打開的視頻文件的路徑。
	// 視頻打開後,視頻讀取結構將會包含所有的關於這個視頻文件可以讀取的屬性,包括狀態信息。
	cap.open( "D:\\mgtv\\[高清]《媽媽是超人》第二季先導片:安吉“魔音”亂入嚇哭小魚兒 鬼馬精靈包餃子實力坑媽.mp4" );
	// 聲明一個可以保存視頻幀的結構。
	cv::Mat frame;
	for ( ; ; )
	{
		// 按照幀從視頻流中讀取視頻文件
		cap >> frame;
		// 檢查是否讀取成功
		if ( frame.empty() )
		{
			break;
		}
		// 顯示圖片
		cv::imshow("Example3", frame);
		// 等待33毫秒,在此等待時間內按任何鍵推出循環,若沒有進行下一層循環。
		// 注:設置爲33ms是因爲這能讓視頻以30FPS的速度播放,並能允許用戶在播放的時候打斷。
		if(cv::waitKey(33) >= 0 )
		{
			break;
		}
		
	}
	cv::destroyWindow("Example3");
    return 0;
}

3. 加入了滑動條的基本瀏覽窗口

// example2-4.cpp: 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <fstream>

using namespace std;

// 全局變量,存儲滑動條位置
int g_slider_position = 0;
// g_run爲1進入單步模式;g_dontset用來避免調整進度條位置的時候觸發單例模式
int g_run = 1, g_dontset = 0;
// 數據讀取結構
cv::VideoCapture g_cap;

// 用戶調整滑動條時將觸發的回調函數,來重新定位視頻讀取的位置
void onTrackbarSlide(int pos, void *) {
	// 根據滑動條位置重定向視頻讀取位置
	g_cap.set(cv::CAP_PROP_POS_FRAMES, pos);

	if (!g_dontset)
		g_run = 1;
	g_dontset = 0;
}

int main()
{
	cv::namedWindow("Example4", cv::WINDOW_AUTOSIZE );
	g_cap.open("D:\\mgtv\\[高清]《媽媽是超人》第二季先導片:安吉“魔音”亂入嚇哭小魚兒 鬼馬精靈包餃子實力坑媽.mp4");
	// 確定總幀數
	int frames = (int)g_cap.get(cv::CAP_PROP_FRAME_COUNT);
	// 確定視頻的寬度
	int tmpw = (int)g_cap.get(cv::CAP_PROP_FRAME_WIDTH);
	// 確定視頻的高度
	int tmph = (int)g_cap.get(cv::CAP_PROP_FRAME_HEIGHT);
	// 輸出視頻的信息
	cout << "Video has " << frames << " frames of dimensions(" << tmpw << ", " << tmph << ")." << endl;
	// 創建滑動條,第一個參數是滑動條標籤,第二個參數指定窗口,第三個參數是滑動條的初始位置,第四個參數是視頻總幀數,第五個參數是回調函數,不要時可設置爲0
	cv::createTrackbar("Position", "Example4", &g_slider_position, frames, onTrackbarSlide);
	cv::Mat frame;
	for (;;) {
		if (g_run != 0) {
			// 按幀從視頻流中讀取視頻文件
			g_cap >> frame;
			if (frame.empty()){
				break;
			}
			// 獲取當前幀集合讀取的位置
			int current_pos = (int)g_cap.get(cv::CAP_PROP_POS_FRAMES);
			g_dontset = 1;
			// 更新進度條位置,將觸發回調函數
			cv::setTrackbarPos("Position", "Example4", current_pos);
			// 顯示圖片
			cv::imshow("Example4", frame);
			// 若爲單步模式,那麼此運算後g_run爲0,則之後的循環無法進入該語句段;
			// 若爲連續模式,那麼此運算後g_run依舊不爲0,所以可以連續播放視頻。
			g_run -= 1;
		}
		// 從鍵盤輸入獲取值
		char c = (char)cv::waitKey(10);
		// 如果按鍵是s,則進入單步模式
		if (c == 's') {
			g_run = 1;
			cout << "Single step, run = " << g_run << endl;
		}
		// 如果按鍵是r,則恢復連續模式
		else if(c == 'r'){
			g_run = -1;
			cout << "Run mode, run = " << g_run << endl;
		}
		// 如果按鍵是esc,則退出播放
		else if(c == 27){
			break;
		}
	}
    return 0;
}

對於上述添加滑動條並實現單步模式和連續模式切換的代碼,邏輯上有一點繞,具體分析如下:

① 初始狀態,g_run=1,g_dontset=0,則採用單步模式。當第一次循環結束,g_run=0,g_dontset=0,則在不輸入r、s或esc的情況下,不會進入視頻讀取的代碼段,因此圖片顯示會停留在當前狀態。

② 當按下“s”鍵後,g_run=1,g_dontset=0,和初始狀態相同,則運行過程如①所示。

③ 當按下“r”鍵後,g_run=-1,g_dontset=0,採用連續模式。在每次循環後g_run減少1,則g_run永遠是負值不爲0,因此在沒有其他操作情況下,會繼續執行,實現連續播放。

④ 當手動調整進度條時,沒有進入for循環中的if,所以g_dontset=0,此時則滿足回調函數中的if條件,則g_run=1,g_dontset=0,和初始狀態相同,採用單步模式繼續進行。

⑤ 注意,在系統自動調用回調函數前g_dontset都被賦值爲1,因此不會使得g_run=1,單步模式不會生效;只有當用戶手動觸發滑動條事件時,g_dontset=0,使得回調函數將g_run賦值爲1,單步模式生效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章