vspline 1.1.0
Generic C++11 Code for Uniform B-Splines
metafilter.cc
Go to the documentation of this file.
1/************************************************************************/
2/* */
3/* vspline - a set of generic tools for creation and evaluation */
4/* of uniform b-splines */
5/* */
6/* Copyright 2015 - 2023 by Kay F. Jahnke */
7/* */
8/* Permission is hereby granted, free of charge, to any person */
9/* obtaining a copy of this software and associated documentation */
10/* files (the "Software"), to deal in the Software without */
11/* restriction, including without limitation the rights to use, */
12/* copy, modify, merge, publish, distribute, sublicense, and/or */
13/* sell copies of the Software, and to permit persons to whom the */
14/* Software is furnished to do so, subject to the following */
15/* conditions: */
16/* */
17/* The above copyright notice and this permission notice shall be */
18/* included in all copies or substantial portions of the */
19/* Software. */
20/* */
21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
23/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
24/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
25/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
26/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
27/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
28/* OTHER DEALINGS IN THE SOFTWARE. */
29/* */
30/************************************************************************/
31
32/// \file metafilter.cc
33///
34/// \brief filter by weighted summation of spline values
35///
36/// convolution forms a weighted sum of a window of values from
37/// a raster. But some filters are easier to formulate by the formation
38/// of a weighted sum over a pattern of 'pickup' points which do not
39/// coincide with raster points. To realize such a filter, we first
40/// create an interpolator over the raster data which provides a
41/// contiguous signal. Then we can pick up values at arbitrary
42/// offsets (delta) and form a weighted sum from them. Obviously this
43/// is computationally intensive, as we need to evaluate the interpolator
44/// for every contributing pickup point, but the method is extremely
45/// flexible, and with fast, multithreaded, vectorized evaluation
46/// it's still very fast.
47///
48/// This file has a simple example implementing an x-shaped filter.
49///
50/// The filter mechanism introduced here provides a reasonably efficient
51/// way to code stuff like 'perceptrons' liberated from the corset of
52/// the grid of the incoming raster data. It allows arbitrary patterns,
53/// among them concentric polygons, cross shapes and many more, and
54/// when using b-splines as 'underlying' interpolators, it's also an
55/// option to not look at the spline itsef, but at it's derivative(s),
56/// which opens up yet more interesting detectors. And with the meta
57/// filter 'looking at' a continuous signal, we can pick up filtered
58/// values from every valid continuous coordinate, not just from a
59/// unit-spaced raster of discrete coordinates as we would when doing
60/// a convolution, so we can throw in decimation/upsampling, geometric
61/// transformations etc. pp.
62
63#include <iostream>
64
65#include <vspline/vspline.h>
66
67#include <vigra/stdimage.hxx>
68#include <vigra/imageinfo.hxx>
69#include <vigra/impex.hxx>
70
71// we silently assume we have a colour image
72typedef vigra::RGBValue < float , 0 , 1 , 2 > pixel_type;
73
74// coordinate_type has a 2D coordinate
75typedef vigra::TinyVector < float , 2 > coordinate_type ;
76
77// type of b-spline object
79
80// target_type is a 2D array of pixels
81typedef vigra::MultiArray < 2 , pixel_type > target_type ;
82
83// struct meta_filter holds two MultiArrayViews: the first one,
84// 'delta', holds a sequence of coordinate offsets. When the filter
85// is applied at a location (x,y), the interpolator is evaluated at
86// all points (x,y) + delta[i], and the resulting values are multipled
87// with corresponding weights from the second MultiArrayView 'weight'
88// and summed up to form the output of the filter.
89
91{
92 vigra::MultiArrayView < 1 , coordinate_type > delta ;
93 vigra::MultiArrayView < 1 , float > weight ;
94} ;
95
96// the filter is built by functor composition. 'inner_type' is the
97// type of the interpolator producing the pickup values.
98
99template < class inner_type >
101: public vspline::unary_functor < coordinate_type , pixel_type >
102{
103 // the filter holds these values:
104
105 const inner_type inner ;
107 const size_t sz ;
108
109 // which are initialized in it's constructor:
110
111 ev_meta ( const inner_type & _inner ,
112 const meta_filter & _mf )
113 : inner ( _inner ) ,
114 mf ( _mf ) ,
115 sz ( _mf.delta.size() )
116 {
117 // just to make sure
118 assert ( mf.delta.size() == mf.weight.size() ) ;
119 } ;
120
121 // since the code is the same for vectorized and unvectorized
122 // operation, we can write a template:
123
124 template < class IN , class OUT >
125 void eval ( const IN & c ,
126 OUT & result ) const
127 {
128 // clear 'result'
129 result = 0.0f ;
130
131 // iterate over the deltas/weights
132 for ( size_t i = 0 ; i < sz ; i++ )
133 {
134 OUT pickup ;
135 auto cc ( c ) ;
136
137 // apply the current delta to the coordinate
138
139 cc[0] += mf.delta[i][0] ;
140 cc[1] += mf.delta[i][1] ;
141
142 // evaluate the interpolator to yield the pickup value
143
144 inner.eval ( cc , pickup ) ;
145
146 // apply the current weight to the pickup value and sum up
147
148 result[0] += mf.weight [ i ] * pickup[0] ;
149 result[1] += mf.weight [ i ] * pickup[1] ;
150 result[2] += mf.weight [ i ] * pickup[2] ;
151 }
152 }
153
154} ;
155
156int main ( int argc , char * argv[] )
157{
158 if ( argc < 2 )
159 {
160 std::cerr << "pass a colour image file as argument" << std::endl ;
161 exit( -1 ) ;
162 }
163
164 // get the image file name
165
166 vigra::ImageImportInfo imageInfo ( argv[1] ) ;
167
168 // create cubic 2D b-spline object containing the image data
169
170 spline_type bspl ( imageInfo.shape() ) ;
171
172 // load the image data into the b-spline's core.
173
174 vigra::importImage ( imageInfo , bspl.core ) ;
175
176 // prefilter the b-spline
177
178 bspl.prefilter() ;
179
180 // create a 'safe' evaluator from the b-spline
181
182 auto ev = make_safe_evaluator ( bspl ) ;
183
184 // now we set up the meta filter. first the deltas:
185
186 coordinate_type delta[]
187 {
188 { -1.6f , -1.6f } ,
189 { 1.6f , -1.6f } ,
190 { -0.7f , -0.7f } ,
191 { 0.7f , -0.7f } ,
192 { 0.0f , 0.0f } ,
193 { 0.7f , -0.7f } ,
194 { 0.7f , 0.7f } ,
195 { 1.6f , -1.6f } ,
196 { 1.6f , 1.6f }
197 } ;
198
199 // then the weights
200
201 float weight[]
202 { .05f ,
203 .05f ,
204 .1f ,
205 .1f ,
206 .4f ,
207 .1f ,
208 .1f ,
209 .05f ,
210 .05f
211 } ;
212
213 // both are now packaged in the meta_filter struct
214
215 meta_filter mf ;
216
217 mf.delta = vigra::MultiArrayView < 1 , coordinate_type >
218 ( vigra::Shape1 ( 9 ) , delta ) ;
219
220 mf.weight = vigra::MultiArrayView < 1 , float >
221 ( vigra::Shape1 ( 9 ) , weight ) ;
222
223 // now we create the actual meta filter function from the
224 // interpolator and the filter data
225
227 ( ev , mf ) ;
228
229 // this is where the result should go:
230
231 target_type target ( imageInfo.shape() ) ;
232
233 // for the sake of this demonstration, we simply use vspline::transform
234 // with no source argument, which evaluates 'mev' for every coordinate
235 // in 'target', an 'index-based transform'.
236
237 vspline::transform ( mev , target ) ;
238
239 // store the result with vigra impex
240
241 vigra::ImageExportInfo eximageInfo ( "metafilter.tif" );
242
243 std::cout << "storing the target image as 'metafilter.tif'" << std::endl ;
244
245 vigra::exportImage ( target ,
246 eximageInfo
247 .setPixelType("UINT8") ) ;
248
249 exit ( 0 ) ;
250}
vigra::TinyVector< float, 2 > coordinate_type
Definition: ca_correct.cc:107
vigra::MultiArray< 2, pixel_type > target_type
Definition: ca_correct.cc:115
int main(int argc, char *argv[])
Definition: metafilter.cc:156
vigra::TinyVector< float, 2 > coordinate_type
Definition: metafilter.cc:75
vspline::bspline< pixel_type, 2 > spline_type
Definition: metafilter.cc:78
vigra::RGBValue< float, 0, 1, 2 > pixel_type
Definition: metafilter.cc:72
vigra::MultiArray< 2, pixel_type > target_type
Definition: metafilter.cc:81
void transform(const unary_functor_type &functor, const vigra::MultiArrayView< dimension, typename unary_functor_type::in_type > &input, vigra::MultiArrayView< dimension, typename unary_functor_type::out_type > &output, int njobs=vspline::default_njobs, vspline::atomic< bool > *p_cancel=0)
implementation of two-array transform using wielding::coupled_wield.
Definition: transform.h:211
vspline::grok_type< bspl_coordinate_type< spline_type, rc_type >, result_type, _vsize > make_safe_evaluator(const spline_type &bspl, vigra::TinyVector< int, spline_type::dimension > dspec=vigra::TinyVector< int, spline_type::dimension >(0), int shift=0)
make_safe_evaluator is a factory function, producing a functor which provides safe access to an evalu...
Definition: eval.h:2390
const inner_type inner
Definition: metafilter.cc:105
const size_t sz
Definition: metafilter.cc:107
void eval(const IN &c, OUT &result) const
Definition: metafilter.cc:125
ev_meta(const inner_type &_inner, const meta_filter &_mf)
Definition: metafilter.cc:111
const meta_filter mf
Definition: metafilter.cc:106
vigra::MultiArrayView< 1, float > weight
Definition: metafilter.cc:93
vigra::MultiArrayView< 1, coordinate_type > delta
Definition: metafilter.cc:92
class bspline now builds on class bspline_base, adding coefficient storage, while bspline_base provid...
Definition: bspline.h:499
view_type core
Definition: bspline.h:566
void prefilter(vspline::xlf_type boost=vspline::xlf_type(1), int njobs=vspline::default_njobs)
prefilter converts the knot point data in the 'core' area into b-spline coefficients....
Definition: bspline.h:815
class unary_functor provides a functor object which offers a system of types for concrete unary funct...
includes all headers from vspline (most of them indirectly)