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 <math.h>
35
36#include "drain/util/Fuzzy.h"
37
38#include "FastOpticalFlowOp.h" // OpticalFlowConfig, OpticalFlowCore1
39
40
41namespace drain
42{
43
44namespace image
45{
46
47
48
49
51
52public:
53
54 // Sources
55 static inline
56 size_t getDiffChannelCount(){return 5;};
57
58 ImageView GXX;
59 ImageView GXY;
60 ImageView GYY;
61
62 ImageView GXT;
63 ImageView GYT;
64
65
67
76 void setSrcFrames(const ImageTray<const Channel> & srcTray);
77
78
79protected:
80
82
83};
84
85
87
90template <class R = OpticalFlowCore2 >
91class SlidingOpticalFlow2 : public SlidingWindow<OpticalFlowConfig, R> {
92
93public:
94
95 SlidingOpticalFlow2(int width = 0, int height = 0) : SlidingWindow<OpticalFlowConfig, R>(width, height) {
96 address = 0;
97 w = u = v = nom = quality = 0.0;
98 }
99
101 address = 0;
102 w = u = v = nom = quality = 0.0;
103 }
104
105 virtual inline
107
108 // "Inherit" data types.
109 typedef OpticalFlowCore1::data_t data_t;
110 typedef OpticalFlowCore1::cumul_t cumul_t;
111
112 virtual
113 inline
114 void setImageLimits() const {
115 this->coordinateHandler.setPolicy(this->GXX.getCoordinatePolicy());
116 this->coordinateHandler.setLimits(this->GXX.getWidth(), this->GXX.getHeight());
117 }
118
119
120 virtual
122
123
124 virtual inline
126
127 Logger mout(getImgLog(), "SlidingOpticalFlow", __FUNCTION__);
128 mout.error("unimplemented" );
129 /*
130 if (! this->coordinateHandler.validate(p))
131 return;
132
133 address = this->GXX.address(p.x, p.y);
134
135 Gxx += this->GXX.template get<data_t>(this->address);
136 Gxy += this->GXY.template get<data_t>(this->address);
137 Gyy += this->GYY.template get<data_t>(this->address);
138 Gxt += this->GXT.template get<data_t>(this->address);
139 Gyt += this->GYT.template get<data_t>(this->address);
140
141 // Quality only
142 W += this->srcW.template get<data_t>(this->address);
143 */
144 }
145
146 virtual inline
148
149 Logger mout(getImgLog(), "SlidingOpticalFlow", __FUNCTION__);
150 mout.error("unimplemented" );
151
152 /*
153 if (! this->coordinateHandler.validate(p))
154 return;
155
156 address = this->GXX.address(p.x, p.y);
157
158 Gxx -= this->GXX.template get<data_t>(this->address);
159 Gxy -= this->GXY.template get<data_t>(this->address);
160 Gyy -= this->GYY.template get<data_t>(this->address);
161 Gxt -= this->GXT.template get<data_t>(this->address);
162 Gyt -= this->GYT.template get<data_t>(this->address);
163
164 // Quality only
165 W -= this->srcW.template get<data_t>(this->address);
166 */
167 }
168
169
170
172 /*
173 inline
174 data_t predictionError(double u, double v) const {
175 //return u*Dx.get<double>(address) + v*Dy.get<double>(address) - Dt.get<double>(address);
176 if (W > 0.0)
177 //return sqrt((Gtt - 2.0*(Gxt*u + Gyt*v) + Gxx*u*u + 2.0*Gxy*u*v + Gyy*v*v)/W);
178 return sqrt((Gtt + 2.0*(Gxy*u*v - Gxt*u - Gyt*v) + Gxx*u*u + Gyy*v*v)/W);
179 else
180 return 0;
181 };
182 */
183
184 virtual inline
185 void write(){
186
187
188 nom = this->nominator();
189
190 /*
191 if (this->debugDiag(4)){
192 // std::cerr << this->location << '\t' << this->nominator() << '\t' << this->uDenominator() << ',' << this->vDenominator() << '\n';
193 // this->uField.put(this->location, rand());
194
195 std::cerr << this->location << " \t"
196 << this->GXX.template get<double>(this->location) << '\t'
197 << '\n';
198 if (nom != 0.0){
199 u = this->uDenominator()/nom;
200 v = this->vDenominator()/nom;
201 std::cerr << " => " << u << ',' << v << '\n';
202 }
203 }
204 */
205
206 if (nom > 0.00000001){ // todo minQuality
207
208 u = this->uDenominator()/nom;
209 v = this->vDenominator()/nom;
210 this->uField.put(this->location, this->conf.invertU ? -u : u);
211 this->vField.put(this->location, this->conf.invertV ? -v : v);
212
213 static const drain::FuzzySigmoid<double> sigmoid(0.0, 127.0, 254.0);
214 quality = sqrt(nom/this->W);
215 this->dstWeight.put(this->location, sigmoid(quality));
216 }
217 else {
218 this->uField.put(this->location, 0);
219 this->vField.put(this->location, 0);
220 this->dstWeight.put(this->location, 0);
221 }
222
223 }
224
225protected:
226
227 virtual
228 void clear(){
229 this->clearStats();
230 //std::cerr << "SlidingOpticalFlow2::" << __FUNCTION__ << ": " << this->nominator() << ", " << this->uDenominator() << ", " << this->vDenominator() << std::endl;
231 }
232
233 // Used by addPixel, removePixel
234 mutable size_t address;
235 //mutable data_t dx, dy, dt, w; // inner-loop (instantaneous)
236 mutable data_t w; // inner-loop (instantaneous)
237
238 // Used by write
239 mutable data_t u, v;
240 mutable data_t nom;
241 mutable data_t quality;
242
243};
244
245template <class R>
247
248 Logger mout(getImgLog(), "SlidingOpticalFlow2", __FUNCTION__);
249
250 this->setImageLimits();
251 this->setLoopLimits();
252 this->location.setLocation(0,0);
253
254 mout.debug("window: " , *this );
255 mout.debug2();
256 mout << "GXX: " << this->GXX << '\n';
257 mout << "GXY: " << this->GXY << '\n';
258 mout << "GXX: " << this->GYY << '\n';
259 mout << "GXX: " << this->GXT << '\n';
260 mout << "GXX: " << this->GYT << '\n';
261 mout << "W: " << this->srcWeight << '\n';
262 mout << mout.endl;
263 //this->resetAtEdges = true;
264
265 /*
266 std::cout << "Annapa input\n";
267 drain::Point2D<int> p;
268 std::string s;
269 while (getline(std::cin, s)){
270 //while ((std::cin>>p.x) && (std::cin>>p.y)){
271 std::stringstream sstr(s);
272 sstr >> p.x >> p.y;
273 std::cout << p << "\t =>";
274 int result = this->coordinateHandler.validate(p);
275 std::cout << p << "\t (" << result << ")\n" ;
276 }
277 */
278
279}
280
281
282
283class SlidingOpticalFlowWeighted2 : public SlidingOpticalFlow2<OpticalFlowCore2> {
284
285public:
286
288 }
289
291
292
293 virtual inline
295
296 if (! this->coordinateHandler.validate(p))
297 return;
298
299 address = this->GXX.address(p.x, p.y);
300 /*
301 if (p.y > GXX.getHeight()){
302 std::cerr << " coord overflow at " << p << std::endl;
303 }
304 */
305 w = this->srcWeight.get<data_t>(address);
306
307 W += w;
308 // w already included in cumulants
309 Gxx += this->GXX.get<data_t>(address);
310 Gxy += this->GXY.get<data_t>(address);
311 Gyy += this->GYY.get<data_t>(address);
312 Gxt += this->GXT.get<data_t>(address);
313 Gyt += this->GYT.get<data_t>(address);
314
315 // Quality only
316 }
317
318 virtual inline
320
321 if (! this->coordinateHandler.validate(p))
322 return;
323
324 address = this->GXX.address(p.x, p.y);
325
326 // Quality
327 w = this->srcWeight.get<data_t>(address);
328
329 W -= w;
330 // w already included in cumulants
331 Gxx -= this->GXX.get<data_t>(address);
332 Gxy -= this->GXY.get<data_t>(address);
333 Gyy -= this->GYY.get<data_t>(address);
334 Gxt -= this->GXT.get<data_t>(address);
335 Gyt -= this->GYT.get<data_t>(address);
336
337
338 }
339
340
341};
342
343//--------------------------------------------------------------std::cout << locationHandled << '\n';----------------------------
344
345
348
369class FastOpticalFlow2Op : public SlidingWindowOp<SlidingOpticalFlowWeighted2> { // = window_t
370
371public:
372
373 typedef window_t::data_t data_t;
374
375 FastOpticalFlow2Op(int width=5, int height=5): //, double smoothing=0.01) : //, double gradPow=2.0) : //, double gradWidth = 16) :
376 SlidingWindowOp<SlidingOpticalFlowWeighted2>(__FUNCTION__, "Optical flow computed based on differential accumulation layers.")
377 {
378 //parameters.append(blender.getParameters(), false);
379 //blender.setParameter("mix", "b");
380 // New. Blender will be obsolete
381 parameters.link("resize", resize = 0, "0.0..1.0|pix");
382 parameters.link("threshold", threshold = NAN, "value");
383 parameters.link("spread", spread = 0, "0|1");
384 parameters.link("smooth", smoother = 0, "0|1");
385 setSize(width, height);
386 }
387
388 inline
390 //std::cerr << __FUNCTION__ << op.getParameters() << '\n';
391 parameters.copyStruct(op.getParameters(), op, *this);
392 }
393
394
396 virtual inline
397 //void makeCompatible(const ImageFrame & src, Image & dst) const {
398 void getDstConf(const ImageConf & src, ImageConf & dst) const {
399 //dst.initialize(typeid(OpticalFlowCore2::data_t), src.getWidth(), src.getHeight(), 2, 1);
400 dst.setType(typeid(OpticalFlowCore2::data_t));
401 dst.setArea(src.getGeometry());
402 dst.setChannelCount(2, 1);
403 };
404
405 virtual inline
406 size_t getDiffChannelCount() const {
407 return window_t::getDiffChannelCount();
408 }
409
410 virtual inline
411 void traverseChannels(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const {
412 this->traverseMultiChannel(src, dst);
413 }
414
416
419 virtual
420 void computeDifferentials(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const;
421
422
423
424 virtual
425 void preprocess(const Channel & srcImage, const Channel & srcWeight, Image & dstImage, Image & dstWeight) const;
426
428 inline
429 bool optPreprocess() const {
430 return optResize() || optThreshold() || optSmoother() || optSpread();
431 }
432
434 inline
435 bool optResize() const { return resize > 0.0; } ;
436
437protected:
438
439 // NEW
440 //std::vector<double> resize;
441 double resize;
442 double threshold;
443 bool spread;
444 bool smoother;
445
446
447
449 inline
450 bool optThreshold() const { return !std::isnan(threshold); };
451
452 inline
453 bool optSpread() const { return spread; };
454
455 inline
456 bool optSmoother() const { return smoother; };
457
458
459
460 inline
461 bool checkQuality(const Channel & alpha, std::size_t address, int DX, int DY) const {
462
463 if (alpha.get<data_t>(address) == 0.0)
464 return false;
465
466 if (alpha.get<data_t>(address + DX) == 0.0)
467 return false;
468
469 if (alpha.get<data_t>(address - DX) == 0.0)
470 return false;
471
472 if (alpha.get<data_t>(address + DY) == 0.0)
473 return false;
474
475 if (alpha.get<data_t>(address - DY) == 0.0)
476 return false;
477
478 return true;
479 }
480
481};
482
483}
484}
485
486#endif
487
488// Drain
A smooth step function, by default from -1.0 to +1.0.
Definition Fuzzy.h:571
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition Log.h:313
Logger & debug(const TT &... args)
Debug information.
Definition Log.h:667
Logger & error(const TT &... args)
Echoes.
Definition Log.h:417
Logger & debug2(const TT &... args)
Debug information.
Definition Log.h:677
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:415
void setLimits(int xMin, int yMin, int xUpperLimit, int yUpperLimit)
Sets minimum values and outer upper limits for x and y.
Definition CoordinateHandler.h:147
bool validate(Point2D< int > &p) const
Handles the coordinate, returning true if the position is reversible.
Definition CoordinateHandler.h:235
void setPolicy(const CoordinatePolicy &p)
Assigns internal function pointers.
Definition CoordinateHandler.h:172
void setType(const std::type_info &t)
Set storage type.
Definition ImageConf.h:121
Definition FastOpticalFlowOp2.h:369
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:188
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:398
bool optResize() const
Returns true, if resizing is requested.
Definition FastOpticalFlowOp2.h:435
bool optThreshold() const
Returns true, if threshold is requested as postprocessing.
Definition FastOpticalFlowOp2.h:450
bool optPreprocess() const
Returns true, if resizing, thresholding or smoothing is requested.
Definition FastOpticalFlowOp2.h:429
Struct for image (excluding data)
Definition ImageConf.h:333
Container applicable for Channels and Images, with alpha support.
Definition ImageTray.h:266
ImageFrame that also has channels.
Definition ImageView.h:52
Consider using SlidingStripeOpticalFlow instead.
Definition FastOpticalFlowOp.h:55
bool invertV
If true, negate Y so that it will increase towards top (North)
Definition FastOpticalFlowOp.h:68
bool invertU
If true, negate X so that it will increase towards left (West)
Definition FastOpticalFlowOp.h:65
Definition FastOpticalFlowOp2.h:50
void setSrcFrames(const ImageTray< const Channel > &srcTray)
Set inputs as channels.
Definition FastOpticalFlowOp2.cpp:52
Definition FastOpticalFlowOp.h:73
Currently not in use. See SlidingOpticalFlowWeighted2 below.
Definition FastOpticalFlowOp2.h:91
virtual void setImageLimits() const
Sets internal limits corresponding to image geometries. Typically using coordHandler.
Definition FastOpticalFlowOp2.h:114
virtual void write()
Returns the mean squared error of predicted.
Definition FastOpticalFlowOp2.h:185
virtual void initialize()
Sets class-specific initial values. Does not change general window state (e.g. location)....
Definition FastOpticalFlowOp2.h:246
virtual void removePixel(Point2D< int > &p)
Removes a pixel from window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:147
virtual void addPixel(Point2D< int > &p)
Adds a pixel to window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:125
virtual void clear()
Clears the applied statistics. Redefined in derived classes.
Definition FastOpticalFlowOp2.h:228
Definition FastOpticalFlowOp2.h:283
virtual void removePixel(Point2D< int > &p)
Removes a pixel from window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:319
virtual void addPixel(Point2D< int > &p)
Adds a pixel to window statistics. Unvalidated location.
Definition FastOpticalFlowOp2.h:294
Template for operators applying pipeline-like sliding window.
Definition SlidingWindowOp.h:57
Window implementation that uses incremental update of state.
Definition SlidingWindow.h:50
Point2D< int > location
Current location of this window.
Definition Window.h:521
Definition DataSelector.cpp:1277
Definition Point.h:48