MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
visualizer.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#include <stdexcept>
11
12#include "mve/image_tools.h"
13#include "mve/image_drawing.h"
14#include "sfm/visualizer.h"
15
17
18namespace
19{
20 unsigned char color_table[12][3] =
21 {
22 { 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 },
23 { 255, 255, 0 }, { 255, 0, 255 }, { 0, 255, 255 },
24 { 127, 255, 0 }, { 255, 127, 0 }, { 127, 0, 255 },
25 { 255, 0, 127 }, { 0, 127, 255 }, { 0, 255, 127 }
26 };
27
28 void
29 draw_box (mve::ByteImage& image, float x, float y,
30 float size, float orientation, uint8_t const* color)
31 {
32 float const sin_ori = std::sin(orientation);
33 float const cos_ori = std::cos(orientation);
34
35 float const x0 = (cos_ori * -size - sin_ori * -size);
36 float const y0 = (sin_ori * -size + cos_ori * -size);
37 float const x1 = (cos_ori * +size - sin_ori * -size);
38 float const y1 = (sin_ori * +size + cos_ori * -size);
39 float const x2 = (cos_ori * +size - sin_ori * +size);
40 float const y2 = (sin_ori * +size + cos_ori * +size);
41 float const x3 = (cos_ori * -size - sin_ori * +size);
42 float const y3 = (sin_ori * -size + cos_ori * +size);
43
44 mve::image::draw_line(image, static_cast<int>(x + x0 + 0.5f),
45 static_cast<int>(y + y0 + 0.5f), static_cast<int>(x + x1 + 0.5f),
46 static_cast<int>(y + y1 + 0.5f), color);
47 mve::image::draw_line(image, static_cast<int>(x + x1 + 0.5f),
48 static_cast<int>(y + y1 + 0.5f), static_cast<int>(x + x2 + 0.5f),
49 static_cast<int>(y + y2 + 0.5f), color);
50 mve::image::draw_line(image, static_cast<int>(x + x2 + 0.5f),
51 static_cast<int>(y + y2 + 0.5f), static_cast<int>(x + x3 + 0.5f),
52 static_cast<int>(y + y3 + 0.5f), color);
53 mve::image::draw_line(image, static_cast<int>(x + x3 + 0.5f),
54 static_cast<int>(y + y3 + 0.5f), static_cast<int>(x + x0 + 0.5f),
55 static_cast<int>(y + y0 + 0.5f), color);
56 }
57
58} // namespace
59
60/* ---------------------------------------------------------------- */
61
62void
63Visualizer::draw_keypoint (mve::ByteImage& image,
65 uint8_t const* color)
66{
67 int const x = static_cast<int>(keypoint.x + 0.5);
68 int const y = static_cast<int>(keypoint.y + 0.5);
69 int const width = image.width();
70 int const height = image.height();
71 int const channels = image.channels();
72
73 if (x < 0 || x >= width || y < 0 || y >= height)
74 return;
75
76 int required_space = 0;
77 bool draw_orientation = false;
78 switch (style)
79 {
80 default:
81 case SMALL_DOT_STATIC:
82 required_space = 0;
83 draw_orientation = false;
84 break;
85 case SMALL_CIRCLE_STATIC:
86 required_space = 3;
87 draw_orientation = false;
88 break;
89 case RADIUS_BOX_ORIENTATION:
90 required_space = static_cast<int>(std::sqrt
91 (2.0f * keypoint.radius * keypoint.radius)) + 1;
92 draw_orientation = true;
93 break;
94 case RADIUS_CIRCLE_ORIENTATION:
95 required_space = static_cast<int>(keypoint.radius);
96 draw_orientation = true;
97 break;
98 }
99
100 if (x < required_space || x >= width - required_space
101 || y < required_space || y >= height - required_space)
102 {
103 style = SMALL_DOT_STATIC;
104 required_space = 0;
105 draw_orientation = false;
106 }
107
108 switch (style)
109 {
110 default:
111 case SMALL_DOT_STATIC:
112 std::copy(color, color + channels, &image.at(x, y, 0));
113 break;
114 case SMALL_CIRCLE_STATIC:
115 mve::image::draw_circle(image, x, y, 3, color);
116 break;
117 case RADIUS_BOX_ORIENTATION:
118 draw_box(image, keypoint.x, keypoint.y,
119 keypoint.radius, keypoint.orientation, color);
120 break;
121 case RADIUS_CIRCLE_ORIENTATION:
122 mve::image::draw_circle(image, x, y, required_space, color);
123 break;
124 }
125
126 if (draw_orientation)
127 {
128 float const sin_ori = std::sin(keypoint.orientation);
129 float const cos_ori = std::cos(keypoint.orientation);
130 float const x1 = (cos_ori * keypoint.radius);
131 float const y1 = (sin_ori * keypoint.radius);
132 mve::image::draw_line(image, static_cast<int>(keypoint.x + 0.5f),
133 static_cast<int>(keypoint.y + 0.5f),
134 static_cast<int>(keypoint.x + x1 + 0.5f),
135 static_cast<int>(keypoint.y + y1 + 0.5f), color);
136 }
137}
138
139/* ---------------------------------------------------------------- */
140
142Visualizer::draw_keypoints(mve::ByteImage::ConstPtr image,
143 std::vector<Visualizer::Keypoint> const& matches,
145{
147 if (image->channels() == 3)
148 {
149 ret = mve::image::desaturate<unsigned char>(image, mve::image::DESATURATE_AVERAGE);
150 ret = mve::image::expand_grayscale<unsigned char>(ret);
151 }
152 else if (image->channels() == 1)
153 {
154 ret = mve::image::expand_grayscale<unsigned char>(image);
155 }
156
157 uint8_t* color = color_table[3];
158 for (std::size_t i = 0; i < matches.size(); ++i)
159 {
160 Visualizer::draw_keypoint(*ret, matches[i], style, color);
161 }
162
163 return ret;
164}
165
166/* ---------------------------------------------------------------- */
167
169Visualizer::draw_matches (mve::ByteImage::ConstPtr image1,
171 Correspondences2D2D const& matches)
172{
173 if (image1->channels() != 3 || image2->channels() != 3)
174 throw std::invalid_argument("Only 3-channel images allowed");
175
176 int const img1_width = image1->width();
177 int const img1_height = image1->height();
178 int const img2_width = image2->width();
179 int const img2_height = image2->height();
180 int const out_width = img1_width + img2_width;
181 int const out_height = std::max(img1_height, img2_height);
182
183 mve::ByteImage::Ptr ret = mve::ByteImage::create(out_width, out_height, 3);
184 ret->fill(0);
185
186 /* Copy images into output image. */
187 unsigned char* out_ptr = ret->begin();
188 unsigned char const* img1_ptr = image1->begin();
189 unsigned char const* img2_ptr = image2->begin();
190 for (int y = 0; y < out_height; ++y)
191 {
192 if (y < img1_height)
193 {
194 std::copy(img1_ptr, img1_ptr + img1_width * 3, out_ptr);
195 img1_ptr += img1_width * 3;
196 }
197 out_ptr += img1_width * 3;
198 if (y < img2_height)
199 {
200 std::copy(img2_ptr, img2_ptr + img2_width * 3, out_ptr);
201 img2_ptr += img2_width * 3;
202 }
203 out_ptr += img2_width * 3;
204 }
205
206 /* Draw matches. */
207 for (std::size_t i = 0; i < matches.size(); ++i)
208 {
209 mve::image::draw_line(*ret, matches[i].p1[0], matches[i].p1[1],
210 matches[i].p2[0] + img1_width, matches[i].p2[1],
211 color_table[i % 12]);
212 }
213
214 return ret;
215}
216
int64_t height(void) const
Returns the height of the image.
Definition image_base.h:207
int64_t channels(void) const
Returns the amount of channels in the image.
Definition image_base.h:213
int64_t width(void) const
Returns the width of the image.
Definition image_base.h:201
Multi-channel image class of arbitrary but homogenous data type.
Definition image.h:40
std::shared_ptr< Image< T > > Ptr
Definition image.h:42
std::shared_ptr< Image< T > const > ConstPtr
Definition image.h:43
T const & at(int64_t index) const
Linear indexing of image data.
Definition image.h:307
static Ptr create(void)
Smart pointer image constructor.
Definition image.h:191
void draw_line(Image< T > &image, int64_t x1, int64_t y1, int64_t x2, int64_t y2, T const *color)
Draws a line from (x0,y0) to (x1,y1) with given color on the image.
void draw_circle(Image< T > &image, int64_t x, int64_t y, int64_t radius, T const *color)
Draws a circle with midpoint (x,y) and given 'radius' on the image.
@ DESATURATE_AVERAGE
(R + G + B) * 1/3
std::vector< Correspondence2D2D > Correspondences2D2D
#define SFM_NAMESPACE_END
Definition defines.h:14
#define SFM_NAMESPACE_BEGIN
Definition defines.h:13