#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/xfeatures2d.hpp>
#include<vector>
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
//全局变量
Mat src_img = imread("../Tulips.jpg", 1);
Mat frame,gray,prev_frame,mask;
vector<Point2f> one_frame_point4;//第一张图片四点
vector<Point> next_frame_point4;
Point point_one;
vector<uchar> status;
vector<float> errors;
// sift特征变量
Mat description_one;
Mat description_two;
vector<Point2f> fpts[2];
vector<Point2f> src_points_4;
//获取贴图图片的坐标
void get_img_points()
{
Size src_size = src_img.size();
src_points_4.push_back(Point2f(0, 0));
src_points_4.push_back(Point2f(src_size.width - 1, 0));
src_points_4.push_back(Point2f(src_size.width - 1, src_size.height - 1));
src_points_4.push_back(Point2f(0, src_size.height - 1));
}
//鼠标交互获取mask区域和第一张图片特征点
void on_Left_Mouse(int event,int x,int y,int flags,void* param)
{
Mat& image = *(Mat*)param;
switch (event)
{
case EVENT_LBUTTONDOWN:
{
point_one.x = x;
point_one.y = y;
one_frame_point4.push_back(point_one);
circle(image, point_one, 5, Scalar(0, 0, 255), -1, 8);
}
break;
default:
break;
}
}
//获取特征点
void detectFeature(Mat &ingray)
{
Ptr<ORB> orb = ORB::create(150, 1.2f, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20);
vector<KeyPoint> keyPoint_one;
orb->detectAndCompute(ingray, mask, keyPoint_one, description_one);
vector<Point2f> feature_one;
for (int i = 0; i < keyPoint_one.size(); i++)
{
feature_one.push_back(keyPoint_one[i].pt);
}
fpts[0] = feature_one;
cout << "第一张图片特征点个数" << fpts[0].size() << endl;
}
void LKTrackFeature()
{
//光流追踪
calcOpticalFlowPyrLK(prev_frame, gray, fpts[0], fpts[1], status, errors);
//提取sift特征点
Ptr<ORB> orb = ORB::create(150, 1.2f, 8, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20);
vector<KeyPoint> keyPoint_two;
orb->detectAndCompute(gray, mask, keyPoint_two, description_two);
cout << keyPoint_two.size() << endl;
vector<DMatch> matches;
BFMatcher matcher(NORM_HAMMING);
matcher.match(description_one,description_two,matches);
cout << description_one.rows << endl;
double min_dist = 10000, max_dist = 0;
for (int i = 0; i < description_one.rows; i++)
{
double dist = matches[i].distance;
if (dist < min_dist) { min_dist = dist; }
if (dist > max_dist) { max_dist = dist; }
}
cout << "min:" << min_dist << "\t" << "max:" << max_dist << endl;
//vector<DMatch> good_match;
int k = 0;
for (int j = 0; j < fpts[0].size(); j++)
{
//float a = fpts[1][j].x-keyPoint_two[j].pt.x;
//float b = fpts[1][j].y - keyPoint_two[j].pt.y;
//cout << "a:" << a << "b:" << b << endl;
float a = max(2 * min_dist, 10.0);
if ((matches[j].distance<= a)&&status[j])
{
fpts[0][k] = fpts[0][j];
fpts[1][k++] = fpts[1][j];
//good_match.push_back(matches[j]);
}
}
fpts[0].resize(k);
fpts[1].resize(k);
cout << fpts[0].size() << endl;
cout << fpts[1].size() << endl;
}
int main()
{
VideoCapture capture("../41_output.mp4");
if (!capture.isOpened())
{
cout << "could not load video file..." << endl;
return -1;
}
int num_frames = capture.get(CAP_PROP_FRAME_COUNT);
double num_fps = capture.get(CAP_PROP_FPS);
Size num_size = Size(capture.get(CAP_PROP_FRAME_WIDTH), capture.get(CAP_PROP_FRAME_HEIGHT));
cout << "frames:" << num_frames << endl;
cout << "fps:" << num_fps << endl;
cout << "size:" << num_size << endl;
VideoWriter writer;
writer.open("../sift_LK_test.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), num_fps, num_size);
namedWindow("video_input", 0);
namedWindow("video_output", 0);
//获取贴图的四个点坐标集合
get_img_points();
//读取视频图片进行处理
int n = 0;
while (capture.read(frame))
{
n++;
cvtColor(frame, gray, COLOR_BGR2GRAY);
if (prev_frame.empty())
{
gray.copyTo(prev_frame);
}
if (n==1)
{
Mat frame_one;
frame.copyTo(frame_one);
setMouseCallback("video_input",on_Left_Mouse,&frame_one);
Mat tempImage;
frame.copyTo(tempImage);
while (true)
{
circle(tempImage,point_one,5,Scalar(0,0,255),-1,8);
imshow("video_input", tempImage);
if (waitKey(10) == 27)break;
}
mask = Mat::zeros(gray.size(),gray.type());
vector<Point> points_mask;
for (int i = 0; i <4 ; ++i) {
points_mask.push_back(one_frame_point4[i]);
}
fillConvexPoly(mask,points_mask,Scalar(255),LINE_AA);
detectFeature(gray);
//贴图
Mat warp_Homo = getPerspectiveTransform(src_points_4, one_frame_point4);
Mat frame_clone, frame_fill;
frame.copyTo(frame_clone);
frame.copyTo(frame_fill);
warpPerspective(src_img,frame_clone,warp_Homo,frame_clone.size());
fillConvexPoly(frame_fill,points_mask,Scalar(0,0,0),LINE_AA);
frame_fill = frame_fill + frame_clone;
writer << frame_fill;
}
if (n>=2)
{
imshow("video_output", frame);
LKTrackFeature();
Mat homography_H;
homography_H = findHomography(fpts[0],fpts[1],RANSAC,3,noArray(),2000,0.995);
cout << "homograyphy_H:" << homography_H << endl;
//贴图操作
vector<Point2f> points_tran;
perspectiveTransform(one_frame_point4,points_tran,homography_H);
Mat warp_Homo = getPerspectiveTransform(src_points_4, points_tran);
Mat frame_clone, frame_fill;
frame.copyTo(frame_clone);
frame.copyTo(frame_fill);
warpPerspective(src_img,frame_clone,warp_Homo,frame_clone.size());
vector<Point> points_mask;
for (int i = 0; i <4 ; ++i) {
points_mask.push_back(points_tran[i]);
}
fillConvexPoly(frame_fill,points_mask,Scalar(0,0,0),LINE_AA);
frame_fill = frame_fill + frame_clone;
writer << frame_fill;
//把第二张图片看成第一张
mask = Mat::zeros(gray.size(), gray.type());
fillConvexPoly(mask, points_mask ,Scalar(255), LINE_AA);
gray.copyTo(prev_frame);
detectFeature(prev_frame);
for (int i = 0; i < 4; i++)
{
one_frame_point4[i] = points_tran[i];
}
}
char c = waitKey(1);
if (c==27)
{
break;
}
}
waitKey(0);
return 0;
}
ORB_LK视频贴图
最新推荐文章于 2023-02-20 23:39:25 发布