diff --git a/include/vcl/Image.h b/include/vcl/Image.h index bd643724..2b56ddf6 100644 --- a/include/vcl/Image.h +++ b/include/vcl/Image.h @@ -86,6 +86,8 @@ namespace VCL { */ Image(const cv::Mat &cv_img); + Image(cv::Mat &cv_img); + /** * Creates an Image object from an encoded buffer * @@ -112,11 +114,21 @@ namespace VCL { /** * Creates a new Image object from an existing Image object + * This will make a deep copy of the arrays. * * @param img An existing Image object */ Image(const Image &img); + /** + * Move constructor, needed to avoid copies of the arrays. + * noexcept is needed to let vectors grow and call the move + * instead of copy constructor. + * + * @param img An existing Image object + */ + Image(const Image &&img) noexcept; + /** * Sets an Image object equal to another Image object * @@ -173,14 +185,16 @@ namespace VCL { * y coordinate, height, width) * @return A new Image object that is only the requested area */ - Image get_area(const Rectangle &roi) const; + Image get_area(const Rectangle &roi); /** * Gets an OpenCV Mat that contains the image data * + * @param copy Specify if a deep copy of the cvmat will be made before + * returning the cvmat object. * @return An OpenCV Mat */ - cv::Mat get_cvmat() const; + cv::Mat get_cvmat(bool copy=false); /** * Gets the raw image data diff --git a/src/vcl/Image.cc b/src/vcl/Image.cc index 3c413f30..5cd637f8 100644 --- a/src/vcl/Image.cc +++ b/src/vcl/Image.cc @@ -56,6 +56,15 @@ Image::Image(const cv::Mat &cv_img) } +Image::Image(cv::Mat &cv_img) +{ + if ( cv_img.empty() ) { + throw VCLException(ObjectEmpty, "Image object is empty"); + } + + _image = new ImageData(cv_img); +} + Image::Image(void* buffer, long size, int flags) { cv::Mat raw_data(cv::Size(size, 1), CV_8UC1, buffer); @@ -77,6 +86,11 @@ Image::Image(const Image &img) _image = new ImageData(*img._image); } +Image::Image(const Image &&img) noexcept +{ + _image = new ImageData(*img._image, false); +} + void Image::operator=(const Image &img) { ImageData *temp = _image; @@ -84,14 +98,11 @@ void Image::operator=(const Image &img) delete temp; } - Image::~Image() { delete _image; } - - /* *********************** */ /* GET FUNCTIONS */ /* *********************** */ @@ -122,7 +133,7 @@ int Image::get_image_type() const } -Image Image::get_area(const Rectangle &roi) const +Image Image::get_area(const Rectangle &roi) { Image img_copy(*this); *(img_copy._image) = _image->get_area(roi); @@ -130,11 +141,14 @@ Image Image::get_area(const Rectangle &roi) const return img_copy; } -cv::Mat Image::get_cvmat() const +cv::Mat Image::get_cvmat(bool copy) { cv::Mat mat = _image->get_cvmat(); - return mat.clone(); + if (copy) + return mat.clone(); + else + return mat; } void Image::get_raw_data(void* buffer, long buffer_size ) const diff --git a/src/vcl/ImageData.cc b/src/vcl/ImageData.cc index f46bb4dc..7151b544 100644 --- a/src/vcl/ImageData.cc +++ b/src/vcl/ImageData.cc @@ -35,7 +35,6 @@ #include "ImageData.h" - using namespace VCL; /* *********************** */ @@ -45,6 +44,7 @@ using namespace VCL; /* *********************** */ /* READ OPERATION */ /* *********************** */ + ImageData::Read::Read(const std::string& filename, Image::Format format) : Operation(format), _fullpath(filename) @@ -64,7 +64,8 @@ void ImageData::Read::operator()(ImageData *img) img->_channels = img->_tdb->get_image_channels(); } else { - img->copy_cv(cv::imread(_fullpath, cv::IMREAD_ANYCOLOR)); + auto img_read = cv::imread(_fullpath, cv::IMREAD_ANYCOLOR); + img->shallow_copy_cv(img_read); if ( img->_cv_img.empty() ) throw VCLException(ObjectEmpty, _fullpath + " could not be read, \ object is empty"); @@ -74,6 +75,7 @@ void ImageData::Read::operator()(ImageData *img) /* *********************** */ /* WRITE OPERATION */ /* *********************** */ + ImageData::Write::Write(const std::string& filename, Image::Format format, Image::Format old_format, bool metadata) : Operation(format), @@ -128,7 +130,7 @@ void ImageData::Resize::operator()(ImageData *img) if ( !img->_cv_img.empty() ) { cv::Mat cv_resized; cv::resize(img->_cv_img, cv_resized, cv::Size(_rect.width, _rect.height)); - img->copy_cv(cv_resized); + img->shallow_copy_cv(cv_resized); } else throw VCLException(ObjectEmpty, "Image object is empty"); @@ -152,7 +154,7 @@ void ImageData::Crop::operator()(ImageData *img) if ( img->_cv_img.rows < _rect.height + _rect.y || img->_cv_img.cols < _rect.width + _rect.x ) throw VCLException(SizeMismatch, "Requested area is not within the image"); cv::Mat roi_img(img->_cv_img, _rect); - img->copy_cv(roi_img); + img->shallow_copy_cv(roi_img); } else throw VCLException(ObjectEmpty, "Image object is empty"); @@ -192,7 +194,7 @@ void ImageData::Flip::operator()(ImageData *img) cv::Mat dst = cv::Mat(img->_cv_img.rows, img->_cv_img.cols, img->_cv_img.type()); cv::flip(img->_cv_img, dst, _code); - img->_cv_img = dst.clone(); + img->shallow_copy_cv(dst); } else throw VCLException(ObjectEmpty, "Image object is empty"); @@ -239,7 +241,7 @@ void ImageData::Rotate::operator()(ImageData *img) cv::Mat dst; cv::warpAffine(img->_cv_img, dst, r, bbox.size()); - img->_cv_img = dst.clone(); + img->shallow_copy_cv(dst); } } else @@ -271,7 +273,18 @@ ImageData::ImageData() ImageData::ImageData(const cv::Mat &cv_img) { - copy_cv(cv_img); + deep_copy_cv(cv_img); + + _format = Image::Format::NONE_IMAGE; + _compress = CompressionType::LZ4; + _image_id = ""; + + _tdb = NULL; +} + +ImageData::ImageData(cv::Mat &cv_img) +{ + shallow_copy_cv(cv_img); _format = Image::Format::NONE_IMAGE; _compress = CompressionType::LZ4; @@ -300,7 +313,6 @@ ImageData::ImageData(const std::string &image_id) } else _tdb = NULL; - } ImageData::ImageData(void* buffer, cv::Size dimensions, int cv_type) @@ -318,14 +330,20 @@ ImageData::ImageData(void* buffer, cv::Size dimensions, int cv_type) _tdb->set_compression(_compress); } -ImageData::ImageData(const ImageData &img) +ImageData::ImageData(const ImageData &img, bool copy) { _format = img._format; _compress = img._compress; _image_id = img._image_id; - if ( !(img._cv_img).empty() ) - copy_cv(img._cv_img); + if ( !(img._cv_img).empty() ) { + if (copy) { + deep_copy_cv(img._cv_img); + } + else { + shallow_copy_cv(img._cv_img); + } + } if ( img._tdb != NULL ) _tdb = new TDBImage(*img._tdb); @@ -333,11 +351,13 @@ ImageData::ImageData(const ImageData &img) _tdb = NULL; int start; + // TODO IS THIS REALLY NEEDED???? if ( img._operations.size() > 0 ) { std::shared_ptr front = img._operations.front(); if (front->get_type() == OperationType::READ) { start = 1; - copy_cv(cv::imread(img._image_id, cv::IMREAD_ANYCOLOR)); + cv::Mat img_read = cv::imread(img._image_id, cv::IMREAD_ANYCOLOR); + shallow_copy_cv(img_read); } else start = 0; @@ -352,7 +372,7 @@ void ImageData::operator=(const ImageData &img) TDBImage *temp = _tdb; if ( !(img._cv_img).empty() ) - copy_cv(img._cv_img); + deep_copy_cv(img._cv_img); else { _channels = img._channels; @@ -381,7 +401,8 @@ void ImageData::operator=(const ImageData &img) std::shared_ptr front = img._operations.front(); if (front->get_type() == OperationType::READ) { start = 1; - copy_cv(cv::imread(img._image_id, cv::IMREAD_ANYCOLOR)); + cv::Mat img_read = cv::imread(img._image_id, cv::IMREAD_ANYCOLOR); + shallow_copy_cv(img_read); } else start = 0; @@ -545,8 +566,10 @@ std::vector ImageData::get_encoded(Image::Format format, if ( _cv_img.empty() ) { if ( _tdb == NULL) throw VCLException(ObjectEmpty, "No data to encode"); - else - copy_cv(_tdb->get_cvmat()); + else { + cv::Mat img = _tdb->get_cvmat(); + shallow_copy_cv(img); + } } std::vector buffer; @@ -653,7 +676,8 @@ void ImageData::set_data_from_raw(void* buffer, long size) void ImageData::set_data_from_encoded(const std::vector &buffer) { - copy_cv(cv::imdecode(buffer, cv::IMREAD_ANYCOLOR)); + cv::Mat img_read = cv::imdecode(buffer, cv::IMREAD_ANYCOLOR); + shallow_copy_cv(img_read); } void ImageData::set_minimum(int dimension) @@ -666,7 +690,6 @@ void ImageData::set_minimum(int dimension) } } - /* *********************** */ /* IMAGEDATA INTERACTION */ /* *********************** */ @@ -752,16 +775,28 @@ void ImageData::delete_object() /* COPY FUNCTIONS */ /* *********************** */ -void ImageData::copy_cv(const cv::Mat &cv_img) +void ImageData::deep_copy_cv(const cv::Mat &cv_img) +{ + _channels = cv_img.channels(); + + _height = cv_img.rows; + _width = cv_img.cols; + + _cv_type = cv_img.type(); + + _cv_img = cv_img.clone(); // deep copy +} + +void ImageData::shallow_copy_cv(const cv::Mat &cv_img) { _channels = cv_img.channels(); _height = cv_img.rows; - _width = cv_img.cols; + _width = cv_img.cols; _cv_type = cv_img.type(); - _cv_img = cv_img.clone(); + _cv_img = cv_img; // shallow copy } template @@ -819,4 +854,3 @@ std::string ImageData::create_fullpath(const std::string &filename, else return filename + "." + ext; } - diff --git a/src/vcl/ImageData.h b/src/vcl/ImageData.h index 466a8b33..d257ecc1 100644 --- a/src/vcl/ImageData.h +++ b/src/vcl/ImageData.h @@ -370,12 +370,21 @@ namespace VCL { ImageData(); /** - * Creates an ImageData object from the OpenCV Mat. + * Creates an ImageData object from the OpenCV Mat, + * making a deep copy. * * @param cv_img An OpenCV Mat that contains an image */ ImageData(const cv::Mat &cv_img); + /** + * Creates an ImageData object from the OpenCV Mat, making a + * shallow copy of the cvmat. + * + * @param cv_img An OpenCV Mat that contains an image + */ + ImageData(cv::Mat &cv_img); + /** * Creates an ImageData object from the filename * @@ -400,7 +409,7 @@ namespace VCL { * * @param img A reference to an existing ImageData object */ - ImageData(const ImageData &img); + ImageData(const ImageData &img, bool copy=true); /** * Sets an ImageData object equal to another ImageData object @@ -643,18 +652,23 @@ namespace VCL { */ void delete_object(); - - private: /* *********************** */ /* COPY FUNCTIONS */ /* *********************** */ /** - * Copies an OpenCV Mat into the ImageData OpenCV Mat + * Copies (deep copy) an OpenCV Mat into the ImageData OpenCV Mat + * + * @param cv_img An existing OpenCV Mat + */ + void deep_copy_cv(const cv::Mat &cv_img); + + /** + * Copies (shallow copy) an OpenCV Mat into the ImageData OpenCV Mat * * @param cv_img An existing OpenCV Mat */ - void copy_cv(const cv::Mat &cv_img); + void shallow_copy_cv(const cv::Mat &cv_img); /** * Copies the ImageData OpenCV Mat into a buffer diff --git a/src/vcl/VideoData.cc b/src/vcl/VideoData.cc index 1a9abfbd..a3db5233 100644 --- a/src/vcl/VideoData.cc +++ b/src/vcl/VideoData.cc @@ -137,7 +137,7 @@ void VideoData::Write::operator()(VideoData *video) std::vector& frames = video->get_frames(); for (auto& frame : frames) { - outputVideo << frame.get_cvmat(); + outputVideo << frame.get_cvmat(false); } outputVideo.release();