1/*M///////////////////////////////////////////////////////////////////////////////////////
2//
3//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4//
5//  By downloading, copying, installing or using the software you agree to this license.
6//  If you do not agree to this license, do not download, install,
7//  copy or use the software.
8//
9//
10//                        Intel License Agreement
11//                For Open Source Computer Vision Library
12//
13// Copyright (C) 2000, Intel Corporation, all rights reserved.
14// Third party copyrights are property of their respective owners.
15//
16// Redistribution and use in source and binary forms, with or without modification,
17// are permitted provided that the following conditions are met:
18//
19//   * Redistribution's of source code must retain the above copyright notice,
20//     this list of conditions and the following disclaimer.
21//
22//   * Redistribution's in binary form must reproduce the above copyright notice,
23//     this list of conditions and the following disclaimer in the documentation
24//     and/or other materials provided with the distribution.
25//
26//   * The name of Intel Corporation may not be used to endorse or promote products
27//     derived from this software without specific prior written permission.
28//
29// This software is provided by the copyright holders and contributors "as is" and
30// any express or implied warranties, including, but not limited to, the implied
31// warranties of merchantability and fitness for a particular purpose are disclaimed.
32// In no event shall the Intel Corporation or contributors be liable for any direct,
33// indirect, incidental, special, exemplary, or consequential damages
34// (including, but not limited to, procurement of substitute goods or services;
35// loss of use, data, or profits; or business interruption) however caused
36// and on any theory of liability, whether in contract, strict liability,
37// or tort (including negligence or otherwise) arising in any way out of
38// the use of this software, even if advised of the possibility of such damage.
39//
40//M*/
41
42#include "precomp.hpp"
43
44namespace cv
45{
46
47/*!  */
48class NormHistogramCostExtractorImpl : public NormHistogramCostExtractor
49{
50public:
51    /* Constructors */
52    NormHistogramCostExtractorImpl(int _flag, int _nDummies, float _defaultCost)
53    {
54        flag=_flag;
55        nDummies=_nDummies;
56        defaultCost=_defaultCost;
57        name_ = "HistogramCostExtractor.NOR";
58    }
59
60    /* Destructor */
61    ~NormHistogramCostExtractorImpl()
62    {
63    }
64
65    //! the main operator
66    virtual void buildCostMatrix(InputArray descriptors1, InputArray descriptors2, OutputArray costMatrix);
67
68    //! Setters/Getters
69    void setNDummies(int _nDummies)
70    {
71        nDummies=_nDummies;
72    }
73
74    int getNDummies() const
75    {
76        return nDummies;
77    }
78
79    void setDefaultCost(float _defaultCost)
80    {
81        defaultCost=_defaultCost;
82    }
83
84    float getDefaultCost() const
85    {
86        return defaultCost;
87    }
88
89    virtual void setNormFlag(int _flag)
90    {
91        flag=_flag;
92    }
93
94    virtual int getNormFlag() const
95    {
96        return flag;
97    }
98
99    //! write/read
100    virtual void write(FileStorage& fs) const
101    {
102        fs << "name" << name_
103           << "flag" << flag
104           << "dummies" << nDummies
105           << "default" << defaultCost;
106    }
107
108    virtual void read(const FileNode& fn)
109    {
110        CV_Assert( (String)fn["name"] == name_ );
111        flag = (int)fn["flag"];
112        nDummies = (int)fn["dummies"];
113        defaultCost = (float)fn["default"];
114    }
115
116private:
117    int flag;
118    int nDummies;
119    float defaultCost;
120
121protected:
122    String name_;
123};
124
125void NormHistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix)
126{
127    // size of the costMatrix with dummies //
128    Mat descriptors1=_descriptors1.getMat();
129    Mat descriptors2=_descriptors2.getMat();
130    int costrows = std::max(descriptors1.rows, descriptors2.rows)+nDummies;
131    _costMatrix.create(costrows, costrows, CV_32F);
132    Mat costMatrix=_costMatrix.getMat();
133
134
135    // Obtain copies of the descriptors //
136    cv::Mat scd1 = descriptors1.clone();
137    cv::Mat scd2 = descriptors2.clone();
138
139    // row normalization //
140    for(int i=0; i<scd1.rows; i++)
141    {
142        scd1.row(i)/=(sum(scd1.row(i))[0]+FLT_EPSILON);
143    }
144    for(int i=0; i<scd2.rows; i++)
145    {
146        scd2.row(i)/=(sum(scd2.row(i))[0]+FLT_EPSILON);
147    }
148
149    // Compute the Cost Matrix //
150    for(int i=0; i<costrows; i++)
151    {
152        for(int j=0; j<costrows; j++)
153        {
154            if (i<scd1.rows && j<scd2.rows)
155            {
156                Mat columnDiff = scd1.row(i)-scd2.row(j);
157                costMatrix.at<float>(i,j)=(float)norm(columnDiff, flag);
158            }
159            else
160            {
161                costMatrix.at<float>(i,j)=defaultCost;
162            }
163        }
164    }
165}
166
167Ptr <HistogramCostExtractor> createNormHistogramCostExtractor(int flag, int nDummies, float defaultCost)
168{
169    return Ptr <HistogramCostExtractor>( new NormHistogramCostExtractorImpl(flag, nDummies, defaultCost) );
170}
171
172/*!  */
173class EMDHistogramCostExtractorImpl : public EMDHistogramCostExtractor
174{
175public:
176    /* Constructors */
177    EMDHistogramCostExtractorImpl(int _flag, int _nDummies, float _defaultCost)
178    {
179        flag=_flag;
180        nDummies=_nDummies;
181        defaultCost=_defaultCost;
182        name_ = "HistogramCostExtractor.EMD";
183    }
184
185    /* Destructor */
186    ~EMDHistogramCostExtractorImpl()
187    {
188    }
189
190    //! the main operator
191    virtual void buildCostMatrix(InputArray descriptors1, InputArray descriptors2, OutputArray costMatrix);
192
193    //! Setters/Getters
194    void setNDummies(int _nDummies)
195    {
196        nDummies=_nDummies;
197    }
198
199    int getNDummies() const
200    {
201        return nDummies;
202    }
203
204    void setDefaultCost(float _defaultCost)
205    {
206        defaultCost=_defaultCost;
207    }
208
209    float getDefaultCost() const
210    {
211        return defaultCost;
212    }
213
214    virtual void setNormFlag(int _flag)
215    {
216        flag=_flag;
217    }
218
219    virtual int getNormFlag() const
220    {
221        return flag;
222    }
223
224    //! write/read
225    virtual void write(FileStorage& fs) const
226    {
227        fs << "name" << name_
228           << "flag" << flag
229           << "dummies" << nDummies
230           << "default" << defaultCost;
231    }
232
233    virtual void read(const FileNode& fn)
234    {
235        CV_Assert( (String)fn["name"] == name_ );
236        flag = (int)fn["flag"];
237        nDummies = (int)fn["dummies"];
238        defaultCost = (float)fn["default"];
239    }
240
241private:
242    int flag;
243    int nDummies;
244    float defaultCost;
245
246protected:
247    String name_;
248};
249
250void EMDHistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix)
251{
252    // size of the costMatrix with dummies //
253    Mat descriptors1=_descriptors1.getMat();
254    Mat descriptors2=_descriptors2.getMat();
255    int costrows = std::max(descriptors1.rows, descriptors2.rows)+nDummies;
256    _costMatrix.create(costrows, costrows, CV_32F);
257    Mat costMatrix=_costMatrix.getMat();
258
259    // Obtain copies of the descriptors //
260    cv::Mat scd1=descriptors1.clone();
261    cv::Mat scd2=descriptors2.clone();
262
263    // row normalization //
264    for(int i=0; i<scd1.rows; i++)
265    {
266        cv::Mat row = scd1.row(i);
267        scd1.row(i)/=(sum(row)[0]+FLT_EPSILON);
268    }
269    for(int i=0; i<scd2.rows; i++)
270    {
271        cv::Mat row = scd2.row(i);
272        scd2.row(i)/=(sum(row)[0]+FLT_EPSILON);
273    }
274
275    // Compute the Cost Matrix //
276    for(int i=0; i<costrows; i++)
277    {
278        for(int j=0; j<costrows; j++)
279        {
280            if (i<scd1.rows && j<scd2.rows)
281            {
282                cv::Mat sig1(scd1.cols,2,CV_32F), sig2(scd2.cols,2,CV_32F);
283                sig1.col(0)=scd1.row(i).t();
284                sig2.col(0)=scd2.row(j).t();
285                for (int k=0; k<sig1.rows; k++)
286                {
287                    sig1.at<float>(k,1)=float(k);
288                }
289                for (int k=0; k<sig2.rows; k++)
290                {
291                    sig2.at<float>(k,1)=float(k);
292                }
293
294                costMatrix.at<float>(i,j) = cv::EMD(sig1, sig2, flag);
295            }
296            else
297            {
298                costMatrix.at<float>(i,j) = defaultCost;
299            }
300        }
301    }
302}
303
304Ptr <HistogramCostExtractor> createEMDHistogramCostExtractor(int flag, int nDummies, float defaultCost)
305{
306    return Ptr <HistogramCostExtractor>( new EMDHistogramCostExtractorImpl(flag, nDummies, defaultCost) );
307}
308
309/*!  */
310class ChiHistogramCostExtractorImpl : public ChiHistogramCostExtractor
311{
312public:
313    /* Constructors */
314    ChiHistogramCostExtractorImpl(int _nDummies, float _defaultCost)
315    {
316        name_ = "HistogramCostExtractor.CHI";
317        nDummies=_nDummies;
318        defaultCost=_defaultCost;
319    }
320
321    /* Destructor */
322    ~ChiHistogramCostExtractorImpl()
323    {
324    }
325
326    //! the main operator
327    virtual void buildCostMatrix(InputArray descriptors1, InputArray descriptors2, OutputArray costMatrix);
328
329    //! setters / getters
330    void setNDummies(int _nDummies)
331    {
332        nDummies=_nDummies;
333    }
334
335    int getNDummies() const
336    {
337        return nDummies;
338    }
339
340    void setDefaultCost(float _defaultCost)
341    {
342        defaultCost=_defaultCost;
343    }
344
345    float getDefaultCost() const
346    {
347        return defaultCost;
348    }
349
350    //! write/read
351    virtual void write(FileStorage& fs) const
352    {
353        fs << "name" << name_
354           << "dummies" << nDummies
355           << "default" << defaultCost;
356    }
357
358    virtual void read(const FileNode& fn)
359    {
360        CV_Assert( (String)fn["name"] == name_ );
361        nDummies = (int)fn["dummies"];
362        defaultCost = (float)fn["default"];
363    }
364
365protected:
366    String name_;
367    int nDummies;
368    float defaultCost;
369};
370
371void ChiHistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix)
372{
373    // size of the costMatrix with dummies //
374    Mat descriptors1=_descriptors1.getMat();
375    Mat descriptors2=_descriptors2.getMat();
376    int costrows = std::max(descriptors1.rows, descriptors2.rows)+nDummies;
377    _costMatrix.create(costrows, costrows, CV_32FC1);
378    Mat costMatrix=_costMatrix.getMat();
379
380    // Obtain copies of the descriptors //
381    cv::Mat scd1=descriptors1.clone();
382    cv::Mat scd2=descriptors2.clone();
383
384    // row normalization //
385    for(int i=0; i<scd1.rows; i++)
386    {
387        cv::Mat row = scd1.row(i);
388        scd1.row(i)/=(sum(row)[0]+FLT_EPSILON);
389    }
390    for(int i=0; i<scd2.rows; i++)
391    {
392       cv::Mat row = scd2.row(i);
393        scd2.row(i)/=(sum(row)[0]+FLT_EPSILON);
394    }
395
396    // Compute the Cost Matrix //
397    for(int i=0; i<costrows; i++)
398    {
399        for(int j=0; j<costrows; j++)
400        {
401            if (i<scd1.rows && j<scd2.rows)
402            {
403                float csum = 0;
404                for(int k=0; k<scd2.cols; k++)
405                {
406                    float resta=scd1.at<float>(i,k)-scd2.at<float>(j,k);
407                    float suma=scd1.at<float>(i,k)+scd2.at<float>(j,k);
408                    csum += resta*resta/(FLT_EPSILON+suma);
409                }
410                costMatrix.at<float>(i,j)=csum/2;
411            }
412            else
413            {
414                costMatrix.at<float>(i,j)=defaultCost;
415            }
416        }
417    }
418}
419
420Ptr <HistogramCostExtractor> createChiHistogramCostExtractor(int nDummies, float defaultCost)
421{
422    return Ptr <HistogramCostExtractor>( new ChiHistogramCostExtractorImpl(nDummies, defaultCost) );
423}
424
425/*!  */
426class EMDL1HistogramCostExtractorImpl : public EMDL1HistogramCostExtractor
427{
428public:
429    /* Constructors */
430    EMDL1HistogramCostExtractorImpl(int _nDummies, float _defaultCost)
431    {
432        name_ = "HistogramCostExtractor.CHI";
433        nDummies=_nDummies;
434        defaultCost=_defaultCost;
435    }
436
437    /* Destructor */
438    ~EMDL1HistogramCostExtractorImpl()
439    {
440    }
441
442    //! the main operator
443    virtual void buildCostMatrix(InputArray descriptors1, InputArray descriptors2, OutputArray costMatrix);
444
445    //! setters / getters
446    void setNDummies(int _nDummies)
447    {
448        nDummies=_nDummies;
449    }
450
451    int getNDummies() const
452    {
453        return nDummies;
454    }
455
456    void setDefaultCost(float _defaultCost)
457    {
458        defaultCost=_defaultCost;
459    }
460
461    float getDefaultCost() const
462    {
463        return defaultCost;
464    }
465
466    //! write/read
467    virtual void write(FileStorage& fs) const
468    {
469        fs << "name" << name_
470           << "dummies" << nDummies
471           << "default" << defaultCost;
472    }
473
474    virtual void read(const FileNode& fn)
475    {
476        CV_Assert( (String)fn["name"] == name_ );
477        nDummies = (int)fn["dummies"];
478        defaultCost = (float)fn["default"];
479    }
480
481protected:
482    String name_;
483    int nDummies;
484    float defaultCost;
485};
486
487void EMDL1HistogramCostExtractorImpl::buildCostMatrix(InputArray _descriptors1, InputArray _descriptors2, OutputArray _costMatrix)
488{
489    // size of the costMatrix with dummies //
490    Mat descriptors1=_descriptors1.getMat();
491    Mat descriptors2=_descriptors2.getMat();
492    int costrows = std::max(descriptors1.rows, descriptors2.rows)+nDummies;
493    _costMatrix.create(costrows, costrows, CV_32F);
494    Mat costMatrix=_costMatrix.getMat();
495
496    // Obtain copies of the descriptors //
497    cv::Mat scd1=descriptors1.clone();
498    cv::Mat scd2=descriptors2.clone();
499
500    // row normalization //
501    for(int i=0; i<scd1.rows; i++)
502    {
503        cv::Mat row = scd1.row(i);
504        scd1.row(i)/=(sum(row)[0]+FLT_EPSILON);
505    }
506    for(int i=0; i<scd2.rows; i++)
507    {
508        cv::Mat row = scd2.row(i);
509        scd2.row(i)/=(sum(row)[0]+FLT_EPSILON);
510    }
511
512    // Compute the Cost Matrix //
513    for(int i=0; i<costrows; i++)
514    {
515        for(int j=0; j<costrows; j++)
516        {
517            if (i<scd1.rows && j<scd2.rows)
518            {
519                cv::Mat sig1(scd1.cols,1,CV_32F), sig2(scd2.cols,1,CV_32F);
520                sig1.col(0)=scd1.row(i).t();
521                sig2.col(0)=scd2.row(j).t();
522                costMatrix.at<float>(i,j) = cv::EMDL1(sig1, sig2);
523            }
524            else
525            {
526                costMatrix.at<float>(i,j) = defaultCost;
527            }
528        }
529    }
530}
531
532Ptr <HistogramCostExtractor> createEMDL1HistogramCostExtractor(int nDummies, float defaultCost)
533{
534    return Ptr <HistogramCostExtractor>( new EMDL1HistogramCostExtractorImpl(nDummies, defaultCost) );
535}
536
537} // cv
538