C++ & OpenCV & .net & Kopierkonstruktur



  • Hallo!

    Ich bin derzeit am Testen, was mit OpenCV so alles möglich ist. Aus diesem Grund, habe ich mir ein kleines CLI Progrämmchen gebastelt, was mit OpenCV zusammen arbeitet. Ja ich weiß, man soll managed und unmanaged nicht mischen, aber das ist gerade weniger mein Problem. Um so wenig wie möglich Interaktionen zwischen dem Unmanaged OpenCV und meiner managed Gui zu haben, speichere ich meine eingelesene Bilder in einer extra Klasse. Diese Klasse heißt myImage.

    myImage.h:

    #include <cv.h>
    #include <highgui.h>
    namespace Übung1 
    {
    	class myImage
    	{
    		private:
    			cv::Mat MyImg;
    
    		public:
    			myImage(cv::Mat Img);
    			cv::Mat getImageData();
    			void setImageData(cv::Mat Img);
    	};
    }
    

    myImage.cpp

    using namespace Übung1;
    myImage::myImage(cv::Mat Img)
    {
    	MyImg = Img;
    }
    
    cv::Mat myImage::getImageData()
    {
    	return MyImg;
    }
    
    void myImage::setImageData(cv::Mat Img)
    {
    	MyImg = Img;
    }
    

    In meiner .net Klasse habe ich die globalen Pointer

    Übung1::myImage* Image;
    Übung1::myImage* ImageOrig;
    

    welche über

    this->Image	= new myImage(Img);
    this->ImageOrig	= new myImage(ImgOrig);
    

    instanziert werden.

    Soweit, so gut. Nun bearbeite ich das eine Bild in meiner .net Klasse über etliche Funktionen und speichere diese über

    this->Image->setImageData(Img);
    

    in meine instanzierte Klasse.

    Jetzt habe ich noch die Funktion "zurücksetzen" eingeführt und möchte gerne die originalen Bild-Information, die in "ImageOrig" gespeichert sind an "Image" übergeben. Doch genau hier gehts immer schief. Statt den Speicherinhalt des "alten" Image zu löschen und dafür den des "ImageOrig" einzusetzten, kopiert er einfach die Speicheradresse. So haben haben z.b. erst
    this->Image die Adresse 07EA7D50 und
    this->ImageOrig die Adresse 07EDD5F0 und nach dem Befehl

    this->Image = this->ImageOrig
    

    haben beide die Speicheradresse des Originals drinn stehen (07EDD5F0).

    Ich habe mich ein wenig belesen und ich glaube ein Kopierkonstruktur wäre genau das was mir da jetzt weiterhelfen würde. Allerdings hab ich das immer nur bei .net klassen gemacht (über die ICloneable-Schnittstelle) bei klassichen C++ Klasse bin ich mir nicht sicher wie das geht. Ich hoffe ihr helft mir ein wenig auf die Sprünge! Vlt. ist mein Ansatz auch vollkommen falsch und ihr wisst da was besseres 🙂



  • Du kopierst (=weist zu) einfach Pointer - selbst wenn Du ein Copy Ctor bzw. Assignment Operator hättest würde er so nicht aufgerufen werden.



  • ja, aber selbst wenn ich folgendes mache, wird nicht der Inhalt sondern die adresse übergeben

    cv::Mat orig = this->ImageOrig->getImageData();
    this->Image->setImageData(orig);
    


  • Welchen Inhalt? cv::Mat orig?
    Das kommt auf cv::Mat draufan wie und ob da was kopiert wird.

    Edit:
    BTW: Dein Problem hat nichts mit .NET zu tun, sondern ist reines C++.



  • Welchen Inhalt? cv::Mat orig?

    Wie schon gesagt, diese cv::Mat orig Variable ermöglicht es ganz einfach (über orig[x,y]) Zugriff auf jeden Pixel eines Bildes zu bekommen. Als Rückgabewert gibt es dann ein unsigned char.
    Leider bekomme ich aber wenn ich es so mache:

    cv::Mat orig = this->ImageOrig->getImageData();
    this->ImageWorking->setImageData(orig);
    

    Nur die Speicheradresse und nicht den Inhalt kopiert. Das heist, in meiner neuangelegten Variable "cv::Mat Orig" wird nur ein Link zu meiner ImageOrig gespeichert. Und nachdem dieser Link durch den zweiten Schritt in mein ImageWorking gesetzt ist, wird in meinem nächsten Arbeitsgang das Originalbild verändert (und nicht mein WorkingImage) und ich kann das dann nicht mehr zurück setzten. Ich hoffe du verstehst auf was ich hinaus möchte? 🙂

    PS: Ja, ich denke mittlerweile auch, dass das ein reines C++ Problem ist.

    cv::Mat ist ein Klasse, die als Speichermatrix für die Bilder in openCV verwendet wird.

    Sie lautet so:

    class CV_EXPORTS Mat
    {
    public:
        // constructors
        Mat();
        // constructs matrix of the specified size and type
        // (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
        Mat(int _rows, int _cols, int _type);
        Mat(Size _size, int _type);
        // constucts matrix and fills it with the specified value _s.
        Mat(int _rows, int _cols, int _type, const Scalar& _s);
        Mat(Size _size, int _type, const Scalar& _s);
        // copy constructor
        Mat(const Mat& m);
        // constructor for matrix headers pointing to user-allocated data
        Mat(int _rows, int _cols, int _type, void* _data, size_t _step=AUTO_STEP);
        Mat(Size _size, int _type, void* _data, size_t _step=AUTO_STEP);
        // creates a matrix header for a part of the bigger matrix
        Mat(const Mat& m, const Range& rowRange, const Range& colRange);
        Mat(const Mat& m, const Rect& roi);
        // converts old-style CvMat to the new matrix; the data is not copied by default
        Mat(const CvMat* m, bool copyData=false);
        // converts old-style IplImage to the new matrix; the data is not copied by default
        Mat(const IplImage* img, bool copyData=false);
        // builds matrix from std::vector with or without copying the data
        template<typename _Tp> explicit Mat(const vector<_Tp>& vec, bool copyData=false);
        // helper constructor to compile matrix expressions
        Mat(const MatExpr_Base& expr);
        // destructor - calls release()
        ~Mat();
        // assignment operators
        Mat& operator = (const Mat& m);
        Mat& operator = (const MatExpr_Base& expr);
    
        operator MatExpr_<Mat, Mat>() const;
    
        // returns a new matrix header for the specified row
        Mat row(int y) const;
        // returns a new matrix header for the specified column
        Mat col(int x) const;
        // ... for the specified row span
        Mat rowRange(int startrow, int endrow) const;
        Mat rowRange(const Range& r) const;
        // ... for the specified column span
        Mat colRange(int startcol, int endcol) const;
        Mat colRange(const Range& r) const;
        // ... for the specified diagonal
        // (d=0 - the main diagonal,
        //  >0 - a diagonal from the lower half,
        //  <0 - a diagonal from the upper half)
        Mat diag(int d=0) const;
        // constructs a square diagonal matrix which main diagonal is vector "d"
        static Mat diag(const Mat& d);
    
        // returns deep copy of the matrix, i.e. the data is copied
        Mat clone() const;
        // copies the matrix content to "m".
        // It calls m.create(this->size(), this->type()).
        void copyTo( Mat& m ) const;
        // copies those matrix elements to "m" that are marked with non-zero mask elements.
        void copyTo( Mat& m, const Mat& mask ) const;
        // converts matrix to another datatype with optional scalng. See cvConvertScale.
        void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;
    
        void assignTo( Mat& m, int type=-1 ) const;
    
        // sets every matrix element to s
        Mat& operator = (const Scalar& s);
        // sets some of the matrix elements to s, according to the mask
        Mat& setTo(const Scalar& s, const Mat& mask=Mat());
        // creates alternative matrix header for the same data, with different
        // number of channels and/or different number of rows. see cvReshape.
        Mat reshape(int _cn, int _rows=0) const;
    
        // matrix transposition by means of matrix expressions
        MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_T_<Mat> >, Mat>
        t() const;
        // matrix inversion by means of matrix expressions
        MatExpr_<MatExpr_Op2_<Mat, int, Mat, MatOp_Inv_<Mat> >, Mat>
            inv(int method=DECOMP_LU) const;
        MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
        // per-element matrix multiplication by means of matrix expressions
        mul(const Mat& m, double scale=1) const;
        MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>
        mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_Scale_<Mat> >, Mat>& m, double scale=1) const;
        MatExpr_<MatExpr_Op4_<Mat, Mat, double, char, Mat, MatOp_MulDiv_<Mat> >, Mat>    
        mul(const MatExpr_<MatExpr_Op2_<Mat, double, Mat, MatOp_DivRS_<Mat> >, Mat>& m, double scale=1) const;
    
        // computes cross-product of 2 3D vectors
        Mat cross(const Mat& m) const;
        // computes dot-product
        double dot(const Mat& m) const;
    
        // Matlab-style matrix initialization
        static MatExpr_Initializer zeros(int rows, int cols, int type);
        static MatExpr_Initializer zeros(Size size, int type);
        static MatExpr_Initializer ones(int rows, int cols, int type);
        static MatExpr_Initializer ones(Size size, int type);
        static MatExpr_Initializer eye(int rows, int cols, int type);
        static MatExpr_Initializer eye(Size size, int type);
    
        // allocates new matrix data unless the matrix already has specified size and type.
        // previous data is unreferenced if needed.
        void create(int _rows, int _cols, int _type);
        void create(Size _size, int _type);
        // increases the reference counter; use with care to avoid memleaks
        void addref();
        // decreases reference counter;
        // deallocate the data when reference counter reaches 0.
        void release();
    
        // locates matrix header within a parent matrix. See below
        void locateROI( Size& wholeSize, Point& ofs ) const;
        // moves/resizes the current matrix ROI inside the parent matrix.
        Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );
        // extracts a rectangular sub-matrix
        // (this is a generalized form of row, rowRange etc.)
        Mat operator()( Range rowRange, Range colRange ) const;
        Mat operator()( const Rect& roi ) const;
    
        // converts header to CvMat; no data is copied
        operator CvMat() const;
        // converts header to IplImage; no data is copied
        operator IplImage() const;
    
        // returns true iff the matrix data is continuous
        // (i.e. when there are no gaps between successive rows).
        // similar to CV_IS_MAT_CONT(cvmat->type)
        bool isContinuous() const;
        // returns element size in bytes,
        // similar to CV_ELEM_SIZE(cvmat->type)
        size_t elemSize() const;
        // returns the size of element channel in bytes.
        size_t elemSize1() const;
        // returns element type, similar to CV_MAT_TYPE(cvmat->type)
        int type() const;
        // returns element type, similar to CV_MAT_DEPTH(cvmat->type)
        int depth() const;
        // returns element type, similar to CV_MAT_CN(cvmat->type)
        int channels() const;
        // returns step/elemSize1()
        size_t step1() const;
        // returns matrix size:
        // width == number of columns, height == number of rows
        Size size() const;
        // returns true if matrix data is NULL
        bool empty() const;
    
        // returns pointer to y-th row
        uchar* ptr(int y=0);
        const uchar* ptr(int y=0) const;
    
        // template version of the above method
        template<typename _Tp> _Tp* ptr(int y=0);
        template<typename _Tp> const _Tp* ptr(int y=0) const;
    
        // template methods for read-write or read-only element access.
        // note that _Tp must match the actual matrix type -
        // the functions do not do any on-fly type conversion
        template<typename _Tp> _Tp& at(int y, int x);
        template<typename _Tp> _Tp& at(Point pt);
        template<typename _Tp> const _Tp& at(int y, int x) const;
        template<typename _Tp> const _Tp& at(Point pt) const;
    
        // template methods for iteration over matrix elements.
        // the iterators take care of skipping gaps in the end of rows (if any)
        template<typename _Tp> MatIterator_<_Tp> begin();
        template<typename _Tp> MatIterator_<_Tp> end();
        template<typename _Tp> MatConstIterator_<_Tp> begin() const;
        template<typename _Tp> MatConstIterator_<_Tp> end() const;
    
        enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG };
    
        // includes several bit-fields:
        //  * the magic signature
        //  * continuity flag
        //  * depth
        //  * number of channels
        int flags;
        // the number of rows and columns
        int rows, cols;
        // a distance between successive rows in bytes; includes the gap if any
        size_t step;
        // pointer to the data
        uchar* data;
    
        // pointer to the reference counter;
        // when matrix points to user-allocated data, the pointer is NULL
        int* refcount;
    
        // helper fields used in locateROI and adjustROI
        uchar* datastart;
        uchar* dataend;
    };
    


  • Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum C++/CLI mit .NET in das Forum C++ (auch C++0x) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • nachdem ich mir gerade die klasse und alle ihre member mal gründlich angeschaut habe, hat sich die sache nun erledigt!

    für alle die mal genauso aufm schlauch stehen:

    cv::Mat orig = 	ImageOrig->getImageData();
    cv::Mat work =  orig.clone();
    Image->setImageData(work);
    

Anmelden zum Antworten