Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

dziedziczenie w programie klasy z biblioteki

Ostatnio zmodyfikowano 2013-07-15 13:18
Autor Wiadomość
roserek
Temat założony przez niniejszego użytkownika
dziedziczenie w programie klasy z biblioteki
» 2013-07-13 12:26:59
Witam. Próbuję napisać program który będzie rozpoznawał twarze. Używam do tego biblioteki opencv i gotowej klasy z tej biblioteki fisherface. Ta klasa uczy się twarzy za pomocą metod train i save, zapisuje wektory zdjęć do pliku yml. W tym miejscy chciałbym wnieść poprawki w tej klasie aby te funkcje nie zapisywały wektorów do pliku ale bezpośrednio do bazy danych mysql. Zastanawiam się jak będzie lepiej to zrobić, czy zmienić funkcję w bibliotece ( ale tutaj jest problem ponieważ samo zmienianie kodu nie pomaga, trzeba chyba jeszcze przekompilować bibliotekę a nie wiem jak to zrobić ), innym pomysłem jest napisanie nowej klasy w moim programie która będzie dziedziczyć po klasie fisherface z biblioteki i nadpisać interesujące mnie funkcje. W tej chwili jestem bardziej przychylny tej drugiej opcji ale nie mogę sobie poradzić z dziedziczeniem, cały czas jak próbuję dziedziczyć pokazuje mi błąd: "not a class or struct name" , czyli nie widzi tej klasy. Dlatego moje pytanie czy ktoś wie jak odziedziczyć klasę z biblioteki , czy w ogóle jest to możliwe ??? Przekopałem już całe google i nic nie znalazłem konkretnego na ten temat.
P-87726
pekfos
» 2013-07-13 13:13:05
Po każdej klasie można dziedziczyć, ale czasem nie ma sensu tego robić.

cały czas jak próbuję dziedziczyć pokazuje mi błąd: "not a class or struct name" , czyli nie widzi tej klasy.
Błąd jest w twoim kodzie i/lub w OpenCV nie da się tego zrobić. Podaj kod..
P-87731
roserek
Temat założony przez niniejszego użytkownika
» 2013-07-13 13:33:21
Podejrzewam, że na pewno błąd jest w moim kodzie. Nigdy nie potrzebowałem takich zabiegów jak poprawki biblioteki... Mój kod nie jest rozbudowany, ponieważ cały czas się zastanawiam czemu nie mogę odziedziczyć. Ale ok kopiuję swój "kod" i najważniejsze fragmenty pliku *.cpp z biblioteki (które mnie interesują).

kod biblioteki:
C/C++
#include "precomp.hpp"
#include <set>

namespace cv
{
   
    using std::set;
   
    // Reads a sequence from a FileNode::SEQ with type _Tp into a result vector.
    template < typename _Tp >
    inline void readFileNodeList( const FileNode & fn, vector < _Tp >& result ) {
        if( fn.type() == FileNode::SEQ ) {
            for( FileNodeIterator it = fn.begin(); it != fn.end(); ) {
                _Tp item;
                it >> item;
                result.push_back( item );
            }
        }
    }
   
    // Writes the a list of given items to a cv::FileStorage.
    template < typename _Tp >
    inline void writeFileNodeList( FileStorage & fs, const string & name,
    const vector < _Tp >& items ) {
        // typedefs
        typedef typename vector < _Tp >::const_iterator constVecIterator;
        // write the elements in item to fs
        fs << name << "[";
        for( constVecIterator it = items.begin(); it != items.end(); ++it ) {
            fs << * it;
        }
        fs << "]";
    }
   
    static Mat asRowMatrix( InputArrayOfArrays src, int rtype, double alpha = 1, double beta = 0 ) {
        // make sure the input data is a vector of matrices or vector of vector
        if( src.kind() != _InputArray::STD_VECTOR_MAT && src.kind() != _InputArray::STD_VECTOR_VECTOR ) {
            string error_message = "The data is expected as InputArray::STD_VECTOR_MAT (a std::vector<Mat>) or _InputArray::STD_VECTOR_VECTOR (a std::vector< vector<...> >).";
            CV_Error( CV_StsBadArg, error_message );
        }
        // number of samples
        size_t n = src.total();
        // return empty matrix if no matrices given
        if( n == 0 )
             return Mat();
        // dimensionality of (reshaped) samples
        size_t d = src.getMat( 0 ).total();
        // create data matrix
        Mat data(( int ) n,( int ) d, rtype );
        // now copy data
        for( unsigned int i = 0; i < n; i++ ) {
            // make sure data can be reshaped, throw exception if not!
            if( src.getMat( i ).total() != d ) {
                string error_message = format( "Wrong number of elements in matrix #%d! Expected %d was %d.", i, d, src.getMat( i ).total() );
                CV_Error( CV_StsBadArg, error_message );
            }
            // get a hold of the current row
            Mat xi = data.row( i );
            // make reshape happy by cloning for non-continuous matrices
            if( src.getMat( i ).isContinuous() ) {
                src.getMat( i ).reshape( 1, 1 ).convertTo( xi, rtype, alpha, beta );
            } else {
                src.getMat( i ).clone().reshape( 1, 1 ).convertTo( xi, rtype, alpha, beta );
            }
        }
        return data;
    }
   
   
    // Removes duplicate elements in a given vector.
    template < typename _Tp >
    inline vector < _Tp > remove_dups( const vector < _Tp >& src ) {
        typedef typename set < _Tp >::const_iterator constSetIterator;
        typedef typename vector < _Tp >::const_iterator constVecIterator;
        set < _Tp > set_elems;
        for( constVecIterator it = src.begin(); it != src.end(); ++it )
             set_elems.insert( * it );
       
        vector < _Tp > elems;
        for( constSetIterator it = set_elems.begin(); it != set_elems.end(); ++it )
             elems.push_back( * it );
       
        return elems;
    }
   
   
    // Turk, M., and Pentland, A. "Eigenfaces for recognition.". Journal of
    // Cognitive Neuroscience 3 (1991), 71–86.
    class Eigenfaces
        : public FaceRecognizer
    {
    private:
        int _num_components;
        double _threshold;
        vector < Mat > _projections;
        Mat _labels;
        Mat _eigenvectors;
        Mat _eigenvalues;
        Mat _mean;
       
    public:
        using FaceRecognizer::save;
        using FaceRecognizer::load;
       
        // Initializes an empty Eigenfaces model.
        Eigenfaces( int num_components = 0, double threshold = DBL_MAX )
            : _num_components( num_components )
            , _threshold( threshold )
        { }
       
        // Initializes and computes an Eigenfaces model with images in src and
        // corresponding labels in labels. num_components will be kept for
        // classification.
        Eigenfaces( InputArrayOfArrays src, InputArray labels,
        int num_components = 0, double threshold = DBL_MAX )
            : _num_components( num_components )
            , _threshold( threshold )
        {
            train( src, labels );
        }
       
        // Computes an Eigenfaces model with images in src and corresponding labels
        // in labels.
        void train( InputArrayOfArrays src, InputArray labels );
       
        // Predicts the label of a query image in src.
        int predict( InputArray src ) const;
       
        // Predicts the label and confidence for a given sample.
        void predict( InputArray _src, int & label, double & dist ) const;
       
        // See FaceRecognizer::load.
        void load( const FileStorage & fs );
       
        // See FaceRecognizer::save.
        void save( FileStorage & fs ) const;
       
        AlgorithmInfo * info() const;
    };
   
   
    class Fisherfaces
        : public FaceRecognizer
    {
    private:
        int _num_components; //nr elementu
        double _threshold; //próg
        Mat _eigenvectors; //wektory własne
        Mat _eigenvalues; //wartości własne
        Mat _mean; //średnia
        vector < Mat > _projections; //odwzorowanie
        Mat _labels; //etykiety
       
    public:
        using FaceRecognizer::save;
        using FaceRecognizer::load;
       
        // Initializes an empty Fisherfaces model.
        myFisherfaces( int num_components = 0, double threshold = DBL_MAX )
            : _num_components( num_components )
            , _threshold( threshold )
        { }
       
        // Initializes and computes a Fisherfaces model with images in src and
        // corresponding labels in labels. num_components will be kept for
        // classification.
        myFisherfaces( InputArrayOfArrays src, InputArray labels,
        int num_components = 0, double threshold = DBL_MAX )
            : _num_components( num_components )
            , _threshold( threshold )
        {
            train( src, labels );
        }
       
        ~myFisherfaces() { }
       
        // Computes a Fisherfaces model with images in src and corresponding labels
        // in labels.
        void train( InputArrayOfArrays src, InputArray labels );
       
        // Predicts the label of a query image in src.
        int predict( InputArray src ) const;
       
        // Predicts the label and confidence for a given sample.
        void predict( InputArray _src, int & label, double & dist ) const;
       
        // See FaceRecognizer::load.
        void load( const FileStorage & fs );
       
        // See FaceRecognizer::save.
        void save( FileStorage & fs ) const;
       
        AlgorithmInfo * info() const;
    };
   
    //------------------------------------------------------------------------------
    // Fisherfaces
    //------------------------------------------------------------------------------
    void Fisherfaces::train( InputArrayOfArrays src, InputArray _lbls ) {
        if( src.total() == 0 ) {
            string error_message = format( "Empty training data was given. You'll need more than one sample to learn a model." );
            CV_Error( CV_StsBadArg, error_message );
        } else if( _lbls.getMat().type() != CV_32SC1 ) {
            string error_message = format( "Labels must be given as integer (CV_32SC1). Expected %d, but was %d.", CV_32SC1, _lbls.type() );
            CV_Error( CV_StsBadArg, error_message );
        }
        // make sure data has correct size
        if( src.total() > 1 ) {
            for( int i = 1; i < static_cast < int >( src.total() ); i++ ) {
                if( src.getMat( i - 1 ).total() != src.getMat( i ).total() ) {
                    string error_message = format( "In the Fisherfaces method all input samples (training images) must be of equal size! Expected %d pixels, but was %d pixels.", src.getMat( i - 1 ).total(), src.getMat( i ).total() );
                    CV_Error( CV_StsUnsupportedFormat, error_message );
                }
            }
        }
        // get data
        Mat labels = _lbls.getMat();
        Mat data = asRowMatrix( src, CV_64FC1 );
        // number of samples
        int N = data.rows;
        // make sure labels are passed in correct shape - upewnia się, że etykiety są przekazywane w odpowiedniej formie
        if( labels.total() !=( size_t ) N ) {
            string error_message = format( "The number of samples (src) must equal the number of labels (labels)! len(src)=%d, len(labels)=%d.", N, labels.total() );
            CV_Error( CV_StsBadArg, error_message );
        } else if( labels.rows != 1 && labels.cols != 1 ) {
            string error_message = format( "Expected the labels in a matrix with one row or column! Given dimensions are rows=%s, cols=%d.", labels.rows, labels.cols );
            CV_Error( CV_StsBadArg, error_message );
        }
        // clear existing model data
        _labels.release();
        _projections.clear();
        // safely copy from cv::Mat to std::vector
        vector < int > ll;
        for( unsigned int i = 0; i < labels.total(); i++ ) {
            ll.push_back( labels.at < int >( i ) );
        }
        // get the number of unique classes
        int C =( int ) remove_dups( ll ).size();
        // clip number of components to be a valid number
        if(( _num_components <= 0 ) ||( _num_components >( C - 1 ) ) )
             _num_components =( C - 1 );
        // perform a PCA and keep (N-C) components
        PCA pca( data, Mat(), CV_PCA_DATA_AS_ROW,( N - C ) );
        // project the data and perform a LDA on it
        LDA lda( pca.project( data ), labels, _num_components );
        // store the total mean vector
        _mean = pca.mean.reshape( 1, 1 );
        // store labels
        _labels = labels.clone();
        // store the eigenvalues of the discriminants
        lda.eigenvalues().convertTo( _eigenvalues, CV_64FC1 );
        // Now calculate the projection matrix as pca.eigenvectors * lda.eigenvectors.
        // Note: OpenCV stores the eigenvectors by row, so we need to transpose it!
        gemm( pca.eigenvectors, lda.eigenvectors(), 1.0, Mat(), 0.0, _eigenvectors, GEMM_1_T );
        // store the projections of the original data
        for( int sampleIdx = 0; sampleIdx < data.rows; sampleIdx++ ) {
            Mat p = subspaceProject( _eigenvectors, _mean, data.row( sampleIdx ) );
            _projections.push_back( p );
        }
    }
   
    void Fisherfaces::predict( InputArray _src, int & minClass, double & minDist ) const {
        Mat src = _src.getMat();
        // check data alignment just for clearer exception messages
        if( _projections.empty() ) {
            // throw error if no data (or simply return -1?)
            string error_message = "This Fisherfaces model is not computed yet. Did you call Fisherfaces::train?";
            CV_Error( CV_StsBadArg, error_message );
        } else if( src.total() !=( size_t ) _eigenvectors.rows ) {
            string error_message = format( "Wrong input image size. Reason: Training and Test images must be of equal size! Expected an image with %d elements, but got %d.", _eigenvectors.rows, src.total() );
            CV_Error( CV_StsBadArg, error_message );
        }
        // project into LDA subspace
        Mat q = subspaceProject( _eigenvectors, _mean, src.reshape( 1, 1 ) );
        // find 1-nearest neighbor
        minDist = DBL_MAX;
        minClass = - 1;
        for( size_t sampleIdx = 0; sampleIdx < _projections.size(); sampleIdx++ ) {
            double dist = norm( _projections[ sampleIdx ], q, NORM_L2 );
            if(( dist < minDist ) &&( dist < _threshold ) ) {
                minDist = dist;
                minClass = _labels.at < int >(( int ) sampleIdx );
            }
        }
    }
   
    int Fisherfaces::predict( InputArray _src ) const {
        int label;
        double dummy;
        predict( _src, label, dummy );
        return label;
    }
   
    // See FaceRecognizer::load.
    void Fisherfaces::load( const FileStorage & fs ) {
        //read matrices
        fs[ "num_components" ] >> _num_components;
        fs[ "mean" ] >> _mean;
        fs[ "eigenvalues" ] >> _eigenvalues;
        fs[ "eigenvectors" ] >> _eigenvectors;
        // read sequences
        readFileNodeList( fs[ "projections" ], _projections );
        fs[ "labels" ] >> _labels;
    }
   
    // See FaceRecognizer::save.
    void Fisherfaces::save( FileStorage & fs ) const {
        write matrices
        fs << "num_components" << _num_components;
        fs << "mean" << _mean;
        fs << "eigenvalues" << _eigenvalues;
        fs << "eigenvectors" << _eigenvectors;
        write sequences
        writeFileNodeList( fs, "projections", _projections );
        fs << "labels" << _labels;
    }

Teraz mój kod - ubogi ;)
C/C++
#pragma once

#include "opencv.hpp"
#include <set>

class mojfisher
    : public Fisherface
{
public:
    mojfisher( void );
    ~mojfisher( void );
};
P-87735
pekfos
» 2013-07-13 13:37:25
I jak chcesz dziedziczyć po Fisherface skoro takiego typu nie ma?
P-87736
roserek
Temat założony przez niniejszego użytkownika
» 2013-07-13 13:51:16
Chcę odziedziczyć po tej klasie :

C/C++
class Fisherfaces
    : public FaceRecognizer
{
private:
    int _num_components; //nr elementu
    double _threshold; //próg
    Mat _eigenvectors; //wektory własne
    Mat _eigenvalues; //wartości własne
    Mat _mean; //średnia
    vector < Mat > _projections; //odwzorowanie
    Mat _labels; //etykiety
   
public:
    using FaceRecognizer::save;
    using FaceRecognizer::load;
   
    // Initializes an empty Fisherfaces model.
    myFisherfaces( int num_components = 0, double threshold = DBL_MAX )
        : _num_components( num_components )
        , _threshold( threshold )
    { }
   
    // Initializes and computes a Fisherfaces model with images in src and
    // corresponding labels in labels. num_components will be kept for
    // classification.
    myFisherfaces( InputArrayOfArrays src, InputArray labels,
    int num_components = 0, double threshold = DBL_MAX )
        : _num_components( num_components )
        , _threshold( threshold )
    {
        train( src, labels );
    }
   
    ~myFisherfaces() { }
   
    // Computes a Fisherfaces model with images in src and corresponding labels
    // in labels.
    void train( InputArrayOfArrays src, InputArray labels );
   
    // Predicts the label of a query image in src.
    int predict( InputArray src ) const;
   
    // Predicts the label and confidence for a given sample.
    void predict( InputArray _src, int & label, double & dist ) const;
   
    // See FaceRecognizer::load.
    void load( const FileStorage & fs );
   
    // See FaceRecognizer::save.
    void save( FileStorage & fs ) const;
   
    AlgorithmInfo * info() const;
};

Literówka na końcu niema znaczenia. Mój błąd, przy kopiowaniu. Ale po poprawieniu też nie wykrywa.
P-87737
Monika90
» 2013-07-13 13:58:19
Jeżeli ta klasa znajduje się tak jak napisałeś w pliku cpp, a nie w h czy w hpp, to jest oczywiste, że nie możesz z niej dziedziczyć.

Zainteresuj się flagą FileStorage::MEMORY.
P-87738
pekfos
» 2013-07-13 14:06:38
Ale po poprawieniu też nie wykrywa
Nie określiłeś przestrzeni nazw.
P-87739
roserek
Temat założony przez niniejszego użytkownika
» 2013-07-13 14:15:28
C/C++
#pragma once

#include "opencv.hpp"
#include <set>

using namespace cv;

class mojfisher
    : public Fisherfaces
{
public:
    mojfisher( void );
    ~mojfisher( void );
};

Dalej to samo....

Monika90 mogła byś trochę mi to rozjaśnić... (sory za moją tempotę :P)
P-87741
« 1 » 2 3
  Strona 1 z 3 Następna strona