001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.image.processing.face.detection.benchmarking;
031
032import java.util.ArrayList;
033import java.util.List;
034
035import org.openimaj.image.processing.face.detection.DetectedFace;
036import org.openimaj.image.processing.face.detection.benchmarking.Matcher.Match;
037
038public class Results {
039        // / number of annotated regions (TP+FN)
040        int N;
041
042        // / threshold used for computing this result
043        double scoreThreshold;
044
045        // / True positives -- continuous
046        double TPCont;
047
048        // / True positives -- discrete
049        double TPDisc;
050
051        // / False positives -- discrete
052        double FP;
053
054        // / Name of the image
055        String imName;
056
057        Results() {
058        }
059
060        Results(Results r) {
061                if (r != null) {
062                        N = r.N;
063                        TPCont = r.TPCont;
064                        TPDisc = r.TPDisc;
065                        FP = r.FP;
066                        scoreThreshold = r.scoreThreshold;
067                }
068        }
069
070        Results(Results r, int N2) {
071                if (r != null) {
072                        imName = r.imName;
073                        N = r.N + N2;
074                        TPCont = r.TPCont;
075                        TPDisc = r.TPDisc;
076                        FP = r.FP;
077                        scoreThreshold = r.scoreThreshold;
078                }
079        }
080
081        Results(Results r1, Results r2) {
082                N = 0;
083                TPDisc = 0;
084                TPCont = 0;
085                FP = 0;
086                scoreThreshold = Double.MAX_VALUE;
087
088                if (r1 != null) {
089                        imName = r1.imName;
090                        N += r1.N;
091                        TPCont += r1.TPCont;
092                        TPDisc += r1.TPDisc;
093                        FP += r1.FP;
094                        if (r1.scoreThreshold < scoreThreshold)
095                                scoreThreshold = r1.scoreThreshold;
096                }
097
098                if (r2 != null) {
099                        imName = r2.imName;
100                        N += r2.N;
101                        TPCont += r2.TPCont;
102                        TPDisc += r2.TPDisc;
103                        FP += r2.FP;
104                        if (r2.scoreThreshold < scoreThreshold)
105                                scoreThreshold = r2.scoreThreshold;
106                }
107        }
108
109        Results(String s, double scoreThresh, List<Match> mp, List<? extends DetectedFace> annot,
110                        List<? extends DetectedFace> det)
111        {
112                imName = s;
113                scoreThreshold = scoreThresh;
114
115                N = annot.size();
116
117                FP = det.size();
118
119                TPCont = 0;
120                TPDisc = 0;
121                if (mp != null)
122                        for (int i = 0; i < mp.size(); i++) {
123                                final double score = mp.get(i).score;
124                                TPCont += score;
125                                if (score > 0.5) {
126                                        TPDisc++;
127                                        FP--;
128                                }
129                        }
130
131        }
132
133        static List<Results> merge(List<Results> rv1, List<Results> rv2) {
134
135                final List<Results> mergeV = new ArrayList<Results>();
136                int n1 = 0;
137                if (rv1 != null)
138                        n1 = rv1.size();
139                int n2 = 0;
140                if (rv2 != null)
141                        n2 = rv2.size();
142
143                int nAnnot1 = 0, nAnnot2 = 0;
144
145                if (n1 > 0) {
146                        nAnnot1 = rv1.get(0).getN();
147                        if (n2 > 0)
148                                nAnnot2 = rv2.get(0).getN();
149
150                        int i1 = 0, i2 = 0;
151                        double score1, score2;
152
153                        Results r1 = null;
154                        Results r2 = null;
155
156                        while (i1 < n1) {
157                                r1 = rv1.get(i1);
158                                score1 = rv1.get(i1).scoreThreshold;
159                                if (i2 < n2) {
160                                        r2 = rv2.get(i2);
161                                        score2 = rv2.get(i2).scoreThreshold;
162                                        final Results newR = new Results(r1, r2);
163                                        mergeV.add(newR);
164                                        if (score1 < score2) {
165                                                i1++;
166                                        } else if (score1 == score2) {
167                                                i1++;
168                                                i2++;
169                                        } else {
170                                                i2++;
171                                        }
172                                } else {
173                                        while (i1 < n1) {
174                                                // add from rv1
175                                                r1 = rv1.get(i1);
176
177                                                final Results newR = new Results(r1, nAnnot2);
178                                                mergeV.add(newR);
179                                                i1++;
180                                        }
181                                }
182                        }
183
184                        while (i2 < n2) {
185                                // add from rv2
186                                r2 = rv2.get(i2);
187                                final Results newR = new Results(r2, nAnnot1);
188                                mergeV.add(newR);
189                                i2++;
190                        }
191                } else {
192                        if (n2 > 0) {
193                                for (int i = 0; i < n2; i++)
194                                        mergeV.add(new Results(rv2.get(i)));
195                        }
196                }
197                return mergeV;
198        }
199
200        @Override
201        public String toString() {
202                return imName + " Threshold = " + scoreThreshold + " N = " + N + " TP cont = " + TPCont + " TP disc = " + TPDisc
203                                + " FP = " + FP;
204        }
205
206        public static String getROCData(List<Results> rv) {
207                String osc = "";
208                String osd = "";
209
210                for (int i = 0; i < rv.size(); i++)
211                {
212                        final Results r = rv.get(i);
213                        if (r.N > 0)
214                        {
215                                osc += (r.TPCont / r.N) + " " + r.FP + "\n";
216                                osd += (r.TPDisc / r.N) + " " + r.FP + " " + r.scoreThreshold + "\n";
217                        }
218                        else
219                        {
220                                osc += "0 0" + "\n";
221                                osd += "0 0 " + r.scoreThreshold + "\n";
222                        }
223                }
224                return "DISCRETE:\n" + osd + "\nCONTINOUS:\n" + osc;
225        }
226
227        public int getN() {
228                return N;
229        }
230}