1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31
32 #include "ui/qt_utils.h"
33
34 #include "base/camera_models.h"
35 #include "util/misc.h"
36
37 namespace colmap {
38
QMatrixToEigen(const QMatrix4x4 & matrix)39 Eigen::Matrix4f QMatrixToEigen(const QMatrix4x4& matrix) {
40 Eigen::Matrix4f eigen;
41 for (size_t r = 0; r < 4; ++r) {
42 for (size_t c = 0; c < 4; ++c) {
43 eigen(r, c) = matrix(r, c);
44 }
45 }
46 return eigen;
47 }
48
EigenToQMatrix(const Eigen::Matrix4f & matrix)49 QMatrix4x4 EigenToQMatrix(const Eigen::Matrix4f& matrix) {
50 QMatrix4x4 qt;
51 for (size_t r = 0; r < 4; ++r) {
52 for (size_t c = 0; c < 4; ++c) {
53 qt(r, c) = matrix(r, c);
54 }
55 }
56 return qt;
57 }
58
BitmapToQImageRGB(const Bitmap & bitmap)59 QImage BitmapToQImageRGB(const Bitmap& bitmap) {
60 QImage image(bitmap.Width(), bitmap.Height(), QImage::Format_RGB32);
61 for (int y = 0; y < image.height(); ++y) {
62 QRgb* image_line = (QRgb*)image.scanLine(y);
63 for (int x = 0; x < image.width(); ++x) {
64 BitmapColor<uint8_t> color;
65 if (bitmap.GetPixel(x, y, &color)) {
66 image_line[x] = qRgba(color.r, color.g, color.b, 255);
67 }
68 }
69 }
70 return image;
71 }
72
ShowImagesSideBySide(const QPixmap & image1,const QPixmap & image2)73 QPixmap ShowImagesSideBySide(const QPixmap& image1, const QPixmap& image2) {
74 QPixmap image = QPixmap(QSize(image1.width() + image2.width(),
75 std::max(image1.height(), image2.height())));
76
77 image.fill(Qt::black);
78
79 QPainter painter(&image);
80 painter.drawImage(0, 0, image1.toImage());
81 painter.drawImage(image1.width(), 0, image2.toImage());
82
83 return image;
84 }
85
DrawKeypoints(QPixmap * pixmap,const FeatureKeypoints & points,const QColor & color)86 void DrawKeypoints(QPixmap* pixmap, const FeatureKeypoints& points,
87 const QColor& color) {
88 if (pixmap->isNull()) {
89 return;
90 }
91
92 const int pen_width = std::max(pixmap->width(), pixmap->height()) / 2048 + 1;
93 const int radius = 3 * pen_width + (3 * pen_width) % 2;
94 const float radius2 = radius / 2.0f;
95
96 QPainter painter(pixmap);
97 painter.setRenderHint(QPainter::Antialiasing);
98
99 QPen pen;
100 pen.setWidth(pen_width);
101 pen.setColor(color);
102 painter.setPen(pen);
103
104 for (const auto& point : points) {
105 painter.drawEllipse(point.x - radius2, point.y - radius2, radius, radius);
106 }
107 }
108
DrawMatches(const QPixmap & image1,const QPixmap & image2,const FeatureKeypoints & points1,const FeatureKeypoints & points2,const FeatureMatches & matches,const QColor & keypoints_color)109 QPixmap DrawMatches(const QPixmap& image1, const QPixmap& image2,
110 const FeatureKeypoints& points1,
111 const FeatureKeypoints& points2,
112 const FeatureMatches& matches,
113 const QColor& keypoints_color) {
114 QPixmap image = ShowImagesSideBySide(image1, image2);
115
116 QPainter painter(&image);
117 painter.setRenderHint(QPainter::Antialiasing);
118
119 // Draw keypoints
120
121 const int pen_width = std::max(image.width(), image.height()) / 2048 + 1;
122 const int radius = 3 * pen_width + (3 * pen_width) % 2;
123 const float radius2 = radius / 2.0f;
124
125 QPen pen;
126 pen.setWidth(pen_width);
127 pen.setColor(keypoints_color);
128 painter.setPen(pen);
129
130 for (const auto& point : points1) {
131 painter.drawEllipse(point.x - radius2, point.y - radius2, radius, radius);
132 }
133 for (const auto& point : points2) {
134 painter.drawEllipse(image1.width() + point.x - radius2, point.y - radius2,
135 radius, radius);
136 }
137
138 // Draw matches
139
140 pen.setWidth(std::max(pen_width / 2, 1));
141
142 for (const auto& match : matches) {
143 const point2D_t idx1 = match.point2D_idx1;
144 const point2D_t idx2 = match.point2D_idx2;
145 pen.setColor(QColor(0, 255, 0));
146 painter.setPen(pen);
147 painter.drawLine(QPoint(points1[idx1].x, points1[idx1].y),
148 QPoint(image1.width() + points2[idx2].x, points2[idx2].y));
149 }
150
151 return image;
152 }
153
154 } // namespace colmap
155