MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
image_pyramid.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Benjamin Richter, 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
11
12#include "mve/image_tools.h"
13#include <cassert>
14
16
17namespace
18{
19 int const MIN_IMAGE_DIM = 30;
20
21 ImagePyramid::Ptr
22 buildPyramid(mve::View::Ptr view, std::string embeddingName)
23 {
24 ImagePyramid::Ptr pyramid(new ImagePyramid());
25 ImagePyramid& levels = *pyramid;
26
27 mve::View::ImageProxy const* proxy = view->get_image_proxy(embeddingName);
28 mve::CameraInfo cam = view->get_camera();
29
30 assert(proxy != nullptr);
31
32 int curr_width = proxy->width;
33 int curr_height = proxy->height;
34
35 levels.push_back(ImagePyramidLevel(cam, curr_width, curr_height));
36
37 while (std::min(curr_width, curr_height) >= MIN_IMAGE_DIM)
38 {
39 if (curr_width % 2 == 1)
40 cam.ppoint[0] = cam.ppoint[0] * float(curr_width)
41 / float(curr_width + 1);
42 if (curr_height % 2 == 1)
43 cam.ppoint[1] = cam.ppoint[1] * float(curr_height)
44 / float(curr_height + 1);
45
46 curr_width = (curr_width + 1) / 2;
47 curr_height = (curr_height + 1) / 2;
48
49 levels.push_back(ImagePyramidLevel(cam, curr_width, curr_height));
50 }
51
52 return pyramid;
53 }
54
55 void
56 ensureImages(ImagePyramid& levels, mve::View::Ptr view,
57 std::string embeddingName, int minLevel)
58 {
59 if (levels[minLevel].image != nullptr)
60 return;
61
62 mve::ByteImage::Ptr img = view->get_byte_image(embeddingName);
63 int channels = img->channels();
64
65 /* Remove alpha channel. */
66 if (channels == 2 || channels == 4)
67 mve::image::reduce_alpha<uint8_t>(img);
68 /* Expand grayscale images to RGB. */
69 if (img->channels() == 1)
70 img = mve::image::expand_grayscale<uint8_t>(img);
71 /* Expect 3-channel images. */
72 if (img->channels() != 3)
73 throw std::invalid_argument("Image with invalid number of channels");
74
75 /* Create image pyramid. */
76 int curr_width = img->width();
77 int curr_height = img->height();
78 for (int i = 0; std::min(curr_width, curr_height) >= MIN_IMAGE_DIM; ++i)
79 {
80 if (levels[i].image != nullptr)
81 break;
82
83 if (i > 0)
84 {
85 img = mve::image::rescale_half_size_gaussian<uint8_t>(img, 1.f);
86 curr_width = img->width();
87 curr_height = img->height();
88 }
89
90 if (minLevel <= i)
91 levels[i].image = img;
92 }
93
94 view->cache_cleanup();
95 }
96}
97
98ImagePyramid::ConstPtr
99ImagePyramidCache::get(mve::Scene::Ptr scene, mve::View::Ptr view,
100 std::string embeddingName, int minLevel)
101{
102 std::lock_guard<std::mutex> lock(ImagePyramidCache::metadataMutex);
103
104 /* Initialize on first access. */
105 if (ImagePyramidCache::cachedScene == nullptr)
106 {
107 ImagePyramidCache::cachedScene = scene;
108 ImagePyramidCache::cachedEmbedding = embeddingName;
109 }
110
111 ImagePyramid::Ptr pyramid;
112
113 if (scene != ImagePyramidCache::cachedScene
114 || embeddingName != ImagePyramidCache::cachedEmbedding)
115 {
116 /* create own pyramid because shared pyramid is incompatible. */
117 pyramid = buildPyramid(view, embeddingName);
118 }
119 else
120 {
121 /* Either re-recreate or use cached entry. */
122 pyramid = ImagePyramidCache::entries[view->get_id()];
123 if (pyramid == nullptr)
124 {
125 pyramid = buildPyramid(view, embeddingName);
126 ImagePyramidCache::entries[view->get_id()] = pyramid;
127 }
128 }
129
130 ensureImages(*pyramid, view, embeddingName, minLevel);
131 return pyramid;
132}
133
134void
135ImagePyramidCache::cleanup()
136{
137 std::lock_guard<std::mutex> lock(ImagePyramidCache::metadataMutex);
138
139 if (ImagePyramidCache::cachedScene == nullptr)
140 return;
141
142 for (std::map<int, ImagePyramid::Ptr>::iterator it = ImagePyramidCache::entries.begin();
143 it != ImagePyramidCache::entries.end(); ++it)
144 {
145 if (it->second == nullptr)
146 continue;
147
148 if (it->second.use_count() == 1)
149 {
150 it->second.reset();
151 ImagePyramidCache::cachedScene->get_view_by_id(it->first)->cache_cleanup();
152 }
153 }
154}
155
156/* static fields of ImgPyramidCache: */
157std::mutex ImagePyramidCache::metadataMutex;
158mve::Scene::Ptr ImagePyramidCache::cachedScene;
159std::string ImagePyramidCache::cachedEmbedding = "";
160std::map<int, ImagePyramid::Ptr> ImagePyramidCache::entries;
161
std::shared_ptr< Image< T > > Ptr
Definition image.h:42
std::shared_ptr< Scene > Ptr
Definition scene.h:37
std::shared_ptr< View > Ptr
Definition view.h:68
std::shared_ptr< ImagePyramid > Ptr
#define MVS_NAMESPACE_BEGIN
Definition defines.h:18
#define MVS_NAMESPACE_END
Definition defines.h:19
Per-view camera information with various helper functions.
Definition camera.h:24
float ppoint[2]
Principal point in x- and y-direction.
Definition camera.h:158
Proxy for images.
Definition view.h:87