Skip to content

Commit

Permalink
Bugfix incomplete panos (#123)
Browse files Browse the repository at this point in the history
* add image indices to saved camera parameters

* add test for incomplete panos

* tidy

* update default sidebar width
  • Loading branch information
krupkat committed Feb 10, 2024
1 parent 1856277 commit 065db29
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 13 deletions.
37 changes: 36 additions & 1 deletion tests/stitcher_pipeline_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,41 @@ TEST_CASE("Pano too large") {
xpano::algorithm::stitcher::Status::kErrPanoTooLarge);
}

const std::vector<std::filesystem::path> kInputsIncomplete = {
"data/image05.jpg", // pano 1
"data/image06.jpg", // pano 2
"data/image07.jpg" // pano 2
};

TEST_CASE("Incomplete pano") {
xpano::pipeline::StitcherPipeline<kReturnFuture> stitcher;

auto loading_task = stitcher.RunLoading(kInputsIncomplete, {}, {});
auto stitch_data = loading_task.future.get();
auto progress = loading_task.progress->Report();
CHECK(progress.tasks_done == progress.num_tasks);

CHECK(stitch_data.images.size() == 3);
REQUIRE(stitch_data.panos.size() == 1);
REQUIRE_THAT(stitch_data.panos[0].ids, Equals<int>({1, 2}));

// add an unrelated image to the pano
stitch_data.panos[0].ids = {0, 1, 2};

// stitch
auto stitching_task0 = stitcher.RunStitching(stitch_data, {.pano_id = 0});
auto stitch_result0 = stitching_task0.future.get();

// TODO(krupkat): fix, this is currently not equal
// progress = stitching_task0.progress->Report();
// CHECK(progress.tasks_done == progress.num_tasks);

REQUIRE(stitch_result0.pano.has_value());
REQUIRE(stitch_result0.cameras.has_value());
CHECK(stitch_result0.cameras->cameras.size() == 2);
CHECK_THAT(stitch_result0.cameras->component, Equals<int>({1, 2}));
}

TEST_CASE("Stitcher pipeline single pano matching") {
xpano::pipeline::StitcherPipeline<kReturnFuture> stitcher;
auto loading_task = stitcher.RunLoading(
Expand Down Expand Up @@ -657,4 +692,4 @@ TEST_CASE("Stitcher pipeline stack detection") {
CHECK_THAT(result.panos[0].ids, Equals<int>({2, 3}));
}

// NOLINTEND(readability-function-cognitive-complexity)
// NOLINTEND(readability-function-cognitive-complexity)
11 changes: 5 additions & 6 deletions xpano/algorithm/algorithm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,9 @@ StitchResult Stitch(const std::vector<cv::Mat>& images,
stitcher::Status status;

if (cameras &&
cameras->wave_correction_user == user_options.wave_correction &&
cameras->cameras.size() == images.size()) {
cameras->wave_correction_user == user_options.wave_correction) {
stitcher->SetWaveCorrectKind(cameras->wave_correction_auto);
stitcher->SetTransform(images, cameras->cameras);
stitcher->SetTransform(images, cameras->cameras, cameras->component);
status = stitcher->ComposePanorama(pano);
} else {
status = stitcher->Stitch(images, pano);
Expand All @@ -290,9 +289,9 @@ StitchResult Stitch(const std::vector<cv::Mat>& images,
stitcher->ResultMask().copyTo(mask);
}

auto result_cameras =
Cameras{stitcher->Cameras(), user_options.wave_correction,
stitcher->WaveCorrectKind(), stitcher->GetWarpHelper()};
auto result_cameras = Cameras{
stitcher->Cameras(), stitcher->Component(), user_options.wave_correction,
stitcher->WaveCorrectKind(), stitcher->GetWarpHelper()};
return {status, pano, mask, std::move(result_cameras)};
}

Expand Down
1 change: 1 addition & 0 deletions xpano/algorithm/algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace xpano::algorithm {

struct Cameras {
std::vector<cv::detail::CameraParams> cameras;
std::vector<int> component;
WaveCorrectionType wave_correction_user; // set by user
cv::detail::WaveCorrectKind wave_correction_auto; // computed by OpenCV
stitcher::WarpHelper warp_helper;
Expand Down
2 changes: 1 addition & 1 deletion xpano/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ constexpr int kMaxPngCompression = 9;

constexpr int kAboutBoxWidth = 70;
constexpr int kAboutBoxHeight = 30;
constexpr int kSidebarWidth = 27;
constexpr int kSidebarWidth = 35;
constexpr int kWideButtonWidth = 12;

const std::string kOrgName = "krupkat";
Expand Down
1 change: 1 addition & 0 deletions xpano/gui/action.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct ShowPanoExtra {
bool full_res = false;
bool scroll_thumbnails = false;
bool reset_crop = false;
bool reset_cameras = false;
};

using LoadFilesExtra = std::vector<std::filesystem::path>;
Expand Down
14 changes: 9 additions & 5 deletions xpano/gui/pano_gui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Action ModifyPano(int clicked_image, Selection* selection,
return {.type = ActionType::kShowPano,
.target_id = selection->target_id,
.delayed = true,
.extra = ShowPanoExtra{.reset_crop = true}};
.extra = ShowPanoExtra{.reset_crop = true, .reset_cameras = true}};
}
return {};
}
Expand Down Expand Up @@ -454,18 +454,22 @@ Action PanoGui::PerformAction(const Action& action) {
spdlog::info("Calculating pano {}", selection_.target_id);
status_message_ = {};
auto extra = ValueOrDefault<ShowPanoExtra>(action);
auto& pano = stitcher_data_->panos[selection_.target_id];
if (extra.reset_cameras) {
pano.cameras.reset();
pano.backup_cameras.reset();
}
if (extra.reset_crop) {
pano.crop.reset();
}
stitcher_pipeline_.RunStitching(*stitcher_data_,
{.pano_id = selection_.target_id,
.full_res = extra.full_res,
.stitch_algorithm = options_.stitch});
auto& pano = stitcher_data_->panos[selection_.target_id];
thumbnail_pane_.Highlight(pano.ids);
if (extra.scroll_thumbnails) {
thumbnail_pane_.SetScrollX(pano.ids);
}
if (extra.reset_crop) {
pano.crop.reset();
}
break;
}
case ActionType::kModifyPano: {
Expand Down

0 comments on commit 065db29

Please sign in to comment.