virtual int same(const Mat & a, const Mat &b) const
    {
        Mat feat1, feat2;
        ext->extract(pre.process(a), feat1);
        //if (feat1.type() != CV_32F)
        //    feat1.convertTo(feat1,CV_32F);
        ext->extract(pre.process(b), feat2);
        //if (feat2.type() != CV_32F)
        //    feat2.convertTo(feat2,CV_32F);

        if (! fil.empty())
        {
            fil->filter(feat1,feat1);
            fil->filter(feat2,feat2);
        }

        if (!ver.empty())
            return ver->same(feat1,feat2);

        Mat_<float> r1,r2;
        cls->predict(feat1,r1);
        cls->predict(feat2,r2);
        //cerr << format("%4d %4d\t",int(r1(0)),int(r2(0)));
        return int(r1(0)) == int(r2(0));
    }
    Mat extract(const Mat & a) const
    {
        Mat feat1;
        ext->extract(pre.process(a), feat1);

        if (feat1.type() != CV_32F)
            feat1.convertTo(feat1,CV_32F);
        return feat1.reshape(1,1);
    }
 virtual int same(const Mat & a, const Mat &b) const
 {
     Mat feat1, feat2;
     ext->extract(pre.process(a), feat1);
     ext->extract(pre.process(b), feat2);
     if (! fil.empty())
     {
         fil->filter(feat1,feat1);
         fil->filter(feat2,feat2);
     }
     return cls->same(feat1,feat2);
 }
    virtual int addTraining(const Mat & img, int label) 
    {
        Mat feat1;
        ext->extract(pre.process(img), feat1);

        Mat fr = feat1.reshape(1,1);
        //if (fr.type() != CV_32F)
        //    fr.convertTo(fr,CV_32F);

        if (! fil.empty())
            fil->filter(fr,fr);

        //features.push_back(fr); // damn memory problems
        if ( features.empty() )
        {
            features = Mat(nimg, feat1.total(), feat1.type()); 
        }
        feat1.copyTo(features.row(labels.rows));
        labels.push_back(label);
        cerr << fr.cols << " i_" << labels.rows << "\r";
        return labels.rows;
    }