利用opencv计算光流以及optical flow strain

计算optical flow以及strain,作为微表情识别的输入

#include <iostream>
#include <opencv2/opencv.hpp>

class OptFlowStrain {

public:
	typedef struct _flow_strain {
		cv::Mat u;
		cv::Mat v;
		cv::Mat s;
	}flow_strain;

	OptFlowStrain(){}
	~OptFlowStrain(){}

public:
	void run(const cv::Mat& img0, const cv::Mat& img1) {
		cal_opt_flow(img0, img1, fres);
	}
	void get_opt_res(cv::Mat& u, cv::Mat& v, cv::Mat& s) {
		u = fres.u;
		v = fres.v;
		s = fres.s;
	}
	flow_strain get_opt_res() {
		return fres;
	}
protected:
	//nx -- x方向移动的像素个数 
	//ny -- y方向移动的像素个数
	cv::Mat get_translation_matrix(int nx, int ny)
	{
		cv::Mat t_mat = cv::Mat::zeros(2, 3, CV_32FC1);
		t_mat.at<float>(0, 0) = 1;
		t_mat.at<float>(0, 2) = nx;
		t_mat.at<float>(1, 1) = 1;
		t_mat.at<float>(1, 2) = ny;
		return t_mat;
	}

	cv::Mat translation(cv::Mat src, int nx, int ny)
	{
		cv::Mat dst;
		cv::Mat tmat = get_translation_matrix(nx, ny);
		cv::warpAffine(src, dst, tmat, src.size());
		return dst;
	}

	void split_opt_flow(const cv::Mat& flow, cv::Mat& u, cv::Mat& v, cv::Mat& s) {
		cv::Mat xy[3];
		cv::split(flow, xy);
		cv::Mat mag, ang;
		cv::cartToPolar(xy[0], xy[1], mag, ang);
		//cv::Mat u, v;
		cv::polarToCart(mag, ang, u, v);

		cv::Mat ux, uy, vx, vy;
		cv::Mat px, py, qx, qy;

		px = translation(u, -1, 0);
		py = translation(u, 0, -1);
		ux = u - px;
		uy = u - py;

		qx = translation(v, -1, 0);
		qy = translation(v, 0, -1);
		vx = v - qx;
		vy = v - qy;

		cv::Mat temp;
		cv::add(uy, vx, temp);
		cv::Mat os = ux.mul(ux) + vy.mul(vy) + 0.5*temp.mul(temp);
		cv::sqrt(os, s);
	}
	
	void cal_opt_flow(const cv::Mat& src0, const cv::Mat& src1, flow_strain& res)
	{
		cv::Mat s0 = src0.clone(), s1 = src1.clone();
		if (s0.type() == CV_8UC3) cv::cvtColor(s0, s0, cv::COLOR_BGR2GRAY);
		if (s1.type() == CV_8UC3) cv::cvtColor(s1, s1, cv::COLOR_BGR2GRAY);

		cv::Mat flow;//CV_32FC2
		cv::Ptr<cv::DualTVL1OpticalFlow> tvl1 = cv::DualTVL1OpticalFlow::create();
		tvl1->calc(s0, s1, flow);
		split_opt_flow(flow, res.u, res.v, res.s);
	}
private:
	flow_strain fres;
	cv::Mat _ou, _ov, _os;
};

int main(int argc, const char* argv[])
{
	cv::Mat frame0 = cv::imread("frame_000100.jpg", cv::IMREAD_GRAYSCALE);
	cv::Mat frame1 = cv::imread("frame_000101.jpg", cv::IMREAD_GRAYSCALE);
	if (frame0.empty())
	{
		//cerr << "Can't open image [" << parser.get<string>("frame0") << "]" << endl;
		return -1;
	}
	if (frame1.empty())
	{
		//cerr << "Can't open image [" << parser.get<string>("frame1") << "]" << endl;
		return -1;
	}

	if (frame1.size() != frame0.size())
	{
		std::cerr << "Images should be of equal sizes" << std::endl;
		return -1;
	}
	OptFlowStrain opt;
	opt.run(frame0, frame1);
	cv::Mat u, v, s;
	//opt.get_opt_res(u, v, s);
	OptFlowStrain::flow_strain res = opt.get_opt_res();
	//flow_strain res;
	//cal_opt_flow(frame0, frame1, res);

	cv::imshow("s.jpg", res.s);
	cv::waitKey(0);

	return 0;
}

输出的光流图为:

posted @ 2021-07-29 02:38  快乐码小农  阅读(199)  评论(0编辑  收藏  举报