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);
98 graphics_scene_.setSceneRect(pixmap.rect());
101 graphics_view_->fitInView(graphics_scene_.sceneRect(), Qt::KeepAspectRatio);
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,
156 const std::vector<char>& tri_mask) {
159 std::cerr <<
"ERROR: Cannot read image at path " <<
path <<
std::endl;
165 const size_t num_tri_keypoints =
166 std::count_if(tri_mask.begin(), tri_mask.end(),
167 [](
const bool tri) { return tri; });
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,
201 if (!bitmap1.
Read(path1,
true) || !bitmap2.
Read(path2,
true)) {
202 std::cerr <<
"ERROR: Cannot read images at paths " << path1 <<
" and "
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;
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(
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()));
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) {
std::shared_ptr< core::Tensor > image
QGraphicsPixmapItem * ImagePixmapItem() const
The Image class stores image with customizable width, height, num of channels and bytes per channel.
bool Read(const std::string &path, const bool as_rgb=true)
std::string ModelName() const
std::string ParamsToString() const
ImageViewerGraphicsScene()
QGraphicsPixmapItem * ImagePixmapItem() const
std::shared_ptr< std::string > image_path
void DeRegisterImage(const image_t image_id)
bool ExistsImage(const image_t image_id) 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.
QPixmap DrawMatches(const QPixmap &image1, const QPixmap &image2, const FeatureKeypoints &points1, const FeatureKeypoints &points2, const FeatureMatches &matches, const QColor &keypoints_color)
QImage BitmapToQImageRGB(const Bitmap &bitmap)
void DrawKeypoints(QPixmap *pixmap, const FeatureKeypoints &points, const QColor &color)
std::vector< FeatureKeypoint > FeatureKeypoints
std::vector< FeatureMatch > FeatureMatches
QPixmap ShowImagesSideBySide(const QPixmap &image1, const QPixmap &image2)
constexpr Rgb magenta(MAX, 0, MAX)
constexpr Rgb red(MAX, 0, 0)