利用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;
}
输出的光流图为:
每天快乐敲代码,快乐生活