|
@@ -0,0 +1,138 @@
|
|
|
+//
|
|
|
+// lenz_stitcher.hpp
|
|
|
+// LenzCameraNativeModuleForRN
|
|
|
+//
|
|
|
+// Created by lr on 2023/2/8.
|
|
|
+//
|
|
|
+
|
|
|
+#ifndef lenz_stitcher_hpp
|
|
|
+#define lenz_stitcher_hpp
|
|
|
+
|
|
|
+#if __cplusplus && __has_include(<opencv2/imgcodecs/ios.h>)
|
|
|
+
|
|
|
+#import <opencv2/core/ocl.hpp>
|
|
|
+#import <opencv2/opencv.hpp>
|
|
|
+
|
|
|
+#include <iostream>
|
|
|
+#include <thread>
|
|
|
+#include <vector>
|
|
|
+#include <string>
|
|
|
+#include <random>
|
|
|
+#include <math.h>
|
|
|
+#include <dirent.h>
|
|
|
+#include <sys/types.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <unistd.h>
|
|
|
+
|
|
|
+using namespace cv;
|
|
|
+using namespace cv::detail;
|
|
|
+using namespace cv::ocl;
|
|
|
+using namespace std;
|
|
|
+
|
|
|
+#define STITCH_STATUS_INIT 0
|
|
|
+#define STITCH_STATUS_CHECKING 1
|
|
|
+#define STITCH_STATUS_STITCHING 2
|
|
|
+#define STITCH_STATUS_FREE 3
|
|
|
+#define STITCH_STATUS_FAILED 4
|
|
|
+
|
|
|
+#define FEATURE_HEIGHT 300
|
|
|
+#define STITCH_HEIGHT 300
|
|
|
+#define BIG_STITCH_HEIGHT 1000
|
|
|
+#define BIG_FEATURE_HEIGHT 800
|
|
|
+
|
|
|
+#define MAX_SIZE 4000 // 缩略图的最大尺寸,长或宽都不能超过MAX_SIZE*MAX_SIZE,否则直接报错
|
|
|
+#define BIG_MAX_SIZE 10000 // 拼接大图的最大尺寸, 长或宽都不能超过BIG_MAX_SIZE
|
|
|
+
|
|
|
+struct stitch_data
|
|
|
+{
|
|
|
+ Mat scaled_gray_frame;
|
|
|
+ float work_scale;
|
|
|
+ vector<KeyPoint> keypoints;
|
|
|
+ Mat descriptors;
|
|
|
+ Mat homo = (Mat_<double>(3, 3) << 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); // store homography matrix to base image
|
|
|
+ Mat base_homo = (Mat_<double>(3, 3) << 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); // store homography matrix to last base image
|
|
|
+};
|
|
|
+
|
|
|
+struct LinePara
|
|
|
+{
|
|
|
+ float k;
|
|
|
+ float b;
|
|
|
+};
|
|
|
+
|
|
|
+string test_image_path = "";
|
|
|
+
|
|
|
+class LenzStitcher
|
|
|
+{
|
|
|
+public:
|
|
|
+ string task_id = "";
|
|
|
+ string local_path = "";
|
|
|
+ int stitcher_status = STITCH_STATUS_INIT; // 0: initialized, 1: checking, 2: stitching, 3: free
|
|
|
+
|
|
|
+ int failed_count = 0; // 当前连续失败的帧数
|
|
|
+ int failed_thresh = 10; // 连续5帧失败才返回失败
|
|
|
+
|
|
|
+ float iou_thresh = 0.7; // iou低于该阈值的时候把这张图片存下来
|
|
|
+ float area_thresh = 0.5; // area threshold for green box
|
|
|
+ float angle_thresh = 10; // angle threshold for green box
|
|
|
+ float inline_thresh = 0.1; // 光流法匹配的点的比例至少要大于这个值,才认为是正确的映射矩阵
|
|
|
+ int matches_thresh = 10; // 前后两帧基于光流的匹配点的个数的阈值,低于该值则无法进行拼接
|
|
|
+ float check_match_conf = 0.2f;
|
|
|
+ int frame_index = 0;
|
|
|
+ vector<Point2f> last_warp_points; // 上一张存下来的图的四个点在拼接图上的坐标
|
|
|
+ int big_frame_index = 0; // 存下来的帧的信息
|
|
|
+ float total_shift_x = 0;
|
|
|
+ float total_shift_y = 0;
|
|
|
+
|
|
|
+ Mat last_frame;
|
|
|
+ Mat last_stitch_image = Mat(); // 最后一张拼接缩略图
|
|
|
+ int last_direction = 0; // 上一帧的手机移动方向
|
|
|
+ vector<float> last_angles = vector<float>{90, 90, 90, 90};
|
|
|
+ string last_stitch_image_path = ""; // 拼接缩略图的本地路径
|
|
|
+ stitch_data last_check_data; // 上一帧的数据
|
|
|
+ string big_stitch_image_path = ""; // 拼接大图的本地路径
|
|
|
+
|
|
|
+ string test_image_path = ""; // test
|
|
|
+
|
|
|
+ LenzStitcher(string input_id);
|
|
|
+ int *ofcheck_stitch(Mat &frame, int const direction, int const is_last_one); // 输入每一帧实时产生拼接缩略图
|
|
|
+
|
|
|
+ bool get_big_image(int get_big_image); // 在收到当前帧是最后一帧的时候运行,会用之前存下来的帧数据产生最后的拼接大图
|
|
|
+ void remove_local_path();
|
|
|
+};
|
|
|
+
|
|
|
+bool is_good_homo(const vector<Point2f> &corners, const Mat &frame, float area_thresh, float angle_thresh);
|
|
|
+bool is_convex(const vector<Point2f> &corners);
|
|
|
+float calc_area(const vector<Point2f> &corners, const Mat &frame);
|
|
|
+float min_axis(vector<float> input_list);
|
|
|
+float max_axis(vector<float> input_list);
|
|
|
+float calc_angle(const vector<cv::Point2f> &conners);
|
|
|
+float calc_vangle(const vector<cv::Point2f> &conners);
|
|
|
+float calc_hangle(const vector<cv::Point2f> &conners);
|
|
|
+void double_match(const Mat &query_des, const Mat &train_des, vector<DMatch> &good_matches, float check_match_conf);
|
|
|
+void single_match(const Mat &query_des, const Mat &train_des, vector<DMatch> &good_matches, float check_match_conf);
|
|
|
+void getFilePath(const char *path, const char *filename, char *filepath);
|
|
|
+void deleteFile(const char *path);
|
|
|
+bool isFloderexit(const char *path);
|
|
|
+void randomSelectKeyPoints(vector<KeyPoint> kpts, vector<Point2f> &pts, int max_num);
|
|
|
+void optimizeSeam(Mat &last_img, Mat &stitched_image, vector<Point2f> &corners);
|
|
|
+void getLinePara(float x1, float y1, float x2, float y2, LinePara &LP);
|
|
|
+float point_2_line(float k, float b, float k2, float x, float y);
|
|
|
+int get_direction(vector<Point2f> &frame_corners, vector<Point2f> &transpose_corners);
|
|
|
+int dcmp(float x);
|
|
|
+float cross(Point2f a, Point2f b, Point2f c);
|
|
|
+float CPIA(vector<Point2f> a, vector<Point2f> b, int na, int nb);
|
|
|
+float SPIA(vector<Point2f> a, vector<Point2f> b, int na, int nb);
|
|
|
+Point2f get_intersection_point(Point2f a, Point2f b, Point2f c, Point2f d);
|
|
|
+float PolygonArea(vector<Point2f> p, int n);
|
|
|
+float single_quadrangle_iou(vector<Point2f> pts1, vector<Point2f> pts2);
|
|
|
+float single_box_iou(vector<Point2f> pts1, vector<Point2f> pts2);
|
|
|
+void stitch_big_image(Mat frame, vector<float> angles, int direction, int big_frame_index);
|
|
|
+void cylindrical_projection(Mat &img, Mat &output, float angle);
|
|
|
+void fill_contours(vector<vector<Point>> contours, Mat &source_image, Mat &target_image);
|
|
|
+float angle_of_two_vector(Point2f &pt1, Point2f &pt2, Point2f &c);
|
|
|
+void calc_angles(vector<Point2f> &conners);
|
|
|
+
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+#endif
|