Dimensionality reduction of feature point descriptors by PCA

Dimensionality reduction is actually a very important part in the field of machine learning, because in high-dimensional situations, the samples are sparse, and it is difficult to calculate distance and inner product, which is a common problem faced by all machine learning, which is called the curse of dimensionality. ), and dimensionality reduction is a solution, it not only simplifies the amount of operations, but also because the projection of the original data on the main feature components can resist some noise interference. Because I want to reduce the computational complexity of feature point matching in the process of image registration through dimensionality reduction, I also saw some dimensionality reduction methods in the public account machine learning algorithm engineer, such as PCA, kernelized (kernelized, it should be the kernel mechanism) Implement nonlinear dimensionality reduction), popular learning, and metric learning. Of course, the most mature is PCA. Although PCA-SIFT appeared very early, I still want to implement it myself. The idea is to export the feature point txt file in Lowe format first, and then modify the function to reduce the dimension during import, write it into the descr_pca array, and then export it to obtain 64-dimensional feature points. At this time, the data after dimensionality reduction is imported, and image registration is achieved through these data.

At this time, the problem occurs again. The process of building the kd tree is very slow, and the registration result cannot be obtained. Later, I realized that the feature point data of the boat image I used was the beaver image used in the experiment. When I corrected this error and imported the original feature point data to do the experiment, the error rate of the matching pair was very high. It's not because stack_imgs displays the two images together, causing the coordinate transformation. But at least the feature points of the img1 part should be normal, the current situation is completely wrong. .

From the debugging point of view, there is no problem in the import part. The first point is (254,297), and the corresponding second picture is (134,258), which is consistent with the data in txt. In the txt feature point file in Lowe format, the first line is the number of feature points and the description sub-dimension. For each feature point, the four data in the first line are the y-coordinate, x-coordinate of the feature point, and the scale, orientation of feature points, then 128 double numbers https://blog.csdn.net/masibuaa/article/details/9204157. The problem seems to be in the process of finding matching pairs after building the kd-tree. The Kd tree is constructed for the feature point feat2 in Figure 2, and the feature points in feat1 are traversed to find the corresponding matching points in the kd tree. The first pair found is (3,15)-(4,20).

Source code, especially the C language, is really complicated to use pointers. As follows, there are double pointers and triple pointers in the process of importing feature points and knn search in the kd tree, respectively.

static int import_lowe_features( char*filename, struct feature** features )//Static functions cannot be used by other files, so other files can also have the same function name

int kdtree_bbf_knn( struct kd_node*kd_root, struct feature* feat, int k,

                       struct feature*** nbrs, int max_nn_chks )

In the import_lowe_features function, there are the following two key sentences:

f = calloc( n, sizeof(struct feature) );//Allocate n continuous spaces of size size in the dynamic storage area of ​​the memory, the function returns a pointer to the starting address of the allocation

*features = f;//equivalent to feature=&f?? point the complex number of features to f //the first address is assigned to *features

So, change import_features(path1, 1, &feat1); to import_features(path1,1, import_feat1);//The third parameter is the pointer of the pointer, struct feature** import_feat1=NULL//Initialization, it is abnormal when running.

It seems that &feat1 is still used, because the original feature point detection in the source code is also written like this: n1 = sift_features( img1, &feat1 );

Later, it was found that before feat = feat1 + i;//before the addition of pointers, after dynamically allocating memory of length n, the fscanf coordinate value went wrong. fscanf reads the txt file and requires that the encoding method of the txt file is ANSI. There is no error in this.

fscanf( file, " %lf %lf %lf %lf", &y, &x, &s, &o ) != 4 )//%lf is double type input fscanf returns the read length

There is a space between the two format control characters %lf, which applies to the space between the data. If there is a comma between the data, the format control character is also a comma, and there is no error.

As a result, I was embarrassed. I debugged step by step, looked at the parameters of the first feature point, the coordinates were correct, looked at the 128-dimensional descriptors one by one, and found that when it reached 64, it jumped to the second feature point. The truth is clear, it turned out that I changed d to 64 when I imported the txt file after dimension reduction, and forgot to change it back when I verified the 128 dimension here. .

The following is the image registration done by importing feature point information in the lowe format:


The feature point importing takes about 4s.

This is the feature point detection and registration done directly on the image:


The feature point detection takes 26s

Look back at importing 64-dimensional descriptors. It is extremely slow and registration cannot be completed. The error says that too few matching pairs were found. Open the txt file after dimension reduction:

7875 64

297.440434 254.241265 80.338874 -1.866019

 2 01 0 0 0 0 0 -1 0 0 0 0 0 0 0 -1 0 0 0

 0 00 0 3 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0

 -1 00 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 1 0 0

 0 00 0

557.449920 181.560168 42.599985 1.464965

 4 -10 -1 0 0 0 3 0 0 1 0 0 0 0 0 -1 -1 0 0

 0 00 0 0 -2 1 0 0 0 0 0 3 1 -1 1 0 0 0 1

 0 21 0 0 0 0 -1 -3 0 -1 0 0 0 0 -1 -2 0 0 0

 0 00 -1

You can see 64 feature data, which are divided into 20*3+4. When importing, the coordinates of the feature points are the first two values ​​of the line with four values, which will mistake some descriptors. As the coordinate value and scale, it is the gradient.

In the Pcad process, the number of rows and columns of eigenvalues ​​and eigenvectors is still not well understood. Finally, the result is written as a square matrix without interruption. Later, it was derived into a 4*4-dimensional descriptor. This is imported into the program for registration, and more than 500 matching pairs are found, but no matching lines can be drawn. During the debugging process, it was found that the matching pair was also incorrect. Could it be that the threshold value in the knn search in the kd tree after dimensionality reduction should also be changed?

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326178978&siteId=291194637