Camera.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2011-2014, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007     * Redistributions of source code must retain the above copyright
00008       notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright
00010       notice, this list of conditions and the following disclaimer in the
00011       documentation and/or other materials provided with the distribution.
00012     * Neither the name of the Universite de Sherbrooke nor the
00013       names of its contributors may be used to endorse or promote products
00014       derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
00020 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 */
00027 
00028 #include "find_object/Camera.h"
00029 #include "find_object/Settings.h"
00030 #include "find_object/utilite/ULogger.h"
00031 #include "find_object/QtOpenCV.h"
00032 
00033 #include <stdio.h>
00034 #include <opencv2/imgproc/imgproc.hpp>
00035 #include <QtCore/QFile>
00036 #include "utilite/UDirectory.h"
00037 #include "CameraTcpServer.h"
00038 
00039 namespace find_object {
00040 
00041 Camera::Camera(QObject * parent) :
00042         QObject(parent),
00043         currentImageIndex_(0),
00044         cameraTcpServer_(0)
00045 {
00046         qRegisterMetaType<cv::Mat>("cv::Mat");
00047         connect(&cameraTimer_, SIGNAL(timeout()), this, SLOT(takeImage()));
00048 }
00049 
00050 Camera::~Camera()
00051 {
00052         this->stop();
00053 }
00054 
00055 void Camera::stop()
00056 {
00057         stopTimer();
00058         capture_.release();
00059         images_.clear();
00060         currentImageIndex_ = 0;
00061         if(cameraTcpServer_)
00062         {
00063                 cameraTcpServer_->close();
00064                 delete cameraTcpServer_;
00065                 cameraTcpServer_ = 0;
00066         }
00067 }
00068 
00069 void Camera::pause()
00070 {
00071         stopTimer();
00072 }
00073 
00074 int Camera::getTotalFrames()
00075 {
00076         if(images_.size())
00077         {
00078                 return images_.size();
00079         }
00080         else if(capture_.isOpened())
00081         {
00082                 return (int)capture_.get(CV_CAP_PROP_FRAME_COUNT);
00083         }
00084         return 0;
00085 }
00086 
00087 int Camera::getCurrentFrameIndex()
00088 {
00089         if(images_.size())
00090         {
00091                 return currentImageIndex_;
00092         }
00093         else if(capture_.isOpened())
00094         {
00095                 return (int)capture_.get(CV_CAP_PROP_POS_FRAMES);
00096         }
00097         return 0;
00098 }
00099 
00100 void Camera::moveToFrame(int frame)
00101 {
00102         if(frame < images_.size())
00103         {
00104                 currentImageIndex_ = frame;
00105         }
00106         else if(capture_.isOpened() && frame < (int)capture_.get(CV_CAP_PROP_FRAME_COUNT))
00107         {
00108                 capture_.set(CV_CAP_PROP_POS_FRAMES, frame);
00109         }
00110 }
00111 
00112 int Camera::getPort()
00113 {
00114         if(cameraTcpServer_)
00115         {
00116                 return cameraTcpServer_->getPort();
00117         }
00118         return 0;
00119 }
00120 
00121 void Camera::takeImage()
00122 {
00123         cv::Mat img;
00124         if(capture_.isOpened())
00125         {
00126                 capture_.read(img);// capture a frame
00127         }
00128         else if(!images_.empty())
00129         {
00130                 if(currentImageIndex_ < (unsigned int)images_.size())
00131                 {
00132                         img = cv::imread(images_[currentImageIndex_++]);
00133                 }
00134         }
00135         else if(cameraTcpServer_)
00136         {
00137                 img = cameraTcpServer_->getImage();
00138                 if(cameraTcpServer_->imagesBuffered() > 0 && Settings::getCamera_9queueSize() == 0)
00139                 {
00140                         UWARN("%d images buffered so far...", cameraTcpServer_->imagesBuffered());
00141                 }
00142         }
00143 
00144         if(img.empty())
00145         {
00146                 if(cameraTcpServer_)
00147                 {
00148                         if(!cameraTcpServer_->isConnected())
00149                         {
00150                                 cameraTcpServer_->waitForNewConnection(100);
00151                         }
00152                 }
00153                 else
00154                 {
00155                         // In case of a directory of images or a video
00156                         this->stop();
00157                         Q_EMIT finished(); // notify that there are no more images
00158                 }
00159         }
00160         else
00161         {
00162                 //resize
00163                 if( Settings::getCamera_2imageWidth() &&
00164                         Settings::getCamera_3imageHeight() &&
00165                         Settings::getCamera_2imageWidth() != img.cols &&
00166                         Settings::getCamera_3imageHeight() != img.rows)
00167                 {
00168                         cv::Mat resampled;
00169                         cv::resize(img, resampled, cv::Size(Settings::getCamera_2imageWidth(), Settings::getCamera_3imageHeight()));
00170                         Q_EMIT imageReceived(resampled);
00171                 }
00172                 else if(capture_.isOpened())
00173                 {
00174                         Q_EMIT imageReceived(img.clone()); // clone required with VideoCapture::read()
00175                 }
00176                 else
00177                 {
00178                         Q_EMIT imageReceived(img); // clone not required with cv::imread()
00179                 }
00180         }
00181 }
00182 
00183 bool Camera::start()
00184 {
00185         if(!capture_.isOpened() && images_.empty() && cameraTcpServer_ == 0)
00186         {
00187                 if(Settings::getCamera_6useTcpCamera())
00188                 {
00189                         cameraTcpServer_ = new CameraTcpServer(Settings::getCamera_8port(), this);
00190                         if(!cameraTcpServer_->isListening())
00191                         {
00192                                 UWARN("CameraTCP: Cannot listen to port %d", cameraTcpServer_->getPort());
00193                                 delete cameraTcpServer_;
00194                                 cameraTcpServer_ = 0;
00195                         }
00196                         else
00197                         {
00198                                 UINFO("CameraTCP: listening to port %d (IP=%s)",
00199                                                 cameraTcpServer_->getPort(),
00200                                                 cameraTcpServer_->getHostAddress().toString().toStdString().c_str());
00201                         }
00202                 }
00203                 else
00204                 {
00205                         QString path = Settings::getCamera_5mediaPath();
00206                         if(UDirectory::exists(path.toStdString()))
00207                         {
00208                                 //Images directory
00209                                 QString ext = Settings::getGeneral_imageFormats();
00210                                 ext.remove('*');
00211                                 ext.remove('.');
00212                                 UDirectory dir(path.toStdString(), ext.toStdString()); // this will load fileNames matching the extensions (in natural order)
00213                                 const std::list<std::string> & fileNames = dir.getFileNames();
00214                                 currentImageIndex_ = 0;
00215                                 images_.clear();
00216                                 // Modify to have full path
00217                                 for(std::list<std::string>::const_iterator iter = fileNames.begin(); iter!=fileNames.end(); ++iter)
00218                                 {
00219                                         images_.append(path.toStdString() + UDirectory::separator() + *iter);
00220                                 }
00221                                 UINFO("Camera: Reading %d images from directory \"%s\"...", (int)images_.size(), path.toStdString().c_str());
00222                                 if(images_.isEmpty())
00223                                 {
00224                                         UWARN("Camera: Directory \"%s\" is empty (no images matching the \"%s\" extensions). "
00225                                                    "If you want to disable loading automatically this directory, "
00226                                                    "clear the Camera/mediaPath parameter. By default, webcam will be used instead of the directory.",
00227                                                    path.toStdString().c_str(),
00228                                                    ext.toStdString().c_str());
00229                                 }
00230                         }
00231                         else if(!path.isEmpty())
00232                         {
00233                                 //Video file
00234                                 capture_.open(path.toStdString().c_str());
00235                                 if(!capture_.isOpened())
00236                                 {
00237                                         UWARN("Camera: Cannot open file \"%s\". If you want to disable loading "
00238                                                   "automatically this video file, clear the Camera/mediaPath parameter. "
00239                                                   "By default, webcam will be used instead of the file.", path.toStdString().c_str());
00240                                 }
00241                                 else
00242                                 {
00243                                         UINFO("Camera: Reading from video file \"%s\"...", path.toStdString().c_str());
00244                                 }
00245                         }
00246                         if(!capture_.isOpened() && images_.empty())
00247                         {
00248                                 //set camera device
00249                                 capture_.open(Settings::getCamera_1deviceId());
00250                                 if(Settings::getCamera_2imageWidth() && Settings::getCamera_3imageHeight())
00251                                 {
00252                                         capture_.set(CV_CAP_PROP_FRAME_WIDTH, double(Settings::getCamera_2imageWidth()));
00253                                         capture_.set(CV_CAP_PROP_FRAME_HEIGHT, double(Settings::getCamera_3imageHeight()));
00254                                 }
00255                                 UINFO("Camera: Reading from camera device %d...", Settings::getCamera_1deviceId());
00256                         }
00257                 }
00258         }
00259         if(!capture_.isOpened() && images_.empty() && cameraTcpServer_ == 0)
00260         {
00261                 UERROR("Camera: Failed to open a capture object!");
00262                 return false;
00263         }
00264 
00265         startTimer();
00266         return true;
00267 }
00268 
00269 void Camera::startTimer()
00270 {
00271         updateImageRate();
00272         cameraTimer_.start();
00273 }
00274 
00275 void Camera::stopTimer()
00276 {
00277         cameraTimer_.stop();
00278 }
00279 
00280 void Camera::updateImageRate()
00281 {
00282         if(Settings::getCamera_4imageRate())
00283         {
00284                 cameraTimer_.setInterval((int)(1000.0/Settings::getCamera_4imageRate()));
00285         }
00286         else
00287         {
00288                 cameraTimer_.setInterval(0);
00289         }
00290 }
00291 
00292 } // namespace find_object
00293 


find_object_2d
Author(s): Mathieu Labbe
autogenerated on Fri Feb 12 2016 01:18:17