DIC源码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
6.0 KiB

3 months ago
#pragma once
#ifndef _SIFT_H_
#define _SIFT_H_
#include "oc_feature.h"
#define IMG_BORDER 1 //gap to the boundary of image
namespace opencorr
{
struct Sift2dConfig //refer to OpenCV document for detailed information
{
int n_features; //number of best features to retain
int n_octave_layers; //number of layers in each octave for feature detection
float contrast_threshold; //contrast threshold used to filter out weak features in semi-uniform (low-contrast) regions
float edge_threshold; //threshold used to filter out edge-like features
float sigma; //sigma of the Gaussian applied to the input image at the octave #0
};
class SIFT2D : public Feature2D
{
protected:
cv::Mat* ref_mat = nullptr; //pointer to ref image
cv::Mat* tar_mat = nullptr; //pointer to tar image
Sift2dConfig sift_config;
float matching_ratio; //ratio of the shortest distance to the second shortest distance
public:
std::vector<Point2D> ref_matched_kp; //matched keypoints in ref image
std::vector<Point2D> tar_matched_kp; //matched keypoints in tar image
SIFT2D();
~SIFT2D();
Sift2dConfig getSiftConfig() const;
float getMatchingRatio() const;
void setSiftConfig(Sift2dConfig sift_config);
void setMatching(float matching_ratio);
void prepare();
void compute();
void clear();
};
struct Sift3dConfig
{
int n_octave_layers; //number of layers in each octave for extrema detection
int n_octave; //number of octave in a pyramid
int min_dimension; //lower limit of the image dimension for downsampling
float alpha; //threshold used to filter out the insufficiently distinct keypoints in DoG pyramid
float beta; //threshold used to filter out the keypoints with ambigous eigenvalues
float gamma; //threshold used to filter out the keypoints with small angle between the eigenvectors
float sigma_source; //scale of the Gaussian blur kernel supposed to be included in the input image
float sigma_base; //base scale of the pyramid
float gradient_threshold; //threshold of Gaussian weighted gradient
float truncate_threshold; //threshold used to truncate the descriptor components
};
struct Layer3D
{
float*** vol_mat;
int dim_xyz[3]; //{ dim_x, dim_y, dim_z }
float unit_xyz[3]; //{ unit_x, unit_y, unit_z }
int octave;
float max_abs; //maximum absolute DoG value in the layer
float scale;
float sigma; //sigma used to blur the current layer based on the previous layer
};
struct Keypoint3D
{
Point3D coor_layer; //coordinate in current layer
Point3D coor_img; //coordinate in original image
int octave, layer;
float scale;
float rotation_matrix[9]; //dimension: 3x3, column first
};
struct EigenMatrix
{
float eigen_value;
float eigen_vector[3];
};
struct TriangleTile
{
Point3D vertices[3]; //vertices of triangle
int vertex_idx[3]; //index of vertex
TriangleTile() {}
TriangleTile(Point3D v1, int vi1, Point3D v2, int vi2, Point3D v3, int vi3)
{
vertices[0] = v1;
vertices[1] = v2;
vertices[2] = v3;
vertex_idx[0] = vi1;
vertex_idx[1] = vi2;
vertex_idx[2] = vi3;
}
};
struct KeypointChecker
{
int ref_idx;
int tar_idx;
float dist;
};
class SIFT3D : public Feature3D
{
private:
TriangleTile icosahedron[20]; //triangles in an icosahedron
protected:
Sift3dConfig sift_config;
float matching_ratio; //ratio of the shortest distance to the second shortest distance
float physical_unit[3]; //physical unit per image voxel
public:
std::vector<Point3D> ref_matched_kp; //matched keypoints in ref image
std::vector<Point3D> tar_matched_kp; //matched keypoints in tar image
SIFT3D();
~SIFT3D();
Sift3dConfig getSiftConfig() const;
float getPhysicalUnit(int dim) const; //dim = 0,1,2 means x,y,z respectively
float getMatchingRatio() const;
void setSiftConfig(Sift3dConfig sift_config);
void setPhysicalUnit(float unit_x, float unit_y, float unit_z);
void setMatchingRatio(float matching_ratio);
void prepare();
void compute();
void clear();
void initializeIcosahedron(TriangleTile* icosahedron);
void gaussianBlur(float*** src_img, float*** dst_img, int* dim_xyz, float* unit_xyz, float sigma); //dim_xyz[] = { x, y, z }
void downSampling(float*** src_img, float*** dst_img, int* dst_dim_xyz); //dim_xyz[] = { x, y, z }
void clearPyramid(std::vector<Layer3D>& pyramid);
int cartisan2Barycentric(Point3D& cart_coor, Point3D& bary_coor, TriangleTile& triangle); //convert the Cartisian coordinates of intersection point to barycentric coordinate system in regular triangle
int bruteforceMatch(std::vector<Keypoint3D>& kp1, float** descriptor1, std::vector<Keypoint3D>& kp2, float** descriptor2, int* matched_idx);
void createGaussianPyramid(Image3D* vol_img, std::vector<Layer3D>& pyramid);
void createDogPyramid(std::vector<Layer3D>& gaussian_pyramid, std::vector<Layer3D>& dog_pyramid);
void detectExtrema(std::vector<Layer3D>& dog_pyramid, std::vector<Keypoint3D>& kp_queue);
void assignOrientation(std::vector<Keypoint3D>& kp_queue, std::vector<Layer3D>& gaussian_pyramid);
void constructDescriptor(std::vector<Keypoint3D>& kp_queue, std::vector<Layer3D>& gaussian_pyramid, float** descriptor);
void monodirectionalMatch(std::vector<Keypoint3D>& kp1, float** descriptor1, std::vector<Keypoint3D>& kp2, float** descriptor2,
std::vector<Point3D>& matched_kp1, std::vector<Point3D>& matched_kp2); //monodirectional matching, but many-to-one correspondences are eliminated through reverse matching
void bidirectionalMatch(std::vector<Keypoint3D>& kp1, float** descriptor1, std::vector<Keypoint3D>& kp2, float** descriptor2,
std::vector<Point3D>& matched_kp1, std::vector<Point3D>& matched_kp2); //rigorous bidirectional matching
};
bool sortByEigenvalue(const EigenMatrix& em1, const EigenMatrix& em2);
bool sortByRefIdx(const KeypointChecker& kc1, const KeypointChecker& kc2);
bool sortByTarIdx(const KeypointChecker& kc1, const KeypointChecker& kc2);
int mirrorLow(int x, int y); //deal the case that the index crosses the lower boundary
int mirrorHigh(int x, int y); //deal the case that the index crosses the higher boundary
}//namespace opencorr
#endif //_SIFT_H_