Open sanersbug opened 1 year ago
@sanersbug Can you add your pics here?
@sanersbug Can you add your pics here?
yes, it like :
Another thing , i find the lisrd can adapt the scene easily, but it is the python version, I haven't compare it with loftr use C++, because i am not good at the onnxruntime. The speed of lisrd more faster than loftr , i think it seems that lisrd is more meaningful in practical application. And can you open Alipay,i pay with Ali-Pay easily, i think you do these match method professionally
I have checked both the cpp code and original python code. For the indoor_new_ds weights, indeed the number of matched points is zero.
However, for the outdoor_weights, LoFTR performed well as you can see in the following pic. (The following pic is from python code).
Sadly, I doubt there is still some bug in loftr that makes the conversion of the outdoor weight unsuccessful. Hence we can not use the old outdoor weight for my C++ program.
LISRD is actually a descriptor model, so somehow it works like SuperPoint (without SuperGlue). Though the inference part of LISRD is more complicated than SuperPoint.
However, as many have asked for LISRD code, I may see what I can do later.
It seems that LISRD works better, and the author of LISRD says that LISRD is faster. @xmba15
LoFTR and SuperGlue are scale-insensitive
LISRD is actually a descriptor model, so somehow it works like SuperPoint (without SuperGlue). Though the inference part of LISRD is more complicated than SuperPoint.
However, as many have asked for LISRD code, I may see what I can do later.
That's it, and I have lisrd onnx model, but when i try to write C++ program about lisrd, it failed. you can use the followling model try the lisrd mothed https://drive.google.com/drive/folders/1bW14nNAzjIl2i3wm8OKUxYhngoib6UC3?usp=sharing
The application of Superglue and LoFTR in 3D comparison is carried out in point cloud point cloud point cloud point cloud or image reconstruction process, even if there is a large amount of occlusion between Matching and position estimation are performed on indoor and indoor and mid-level and mid-level modeling local and global features, so as to obtain better 3D point cloud and scene reconstruction results.
In general, these two algorithms are advanced image registration and 3D reconstruction techniques, which can achieve brilliant results in a variety of scenarios.
LISRD works better in the field of object tracking. The LISRD algorithm is a fast online multi-target tracking algorithm with high accuracy and real-time performance. The LISRD algorithm uses coupled single-model technology to simultaneously estimate and update all target states and corresponding appearance models during each frame tracking process, thereby avoiding the problem of model matching and selection in traditional multi-model tracking algorithms and improving tracking accuracy Spend.
In addition, the LISRD algorithm also introduces a novel sparse representation-based spatio-temporal constraint for filtering and smoothing the target trajectory, which reduces unnecessary false alarms and jumps while maintaining tracking accuracy.
In general, the LISRD algorithm not only achieves good results in the field of target tracking, but also has broad application prospects in other application fields (such as video processing, human-computer interaction, etc.). @sanersbug @xmba15
@xmba15 Have you try to make the LISRD code? In the post-processing , i can't understand the extract_descriptors function, especially the use of torch.nn.functional.grid_sample in grid_sample(descriptors[k], grid_points), dim=1).
@sanersbug @xmba15 This is the translated LISRD I wrote on the basis of the @xmba15 's library, but the effect is a little worse than python, the @xmba15 can continue on my basis.
`
include <opencv2/opencv.hpp>
include
include <torch/torch.h> include <torch/script.h> include "OrtSessionHandler.h"
using namespace std; using namespace Ort;
std::vector
std::vector
cv::Mat detectorMat(detectorShape.size(), detectorShape.data(), CV_32F, inferenceOutput[0].first); // 65 x H/8 x W/8
cv::Mat buffer; transposeNDWrapper(detectorMat, {1, 2, 0}, buffer); buffer.copyTo(detectorMat); // H/8 x W/8 x 65
for (int i = 0; i < detectorShape[1]; ++i)
{
for (int j = 0; j < detectorShape[2]; ++j)
{
softmax(detectorMat.ptr
std::vector
std::vector
//
std::vector<int> sortedIndices(keyPoints.size());
std::iota(sortedIndices.begin(), sortedIndices.end(), 0);
// sort in descending order base on confidence
std::stable_sort(sortedIndices.begin(), sortedIndices.end(),
[&keyPoints](int lidx, int ridx)
{ return keyPoints[lidx].response > keyPoints[ridx].response; });
cv::Mat grid = cv::Mat(height, width, CV_8S, TO_PROCESS);
std::vector<int> keepIndices;
for (int idx : sortedIndices)
{
int x = keyPoints[idx].pt.x;
int y = keyPoints[idx].pt.y;
if (grid.at<schar>(y, x) == TO_PROCESS)
{
for (int i = y - distThresh; i < y + distThresh; ++i)
{
if (i < 0 || i >= height)
{
continue;
}
for (int j = x - distThresh; j < x + distThresh; ++j)
{
if (j < 0 || j >= width)
{
continue;
}
grid.at<int>(i, j) = EMPTY_OR_SUPPRESSED;
}
}
grid.at<int>(y, x) = KEPT;
keepIndices.emplace_back(idx);
}
}
return keepIndices;
}
std::vector
torch::Tensor keyPointsToGrid(const std::vector
std::pair<torch::Tensor, torch::Tensor>
extractDescriptors(const std::vector
torch::Tensor lisrdMatcher(torch::Tensor desc1, torch::Tensor desc2, torch::Tensor meta_desc1, torch::Tensor meta_desc2) { torch::Tensor desc_weights = torch::einsum("nid,mid->nim", {meta_desc1, meta_desc2}); meta_desc1.reset(); meta_desc2.reset(); desc_weights = torch::softmax(desc_weights, 1); torch::Tensor desc_sims = torch::einsum("nid,mid->nim", {desc1, desc2}) * desc_weights; desc1.reset(); desc2.reset(); desc_weights.reset(); desc_sims = torch::sum(desc_sims, 1); torch::Tensor nn12 = torch::argmax(desc_sims, 1); torch::Tensor nn21 = torch::argmax(desc_sims, 0); torch::Tensor ids1 = torch::arange(desc_sims.size(0), torch::dtype(torch::kLong)); desc_sims.reset(); torch::Tensor mask = (ids1 == nn21.index_select(0, nn12)); torch::Tensor mask_bool = mask.nonzero().squeeze(1); torch::Tensor t1 = torch::index_select(ids1, 0, mask_bool); // torch::Tensor t2 = torch::index_select(nn12, 0, mask_bool); // torch::Tensor matches = torch::stack({t1, t2}, 1); return matches; }
std::pair<std::vector
void plot_keypoints(const cv::Mat &img, const std::vector
int main()
{
cv::String img_path1 = "./examples/data/small.png";
cv::String img_path2 = "./examples/data/big.png";
std::string superpoint_model_path = "./model/super_point_danamic_axis.onnx";
std::string lisrd_model_path = "./model/lisrd_vidit_danamic_axis.onnx";
cv::Mat bgr1 = cv::imread(img_path1, cv::IMREAD_COLOR);
cv::Mat bgr2 = cv::imread(img_path2, cv::IMREAD_COLOR);
cv::Mat gray1 = cv::imread(img_path1, cv::IMREAD_GRAYSCALE);
cv::Mat gray2 = cv::imread(img_path2, cv::IMREAD_GRAYSCALE);
cv::Mat rgb1, rgb2, resized_img1, resized_img2;
cv::cvtColor(bgr1, rgb1, cv::COLOR_BGR2RGB);
cv::cvtColor(bgr2, rgb2, cv::COLOR_RGB2BGR);
// cv::resize(rgb1, resized_img1, cv::Size(1280, 720), cv::INTER_CUBIC);
// cv::resize(rgb2, resized_img2, cv::Size(1280, 720), cv::INTER_CUBIC);
//-----------------------------------------------------//
// keypoint from sift
//-----------------------------------------------------//
// std::vector
//-----------------------------------------------------//
// keypoint from superpoint and inference
//-----------------------------------------------------//
Ort::SuperPoint superpoint1(superpoint_model_path, 0, std::vector<std::vector
Ort::SuperPoint superpoint2(superpoint_model_path, 0, std::vector<std::vector
// std::ofstream file1 ("kp_sp_cpp1.txt"); // for (const auto &keypoint: keypoint1) // { // file1 << keypoint.pt.x << " " << keypoint.pt.y << std::endl; // } // file1.close(); // std::ofstream file2 ("kp_sp_cpp2.txt"); // for (const auto &keypoint: keypoint2) // { // file2 << keypoint.pt.x << " " << keypoint.pt.y << std::endl; // } // file2.close();
float ps = 2;
std::vector
//-----------------------------------------------------//
// descriptor from lisrd and inference
//-----------------------------------------------------//
Ort::Lisrd lisrd1(lisrd_model_path, 0, std::vector<std::vector
Ort::Lisrd lisrd2(lisrd_model_path, 0,std::vector<std::vector
std::pair<torch::Tensor, torch::Tensor> result1 = extractDescriptors(lisrd_output1, keypoint1, rgb1.size()); std::pair<torch::Tensor, torch::Tensor> result2 = extractDescriptors(lisrd_output2, keypoint2, rgb2.size());
std::ofstream file1("desc1.txt"); file1 << result1.first; file1.close(); std::ofstream file2("meta_desc1.txt"); file2 << result1.second; file2.close();
std::ofstream file3("desc2.txt"); file3 << result2.first; file3.close(); std::ofstream file4("meta_desc2.txt"); file4 << result2.second; file4.close();
torch::Tensor matches = lisrdMatcher(result1.first, result2.first, result1.second, result2.second);
std::cout << "matches shape:" << matches.sizes() << std::endl;
std::ofstream file("matches.txt");
file << matches;
file.close();
//--------------------------------------------------------------//
// torch::Tensor --> cv::Mat
//--------------------------------------------------------------//
cv::Mat matches_mat(matches.size(0), matches.size(1), CV_32SC1);
matches = matches.to(at::kInt);
auto matches_accessor = matches.accessor<int32_t, 2>();
for (int i = 0; i < matches.size(0); i++)
{
for (int j = 0; j < matches.size(1); j++)
{
matches_mat.at
//-------------------------------------------------------------//
// kp1[matches[:, 0]][:, [1, 0]], kp2[matches[:, 1]][:, [1, 0]]
//-------------------------------------------------------------//
std::vector
//-------------------------------------------------------------//
// python in filter_outliers_ransac
//-------------------------------------------------------------//
std::pair<std::vector
std::vector
cv::Mat matchesImage;
// cv::resize(bgr1, bgr1, cv::Size(640, 480)); //
// cv::resize(bgr2, bgr2, cv::Size(640, 480));
std::cout << "filterKeyPoints first: " << filterKeyPoints.first.size() << " filterKeyPoints second: " << filterKeyPoints.second.size() << std::endl;
cv::drawMatches(bgr1, filterKeyPoints.first, bgr2, filterKeyPoints.second, matches_info, matchesImage,
cv::Scalar::all(-1), cv::Scalar::all(-1), std::vector
return EXIT_SUCCESS; }
`
@xmba15 @sanersbug @WithAIGC @ChmarsLuo @yeluo80808 Any one get good result about lisrd ? it's too hard using C++ make it.
This is only hobby repository so I can only focus on it on my free time. It might take some time until I can get to do it.
@sanersbug You can take a look at the following function to understand grid_sample(descriptors[k], grid_points), dim=1).
https://github.com/xmba15/onnx_runtime_cpp/blob/master/examples/Utility.hpp#L197
@yeluo80808 Thank you for the code. I will use it as reference when I explore LISRD.
This is only hobby repository so I can only focus on it on my free time. It might take some time until I can get to do it.
@sanersbug You can take a look at the following function to understand grid_sample(descriptors[k], grid_points), dim=1).
https://github.com/xmba15/onnx_runtime_cpp/blob/master/examples/Utility.hpp#L197
ok,thanks, I didn't notice it before
It turns out that besides me, there are so many people using LISRD. Looking forward to it.
@yeluo80808 I have tried the code, there is indeed a big problem with this result. Have you tried that ? how to solve it ? @xmba15
Has LISRD had any results and do you guys have any good news to share? @sanersbug @xmba15 @WithAIGC @yeluo80808
@Frown000 Sorry, i haven't solve that problem, it's too hard for me , i gived up, hope @xmba15 can solve that .
@xmba15 Have you tried the LISRD ? No one has made it for such a long time......
Is there any progress?
Sorry, I am quite busy now so currently I have no specific plan to support this in a short term. If you want to accelerate the development, please consider creating an at least runnable PR yourself in this repository. I will take a look and improve from it.
I have tested the loftr,but i find some problem, when i use two image which have same size , the result is normal,but when i use a big picture and a small picture ,it detect nothing!