密集光流提取dense_flow理解

主函数:

输入的参数有:
-f 视频文件名称
-x x方向光流文件前缀
-y y方向光流文件前缀
-i rgb图像文件前缀
-b 约束距离
-t 光流提取算法类别(0- 1-)
-o 输出格式

std::vector<std::vector<uchar> > out_vec_x, out_vec_y, out_vec_img;

	calcDenseFlow(vidFile, bound, type, 1,
					 out_vec_x, out_vec_y, out_vec_img);

	if (output_style == "dir") {
		writeImages(out_vec_x, xFlowFile);
		writeImages(out_vec_y, yFlowFile);
		writeImages(out_vec_img, imgFile);
	}else{
//		LOG(INFO)<<"Writing results to Zip archives";
		writeZipFile(out_vec_x, "x_%05d.jpg", xFlowFile+".zip");
		writeZipFile(out_vec_y, "y_%05d.jpg", yFlowFile+".zip");
		writeZipFile(out_vec_img, "img_%05d.jpg", imgFile+".zip");
	}

光流计算

根据输入的视频文件名称,定义一个视频捕获对象video_stream读取视频。定义五个vector变量。
capture_frame-------t时刻捕获的帧
capture_image-------t时刻运动图片
capture_gray---------t时刻运动图片的灰度化
pre_image-------------t-1时刻运动图片
pre_gray---------------t-1时刻运动图片灰度化
读取视频帧到capture_frame中,如果是第一帧则进行初始化,给以上五个变量分配给capture_frame大小内存。并将读取的第一帧赋值给pre_image并灰度化后赋值给pre_gay。从第二帧开始,计算前一帧和当前帧之前的光流,并存储在flow中,有两种光流计算算法。将计算出的光流split分成x和y两个方向的光流,先将光流转化为图片形式,再接着其编码成数据流,存储在str_x和str_y中。对capture_image直接编码成数据流存储在str_img中。接着将这三个流分别加到对应的流向量中,最后视频每一时刻的RGB图像和X、Y光流数据存储在out_vec_x,out_vec_y,out_vec_img。读取这些向量,将数据流分别写进图片中,一个视频光流提取完成。

光流计算函数
void calcDenseFlow(std::string file_name, int bound, int type, int step,
                   std::vector<std::vector<uchar> >& output_x,
                   std::vector<std::vector<uchar> >& output_y,
                   std::vector<std::vector<uchar> >& output_img){
    #读取file_name视频文件
    VideoCapture video_stream(file_name);
    CHECK(video_stream.isOpened())<<"Cannot open video stream \""
                                  <<file_name
                                  <<"\" for optical flow extraction.";
    Mat capture_frame, capture_image, prev_image, capture_gray, prev_gray;
    Mat flow, flow_split[2];
    //定义一个DualTVL对象
    cv::Ptr<cv::DualTVL1OpticalFlow> alg_tvl1 = cv::createOptFlow_DualTVL1();

    bool initialized = false;
    for(int iter = 0;; iter++){
        //将视频帧读取到Mat中矩阵中
        video_stream >> capture_frame;
        if (capture_frame.empty()) break; // read frames until end
        //build mats for the first frame
        if (!initialized){Mat
            //根据capture_frame,创建同等大小的四个
            initializeMats(capture_frame, capture_image, capture_gray,
                           prev_image, prev_gray);
            //将当前帧赋值给pre_image
            capture_frame.copyTo(prev_image);
            //对prev_image灰度化后赋值给pre_gray
            cvtColor(prev_image, prev_gray, CV_BGR2GRAY);
            initialized = true;
//            LOG(INFO)<<"Initialized";
        }else if(iter % step == 0){
            //将获取的帧数据传给capture_image,并进行灰度转换
            capture_frame.copyTo(capture_image);
            cvtColor(capture_image, capture_gray, CV_BGR2GRAY);
            switch(type){
                case 0: {
                    //Gunnar Farneback算法基于图像梯度恒定假设和局部光流恒定假设。
                    calcOpticalFlowFarneback(prev_gray, capture_gray, flow,
                                             0.702, 5, 10, 2, 7, 1.5,
                                             cv::OPTFLOW_FARNEBACK_GAUSSIAN );
                    break;
                }
                case 1: {
                    //使用python自带的TVL提取光流
                    alg_tvl1->calc(prev_gray, capture_gray, flow);
                    break;
                }
                default:
                    LOG(WARNING)<<"Unknown optical method. Using Farneback";
                    calcOpticalFlowFarneback(prev_gray, capture_gray, flow,
                                             0.702, 5, 10, 2, 7, 1.5,
                                             cv::OPTFLOW_FARNEBACK_GAUSSIAN );
            }
            //定义数据流
            std::vector<uchar> str_x, str_y, str_img;
            //将光流分成x、y方向存在flow_split中
            split(flow, flow_split);
            //对光流、rgb图片编码成数据流
            encodeFlowMap(flow_split[0], flow_split[1], str_x, str_y, bound);
            imencode(".jpg", capture_image, str_img);
            output_x.push_back(str_x);
            output_y.push_back(str_y);
            output_img.push_back(str_img);
			//更新pre_image、pre_gray
            std::swap(prev_gray, capture_gray);
            std::swap(prev_image, capture_image);
        }
    }
}

光流转图片

void convertFlowToImage(const Mat &flow_x, const Mat &flow_y, Mat &img_x, Mat &img_y,
                               double lowerBound, double higherBound) {
#define CAST(v, L, H) ((v) > (H) ? 255 : (v) < (L) ? 0 : cvRound(255*((v) - (L))/((H)-(L))))
    for (int i = 0; i < flow_x.rows; ++i) {
        for (int j = 0; j < flow_y.cols; ++j) {
            float x = flow_x.at<float>(i,j);
            float y = flow_y.at<float>(i,j);
            img_x.at<uchar>(i,j) = CAST(x, lowerBound, higherBound);
            img_y.at<uchar>(i,j) = CAST(y, lowerBound, higherBound);
        }
    }
#undef CAST
}

编码:Mat数据->数据流

void encodeFlowMap(const Mat& flow_map_x, const Mat& flow_map_y,
                   std::vector<uchar>& encoded_x, std::vector<uchar>& encoded_y,
                   int bound, bool to_jpg){
    Mat flow_img_x(flow_map_x.size(), CV_8UC1);
    Mat flow_img_y(flow_map_y.size(), CV_8UC1);

    convertFlowToImage(flow_map_x, flow_map_y, flow_img_x, flow_img_y,
                       -bound, bound);

    if (to_jpg) {
        //将cv2:mat数据flow_img_x转化为数据流存储到encoded_x中
        imencode(".jpg", flow_img_x, encoded_x);
        imencode(".jpg", flow_img_y, encoded_y);
    }else {
        encoded_x.resize(flow_img_x.total());
        encoded_y.resize(flow_img_y.total());
        memcpy(encoded_x.data(), flow_img_x.data, flow_img_x.total());
        memcpy(encoded_y.data(), flow_img_y.data, flow_img_y.total());
    }
}

数据流—>图片

//截取extract_flow
if (output_style == "dir") {
		writeImages(out_vec_x, xFlowFile);
		writeImages(out_vec_y, yFlowFile);
		writeImages(out_vec_img, imgFile);
	}else{
//		LOG(INFO)<<"Writing results to Zip archives";
		writeZipFile(out_vec_x, "x_%05d.jpg", xFlowFile+".zip");
		writeZipFile(out_vec_y, "y_%05d.jpg", yFlowFile+".zip");
		writeZipFile(out_vec_img, "img_%05d.jpg", imgFile+".zip");
	}
//输入数据流及文件前缀
void writeImages(std::vector<std::vector<uchar>> images, std::string name_temp){
    for (int i = 0; i < images.size(); ++i){
        char tmp[256];
        sprintf(tmp, "_%05d.jpg", i+1);
        FILE* fp;
        fp = fopen((name_temp + tmp).c_str(), "wb");
        fwrite( images[i].data(), 1, images[i].size(), fp);
        fclose(fp);
    }
}

你可能感兴趣的:(密集光流提取dense_flow理解)