12 #include "base/projection.h"
13 #include "base/reconstruction.h"
14 #include "ui/qt_utils.h"
15 #include "util/misc.h"
16 #include "util/option_manager.h"
22 const double ImageViewerWidget::kZoomFactor = 1.20;
25 setSceneRect(0, 0, 0, 0);
26 image_pixmap_item_ = addPixmap(QPixmap::fromImage(QImage()));
27 image_pixmap_item_->setZValue(-1);
31 return image_pixmap_item_;
35 setWindowFlags(
Qt::Window | Qt::WindowTitleHint |
36 Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint |
37 Qt::WindowCloseButtonHint);
39 resize(parent->width() - 20, parent->height() - 20);
42 font.setPointSize(10);
48 graphics_view_ =
new QGraphicsView();
49 graphics_view_->setSizePolicy(QSizePolicy::Expanding,
50 QSizePolicy::Expanding);
52 graphics_view_->setScene(&graphics_scene_);
53 graphics_view_->setAlignment(Qt::AlignLeft | Qt::AlignTop);
59 QPushButton* zoom_in_button =
new QPushButton(
"+",
this);
60 zoom_in_button->setFont(font);
61 zoom_in_button->setFixedWidth(50);
63 connect(zoom_in_button, &QPushButton::released,
this,
66 QPushButton* zoom_out_button =
new QPushButton(
"-",
this);
67 zoom_out_button->setFont(font);
68 zoom_out_button->setFixedWidth(50);
70 connect(zoom_out_button, &QPushButton::released,
this,
73 QPushButton* save_button =
new QPushButton(
"Save image",
this);
74 save_button->setFont(font);
76 connect(save_button, &QPushButton::released,
this,
83 QWidget::resizeEvent(
event);
85 graphics_view_->fitInView(graphics_scene_.sceneRect(), Qt::KeepAspectRatio);
93 ShowPixmap(QPixmap::fromImage(BitmapToQImageRGB(bitmap)));
98 graphics_scene_.setSceneRect(pixmap.rect());
101 graphics_view_->fitInView(graphics_scene_.sceneRect(), Qt::KeepAspectRatio);
108 if (!bitmap.Read(
path,
true)) {
109 std::cerr <<
"ERROR: Cannot read image at path " <<
path <<
std::endl;
116 graphics_view_->scale(kZoomFactor, kZoomFactor);
120 graphics_view_->scale(1.0 / kZoomFactor, 1.0 / kZoomFactor);
124 QString filter(
"PNG (*.png)");
125 const QString save_path =
126 QFileDialog::getSaveFileName(
127 this, tr(
"Select destination..."),
"",
128 "PNG (*.png);;JPEG (*.jpg);;BMP (*.bmp)", &filter)
133 if (save_path ==
"") {
141 QWidget* parent,
const std::string& switch_text)
144 switch_text_(switch_text) {
146 new QPushButton(tr((
"Hide " +
switch_text_).c_str()),
this);
154 const std::string&
path,
155 const FeatureKeypoints& keypoints,
156 const std::vector<char>& tri_mask) {
158 if (!bitmap.Read(
path,
true)) {
159 std::cerr <<
"ERROR: Cannot read image at path " <<
path <<
std::endl;
162 image1_ = QPixmap::fromImage(BitmapToQImageRGB(bitmap));
165 const size_t num_tri_keypoints =
166 std::count_if(tri_mask.begin(), tri_mask.end(),
167 [](
const bool tri) { return tri; });
169 FeatureKeypoints keypoints_tri(num_tri_keypoints);
170 FeatureKeypoints keypoints_not_tri(keypoints.size() - num_tri_keypoints);
172 size_t i_not_tri = 0;
173 for (
size_t i = 0; i < tri_mask.size(); ++i) {
175 keypoints_tri[i_tri] = keypoints[i];
178 keypoints_not_tri[i_not_tri] = keypoints[i];
194 const std::string& path1,
195 const std::string& path2,
196 const FeatureKeypoints& keypoints1,
197 const FeatureKeypoints& keypoints2,
198 const FeatureMatches& matches) {
201 if (!bitmap1.Read(path1,
true) || !bitmap2.Read(path2,
true)) {
202 std::cerr <<
"ERROR: Cannot read images at paths " << path1 <<
" and "
207 const auto image1 = QPixmap::fromImage(BitmapToQImageRGB(bitmap1));
208 const auto image2 = QPixmap::fromImage(BitmapToQImageRGB(bitmap2));
210 image1_ = ShowImagesSideBySide(image1, image2);
211 image2_ = DrawMatches(image1, image2, keypoints1, keypoints2, matches);
237 model_viewer_widget_(model_viewer_widget),
239 setWindowTitle(
"Image information");
241 table_widget_ =
new QTableWidget(
this);
242 table_widget_->setColumnCount(2);
243 table_widget_->setRowCount(11);
246 font.setPointSize(10);
247 table_widget_->setFont(font);
251 table_widget_->setEditTriggers(QAbstractItemView::NoEditTriggers);
252 table_widget_->setSelectionMode(QAbstractItemView::SingleSelection);
253 table_widget_->setShowGrid(
true);
255 table_widget_->horizontalHeader()->setStretchLastSection(
true);
256 table_widget_->horizontalHeader()->setVisible(
false);
257 table_widget_->verticalHeader()->setVisible(
false);
258 table_widget_->verticalHeader()->setDefaultSectionSize(18);
262 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"image_id"));
263 image_id_item_ =
new QTableWidgetItem();
264 table_widget_->setItem(table_row, 1, image_id_item_);
267 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"camera_id"));
268 camera_id_item_ =
new QTableWidgetItem();
269 table_widget_->setItem(table_row, 1, camera_id_item_);
272 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"camera_model"));
273 camera_model_item_ =
new QTableWidgetItem();
274 table_widget_->setItem(table_row, 1, camera_model_item_);
277 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"camera_params"));
278 camera_params_item_ =
new QTableWidgetItem();
279 table_widget_->setItem(table_row, 1, camera_params_item_);
282 table_widget_->setItem(table_row, 0,
283 new QTableWidgetItem(
"qw, qx, qy, qz"));
284 qvec_item_ =
new QTableWidgetItem();
285 table_widget_->setItem(table_row, 1, qvec_item_);
288 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"tx, ty, tz"));
289 tvec_item_ =
new QTableWidgetItem();
290 table_widget_->setItem(table_row, 1, tvec_item_);
293 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"dims"));
294 dimensions_item_ =
new QTableWidgetItem();
295 table_widget_->setItem(table_row, 1, dimensions_item_);
298 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"num_points2D"));
299 num_points2D_item_ =
new QTableWidgetItem();
300 num_points2D_item_->setForeground(
Qt::red);
301 table_widget_->setItem(table_row, 1, num_points2D_item_);
304 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"num_points3D"));
305 num_points3D_item_ =
new QTableWidgetItem();
307 table_widget_->setItem(table_row, 1, num_points3D_item_);
310 table_widget_->setItem(table_row, 0,
311 new QTableWidgetItem(
"num_observations"));
312 num_obs_item_ =
new QTableWidgetItem();
313 table_widget_->setItem(table_row, 1, num_obs_item_);
316 table_widget_->setItem(table_row, 0,
new QTableWidgetItem(
"name"));
317 name_item_ =
new QTableWidgetItem();
318 table_widget_->setItem(table_row, 1, name_item_);
323 delete_button_ =
new QPushButton(tr(
"Delete"),
this);
324 delete_button_->setFont(font);
326 connect(delete_button_, &QPushButton::released,
this,
327 &DatabaseImageViewerWidget::DeleteImage);
331 if (model_viewer_widget_->
images.count(image_id) == 0) {
335 image_id_ = image_id;
337 const Image&
image = model_viewer_widget_->
images.at(image_id);
338 const Camera& camera = model_viewer_widget_->
cameras.at(
image.CameraId());
340 image_id_item_->setText(QString::number(image_id));
341 camera_id_item_->setText(QString::number(
image.CameraId()));
342 camera_model_item_->setText(QString::fromStdString(camera.ModelName()));
343 camera_params_item_->setText(
344 QString::fromStdString(camera.ParamsToString()));
345 qvec_item_->setText(QString::number(
image.Qvec(0)) +
", " +
346 QString::number(
image.Qvec(1)) +
", " +
347 QString::number(
image.Qvec(2)) +
", " +
348 QString::number(
image.Qvec(3)));
349 tvec_item_->setText(QString::number(
image.Tvec(0)) +
", " +
350 QString::number(
image.Tvec(1)) +
", " +
351 QString::number(
image.Tvec(2)));
352 dimensions_item_->setText(QString::number(camera.Width()) +
"x" +
353 QString::number(camera.Height()));
354 num_points2D_item_->setText(QString::number(
image.NumPoints2D()));
356 std::vector<char> tri_mask(
image.NumPoints2D());
357 for (
size_t i = 0; i <
image.NumPoints2D(); ++i) {
358 tri_mask[i] =
image.Point2D(i).HasPoint3D();
361 num_points3D_item_->setText(QString::number(
image.NumPoints3D()));
362 num_obs_item_->setText(QString::number(
image.NumObservations()));
363 name_item_->setText(QString::fromStdString(
image.Name()));
367 FeatureKeypoints keypoints(
image.NumPoints2D());
368 for (point2D_t i = 0; i <
image.NumPoints2D(); ++i) {
369 keypoints[i].x =
static_cast<float>(
image.Point2D(i).X());
370 keypoints[i].y =
static_cast<float>(
image.Point2D(i).Y());
377 void DatabaseImageViewerWidget::ResizeTable() {
379 table_widget_->resizeColumnsToContents();
380 int height = table_widget_->horizontalHeader()->height() +
381 2 * table_widget_->frameWidth();
382 for (
int i = 0; i < table_widget_->rowCount(); i++) {
383 height += table_widget_->rowHeight(i);
385 table_widget_->setFixedHeight(
height);
388 void DatabaseImageViewerWidget::DeleteImage() {
389 QMessageBox::StandardButton reply = QMessageBox::question(
390 this,
"", tr(
"Do you really want to delete this image?"),
391 QMessageBox::Yes | QMessageBox::No);
392 if (reply == QMessageBox::Yes) {
393 if (model_viewer_widget_->
reconstruction->ExistsImage(image_id_)) {
std::shared_ptr< core::Tensor > image
ImageViewerGraphicsScene()
QGraphicsPixmapItem * ImagePixmapItem() const
QTextStream & endl(QTextStream &stream)
Tensor Minimum(const Tensor &input, const Tensor &other)
Computes the element-wise minimum of input and other. The tensors must have same data type and device...
static const std::string path
std::string JoinPaths(T const &...paths)
Generic file read and write utility for python interface.
colmap::OptionManager OptionManager
constexpr Rgb magenta(MAX, 0, MAX)
constexpr Rgb red(MAX, 0, 0)