cgv
Loading...
Searching...
No Matches
image_proc.h
1#pragma once
2
3#ifdef SHOW_WAVELET_STATS
4#include <cgv/utils/statistics.h>
5#endif
6#include <cgv/math/permute.h>
7namespace cgv {
8 namespace media {
9 namespace image {
10
11template <typename T_calc, typename T_detail, typename T_store>
12void integer_wavelet_transform(T_store* data, size_t nr_inside, size_t nr_outside, size_t step_inside, size_t step_outside, size_t nr_components, unsigned mask, bool do_split = true, int s_scale = 1, int d_scale = 2)
13{
14#ifdef SHOW_WAVELET_STATS
15 cgv::utils::statistics s_stats, d_stats;
16#endif
17 // perform wavelet transform in x-direction
18 size_t c, x, y;
19 for (y = 0; y < nr_outside; ++y) {
20 T_store* s0_ptr = data + y * step_outside;
21 T_store* d1_ptr = s0_ptr + step_inside;
22 T_store* s0n_ptr = d1_ptr + step_inside;
23
24 T_calc s0n;
25 T_calc d1p;
26 for (c = 0; c < nr_components; ++c) {
27 s0n[c] = (*s0_ptr)[c] / s_scale;
28 d1p[c] = 0;
29 }
30 for (x = 0; x < nr_inside; x += 2) {
31 // if not right boundary reached, step on with second source color
32 if (x + 2 < nr_inside) {
33 for (c = 0; c < nr_components; ++c)
34 s0n[c] = (*s0n_ptr)[c] / s_scale;
35 }
36 // predict and compute detail coefficient
37 T_calc d1, s0;
38 for (c = 0; c < nr_components; ++c) {
39 d1[c] = (*d1_ptr)[c] / s_scale;
40 s0[c] = (*s0_ptr)[c] / s_scale;
41 d1[c] -= (s0[c] + s0n[c] + 1) / 2;
42#ifdef SHOW_WAVELET_STATS
43 d_stats.update(d1[c]);
44#endif
45 (*reinterpret_cast<T_detail*>(d1_ptr))[c] = d1[c] / d_scale;
46 }
47
48 // update source term and previous detail coefficient
49 for (c = 0; c < nr_components; ++c) {
50 s0[c] += (d1p[c] + d1[c] + 2) / 4;
51#ifdef SHOW_WAVELET_STATS
52 s_stats.update(s0[c]);
53#endif
54 (*reinterpret_cast<T_detail*>(s0_ptr))[c] = s0[c];
55 d1p[c] = d1[c];
56 }
57 // step on pointers
58 s0_ptr += 2 * step_inside;
59 d1_ptr += 2 * step_inside;
60 s0n_ptr += 2 * step_inside;
61 }
62 }
63#ifdef SHOW_WAVELET_STATS
64 std::cout << "s_stats=" << s_stats << std::endl;
65 std::cout << "d_stats=" << d_stats << std::endl;
66#endif
67 if (do_split) {
68 // compute permutation
69 std::vector<int> P;
70 P.resize(nr_inside);
71 for (x = 0; x < nr_inside; ++x)
72 P[x] = ((x & 1) == 0) ? x / 2 : (x / 2 + (nr_inside+1) / 2);
73 cgv::math::permute_arrays(data, &P.front(), nr_inside, nr_outside, step_inside, step_outside);
74 }
75}
76
77template <typename T_calc, typename T_detail, typename T_store>
78void integer_inverse_wavelet_transform(T_store* data, size_t nr_inside, size_t nr_outside, size_t step_inside, size_t step_outside, size_t nr_components, unsigned mask, bool do_split = true, int s_scale = 1, int d_scale = 2)
79{
80 size_t c, x, y;
81 if (do_split) {
82 // compute permutation
83 std::vector<int> P;
84 P.resize(nr_inside);
85 for (x = 0; x < nr_inside; ++x)
86 P[x] = (x < nr_inside / 2) ? 2*x : 2*(x-nr_inside / 2)+1;
87
88 cgv::math::permute_arrays(data, &P.front(), nr_inside, nr_outside, step_inside, step_outside);
89 }
90#ifdef SHOW_WAVELET_STATS
91 cgv::utils::statistics s_stats, d_stats;
92#endif
93
94 // perform inverse wavelet transform in x-direction
95 for (y = 0; y < nr_outside; ++y) {
96 T_detail* s0_ptr = reinterpret_cast<T_detail*>(data + y * step_outside);
97 T_detail* d1_ptr = s0_ptr + step_inside;
98 T_detail* d1p_ptr = 0;
99 T_detail* s0n_ptr = d1_ptr + step_inside;
100
101 T_calc s0p, s0;
102 T_calc d1p, d1;
103 for (c = 0; c < nr_components; ++c)
104 d1p[c] = 0;
105
106 for (x = 0; x < nr_inside; x += 2) {
107 // invert source term update
108 for (c = 0; c < nr_components; ++c) {
109 d1[c] = (*d1_ptr)[c] * d_scale;
110 s0[c] = (*s0_ptr)[c];
111 s0[c] -= (d1p[c] + d1[c] + 2) / 4;
112#ifdef SHOW_WAVELET_STATS
113 s_stats.update(s0[c]);
114#endif
115 (*reinterpret_cast<T_store*>(s0_ptr))[c] = s_scale * s0[c];
116 }
117 // invert previous predict step
118 if (x > 0) {
119 for (c = 0; c < nr_components; ++c) {
120 d1p[c] += (s0p[c] + s0[c] + 1) / 2;
121#ifdef SHOW_WAVELET_STATS
122 d_stats.update(d1p[c]);
123#endif
124 (*reinterpret_cast<T_store*>(d1p_ptr))[c] = s_scale * d1p[c];
125 }
126 }
127 for (c = 0; c < nr_components; ++c) {
128 d1p[c] = d1[c];
129 s0p[c] = s0[c];
130 }
131 d1p_ptr = d1_ptr;
132 // step on pointers
133 s0_ptr += 2 * step_inside;
134 d1_ptr += 2 * step_inside;
135 s0n_ptr += 2 * step_inside;
136 }
137 // invert last predict step
138 for (c = 0; c < nr_components; ++c) {
139 d1p[c] += (s0p[c] + s0[c] + 1) / 2;
140#ifdef SHOW_WAVELET_STATS
141 d_stats.update(d1p[c]);
142#endif
143 (*reinterpret_cast<T_store*>(d1p_ptr))[c] = d1p[c];
144 }
145 }
146#ifdef SHOW_WAVELET_STATS
147 std::cout << "inverse s_stats=" << s_stats << std::endl;
148 std::cout << "inverse d_stats=" << d_stats << std::endl;
149#endif
150}
151
152template <typename T_calc, typename T>
153void subsample_image(const T* image_ptr, T* subsampled_image, const int W, const int H, const int nr_components)
154{
155 int w = (W + 1) / 2;
156 int h = (H + 1) / 2;
157 for (int y = 0; y < h; ++y) {
158 bool condense_y = 2 * y + 1 == H;
159 for (int x = 0; x < w; ++x) {
160 T* target_ptr = subsampled_image + y*w + x;
161 const T* src0_ptr = image_ptr + 2 * (y*W + x);
162 const T* src1_ptr = src0_ptr + (condense_y ? 0 : W);
163 int dx = (2 * x + 1 == W ? 0 : 1);
164 for (int c = 0; c < nr_components; ++c)
165 (*target_ptr)[c] = (T_calc(src0_ptr[0][c]) + T_calc(src0_ptr[dx][c]) + T_calc(src1_ptr[0][c]) + T_calc(src1_ptr[dx][c])) / 4;
166 }
167 }
168}
169
170template <typename T_calc, typename T>
171void subsample_slice(const T* slice0_ptr, const T* slice1_ptr, T* subsampled_slice, const int W, const int H, const int nr_components)
172{
173 int w = (W + 1) / 2;
174 int h = (H + 1) / 2;
175 for (int y = 0; y < h; ++y) {
176 bool condense_y = 2 * y + 1 == H;
177 for (int x = 0; x < w; ++x) {
178 T* target_ptr = subsampled_slice + y*w + x;
179 const T* src00_ptr = slice0_ptr + 2 * (y*W + x);
180 const T* src01_ptr = src00_ptr + (condense_y ? 0 : W);
181 const T* src10_ptr = slice1_ptr + 2 * (y*W + x);
182 const T* src11_ptr = src10_ptr + (condense_y ? 0 : W);
183 int dx = (2 * x + 1 == W ? 0 : 1);
184 for (int c = 0; c < nr_components; ++c)
185 (*target_ptr)[c] = (
186 T_calc(src00_ptr[0][c]) + T_calc(src00_ptr[dx][c]) + T_calc(src01_ptr[0][c]) + T_calc(src01_ptr[dx][c]) +
187 T_calc(src10_ptr[0][c]) + T_calc(src10_ptr[dx][c]) + T_calc(src11_ptr[0][c]) + T_calc(src11_ptr[dx][c])
188 ) / 8;
189 }
190 }
191}
192 }
193 }
194}
incrementally accumulate statistical information
Definition statistics.h:13
void update(const double &v)
consider another value
the cgv namespace
Definition print.h:11