1. 程式人生 > 其它 >opencv處理攝像頭或視訊並儲存為MP4視訊

opencv處理攝像頭或視訊並儲存為MP4視訊

程式語言: C++(C11標準)

OpenCV: 4.1.1

Platform: Windows / Linux

大致邏輯:

  1. 讀取攝像頭或者讀取視訊檔案;
  2. 獲取視訊幀的相關資訊:影象尺寸和幀數;
  3. 建立儲存視訊檔案,並設定視訊編碼格式等資訊;
  4. 逐幀讀取並處理,然後寫入到輸出視訊檔案中;
  5. 關閉攝像頭或源視訊檔案,關閉輸出視訊檔案;

程式碼如下:

//
// Created by Administrator on 2019\10\24 0024.
//

#include "TCLStereoDepthAlg.h"

#include "iostream"
#include "tcl_dualcam_def.h"
#include <opencv2/opencv.hpp>

#include <regex>

// phone series
#define P_VENICE 0
#define P_OAKLAND 1
#define P_AK57 2
#define P_HONGKONG 3
#define P_HONGKONG_PRO 4
#define P_VGA 5
#define P_T1PRO 6
#define P_OTTAWA 7

#define PRODUCT_ID P_OTTAWA

#if PRODUCT_ID >= P_T1PRO
#define CALIB_VERSION 8
#else
#define CALIB_VERSION 7
#endif

#if CALIB_VERSION == 7
#define DIST_PARAM_NUM 5
#else
#define DIST_PARAM_NUM 8
#endif


struct CalibrationFile {
#if CALIB_VERSION == 8
	int phone_id;
#endif
	int full_size_w;
	int full_size_h;
	int crop_size_w;
	int crop_size_h;
	int orientation;
	int size_w;
	int size_h;
	float MIN_DISP;
	float MAX_DISP;
	float delta_disp_per_degree;
	double M1[3][3];
	double D1[1][DIST_PARAM_NUM];
	double M2[3][3];
	double D2[1][DIST_PARAM_NUM];
	double R[3][3];
	double T[3][1];
};


int main(int argc, const char ** argv){

	TCL_DEPTH_VIDEO_VERSION_CHECK(2.0, 2021, 06, 17, 10, 19);

	cv::String base_dir = "F:/dump/TEST-ALL/Dataset/EIS/";
	cv::String date_id = "20211013";
	cv::String phone_id = "Prague-WH03-0101";
	cv::String video_id = "easy.mp4";

	cv::String ori_dir = "ori/";
	cv::String cal_dir = "cal/";
	cv::String out_dir = "out/";
	cv::String dump_dir = "dump/";
#if CALIB_VERSION == 7
	cv::String cal_ver = "version7";
#else
	cv::String cal_ver = "version8";
#endif

    double beg_, end_;
    double freq = cv::getTickFrequency();
	tcl_depth_video::TCLStereoDepthAlg_prv *m_DepthAlgorithmPtr = new tcl_depth_video::TCLStereoDepthAlg_prv;
	tcl_depth_video::Param_DepthPreview param_depth;

	// calibration settings
	int orientation;
	cv::Size cali_size;
	cv::Size full_size;
	cv::Size crop_size;
	cv::Mat M1, D1, M2, D2;

	String cali_bin = base_dir + "/" + cal_dir + "/" + phone_id + "/" + cal_ver + "/dualcam_cali.bin";
	std::fstream ifs(cali_bin, std::ios::in | std::ios::binary);
	CalibrationFile califile_in;
	if (!ifs.is_open()) {
		VIDEO_DEPTH_LOGE("dualcam_cali.bin not found!");
		return -1;
	}
	ifs.read((char*)&califile_in, sizeof(califile_in));

	orientation = califile_in.orientation;
	cali_size.width = califile_in.size_w;
	cali_size.height = califile_in.size_h;
	full_size.width = califile_in.full_size_w;
	full_size.height = califile_in.full_size_h;
	crop_size.width = califile_in.crop_size_w;
	crop_size.height = califile_in.crop_size_h;
	M1 = cv::Mat(Size(3, 3), CV_64FC1, califile_in.M1);
	D1 = cv::Mat(Size(1, DIST_PARAM_NUM), CV_64FC1, califile_in.D1);
	M2 = cv::Mat(Size(3, 3), CV_64FC1, califile_in.M2);
	D2 = cv::Mat(Size(1, DIST_PARAM_NUM), CV_64FC1, califile_in.D2);
	
	///////////////// Calibration Data Settings //////////////////
	param_depth.orientation = orientation;
	param_depth.cali_size = cali_size;
	param_depth.full_size = full_size;
	param_depth.crop_size = crop_size;
	param_depth.intrinsics.M1 = M1;
	param_depth.intrinsics.D1 = D1;
	param_depth.intrinsics.M2 = M2;
	param_depth.intrinsics.D2 = D2;

	// algorithm settings
    param_depth.depth_size = cv::Size(384, 288);
    param_depth.dump_enabled = true;
    param_depth.dump_path = base_dir + dump_dir + date_id + "/" + phone_id;

    m_DepthAlgorithmPtr->Init(param_depth);

    cv::String input_video = base_dir + ori_dir + date_id + "/" + phone_id + "/" + video_id;
	cv::VideoCapture input_stream(input_video);
	ASSERT(input_stream.isOpened(), "video not found: %s", input_video.c_str());
	
	float frame_width = input_stream.get(cv::CAP_PROP_FRAME_WIDTH);
	float frame_height = input_stream.get(cv::CAP_PROP_FRAME_HEIGHT);
	int frame_count = input_stream.get(cv::CAP_PROP_FRAME_COUNT);

	//create a video writer for saving processed frames
	cv::String output_dir = base_dir + out_dir + date_id + "/" + phone_id + "/";
	tcl_depth_video::MakeDir(output_dir);
	cv::String output_video = output_dir + video_id;
	cv::VideoWriter output_stream;
	int fps = 30;
	int fourcc = cv::VideoWriter::fourcc('m', 'p', '4', 'v');
	cv::Size frame_size(frame_width, frame_height);
	output_stream.open(output_video, fourcc, fps, frame_size, true);
	ASSERT(output_stream.isOpened(), "video cannot be created: %s", output_video.c_str());
	
    // create a global uid for synchronize log/dump information
    char uid[16];
	// output frame
	cv::Mat input_frame(cv::Size(frame_width, frame_height), CV_8UC3);
	cv::Mat output_frame(cv::Size(frame_width, frame_height), CV_8UC3);

    for (int i=0; i<frame_count; ++i) {
		memset(uid, 0, sizeof(uid));
		sprintf_s(uid, "%08d", i);
        VIDEO_DEPTH_LOGI("filename: %s", uid);
		ASSERT(input_stream.read(input_frame), "video broken or incomplete!");
		ASSERT(input_frame.size().width == frame_width, "width mismatch");
		ASSERT(input_frame.size().height == frame_height, "width mismatch");
		ASSERT(input_frame.channels() == 3, "unexpected channel number of frame");
		beg_ = cv::getTickCount();
        //float err_code = m_DepthAlgorithmPtr->Compute(output_frame, input_frame, cv::String(uid));
		// here's your code
		// a demo one is to convert color into HSV
		cv::cvtColor(input_frame, output_frame, cv::COLOR_BGR2HSV);
        end_ = cv::getTickCount();
        VIDEO_DEPTH_LOGI("frame %d cost: %.4f ms.", i, (1000 * (end_ - beg_) / freq));
		// save this frame to the output video stream
		output_stream.write(output_frame);
    }

	input_stream.release();
	output_stream.release();
    delete(m_DepthAlgorithmPtr);

	PAUSE();
	return 0;
}

完畢。