Loading...
Searching...
No Matches
FastOpticalFlowOp2.h
1/*
2
3MIT License
4
5Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26/*
27Part of Rack development has been done in the BALTRAD projects part-financed
28by the European Union (European Regional Development Fund and European
29Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30*/
31#ifndef SLIDINGWINDOWOPTICALFLOWOP2_H_
32#define SLIDINGWINDOWOPTICALFLOWOP2_H_
33
34#include <drain/image/ImageFile.h>
35#include <sstream>
36#include <math.h>
37
38#include "drain/util/Fuzzy.h"
39
40#include "FastOpticalFlowOp.h" // OpticalFlowConfig, OpticalFlowCore1
41
42
43namespace drain
44{
45
46namespace image
47{
48
49
50
51
53
54public:
55
56 // Sources
57 static inline
58 size_t getDiffChannelCount(){return 5;};
59
60 ImageView GXX;
61 ImageView GXY;
62 ImageView GYY;
63
64 ImageView GXT;
65 ImageView GYT;
66
67
69
78 void setSrcFrames(const ImageTray<const Channel> & srcTray);
79
80
81protected:
82
84
85};
86
87
89
92template <class R = OpticalFlowCore2 >
93class SlidingOpticalFlow2 : public SlidingWindow<OpticalFlowConfig, R> {
94
95public:
96
97 SlidingOpticalFlow2(int width = 0, int height = 0) : SlidingWindow<OpticalFlowConfig, R>(width, height) {
98 address = 0;
99 w = u = v = nom = quality = 0.0;
100 }
101
103 address = 0;
104 w = u = v = nom = quality = 0.0;
105 }
106
107 virtual inline
109
110 // "Inherit" data types.
111 typedef OpticalFlowCore1::data_t data_t;
112 typedef OpticalFlowCore1::cumul_t cumul_t;
113
114 virtual
115 inline
116 void setImageLimits() const {
117 this->coordinateHandler.setPolicy(this->GXX.getCoordinatePolicy());
118 this->coordinateHandler.setLimits(this->GXX.getWidth(), this->GXX.getHeight());
119 }
120
121
122 virtual
124
125
126 virtual inline
128
129 Logger mout(getImgLog(), "SlidingOpticalFlow", __FUNCTION__);
130 mout.error("unimplemented" );
131 /*
132 if (! this->coordinateHandler.validate(p))
133 return;
134
135 address = this->GXX.address(p.x, p.y);
136
137 Gxx += this->GXX.template get<data_t>(this->address);
138 Gxy += this->GXY.template get<data_t>(this->address);
139 Gyy += this->GYY.template get<data_t>(this->address);
140 Gxt += this->GXT.template get<data_t>(this->address);
141 Gyt += this->GYT.template get<data_t>(this->address);
142
143 // Quality only
144 W += this->srcW.template get<data_t>(this->address);
145 */
146 }
147
148 virtual inline
150
151 Logger mout(getImgLog(), "SlidingOpticalFlow", __FUNCTION__);
152 mout.error("unimplemented" );
153
154 /*
155 if (! this->coordinateHandler.validate(p))
156 return;
157
158 address = this->GXX.address(p.x, p.y);
159
160 Gxx -= this->GXX.template get<data_t>(this->address);
161 Gxy -= this->GXY.template get<data_t>(this->address);
162 Gyy -= this->GYY.template get<data_t>(this->address);
163 Gxt -= this->GXT.template get<data_t>(this->address);
164 Gyt -= this->GYT.template get<data_t>(this->address);
165
166 // Quality only
167 W -= this->srcW.template get<data_t>(this->address);
168 */
169 }
170
171
172
174 /*
175 inline
176 data_t predictionError(double u, double v) const {
177 //return u*Dx.get<double>(address) + v*Dy.get<double>(address) - Dt.get<double>(address);
178 if (W > 0.0)
179 //return sqrt((Gtt - 2.0*(Gxt*u + Gyt*v) + Gxx*u*u + 2.0*Gxy*u*v + Gyy*v*v)/W);
180 return sqrt((Gtt + 2.0*(Gxy*u*v - Gxt*u - Gyt*v) + Gxx*u*u + Gyy*v*v)/W);
181 else
182 return 0;
183 };
184 */
185
186 virtual inline
187 void write(){
188
189
190 nom = this->nominator();
191
192 /*
193 if (this->debugDiag(4)){
194 // std::cerr << this->location << '\t' << this->nominator() << '\t' << this->uDenominator() << ',' << this->vDenominator() << '\n';
195 // this->uField.put(this->location, rand());
196
197 std::cerr << this->location << " \t"
198 << this->GXX.template get<double>(this->location) << '\t'
199 << '\n';
200 if (nom != 0.0){
201 u = this->uDenominator()/nom;
202 v = this->vDenominator()/nom;
203 std::cerr << " => " << u << ',' << v << '\n';
204 }
205 }
206 */
207
208 if (nom > 0.00000001){ // todo minQuality
209
210 u = this->uDenominator()/nom;
211 v = this->vDenominator()/nom;
212 this->uField.put(this->location, this->conf.invertU ? -u : u);
213 this->vField.put(this->location, this->conf.invertV ? -v : v);
214
215 static const drain::FuzzySigmoid<double> sigmoid(0.0, 127.0, 254.0);
216 quality = sqrt(nom/this->W);
217 this->dstWeight.put(this->location, sigmoid(quality));
218 }
219 else {
220 this->uField.put(this->location, 0);
221 this->vField.put(this->location, 0);
222 this->dstWeight.put(this->location, 0);
223 }
224
225 }
226
227protected:
228
229 virtual
230 void clear(){
231 this->clearStats();
232 //std::cerr << "SlidingOpticalFlow2::" << __FUNCTION__ << ": " << this->nominator() << ", " << this->uDenominator() << ", " << this->vDenominator() << std::endl;
233 }
234
235 // Used by addPixel, removePixel
236 mutable size_t address;
237 //mutable data_t dx, dy, dt, w; // inner-loop (instantaneous)
238 mutable data_t w; // inner-loop (instantaneous)
239
240 // Used by write
241 mutable data_t u, v;
242 mutable data_t nom;
243 mutable data_t quality;
244
245};
246
247template <class R>
249
250 Logger mout(getImgLog(), "SlidingOpticalFlow2", __FUNCTION__);
251
252 this->setImageLimits();
253 this->setLoopLimits();
254 this->location.setLocation(0,0);
255
256 mout.debug("window: " , *this );
257 mout.debug2();
258 mout << "GXX: " << this->GXX << '\n';
259 mout << "GXY: " << this->GXY << '\n';
260 mout << "GXX: " << this->GYY << '\n';
261 mout << "GXX: " << this->GXT << '\n';
262 mout << "GXX: " << this->GYT << '\n';
263 mout << "W: " << this->srcWeight << '\n';
264 mout << mout.endl;
265 //this->resetAtEdges = true;
266
267 /*
268 std::cout << "Annapa input\n";
269 drain::Point2D<int> p;
270 std::string s;
271 while (getline(std::cin, s)){
272 //while ((std::cin>>p.x) && (std::cin>>p.y)){
273 std::stringstream sstr(s);
274 sstr >> p.x >> p.y;
275 std::cout << p << "\t =>";
276 int result = this->coordinateHandler.validate(p);
277 std::cout << p << "\t (" << result << ")\n" ;
278 }
279 */
280
281}
282
283
284
285class SlidingOpticalFlowWeighted2 : public SlidingOpticalFlow2<OpticalFlowCore2> {
286
287public:
288
290 }
291
293
294
295 virtual inline
297
298 if (! this->coordinateHandler.validate(p))
299 return;
300
301 address = this->GXX.address(p.x, p.y);
302 /*
303 if (p.y > GXX.getHeight()){
304 std::cerr << " coord overflow at " << p << std::endl;
305 }
306 */
307 w = this->srcWeight.get<data_t>(address);
308
309 W += w;
310 // w already included in cumulants
311 Gxx += this->GXX.get<data_t>(address);
312 Gxy += this->GXY.get<data_t>(address);
313 Gyy += this->GYY.get<data_t>(address);
314 Gxt += this->GXT.get<data_t>(address);
315 Gyt += this->GYT.get<data_t>(address);
316
317 // Quality only
318 }
319
320 virtual inline
322
323 if (! this->coordinateHandler.validate(p))
324 return;
325
326 address = this->GXX.address(p.x, p.y);
327
328 // Quality
329 w = this->srcWeight.get<data_t>(address);
330
331 W -= w;
332 // w already included in cumulants
333 Gxx -= this->GXX.get<data_t>(address);
334 Gxy -= this->GXY.get<data_t>(address);
335 Gyy -= this->GYY.get<data_t>(address);
336 Gxt -= this->GXT.get<data_t>(address);
337 Gyt -= this->GYT.get<data_t>(address);
338
339
340 }
341
342
343};
344
345//--------------------------------------------------------------std::cout << locationHandled << '\n';----------------------------
346
347
350
371class FastOpticalFlow2Op : public SlidingWindowOp<SlidingOpticalFlowWeighted2> { // = window_t
372
373public:
374
375 typedef window_t::data_t data_t;
376
377 FastOpticalFlow2Op(int width=5, int height=5): //, double smoothing=0.01) : //, double gradPow=2.0) : //, double gradWidth = 16) :
378 SlidingWindowOp<SlidingOpticalFlowWeighted2>(__FUNCTION__, "Optical flow computed based on differential accumulation layers.")
379 {
380 //parameters.append(blender.getParameters(), false);
381 //blender.setParameter("mix", "b");
382 // New. Blender will be obsolete
383 parameters.link("resize", resize = 0, "0.0..1.0|pix");
384 parameters.link("threshold", threshold = NAN, "value");
385 parameters.link("spread", spread = 0, "0|1");
386 parameters.link("smooth", smoother = 0, "0|1");
387 setSize(width, height);
388 }
389
390 inline
392 //std::cerr << __FUNCTION__ << op.getParameters() << '\n';
393 parameters.copyStruct(op.getParameters(), op, *this);
394 }
395
396
398 virtual inline
399 //void makeCompatible(const ImageFrame & src, Image & dst) const {
400 void getDstConf(const ImageConf & src, ImageConf & dst) const {
401 //dst.initialize(typeid(OpticalFlowCore2::data_t), src.getWidth(), src.getHeight(), 2, 1);
402 dst.setType(typeid(OpticalFlowCore2::data_t));
403 dst.setArea(src.getGeometry());
404 dst.setChannelCount(2, 1);
405 };
406
407 virtual inline
408 size_t getDiffChannelCount() const {
409 return window_t::getDiffChannelCount();
410 }
411
412 virtual inline
413 void traverseChannels(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const {
414 this->traverseMultiChannel(src, dst);
415 }
416
418
421 virtual
422 void computeDifferentials(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const;
423
424
425
426 virtual
427 void preprocess(const Channel & srcImage, const Channel & srcWeight, Image & dstImage, Image & dstWeight) const;
428
430 inline
431 bool optPreprocess() const {
432 return optResize() || optThreshold() || optSmoother() || optSpread();
433 }
434
436 inline
437 bool optResize() const { return resize > 0.0; } ;
438
439protected:
440
441 // NEW
442 //std::vector<double> resize;
443 double resize;
444 double threshold;
445 bool spread;
446 bool smoother;
447
448
449
451 inline
452 bool optThreshold() const { return !std::isnan(threshold); };
453
454 inline
455 bool optSpread() const { return spread; };
456
457 inline
458 bool optSmoother() const { return smoother; };
459
460
461
462 inline
463 bool checkQuality(const Channel & alpha, std::size_t address, int DX, int DY) const {
464
465 if (alpha.get<data_t>(address) == 0.0)
466 return false;
467
468 if (alpha.get<data_t>(address + DX) == 0.0)
469 return false;
470
471 if (alpha.get<data_t>(address - DX) == 0.0)
472 return false;
473
474 if (alpha.get<data_t>(address + DY) == 0.0)
475 return false;
476
477 if (alpha.get<data_t>(address - DY) == 0.0)
478 return false;
479
480 return true;
481 }
482
483};
484
485}
486}
487
488#endif
489
490// Drain
A smooth step function, by default from -1.0 to +1.0.
Definition Fuzzy.h:497
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:312
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:666
Logger & error(const TT &... args)
Echoes.
Definition Log.h:416
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:676
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition ReferenceMap.h:399
void setLimits(int xMin, int yMin, int xUpperLimit, int yUpperLimit)
Sets minimum values and outer upper limits for x and y.
Definition CoordinateHandler.h:150
bool validate(Point2D< int > &p) const
Handles the coordinate, returning true if the position is reversible.
Definition CoordinateHandler.h:238
void setPolicy(const CoordinatePolicy &p)
Assigns internal function pointers.
Definition CoordinateHandler.h:175
void setType(const std::type_info &t)
Set storage type.
Definition ImageConf.h:121
Definition FastOpticalFlowOp2.h:371
virtual void computeDifferentials(const ImageTray< const Channel > &src, ImageTray< Channel > &dst) const
Computes an image with channels Gxx, Gxy, Gyy, Gxt, Gyt and w (quality of gradients)....
Definition FastOpticalFlowOp2.cpp:189
virtual void getDstConf(const ImageConf &src, ImageConf &dst) const
Creates a double precision image of 2+1 channels for storing motion (uField,vField) and quality (q).
Definition FastOpticalFlowOp2.h:400
bool optResize() const
Returns true, if resizing is requested.
Definition FastOpticalFlowOp2.h:437
bool optThreshold() const
Returns true, if threshold is requested as postprocessing.
Definition FastOpticalFlowOp2.h:452
bool optPreprocess() const
Returns true, if resizing, thresholding or smoothing is requested.
Definition FastOpticalFlowOp2.h:431
Struct for image (excluding data)
Definition ImageConf.h:333
Container applicable for Channels and Images, with alpha support.
Definition ImageTray.h:267
ImageFrame that also has channels.
Definition ImageView.h:52
Consider using SlidingStripeOpticalFlow instead.
Definition FastOpticalFlowOp.h:57
bool invertV
If true, negate Y so that it will increase towards top (North)
Definition FastOpticalFlowOp.h:70
bool invertU
If true, negate X so that it will increase towards left (West)
Definition FastOpticalFlowOp.h:67
Definition FastOpticalFlowOp2.h:52
void setSrcFrames(const ImageTray< const Channel > &srcTray)
Set inputs as channels.
Definition FastOpticalFlowOp2.cpp:53
Definition FastOpticalFlowOp.h:75
Currently not in use. See SlidingOpticalFlowWeighted2 below.
Definition FastOpticalFlowOp2.h:93
virtual void setImageLimits() const
Sets internal limits corresponding to image geometries. Typically using coordHandler.
Definition FastOpticalFlowOp2.h:116
virtual void write()
Returns the mean squared error of predicted.
Definition FastOpticalFlowOp2.h:187
virtual void initialize()
Sets class-specific initial values. Does not change general window state (e.g. location)....
Definition FastOpticalFlowOp2.h:248
virtual void removePixel(Point2D< int > &p)
Removes a pixel from window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:149
virtual void addPixel(Point2D< int > &p)
Adds a pixel to window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:127
virtual void clear()
Clears the applied statistics. Redefined in derived classes.
Definition FastOpticalFlowOp2.h:230
Definition FastOpticalFlowOp2.h:285
virtual void removePixel(Point2D< int > &p)
Removes a pixel from window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:321
virtual void addPixel(Point2D< int > &p)
Adds a pixel to window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:296
Template for operators applying pipeline-like sliding window.
Definition SlidingWindowOp.h:59
Window implementation that uses incremental update of state.
Definition SlidingWindow.h:50
Point2D< int > location
Current location of this window.
Definition Window.h:523
Definition DataSelector.cpp:1277
Definition Point.h:48