Skip to content

Commit

Permalink
+ panorama_stitcher.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Loginov committed May 1, 2024
1 parent 31bd290 commit 68a286a
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 18 deletions.
43 changes: 29 additions & 14 deletions src/phg/sfm/panorama_stitcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,22 @@ cv::Mat phg::stitchPanorama(const std::vector<cv::Mat> &imgs,
{
// здесь надо посчитать вектор Hs
// при этом можно обойтись n_images - 1 вызовами функтора homography_builder
throw std::runtime_error("not implemented yet");
std::vector<std::vector<int> > g(n_images);
std::vector<int> q;
for (int i = 0; i < n_images; i++) {
if (parent[i] == -1) {
q = {i};
} else {
g[parent[i]].push_back(i);
}
}
Hs[q[0]] = cv::Mat::eye(3, 3, CV_64F);
for (size_t i = 0; i < q.size(); i++) {
for (auto e : g[q[i]]) {
Hs[e] = Hs[q[i]] * homography_builder(imgs[e], imgs[q[i]]);
q.push_back(e);
}
}
}

bbox2<double, cv::Point2d> bbox;
Expand All @@ -46,19 +61,19 @@ cv::Mat phg::stitchPanorama(const std::vector<cv::Mat> &imgs,
// из-за растяжения пикселей при использовании прямой матрицы гомографии после отображения между пикселями остается пустое пространство
// лучше использовать обратную и для каждого пикселя на итоговвой картинке проверять, с какой картинки он может получить цвет
// тогда в некоторых пикселях цвет будет дублироваться, но изображение будет непрерывным
// for (int i = 0; i < n_images; ++i) {
// for (int y = 0; y < imgs[i].rows; ++y) {
// for (int x = 0; x < imgs[i].cols; ++x) {
// cv::Vec3b color = imgs[i].at<cv::Vec3b>(y, x);
//
// cv::Point2d pt_dst = applyH(cv::Point2d(x, y), Hs[i]) - bbox.min();
// int y_dst = std::max(0, std::min((int) std::round(pt_dst.y), result_height - 1));
// int x_dst = std::max(0, std::min((int) std::round(pt_dst.x), result_width - 1));
//
// result.at<cv::Vec3b>(y_dst, x_dst) = color;
// }
// }
// }
for (int i = 0; i < n_images; ++i) {
for (int y = 0; y < imgs[i].rows; ++y) {
for (int x = 0; x < imgs[i].cols; ++x) {
cv::Vec3b color = imgs[i].at<cv::Vec3b>(y, x);

cv::Point2d pt_dst = phg::transformPoint(cv::Point2d(x, y), Hs[i]) - bbox.min();
int y_dst = std::max(0, std::min((int) std::round(pt_dst.y), result_height - 1));
int x_dst = std::max(0, std::min((int) std::round(pt_dst.x), result_width - 1));

result.at<cv::Vec3b>(y_dst, x_dst) = color;
}
}
}

std::vector<cv::Mat> Hs_inv;
std::transform(Hs.begin(), Hs.end(), std::back_inserter(Hs_inv), [&](const cv::Mat &H){ return H.inv(); });
Expand Down
36 changes: 32 additions & 4 deletions tests/test_matching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,8 @@ TEST (MATCHING, SimpleMatching1) {
cv::Mat img1 = cv::imread("data/src/test_matching/left1.jpg");
cv::Mat img2 = cv::imread("data/src/test_matching/right1.jpg");

cv::resize(img1, img1, cv::Size(img1.size[1] / 4, img1.size[0] / 4), 0.5, 0.5);
cv::resize(img2, img2, cv::Size(img2.size[1] / 4, img2.size[0] / 4), 0.5, 0.5);
cv::resize(img1, img1, cv::Size(img1.size[1] / 4, img1.size[0] / 4), 0, 0);
cv::resize(img2, img2, cv::Size(img2.size[1] / 4, img2.size[0] / 4), 0, 0);

double nn_score, nn2_score, nn_score_cv, nn2_score_cv,
time_my, time_cv, time_bruteforce, time_bruteforce_gpu, good_nn, good_ratio, good_clusters, good_ratio_and_clusters;
Expand All @@ -593,8 +593,8 @@ TEST (MATCHING, SimpleMatching2) {
cv::Mat img1 = cv::imread("data/src/test_matching/left2.jpg");
cv::Mat img2 = cv::imread("data/src/test_matching/right2.jpg");

cv::resize(img1, img1, cv::Size(img1.size[1] / 4, img1.size[0] / 4), 0.5, 0.5);
cv::resize(img2, img2, cv::Size(img2.size[1] / 4, img2.size[0] / 4), 0.5, 0.5);
cv::resize(img1, img1, cv::Size(img1.size[1] / 4, img1.size[0] / 4), 0, 0);
cv::resize(img2, img2, cv::Size(img2.size[1] / 4, img2.size[0] / 4), 0, 0);

double nn_score, nn2_score, nn_score_cv, nn2_score_cv,
time_my, time_cv, time_bruteforce, time_bruteforce_gpu, good_nn, good_ratio, good_clusters, good_ratio_and_clusters;
Expand Down Expand Up @@ -789,6 +789,34 @@ TEST (STITCHING, SimplePanorama) {
#endif
}

TEST (STITCHING, SimplePanorama2_1) {
#if ENABLE_MY_MATCHING
cv::Mat img1 = cv::imread("data/src/test_matching/left2.jpg");
cv::Mat img2 = cv::imread("data/src/test_matching/right2.jpg");

cv::resize(img1, img1, cv::Size(img1.size[1] / 4, img1.size[0] / 4), 0, 0);
cv::resize(img2, img2, cv::Size(img2.size[1] / 4, img2.size[0] / 4), 0, 0);

std::function<cv::Mat(const cv::Mat&, const cv::Mat&)> homography_builder = [](const cv::Mat &lhs, const cv::Mat &rhs){ return getHomography(lhs, rhs); };
cv::Mat pano = phg::stitchPanorama({img1, img2}, {-1, 0}, homography_builder);
cv::imwrite("data/debug/test_matching/" + getTestSuiteName() + "_" + getTestName() + "_" + "panorama.png", pano);
#endif
}

TEST (STITCHING, SimplePanorama2_2) {
#if ENABLE_MY_MATCHING
cv::Mat img1 = cv::imread("data/src/test_matching/left2.jpg");
cv::Mat img2 = cv::imread("data/src/test_matching/right2.jpg");

cv::resize(img1, img1, cv::Size(img1.size[1] / 4, img1.size[0] / 4), 0, 0);
cv::resize(img2, img2, cv::Size(img2.size[1] / 4, img2.size[0] / 4), 0, 0);

std::function<cv::Mat(const cv::Mat&, const cv::Mat&)> homography_builder = [](const cv::Mat &lhs, const cv::Mat &rhs){ return getHomography(lhs, rhs); };
cv::Mat pano = phg::stitchPanorama({img1, img2}, {1, -1}, homography_builder);
cv::imwrite("data/debug/test_matching/" + getTestSuiteName() + "_" + getTestName() + "_" + "panorama.png", pano);
#endif
}

namespace {

int getOrthoScore(const cv::Mat &ortho0, const cv::Mat &ortho1, int threshold_px)
Expand Down

0 comments on commit 68a286a

Please sign in to comment.