Index: python/autogcp/qgsgcpdataset.sip =================================================================== --- python/autogcp/qgsgcpdataset.sip (revision 0) +++ python/autogcp/qgsgcpdataset.sip (revision 0) @@ -0,0 +1,37 @@ +/*************************************************************************** +qgsgcpdataset.cpp - This is a container class that represents an entire set of + GCP's associated with a specific reference model or a specific extraction + and cross-referencing operation. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ +%Import QtCore/QtCoremod.sip +class QgsGCPDataSet +{ + +%TypeHeaderCode +#include +%End + +public: + QgsGCPDataSet(); + virtual ~QgsGCPDataSet(); + void addGcp(QgsGCP* point); + void updateGcp(QgsGCP* oldPoint, QgsGCP* newPoint); + void removeGcp(QgsGCP* point); + void clear(); + int size() const; + const QList& constList() const; + QList list(); +}; + Property changes on: python/autogcp/qgsgcpdataset.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgselevationmanager.sip =================================================================== --- python/autogcp/qgselevationmanager.sip (revision 0) +++ python/autogcp/qgselevationmanager.sip (revision 0) @@ -0,0 +1,34 @@ +/*************************************************************************** +qgselevationmanager.sip - The ElevationManager contains a Digital Elevation + Model of a specific reference image and allows sampling of the ground + elevation at different coordinates. This DEM is used in the orthorectification + process as well as chip projection. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsElevationManager +{ + +%TypeHeaderCode +#include +%End + +public: + QgsElevationManager(); + double sampleHeight(int,int); + void openDEMFile(QString); + virtual ~QgsElevationManager(); + +}; + Property changes on: python/autogcp/qgselevationmanager.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgsimagechip.sip =================================================================== --- python/autogcp/qgsimagechip.sip (revision 0) +++ python/autogcp/qgsimagechip.sip (revision 0) @@ -0,0 +1,38 @@ +/*************************************************************************** +qgsgcp.sip - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: James Meyer +Email : jamesmeyerx@gmail.com +E +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsImageChip : QgsImageDataSet +{ + +%TypeHeaderCode +#include +#include +%End + +public: + +// static QgsImageChip* createImageChip(int width, int height, int type, int bands = 3); + ~QgsImageChip(); + QgsImageChip(const QgsImageChip& other); + + void* data(); +}; + + Property changes on: python/autogcp/qgsimagechip.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgscrosscorrelator.sip =================================================================== --- python/autogcp/qgscrosscorrelator.sip (revision 0) +++ python/autogcp/qgscrosscorrelator.sip (revision 0) @@ -0,0 +1,36 @@ +/*************************************************************************** +qgscrosscorrelator.cpp - This class handles the cross correlation of two +subimages. +-------------------------------------- +Date : 12-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsCrossCorrelator +{ + +%TypeHeaderCode +#include +%End + +public: + /**\brief QgsCrossCorrelator Constructor + Constructs the correlator with the given chip images + */ + QgsCrossCorrelator(QgsImageDataSet* ref, QgsImageDataSet* raw); + /**\brief QgsCrossCorrelator Destructor + Destroys the QgsCrossCorrelator instance, releasing any owned resources. + */ + virtual ~QgsCrossCorrelator(); + + double correlationValue(); + +}; Index: python/autogcp/autogcp.sip =================================================================== --- python/autogcp/autogcp.sip (revision 0) +++ python/autogcp/autogcp.sip (revision 0) @@ -0,0 +1,23 @@ + +%Module qgis.autogcp 0 + +%Import QtCore/QtCoremod.sip +%Import QtGui/QtGuimod.sip +%Import QtXml/QtXmlmod.sip + +%Import core/core.sip + +%Include qgsautogcpmanager.sip +%Include qgsdatarow.sip +%Include qgselevationmanager.sip +%Include qgsgcp.sip +%Include qgsgcpdataset.sip +%Include qgsimageanalyzer.sip +%Include qgsimagedataset.sip +%Include qgsorthorectification.sip +%Include qgswaveletextractor.sip +%Include qgssalientpoint.sip +%Include qgsimagechip.sip +%Include qgsprojectionmanager.sip +%Include qgscrosscorrelator.sip + Index: python/autogcp/qgsimageanalyzer.sip =================================================================== --- python/autogcp/qgsimageanalyzer.sip (revision 0) +++ python/autogcp/qgsimageanalyzer.sip (revision 0) @@ -0,0 +1,52 @@ +/*************************************************************************** +qgsimageanalyzer.sip - The ImageAnalyzer class is responsible for the physical + analysis and processing of image data. This included detecting and extracting + GCP's and GCP chips from images, as well as searching for these reference + GCP chips on a raw image. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsImageAnalyzer +{ + +%TypeHeaderCode +#include +%End + +public: + /*! \brief QgsImageAnalyzer Constructor + Constructs an analyzer for the supplied image, ready to perform processing on this image. + */ + QgsImageAnalyzer(QgsImageDataSet* image = 0); + /*! \brief Extracts ground control points from the assigned image. + This method allocates a new QgsGCPDataSet and transfers ownership to the caller. + The GCP's contained in this set will have geographic reference coordinates and a usable Chip for matching. + If this method fails it returns an ampty set. + */ + QgsGCPDataSet* extractGcps(int amount); + /*! \brief Matches the supplied GCP set to the image dataset, using the GCP chips. + If the method was successful the supplied GCP set will have it's raw coordinates updated. + \param A pointer to the GCP set to use and update. + \return A pointer to the supplied GCP set, with updated coordinates, or NULL on failure + */ + QgsGCPDataSet* matchGcps(QgsGCPDataSet* gcpSet); + /*! \brief Sets the image dataset of this analyzer. + This can be used to change the image between operations, to enable reuse of the same QgsImageAnalyzer object. + */ + void setImage(QgsImageDataSet* image); + /*! \brief QgsImageAnalyzer Destructor + */ + virtual ~QgsImageAnalyzer(); +}; + Property changes on: python/autogcp/qgsimageanalyzer.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgsimagedataset.sip =================================================================== --- python/autogcp/qgsimagedataset.sip (revision 0) +++ python/autogcp/qgsimagedataset.sip (revision 0) @@ -0,0 +1,52 @@ +/*************************************************************************** +qgsimagedataset.sip - This class contains all external data related to an image + including the sensor model associated to the particular image. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ +class GDALDataset; +class QgsImageDataSet +{ + +%TypeHeaderCode +#include +%End + +public: + QgsImageDataSet(QString path); + QgsImageDataSet(GDALDataset* path); + virtual ~QgsImageDataSet(); + /**\brief Returns a pointer to the internal GDALDataset instance or NULL if initialization failed*/ + //GDALDataset* gdalDataset(); + /**\brief Returns true if this object failed to initialize with the given file*/ + bool failed() const; + /**\brief Returns the same as failed()*/ +// bool operator!() const; + /*!\brief Gets the width and height of the raster image in pixels + Returns the width through the xSize reference parameter and the height through ySize. + If the image did not load or initialize correctly it does nothing. + Use failed() to check validity of the object. +**/ + void imageSize(int& xSize, int& ySize) const; + int imageXSize() const; + int imageYSize() const; + /*! \brief Gets the number of raster bands in the image. + Returns the number of rasterbands in the image or 0 if it hasn't been initialized. + */ + int rasterBands(); + + /*! \brief Reads the value of the image at a specified point + */ + double readValue(int band, int xPixel, int yLine); +}; + Property changes on: python/autogcp/qgsimagedataset.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgsconnector.sip =================================================================== --- python/autogcp/qgsconnector.sip (revision 0) +++ python/autogcp/qgsconnector.sip (revision 0) @@ -0,0 +1,35 @@ +/*************************************************************************** +qgsgcpconnector.sip - This is an abstract class that provides an interface for + dealing directly with the underlying database. This includes methods for + creating, reading, updating and deleting data. This class must be extended + for specific database engines. Two included specialisations are planned, + namely the PostgreSQLConnector and the SQLiteConnector. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsGCPConnector +{ + +%TypeHeaderCode +#include +%End + +public: + QgsGCPConnector(); + virtual void insertRow(QgsDataRow); + virtual void updateRow(QgsDataRow); + virtual void selectRow(QgsDataRow); + virtual void deleteRow(QgsDataRow); + +}; Index: python/autogcp/qgsautogcpmanager.sip =================================================================== --- python/autogcp/qgsautogcpmanager.sip (revision 0) +++ python/autogcp/qgsautogcpmanager.sip (revision 0) @@ -0,0 +1,105 @@ +/*************************************************************************** +qgsautogcpmanager.sip - This class manages the operations that need to be performed by + the plug-in interface. Due to the clear separation of the core analysis + classes and the plugin-specific user interface classes, a bridge is required + between these different libraries. This class acts as the bridge, and removes + any business logic from the presentational duties of the UI classes. This is + done by delegating more specific operations to dedicated classes in the core + package. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +Last Modified: 25/07/2010 +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +struct IMAGE_INFO +{ +%TypeHeaderCode +#include +%End + QString pFileName; + QString pFilePath; + QString pFileFormat; + QString pFileSize; + QString pRasterWidth; + QString pRasterHeight; + QString pOriginCoordinates; + QString pPixelSize; + QDateTime pDateCreated; + QDateTime pDateModified; + QDateTime pDateRead; + QString pRasterBands; + QString pProjectionInfo; +}; + +class QgsAutoGCPManager +{ + +%TypeHeaderCode +#include +%End + +public: + QgsAutoGCPManager(); + /*! \brief Opens the sensed (raw) image to use + */ + bool openSensedImage(QString path); + /*! \brief Opens the reference (control) image to use + */ + bool openReferenceImage(QString path); + /*! \brief Sets the Sensor model string + The actual sensor model will be loaded from the registry using this string. + */ + void setSensorModel(QString sensorModel); + /*! \brief Sets the amount of GCP's to extract from the reference image. + */ + void setGcpCount(int count); + void clearGcpSet(); + /*! \brief Performs the extraction of Ground Control Points from the reference image. + This class is the owner of the returned dataset and destroys it when itself is destroyed. + \return A pointer to the managed GCP set. + */ + QgsGCPDataSet* extractControlPoints(); + /*! \brief Matches the current set of owned GCP's to the raw image + This class is the owner of the returned dataset and destroys it when itself is destroyed. + \return A pointer to the managed GCP set, or NULL if the operation failed. + */ + QgsGCPDataSet* matchControlPoints(); + /*! \brief Gets a pointer to the managed GCP set + This class is the owner of the returned dataset and destroys it when itself is destroyed. + \return A pointer to the managed GCP set. + */ + QgsGCPDataSet* gcpSet(); + /*! \brief Returns the raw image. + Return a pointer to the QgsImageDataSet containing the raw image dataset. + */ + QgsImageDataSet* rawImage(); + /*! \brief Returns the reference image. + Return a pointer to the QgsImageDataSet containing the reference image dataset. + */ + QgsImageDataSet* referenceImage(); + /*! \brief QgsAutoGCPManager destructor. + Deallocates all datasets created from any operations. + */ + virtual ~QgsAutoGCPManager(); + + void projectGCPs(); + bool setProjection(QgsImageDataSet *imageDataset, PROJ_INFO *projectionInfo); + + bool exportGcpSet(QString path); + bool exportGcpSet(QgsGCPDataSet *gcpSet, QString path); + void addGcp(QgsGCP *gcp); + void updateGcp(QgsGCP *gcp); + void removeGcp(QgsGCP *gcp); + IMAGE_INFO imageInfo(QString path); +}; + Property changes on: python/autogcp/qgsautogcpmanager.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgsorthorectification.sip =================================================================== --- python/autogcp/qgsorthorectification.sip (revision 0) +++ python/autogcp/qgsorthorectification.sip (revision 0) @@ -0,0 +1,31 @@ +/*************************************************************************** +qgsorthorectification.sip - This class is used to perform actual ortho-correction on images using + a supplied GCPSet, a SensorModel and, optionally, a Digital Elevation Model +(DEM). +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsOrthorectification +{ + +%TypeHeaderCode +#include +%End + +public: + QgsOrthorectification(); + QgsImageDataSet* orthorectify(); + ~QgsOrthorectification(); +}; + Property changes on: python/autogcp/qgsorthorectification.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgsdatarow.sip =================================================================== --- python/autogcp/qgsdatarow.sip (revision 0) +++ python/autogcp/qgsdatarow.sip (revision 0) @@ -0,0 +1,29 @@ +/*************************************************************************** +qgsdatarow.sip - Represents each row of data stored in the Postgre and SQLite +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsDataRow +{ + +%TypeHeaderCode +#include +%End + +public: + QgsDataRow(); + QMap* values; + virtual ~QgsDataRow(); +}; + Property changes on: python/autogcp/qgsdatarow.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgswaveletextractor.sip =================================================================== --- python/autogcp/qgswaveletextractor.sip (revision 0) +++ python/autogcp/qgswaveletextractor.sip (revision 0) @@ -0,0 +1,47 @@ +/*************************************************************************** +qgsgcp.sip - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: James Meyer (FoxHat Solutions) +Email : jamesmeyerx@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ +%Import QtCore/QtCoremod.sip +class QgsWaveletExtractor +{ +%TypeHeaderCode +#include +%End + +public: + /*! \brief QgsWaveletExtractor Constructor. + Performs initialization. + */ + QgsWaveletExtractor(QgsImageDataSet* image, double threshold = 1.0); + QgsWaveletExtractor(QgsImageDataSet* image, int featureXSize, int featureYSize, double threshold = 1.0); + /*! + \brief QgsWaveletExtractor destructor + This does not free the QgsImageDataSet object or any GCP data retrieved. + */ + ~QgsWaveletExtractor(); + /*! \brief performs the extraction of GCP's from the image + This method is guaranteed to extract at least the number of GCP's required, but will likely extract more. + The GCP's are ordered in decreasing order of saliency value (i.e. Sharpest points are first). + The caller of this function is responsible for dealocating the data. + */ + QList* extractFeatures(); + /*! \brief Checks wether this extractor initialized correctly and is ready for extraction. + If this method returns false, a likely reason is that the underlying image is invalid. + */ + bool initialized(); +}; Index: python/autogcp/qgsprojectionmanager.sip =================================================================== --- python/autogcp/qgsprojectionmanager.sip (revision 0) +++ python/autogcp/qgsprojectionmanager.sip (revision 0) @@ -0,0 +1,169 @@ +/*************************************************************************** +qgsprojectionmanager.cpp - The ProjectionManager class is responsible for the +projection of GCPs using the projection information either contained within the +Metadata of the image, or as specified by the user. +This class uses the GDAL Warp library to perform the projection on the provided +GCP chip. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +Author: Francois Maass +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ +class GDALWarpOptions; + +struct PROJ_INFO +{ + +%TypeHeaderCode +#include +%End + QString pGeographicCSName; + QString pProjectedCSName; + QString pVariantName; + QString pGeogName; + QString pDatumName; + QString pSpheroidName; + QString pPMName; + QString pAngularUnits; + double pStdP1; + double pStdP2; + double pCenterLat; + double pCenterLong; + double pFalseEasting; + double pFalseNorthing; + double pStandardParallel; + double pCentralMeridian; + double pPseudoStdParallelLat; + double pPseudoStdParallel1; + double pSatelliteHeight; + double pScale; + double pAzimuth; + double pRectToSkew; + double pLat1; + double pLong1; + double pLat2; + double pLong2; + double pLatitudeOfOrigin; + double pSemiMajor; + double pInvFlattening; + double pPMOffset; + double pConvertToRadians; + int pVariation; + int pZone; + int pNorth; + +}; + + +class QgsProjectionManager +{ +%TypeHeaderCode +#include +%End + +public: + + /*! \brief QgsProjectionManager Constructor + Constructs a projection manager that will handle all projection related processes. + \param A pointer to the GDAL reference image dataset. + \param A pointer to the GDAL raw image dataset. + */ + QgsProjectionManager(QgsImageDataSet *refImageDataset, QgsImageDataSet *rawImageDataset); + /*! \brief QgsProjectionManager Constructor + Constructs a projection manager that will handle all projection related processes. + */ + QgsProjectionManager(); + /*! \brief Set the reference image dataset + Sets the reference image to be used for the projection as a QgsImageDataSet + \param A pointer to the GDAL reference image dataset. + */ + void setReferenceImage(QgsImageDataSet *refImageDataset); + /*! \brief Set the raw image dataset + Sets the raw image to be used for the projection as a QgsImageDataSet + \param A pointer to the GDAL raw image dataset. + */ + void setRawImage(QgsImageDataSet *rawImageDataset); + + /*! \brief Get the reference image dataset + Gets the reference image to be used for the projection as a QgsImageDataSet + */ + QgsImageDataSet* referenceImage(); + /*! \brief Get the reference image dataset + Gets the reference image to be used for the projection as a QgsImageDataSet + */ + QgsImageDataSet* rawImage(); + /*! \brief Static initializer for projection manager + Initializes the required projected- and geographic- Coordinate System data. + */ + void initializeMaps(); + /*! \brief QgsProjectionManager Destructor + */ + ~QgsProjectionManager(); + /*! \brief Notifier for error messages. + Notifies QGSLogger of error that occured. + \param The message describing the error. + */ + void notifyFailure(QString message); + + /*! \brief Project a single GCP between coordinate systems + A single GCP is projected between two defined coordinate systems as retrieved from + the raw- and reference image dataset provided with the constructor. This function handles + all the processes required to fully project the provided GCP chip. + Note: It is assumed that both datasets have valid projection definitions when called. + To check projection information, see QgsProjectionManager::checkProjectionInformation(...). + \param A pointer to the QgsImageDataSet containing the chip. + \param A pointer to the QgsImageDataSet in which the chip is to be returned + */ + bool projectGCPChip(QgsImageDataSet* chipIn, QgsImageDataSet* chipOut); + + /*! \brief Project a single GCP between coordinate systems + A single GCP is projected between two defined coordinate systems as retrieved from + the raw- and reference image dataset provided with the constructor. This function handles + all the processes required to fully project the provided GCP chip. + Note: It is assumed that both datasets have valid projection definitions when called. + To check projection information, see QgsProjectionManager::checkProjectionInformation(...). + \param A pointer to the QgsGCP object containing the extracted GCP chip. + */ + void projectGCP(QgsGCP *originalGCP); + /*! \brief Defines the warp options for projections + Warp Options are defined based on information extracted from the source and destination + datasets. + \param The source GDAL dataset (original coordinate system) + \param The destination GDAL dataset (desired coordinate system) + \param True if a GDAL progress bar should be printed to standard output. + */ + GDALWarpOptions* getWarpOptions(GDALDataset *srcDataset, GDALDataset *dstDataset, bool progressBar); + /*! \brief Warp operation that handles projection + The provided dataset is warped/projected using the projection options provided as well as + information extracted from the GDAL raw- and reference image datasets. + \param The warp options as defined by QgsProjectionManager::getWarpOptions(...). + \param The dataset to be projected + */ + void warpDatasets(GDALWarpOptions *pswops, GDALDataset *dstDataset); + /*! \brief Warp data destroyer + Cleans up all the additional data created for the projection process + \param The warp options as defined by QgsProjectionManager::getWarpOptions(...). + */ + void destroyWarpData(GDALWarpOptions *pswops); + /*! \brief Checks for availability and validity of projection definition strings. + The provided dataset is checked to see if it contains the projection definition string. + \param The dataset to be checked. + */ + bool checkProjectionInformation(QgsImageDataSet *imageDataset); + /*! \brief Sets the projection definition string + The projection definition string is derived from information contained in the projectionInfo + container based on the options provided, and assigned to the dataset. + \param The dataset to which the projection definition string is to be assigned. + \param The projection Information container. + */ + bool setProjectionInformation(QgsImageDataSet *imageDataset, PROJ_INFO *projectionInfo); +}; + Index: python/autogcp/qgsgcp.sip =================================================================== --- python/autogcp/qgsgcp.sip (revision 0) +++ python/autogcp/qgsgcp.sip (revision 0) @@ -0,0 +1,46 @@ +/*************************************************************************** +qgsgcp.sip - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Christoph Stallmann (FoxHat Solutions) +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +class QgsGCP +{ + +%TypeHeaderCode +#include +%End + +public: + QgsGCP(); + ~QgsGCP(); + bool operator==(const QgsGCP& other) const; + double refX() const; + void setRefX(double value); + double refY() const; + void setRefY(double value); + double refZ() const; + void setRefZ(double value); + double rawX() const; + void setRawX(double value); + double rawY() const; + void setRawY(double value); + + QgsImageDataSet* gcpChip() const; + void setGcpChip(QgsImageDataSet* value); +}; + + Property changes on: python/autogcp/qgsgcp.sip ___________________________________________________________________ Added: svn:executable + * Index: python/autogcp/qgssalientpoint.sip =================================================================== --- python/autogcp/qgssalientpoint.sip (revision 0) +++ python/autogcp/qgssalientpoint.sip (revision 0) @@ -0,0 +1,46 @@ +/************************************************************************** +qgsgcp.cpp - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: James Meyer +Email : jamesmeyerx@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + + + +/*! + This class represents any point of interest on a two-dimensional raster image. +*/ +class QgsSalientPoint : QgsPoint +{ +%TypeHeaderCode +#include +#include +%End + public: + /*! \brief QgsFeature constructor + constructs a feature point at the given x, y coordinates and optionally a saliency value. + */ + QgsSalientPoint(double x = 0, double y = 0, double theSaliency = 0); + + /*! \brief Gets the Saliency value of this feature. + */ + double saliency()const; + + /*! \brief Sets the Saliency value of this feature. + */ + void setSaliency(double value); +}; + + Index: python/CMakeLists.txt =================================================================== --- python/CMakeLists.txt (revision 14199) +++ python/CMakeLists.txt (working copy) @@ -35,9 +35,6 @@ ADD_DEFINITIONS(-DNOMINMAX) ENDIF(MSVC) -IF(PYQT4_VERSION_NUM LESS 263680) # 0x040600 - SET(SIP_DISABLE_FEATURES ${SIP_DISABLE_FEATURES} PROXY_FACTORY) -ENDIF(PYQT4_VERSION_NUM LESS 263680) # core module FILE(GLOB sip_files_core core/*.sip) @@ -69,7 +66,18 @@ set(SIP_EXTRA_FILES_DEPEND ${sip_files_core} ${sip_files_analysis}) ADD_SIP_PYTHON_MODULE(qgis.analysis analysis/analysis.sip qgis_core qgis_analysis) +# additional autogcp includes +INCLUDE_DIRECTORIES( + ../src/autogcp + ${CMAKE_BINARY_DIR}/src/autogcp +) +# autogcp module +FILE(GLOB sip_files_autogcp autogcp/*.sip) +set(SIP_EXTRA_FILES_DEPEND ${sip_files_core} ${sip_files_autogcp}) +ADD_SIP_PYTHON_MODULE(qgis.autogcp autogcp/autogcp.sip qgis_core qgis_autogcp) + + SET (QGIS_PYTHON_DIR ${PYTHON_SITE_PACKAGES_DIR}/qgis) ADD_CUSTOM_TARGET(compile_python_files ALL) Index: src/autogcp/qgselevationmanager.h =================================================================== --- src/autogcp/qgselevationmanager.h (revision 0) +++ src/autogcp/qgselevationmanager.h (revision 0) @@ -0,0 +1,35 @@ +/*************************************************************************** +qgselevationmanager.cpp - The ElevationManager contains a Digital Elevation + Model of a specific reference image and allows sampling of the ground + elevation at different coordinates. This DEM is used in the orthorectification + process as well as chip projection. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSELEVATIONMANAGER_H +#define QGSELEVATIONMANAGER_H +#include +#include + +class QgsElevationManager +{ +public: + QgsElevationManager(); + double sampleHeight(int,int); + void openDEMFile(QString); + virtual ~QgsElevationManager(); +private: + QVector* mElevation; +}; + +#endif // QGSELEVATIONMANAGER_H Index: src/autogcp/qgscrosscorrelator.cpp =================================================================== --- src/autogcp/qgscrosscorrelator.cpp (revision 0) +++ src/autogcp/qgscrosscorrelator.cpp (revision 0) @@ -0,0 +1,218 @@ +/*************************************************************************** +qgscrosscorrelator.cpp - This class handles the cross correlation of two +subimages. +-------------------------------------- +Date : 12-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgscrosscorrelator.h" +#include "qgsimagedataset.h" +#include +#include +#include + +QgsCrossCorrelator::QgsCrossCorrelator(QgsImageDataSet* ref, QgsImageDataSet* raw) +{ + refChip = ref; + rawChip = raw; +} + +QgsCrossCorrelator::~QgsCrossCorrelator() +{ +} + +double QgsCrossCorrelator::correlationValue() +{ + //find the band(s) with which to calculate each distinct image's grey level: + int refbands = refChip->rasterBands(); + for (int i = 0; i < refbands; i++) + { + + GDALRasterBand* band = refChip->gdalDataset()->GetRasterBand(1); + GDALColorInterp color = band->GetColorInterpretation(); + + switch ( color ) + { + case GCI_GrayIndex: + { greyRefBand = i+1; refConvert = GREY; } + break; + case GCI_RedBand: + { redRefBand = i+1; refConvert = RGB; } + break; + case GCI_GreenBand: + { greenRefBand = i+1; refConvert = RGB; } + break; + case GCI_BlueBand: + { blueRefBand = i+1; refConvert = RGB; } + break; + case GCI_CyanBand: + { cyanRefBand = i+1; refConvert = CMYK; } + break; + case GCI_MagentaBand: + { magentaRefBand = i+1; refConvert = CMYK; } + break; + case GCI_YellowBand: + { yellowRefBand = i+1; refConvert = CMYK; } + break; + case GCI_BlackBand: + { blackRefBand = i+1; refConvert = CMYK; } + break; + default: + { + if (refbands < 3) + { + greyRefBand = 1; refConvert = GREY; + } + else + { + redRefBand = 1; greenRefBand = 2; blueRefBand = 3; refConvert = RGB; + } + } + break; //ASSUME RGB + } + if (color == GCI_GrayIndex) break; + } + + int rawbands = rawChip->rasterBands(); + for (int j = 0; j < rawbands; j++) + { + GDALRasterBand* band = rawChip->gdalDataset()->GetRasterBand(j+1); + GDALColorInterp color = band->GetColorInterpretation(); + + switch ( color ) + { + case GCI_GrayIndex: + { greyRawBand = j+1; rawConvert = GREY; } + break; + case GCI_RedBand: + { redRawBand = j+1; rawConvert = RGB; } + break; + case GCI_GreenBand: + { greenRawBand = j+1; rawConvert = RGB; } + break; + case GCI_BlueBand: + { blueRawBand = j+1; rawConvert = RGB; } + break; + case GCI_CyanBand: + { cyanRawBand = j+1; rawConvert = CMYK; } + break; + case GCI_MagentaBand: + { magentaRawBand = j+1; rawConvert = CMYK; } + break; + case GCI_YellowBand: + { yellowRawBand = j+1; rawConvert = CMYK; } + break; + case GCI_BlackBand: + { blackRawBand = j+1; rawConvert = CMYK; } + break; + default: + { + if (rawbands < 3) + { + greyRawBand = 1; rawConvert = GREY; + } + else + { + redRawBand = 1; greenRawBand = 2; blueRawBand = 3; rawConvert = RGB; + } + } + break; //ASSUME RGB + } + if (color == GCI_GrayIndex) break; + } + calculateAverages(); + return calculateCC(); +} + +//assumes that bands and Schemes have been set +void QgsCrossCorrelator::calculateAverages() +{ + refAvg = 0; + rawAvg = 0; + for (int i = 0; i < refChip->imageXSize(); i++) + { + + for (int j = 0; j < refChip->imageYSize(); j++) + { + refAvg += greyLevel(true, i, j); + } + } + refAvg = refAvg/(refChip->imageXSize()*refChip->imageYSize()); + + for (int i = 0; i < rawChip->imageXSize(); i++) + { + + for (int j = 0; j < rawChip->imageYSize(); j++) + { + rawAvg += greyLevel(false, i, j); + } + } + rawAvg = rawAvg/(rawChip->imageXSize()*rawChip->imageYSize()); +} + +double QgsCrossCorrelator::calculateCC() +{ + double num = 0.0; + double a = 0.0; + double b = 0.0; + for (int i = 0; i < refChip->imageXSize(); i++) + { + for (int j = 0; j < refChip->imageYSize(); j++) + { + //(ref's gray level - ref's avg gray level)*(raw's gray level - raw's avg gray level) + num += (greyLevel(true,i,j) - refAvg)*(greyLevel(false,i,j) - rawAvg); + //(ref's gray level - ref's avg gray level) + a += pow((greyLevel(true,i,j) - refAvg),2); + //(raw's gray level - raw's avg gray level) + b += pow((greyLevel(false,i,j) - rawAvg),2); + } + } + + double denom = pow((a*b),0.5); + return num/denom; +} + +double QgsCrossCorrelator::greyLevel(bool isRef, int x, int y) +{ + if (isRef) + { + + if (refConvert == GREY) return refChip->readValue(greyRefBand, x, y); + + if (refConvert == RGB) + { + return (refChip->readValue(redRefBand,x,y)*0.299 + refChip->readValue(greenRefBand,x,y)*0.587 + refChip->readValue(blueRefBand,x,y)*0.114); + } + else if (refConvert == CMYK) + { + return (refChip->readValue(cyanRefBand,x,y)*0.299 + refChip->readValue(magentaRefBand,x,y)*0.587 + refChip->readValue(yellowRefBand,x,y)*0.114 + refChip->readValue(blackRefBand,x,y)); + } + } + + else + { + + if (rawConvert == GREY) return rawChip->readValue(greyRawBand, x, y); + + if (rawConvert == RGB) + { + return (rawChip->readValue(redRawBand,x,y)*0.299 + rawChip->readValue(greenRawBand,x,y)*0.587 + rawChip->readValue(blueRawBand,x,y)*0.114); + } + else if (rawConvert == CMYK) + { + return (rawChip->readValue(cyanRawBand,x,y)*0.299 + rawChip->readValue(magentaRawBand,x,y)*0.587 + rawChip->readValue(yellowRawBand,x,y)*0.114 + rawChip->readValue(blackRawBand,x,y)); + } + else return 0.0; + } +} + + Index: src/autogcp/qgsfeatureextractor.cpp =================================================================== --- src/autogcp/qgsfeatureextractor.cpp (revision 0) +++ src/autogcp/qgsfeatureextractor.cpp (revision 0) @@ -0,0 +1,12 @@ +#include "qgsfeatureextractor.h" + +QgsFeatureExtractor::QgsFeatureExtractor() +{ +} + +QgsFeatureExtractor::~QgsFeatureExtractor() +{ +} + + + Index: src/autogcp/qgsimagedataset.cpp =================================================================== --- src/autogcp/qgsimagedataset.cpp (revision 0) +++ src/autogcp/qgsimagedataset.cpp (revision 0) @@ -0,0 +1,340 @@ +/*************************************************************************** +qgsimagedataset.cpp - This class contains all external data related to an image + including the sensor model associated to the particular image. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsimagedataset.h" +#include "qgslogger.h" +#include +#include +QgsImageDataSet::QgsImageDataSet(QString path): + mFilePath(path), + mBuffers(0), + mDataset(0) +{ + if (!initialize()) + { + mFail = true; + QgsLogger::debug("QgsImageDataSet::initialize() failed."); + }else + { + mFail = false; + } +} + +QgsImageDataSet::QgsImageDataSet(GDALDataset* dataset) +{ + if(!dataset) + { + mFail = true; + QgsLogger::debug("QgsImageDataSet::initialize() failed."); + + } else { + mDataset = dataset; + mXSize = mDataset->GetRasterXSize(); + mYSize = mDataset->GetRasterYSize(); + //Create Buffers + int bandCount = mDataset->GetRasterCount(); + mBuffers = new DataBuffer[bandCount]; + mFail = false; + } +} + +bool QgsImageDataSet::initialize() +{ + + registerGdalDrivers(); + + const char* filename = mFilePath.toLatin1().data(); + GDALDatasetH handle = GDALOpen(filename,GA_ReadOnly); + if (handle) + { + + mDataset = (GDALDataset*) handle; + mXSize = mDataset->GetRasterXSize(); + mYSize = mDataset->GetRasterYSize(); + //Create Buffers + int bandCount = mDataset->GetRasterCount(); + mBuffers = new DataBuffer[bandCount]; + + return true; + } + else + { + QgsLogger::debug(QString("Failed to open Image dataset. File path=")+mFilePath,1, "qgsimagedataset.cpp"); + return false; + } +}//bool QgsImageDataSet::initialize() + + + +QgsImageDataSet::~QgsImageDataSet() +{ + //printf("Deleting ImageDS\n"); + //delete mSensor; + if (mDataset) + { + //printf("Closing GDAL DS\n"); + GDALClose((GDALDatasetH)mDataset); + //printf("Closed GDAL DS\n"); + } + finalize(); +} + +GDALDataset* QgsImageDataSet::gdalDataset() +{ + return mDataset; +} + + +void QgsImageDataSet::registerGdalDrivers() +{ + if (0 == GDALGetDriverCount()) + { + GDALAllRegister(); + } +}//void QgsImageDataSet::registerGdalDrivers() + +bool QgsImageDataSet::failed() const +{ + return mFail; +} + +//Wrapper for failed() +bool QgsImageDataSet::operator!() const +{ + return failed(); +} + +QgsImageDataSet::operator bool() const +{ + return !failed(); +} + +void QgsImageDataSet::imageSize(int& xSize, int& ySize) const +{ + if (!failed()) + { + xSize = mXSize; + ySize = mYSize; + } +}//bool QgsImageDataSet::operator!() const + +int QgsImageDataSet::imageXSize() const +{ + return mXSize; +} +int QgsImageDataSet::imageYSize() const +{ + return mYSize; +} + +void* QgsImageDataSet::readLine(int theBand, int line) +{ + char message[100]; + //printf("READING BAND %d, line %d\n",theBand, line); + if (theBand > mDataset->GetRasterCount() || theBand < 1) + { + //Log debug message + return 0; + } + + DataBuffer& buffer = mBuffers[theBand - 1]; + for (int i = 0; i < mBufferCount; i++) + { + + + if (line ==buffer.line[i] && buffer.data[i]) + {//Has this line in the buffer already + sprintf(message, "In buffer: %d %d",line,i); + // QgsLogger::debug(message,1,"QgsImageDataSet::readLine()"); + return buffer.data[i]; + } + } + //ELSE************************************************** + //QgsLogger::debug(QString("Not Cached")); + GDALRasterBand* band = mDataset->GetRasterBand(theBand); + GDALDataType type = band->GetRasterDataType(); + //printf("%p \n", band); + int blockX,blockY; + if (line >= mYSize) + { + return 0; + } + + band->GetBlockSize(&blockX,&blockY); + // QgsLogger::debug(QString("is good ")); + int blocksToRead = mXSize / blockX; //Usually just one. + int yBlock = line / blockY; //Which block will be read + // int toAlloc = blocksToRead * blockX * blockY * GDALGetDataTypeSize(band->GetRasterDataType()); + int toAlloc = 1 * mXSize * (GDALGetDataTypeSize(type) / 8); + int curbuf = buffer.currentBuffer; + //QgsLogger::debug(QString("TO Alloc:")+QString::number(toAlloc)); + + if (!buffer.data[curbuf]) + { + buffer.data[curbuf] = VSIMalloc(toAlloc); + } +//QgsLogger::debug("Allocated Data",1,"QgsImageDataSet::readLine()"); + void* start; + CPLErr result; + /* for (int i = 0; i < blocksToRead; ++i) + { + start = dataIndex(buffer.data[curbuf], theBand, i * blockX); //Where to start reading data into + result = band->ReadBlock(i,yBlock,start); + }*/ + band->RasterIO(GF_Read, 0, line, mXSize, 1, buffer.data[curbuf], mXSize, 1, type,0,0 ); + + // QgsLogger::debug("Not in buffer"); + + + buffer.currentBuffer = ( curbuf + 1) % mBufferCount; + buffer.line[curbuf] = line; + + return buffer.data[curbuf]; +}//void* QgsImageDataSet::readLine(int iband, int line) + + +/*WARNING does NO bounds checking. +Gets a pointer to the index'th element in the array pointed to by data. +*/ +void* QgsImageDataSet::dataIndex(void* data,int band, int index) +{ + GDALDataType type = dataType(band); + switch ( type ) + { + case GDT_Byte: + return ( void* ) &(( GByte * )data )[index]; + break; + case GDT_UInt16: + return ( void* ) &(( GUInt16 * )data )[index]; + break; + case GDT_Int16: + return ( void* ) &(( GInt16 * )data )[index]; + break; + case GDT_UInt32: + return ( void* ) &(( GUInt32 * )data )[index]; + break; + case GDT_Int32: + return ( void* ) &(( GInt32 * )data )[index]; + break; + case GDT_Float32: + return ( void* ) &(( float * )data )[index]; + break; + case GDT_Float64: + // val = (( double * )data )[index]; + return ( void* ) &(( double * )data )[index]; + break; + default:; + // QgsLogger::warning( "GDAL data type is not supported" ); + } +}//void* QgsWaveletExtractor::dataIndex(void* data, int index) + +int QgsImageDataSet::rasterBands() +{ + if (mDataset) + { + return mDataset->GetRasterCount(); + } else + { + return 0; + } +} + +double QgsImageDataSet::readValue(int band, int xPixel, int yLine) +{ + if (xPixel < 0 + || xPixel >= mXSize + || yLine < 0 + || yLine >= mYSize) //Bounds check + { + return 0.0; + } + double value; + void* data = readLine(band, yLine); + // char message[100]; + // sprintf(message, "Data: %p", data); + // QgsLogger::debug(message,1,"QgsImageDataSet::readValue()"); + + GDALDataType type = dataType(band); + //printf("Data TYPE: %s\n", GDALGetDataTypeName(type)); + switch ( type ) + { + case GDT_Byte: + value = (double) (( GByte * )data )[xPixel]; + break; + case GDT_UInt16: + value =( double ) (( GUInt16 * )data )[xPixel]; + break; + case GDT_Int16: + value =( double) (( GInt16 * )data )[xPixel]; + break; + case GDT_UInt32: + value =( double) (( GUInt32 * )data )[xPixel]; + break; + case GDT_Int32: + value =( double) (( GInt32 * )data )[xPixel]; + break; + case GDT_Float32: + value =( double) (( float * )data )[xPixel]; + break; + case GDT_Float64: + // val = (( double * )data )[index]; + value =( double) (( double * )data )[xPixel]; + break; + default: return 0.0; + // QgsLogger::warning( "GDAL data type is not supported" ); + }//switch(type) + // QgsLogger::debug(QString::number(imageXSize())); + return value; +} +bool QgsImageDataSet::transformCoordinate(int& pixelX, int& pixelY, double& geoX, double& geoY, int mode) const +{ + double coef[6]; + if (mDataset->GetGeoTransform(coef) == CE_Failure) + { + return false; + } + if (mode == TM_PIXELGEO) + { + GDALApplyGeoTransform(coef, (double) pixelX, (double) pixelY, &geoX, &geoY); + } else {//TM_GEOPIXEL + double in[6]; + for (int i = 0; i<6; i++) + { + in[i] = coef[i]; + } + GDALInvGeoTransform(in, coef); + double resX, resY; + GDALApplyGeoTransform(coef, geoX, geoY, &resX, &resY); + pixelX = (int) resX; + pixelY = (int) resY; + } + return true; +} +void QgsImageDataSet::setImageSize(int xSize, int ySize) +{ + mXSize = xSize; + mYSize = ySize; +} + +GDALDataType QgsImageDataSet::dataType(int theBand) const +{ + return mDataset->GetRasterBand(theBand)->GetRasterDataType(); +} + +QString QgsImageDataSet::filePath() const +{ + return mFilePath; +} \ No newline at end of file Index: src/autogcp/qgserrorlist.h =================================================================== --- src/autogcp/qgserrorlist.h (revision 0) +++ src/autogcp/qgserrorlist.h (revision 0) @@ -0,0 +1,66 @@ +/*************************************************************************** +qgserrorlist.h - The QgsErrorList is a Singleton extension to the +QVector class that provides container functionality which is used to capture +and store any exceptions that may occur in other classes. +This allows errors or exceptions to be stored with extensive detail for use +by other classes or debugging purposes. +-------------------------------------- +Date : 12-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +Author: Francois Maass +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSERRORLIST_H +#define QGSERRORLIST_H + +#include +#include +#include "qgserror.h" +#include "qgslogger.h" + + +class QgsErrorList : public QVector +{ + public: + /*! \brief Returns the valid instance + Returns a pointer to an existing instance, or creates a new one if no other instance exists. + */ + static QgsErrorList* instance(); + /*! \brief Report an error + Reports an error to the main error list. + \param The message describing the error + \param The class name where the error occured + \param The function name where the error occured + \param The severity description of the error + \param True if the error should be printed to QgsLogger::debug() + */ + void reportError(QString message, QString classOccured, QString functionOccured, QString severity, bool printDebug); + /*! \brief Returns the last entered error + Returns the last submitted error in QString format + */ + QString lastError(); + /*! \brief Deletes the last error + */ + void deleteLastError(); + /*! \brief Composes a message + Composes a QString formatted message based on the provided QgsError + */ + QString composeMessage(QgsError err); + protected: + QgsErrorList(); + QgsErrorList(const QgsErrorList &errList){}; + QgsErrorList& operator=(const QgsErrorList &errList){}; + private: + static QgsErrorList *onlyInstance; +}; + + +#endif //QGSERRORLIST_H \ No newline at end of file Index: src/autogcp/qgsfeaturedetector.h =================================================================== --- src/autogcp/qgsfeaturedetector.h (revision 0) +++ src/autogcp/qgsfeaturedetector.h (revision 0) @@ -0,0 +1,15 @@ +#include "qgsgcpdataset.h" +#include + +/** +Abstract base class for detecting features / control points on an image +*/ +class QgsFeatureExtractor +{ +public: + virtual ~QgsFeatureExtractor(); + virtual QgsGCPDataSet* extractFeatures() = 0; +protected: +private: + QgsFeatureExtractor(); +}; Index: src/autogcp/qgsimagechip.h =================================================================== --- src/autogcp/qgsimagechip.h (revision 0) +++ src/autogcp/qgsimagechip.h (revision 0) @@ -0,0 +1,39 @@ +/*************************************************************************** +qgsgcp.cpp - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSIMAGECHIP_H +#define QGSIMAGECHIP_H +#include "qgsimagedataset.h" +class QgsImageChip : public QgsImageDataSet +{ +public: + static QgsImageChip* createImageChip(int width, int height, GDALDataType type, int bands = 3); + ~QgsImageChip(); + QgsImageChip(const QgsImageChip& other); + + void* data() {return mData;} +protected: + virtual void finalize(); +private: + QgsImageChip(GDALDataset* dataset); + const QgsImageChip& operator =(const QgsImageChip& other); + + void* mData; +}; + +#endif //QGSIMAGECHIP_H Index: src/autogcp/qgsautogcpmanager.cpp =================================================================== --- src/autogcp/qgsautogcpmanager.cpp (revision 0) +++ src/autogcp/qgsautogcpmanager.cpp (revision 0) @@ -0,0 +1,323 @@ +/*************************************************************************** +qgsmanager.cpp - This class manages the operations that need to be performed by + the plug-in interface. Due to the clear separation of the core analysis + classes and the plugin-specific user interface classes, a bridge is required + between these different libraries. This class acts as the bridge, and removes + any business logic from the presentational duties of the UI classes. This is + done by delegating more specific operations to dedicated classes in the core + package. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsautogcpmanager.h" +#include "qgsimageanalyzer.h" +#include "qgslogger.h" + +QgsAutoGCPManager::QgsAutoGCPManager(): +mRawImage(NULL), +mRefImage(NULL), +mGcpSet(NULL), +mProjManager(NULL), +mNumGcps(60) +{ + //mGcpSet = new QgsGCPDataSet(); +} + +bool QgsAutoGCPManager::openSensedImage(QString path) +{ + if (mRawImage) + { + delete mRawImage; + } + mRawImage = new QgsImageDataSet(path); + + if(!mProjManager) + { + mProjManager = new QgsProjectionManager(); + } + bool val = mProjManager->checkProjectionInformation(mRawImage); + return val; +} + +bool QgsAutoGCPManager::openReferenceImage(QString path) +{ + if (mRefImage) + { + delete mRefImage; + } + mRefImage = new QgsImageDataSet(path); + + if(!mProjManager) + { + mProjManager = new QgsProjectionManager(); + } + bool val = mProjManager->checkProjectionInformation(mRefImage); + return val; +} + +void QgsAutoGCPManager::setSensorModel(QString sensorModel) +{ + +} +void QgsAutoGCPManager::setGcpCount(int count) +{ + mNumGcps = count; +} +void QgsAutoGCPManager::clearGcpSet() +{ + if (mGcpSet) + mGcpSet->clear(); +} +QgsGCPDataSet* QgsAutoGCPManager::extractControlPoints() +{ + QgsLogger::debug("Starting Control Point Extraction",1,"qgsautogcpmanager.cpp","QgsAutoGCPManager::extractControlPoints()"); + if (mRefImage) + { + + QgsImageAnalyzer* pIA = new QgsImageAnalyzer(mRefImage); + //QgsGCPDataSet* set = pIA->extractGcps(mNumGcps); + + QgsGCPDataSet* pSet = pIA->extractGcps(mNumGcps); + if (pSet) + { + if (mGcpSet)//If already a current set, add to it. + { + const QList& list = pSet->constList(); + QList::const_iterator it; + for (it = list.constBegin(); it != list.constEnd(); ++it) + { + mGcpSet->addGcp(*it); + } + } else {//Else make this the default set. + mGcpSet = pSet; + } + } else { + QgsLogger::debug("Failed to extract GCPs",1,"qgsautogcpmanager.cpp","QgsAutoGCPManager::extractControlPoints()"); + } +} else { + QgsLogger::debug("Invalid Reference Image",1,"qgsautogcpmanager.cpp","QgsAutoGCPManager::extractControlPoints()"); +} +return mGcpSet; + +} + +QgsGCPDataSet* QgsAutoGCPManager::matchControlPoints() +{ + if (mRawImage) + { + QgsImageAnalyzer* pIA = new QgsImageAnalyzer(mRawImage); + QgsGCPDataSet* pSet = pIA->matchGcps(mGcpSet); + if (pSet) + { + mGcpSet = pSet; + } + } + return mGcpSet; +} + +QgsGCPDataSet* QgsAutoGCPManager::gcpSet() +{ + return mGcpSet; +} + + +QgsAutoGCPManager::~QgsAutoGCPManager() +{ + if (mRawImage) + { + delete mRawImage; + } + if (mRefImage) + { + delete mRefImage; + } + + if (mGcpSet) + { + delete mGcpSet; + } + +} + +void QgsAutoGCPManager::projectGCPs() +{ + if(!mGcpSet) + { + QgsLogger::debug("Cannot project GCPs, invalid GCP set."); + return; + } + //f(!mProjManager) + //{ + // mProjManager = new QgsProjectionManager(mRefImage, mRawImage); + //} + if(mProjManager) + { + std::cout<<"Deleted PROJECTION MANAGER"<& list = mGcpSet->list(); + QList::const_iterator it = list.constBegin(); + for (; it != list.constEnd(); ++it) + { + mProjManager->projectGCP(*it); + } +} + +bool QgsAutoGCPManager::setProjection(QgsImageDataSet *imageDataset, PROJ_INFO *projectionInfo) +{ + if(!mProjManager) + { + mProjManager = new QgsProjectionManager(mRefImage, mRawImage); + } + return mProjManager->setProjectionInformation(imageDataset, projectionInfo); +} + +bool QgsAutoGCPManager::exportGcpSet(QString path) +{ + return exportGcpSet(mGcpSet, path); +} + +bool QgsAutoGCPManager::exportGcpSet(QgsGCPDataSet *gcpSet, QString path) +{ + QFile file(path); + if (file.open(QFile::WriteOnly | QFile::Truncate)) + { + QTextStream out(&file); + out << "mapX\tmapY\tpixelX\tpixelY\n"; + QList gcpList = gcpSet->list(); + for(int i = 0; i < gcpList.size(); i++) + { + QgsGCP *gcp = gcpList[i]; + QString var1; + var1.sprintf("%.15f", gcp->refX()); + QString var2; + var2.sprintf("%.15f", gcp->refY()); + QString var3; + var3.sprintf("%.15f", gcp->rawX()); + QString var4; + var4.sprintf("%.15f", gcp->rawY()); + out << var1 << "\t" << var3 << "\t" << var3 << "\t" << var4 << "\n"; + } + file.close(); + return true; + } + return true; +} + +void QgsAutoGCPManager::addGcp(QgsGCP *gcp) +{ + if (!mGcpSet) //if set wasn't instantiated before + { + mGcpSet = new QgsGCPDataSet(); + } + mGcpSet->addGcp(gcp); + QgsLogger::debug("GCP added to set",1,"qgsautogcpmanager.cpp","QgsAutoGCPManager::addGcp()"); +} + +void QgsAutoGCPManager::updateGcp(QgsGCP *gcp) +{ + QgsGCP *tempGcp; + const QList& list = mGcpSet->constList(); + QList::const_iterator it; + for (it = list.constBegin(); it != list.constEnd(); ++it) + { + tempGcp = (*it); + if(tempGcp->refX() == gcp->refX() && tempGcp->refY() == gcp->refY()) + { + mGcpSet->updateGcp(tempGcp, gcp); + QgsLogger::debug("GCP updated in set",1,"qgsautogcpmanager.cpp","QgsAutoGCPManager::updateGcp()"); + break; + } + } +} + +void QgsAutoGCPManager::removeGcp(QgsGCP *gcp) +{ + QgsGCP *tempGcp; + const QList& list = mGcpSet->constList(); + QList::const_iterator it; + for (it = list.constBegin(); it != list.constEnd(); ++it) + { + tempGcp = (*it); + if(tempGcp->refX() == gcp->refX() && tempGcp->refY() == gcp->refY() && tempGcp->rawX() == gcp->rawX() && tempGcp->rawY() == gcp->rawY()) + { + mGcpSet->removeGcp(tempGcp); + QgsLogger::debug("GCP removed from set",1,"qgsautogcpmanager.cpp","QgsAutoGCPManager::removeGcp()"); + break; + } + } +} + +IMAGE_INFO QgsAutoGCPManager::imageInfo(QString path) +{ + QFileInfo fileInfo(path); + IMAGE_INFO info; + QString fileName = path.right(path.length()-path.lastIndexOf("/")-1); + info.pFileName = fileName.left(fileName.lastIndexOf(".")); + info.pFilePath = path; + info.pFileFormat = fileName.right(fileName.length()-fileName.lastIndexOf(".")-1).toUpper(); + qint64 fileSize = fileInfo.size(); + if(fileSize < 1024) + { + info.pFileSize = QString::number(fileSize)+" B"; + }else if(fileSize < 1048576) + { + info.pFileSize = QString::number(fileSize/1024)+" KB"; + }else if(fileSize < 1073741824) + { + info.pFileSize = QString::number(fileSize/1048576)+" MB"; + }else if(fileSize >= 1073741824) + { + info.pFileSize = QString::number(fileSize/1073741824)+" GB"; + }else + { + info.pFileSize = "Unknown"; + } + QgsImageDataSet *image; + if(mRefImage != NULL && mRefImage->filePath() == path) + { + image = mRefImage; + }else if(mRawImage != NULL && mRawImage->filePath() == path) + { + image = mRawImage; + } + if((*image) != NULL) + { + info.pRasterWidth = QString::number(image->gdalDataset()->GetRasterXSize()); + info.pRasterHeight = QString::number(image->gdalDataset()->GetRasterYSize()); + info.pRasterBands = QString::number(image->gdalDataset()->GetRasterCount()); + double adfGeoTransform[6]; + if(image->gdalDataset()->GetGeoTransform( adfGeoTransform ) == CE_None ) + { + QString var1; + QString var2; + info.pOriginCoordinates = var1.sprintf("%.6f %.6f", adfGeoTransform[0], adfGeoTransform[3]); + info.pPixelSize = var2.sprintf("%.6f %.6f", adfGeoTransform[1], adfGeoTransform[5]); + } + info.pProjectionInfo = image->gdalDataset()->GetProjectionRef(); + }else + { + info.pRasterWidth = "Unknown"; + info.pRasterHeight = "Unknown"; + info.pRasterBands = "Unknown"; + info.pProjectionInfo = "Unknown"; + info.pPixelSize = "Unknown"; + info.pOriginCoordinates = "Unknown"; + } + info.pDateCreated = fileInfo.created(); + info.pDateModified = fileInfo.lastModified(); + info.pDateRead = fileInfo.lastRead(); + return info; +} \ No newline at end of file Index: src/autogcp/qgsimageanalyzer.h =================================================================== --- src/autogcp/qgsimageanalyzer.h (revision 0) +++ src/autogcp/qgsimageanalyzer.h (revision 0) @@ -0,0 +1,126 @@ +/*************************************************************************** +qgsimageanalyzer.cpp - The ImageAnalyzer class is responsible for the physical + analysis and processing of image data. This included detecting and extracting + GCP�s and GCP chips from images, as well as searching for these reference + GCP chips on a raw image. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com + +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSIMAGEANALYZER_H +#define QGSIMAGEANALYZER_H +#include "qgsgcpdataset.h" +#include "qgsimagedataset.h" +#include "qgssalientpoint.h" +#include +#include +#define CHIPTYPE GDT_Byte +#define DEFAULT_CHIP_SIZE 32 +#define DEFAULT_CHIP_BANDS 3 +#define UNKNOWN_TYPE GDT_Unknown +class QgsImageAnalyzer +{ + +friend class QgsGrid; +public: + /*! \brief QgsImageAnalyzer Constructor + Constructs an analyzer for the supplied image, ready to perform processing on this image. + */ + QgsImageAnalyzer(QgsImageDataSet* image = 0); + /*! \brief Extracts ground control points from the assigned image. + This method allocates a new QgsGCPDataSet and transfers ownership to the caller. + The GCP's contained in this set will have geographic reference coordinates and a usable Chip for matching. + If this method fails it returns NULL + */ + QgsGCPDataSet* extractGcps(int amount); + /*! \brief Matches the supplied GCP set to the image dataset, using the GCP chips. + If the method was successful the supplied GCP set will have it's raw coordinates updated. + \param A pointer to the GCP set to use and update. + \return A pointer to the supplied GCP set, with updated coordinates, or NULL on failure + */ + QgsGCPDataSet* matchGcps(QgsGCPDataSet* gcpSet); + + /*! \brief QgsImageAnalyzer Destructor + */ + virtual ~QgsImageAnalyzer(); + + /*! \brief Extracts an area of this image analyzer's dataset into a new dataset. + The size of the area to be extracted must be specified, as well as the point on the source image to start copying from. + The data is read into the destination dataset or, if NULL is specified a new in-memory raster is created for the chip. + The datatype of the extracted chip will be the same + \param sourcePoint The x, y pixel coordinates on the source image to start copying from. + \param xPixels The width in pixels of the area to extract. + \param yLines The height in lines of the area to extract. + \param bands The number of bands to extract. If set to -1 the method will extract as many as the source dataset has. + \param type The datatype of the destination chip. If unknown it defaults to source datatype. + \param dest The destination dataset. + */ + QgsImageDataSet* extractChip(QgsPoint& sourcePoint, int xPixels, int yLines, int bands = -1, GDALDataType type = UNKNOWN_TYPE, QgsImageDataSet* dest = NULL); + + //*****************GETTERS & SETTERS**************************************************** + /*! \brief Sets the image dataset of this analyzer. + This can be used to change the image between operations, to enable reuse of the same QgsImageAnalyzer object. + */ + void setImage(QgsImageDataSet* image){mImageData = image;}; + QgsImageDataSet* image() const {return mImageData;} + void setChipSize(int xSize, int ySize) {mChipSize.width =xSize; mChipSize.height = ySize;} + int chipXSize() const{return mChipSize.width;} + int chipYSize() const{return mChipSize.height;} + void setChipBandCount(int bands) {mChipBandCount = bands;} + int chipBandCount() const {return mChipBandCount;} + GDALDataType chipDataType()const{return mChipType;} + void setChipDataType(GDALDataType type){mChipType = type;} + //******************************************************************************************** +private: + //************PRIVATE TYPES; + typedef GByte ChipType; //Note: this typedef is only the default chiptype and shouldn't be relied on. + typedef struct + { + int width; + int height; + } Dimension; + + typedef struct GridBlock + { + int xBegin, yBegin, xEnd, yEnd; + QList gcps; + } GridBlock; + + //**************PRIVATE CLASSES****************** + class QgsGrid + { + friend class QgsImageAnalyzer; + + QgsGrid(int saSize, QgsImageDataSet* image); + + void fillGrid(QgsGCPDataSet* gcpSet); + QList gridList(QgsGCP* refGcp); + + GridBlock* blocks; + QgsImageDataSet* mImageData; + int rows, cols, blockSize; + }; + //**************PRIVATE METHODS******************* + const char* gdalDriver(char* buffer) const; + void setDataValue(void* data,GDALDataType type, int index, double value); + double dataValue(void* data,GDALDataType type, int index); +private: + //**************PRIVATE MEMBERS****************** + QgsImageDataSet* mImageData; + Dimension mChipSize; + int mChipBandCount; +GDALDataType mChipType; + +}; + +#endif // QGSIMAGEANALYZER_H Index: src/autogcp/qgsdatasource.h =================================================================== --- src/autogcp/qgsdatasource.h (revision 0) +++ src/autogcp/qgsdatasource.h (revision 0) @@ -0,0 +1,71 @@ +/*************************************************************************** +qgsdatasource.cpp - The DataSource class is the data access layer between the + program logic and the database. For different installations of the system, + the DataSource may use a different Connector to interface with different + database engines. The DataSource performs operations such as constructing + mapping objects from database records, as well as the inverse of making these + objects persistent. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSDATASOURCE_H +#define QGSDATASOURCE_H +#include "qgshasher.h" +#include "qgsgcpdataset.h" +#include "qgsimagedataset.h" +#include "qgssqlitedriver.h" +#include "qgssqldriver.h" +#include "qgspostgresdriver.h" +#include +#include +#include +#include + +class QgsDataSource +{ +public: + enum DatabaseType + { + SQLite, + Postgres + }; + QgsDataSource(const DatabaseType type, const QgsHasher::HashAlgorithm hashAlgorithm = QgsHasher::Md5); + bool createDatabase(const QString path); + bool createDatabase(const QString databseName, const QString username, const QString password, const QString host); + bool insertGcpSet(const QgsGCPDataSet *gcpSet, const QgsImageDataSet *refImage); + QgsGCPDataSet* selectByImage(const QgsImageDataSet *image); + + QgsGCPDataSet* selectByHash(const QString hash); + QgsSqlDriver* driver(); + void deleteDriver(); + + QgsHasher::HashAlgorithm hashAlgorithm(); + void setHashAlogorithm(QgsHasher::HashAlgorithm hashAlgorithm); + + QgsGCPDataSet selectByLocation(double, double, double); + bool storeGCPSet(QgsGCPDataSet); + + virtual ~QgsDataSource(); +private: + bool createSqliteDatabase(const QString path); + bool createPostgresDatabase(const QString databseName, const QString username, const QString password, const QString host); + + QSqlQuery executeQuery(const QString query); + QgsHasher::HashAlgorithm mHashAlgorithm; + DatabaseType mType; + QgsHasher *mHasher; + QgsSqliteDriver *mSqliteDriver; + QgsPostgresDriver *mPostgresDriver; +}; + +#endif // QGSDATASOURCE_H Index: src/autogcp/qgsorthorectification.cpp =================================================================== --- src/autogcp/qgsorthorectification.cpp (revision 0) +++ src/autogcp/qgsorthorectification.cpp (revision 0) @@ -0,0 +1,31 @@ +/*************************************************************************** +qgsorthorectification.cpp - This class is used to perform actual ortho-correction on images using + a supplied GCPSet, a SensorModel and, optionally, a Digital Elevation Model +(DEM). +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsorthorectification.h" + +QgsOrthorectification::QgsOrthorectification() +{ +} + +QgsImageDataSet* QgsOrthorectification::orthorectify() +{ + return 0; +} + +QgsOrthorectification::~QgsOrthorectification() +{ +} Index: src/autogcp/qgssensormodel.h =================================================================== --- src/autogcp/qgssensormodel.h (revision 0) +++ src/autogcp/qgssensormodel.h (revision 0) @@ -0,0 +1,34 @@ +/*************************************************************************** +qgssensormodel.cpp - +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSSENSORMODEL_H +#define QGSSENSORMODEL_H +#include "qgsgcp.h" +#include +#include +#include + +class QgsSensorModel +{ +public: + QgsSensorModel(); + void projectGCP(QgsGCP); + void projectPoint(QPoint); + virtual ~QgsSensorModel(); +private: + std::vector mAttributes; +}; + +#endif // QGSSENSORMODEL_H Index: src/autogcp/qgsdatarow.cpp =================================================================== --- src/autogcp/qgsdatarow.cpp (revision 0) +++ src/autogcp/qgsdatarow.cpp (revision 0) @@ -0,0 +1,25 @@ +/*************************************************************************** +qgsdatarow.cpp - Represents each row of data stored in the Postgre and SQLite +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsdatarow.h" + +QgsDataRow::QgsDataRow() +{ +} + +QgsDataRow::~QgsDataRow() +{ + delete values; +} Index: src/autogcp/qgswaveletextractor.cpp =================================================================== --- src/autogcp/qgswaveletextractor.cpp (revision 0) +++ src/autogcp/qgswaveletextractor.cpp (revision 0) @@ -0,0 +1,496 @@ +#include "qgswaveletextractor.h" +#include +#include +#include +#include +#include +#include +#include "qgslogger.h" +#include +#include +#ifndef MAX + #define MAX(x, y) \ + ((x > y) ? x : y) +#endif +QgsWaveletExtractor::QgsWaveletExtractor(QgsImageDataSet* image, double threshold): + mImage(image), + mRasterBand(0), + mLevels(DEFAULT_LEVELS), + mThreshold(threshold), + mLimit(SAL_LIMIT), + mBlackLimit(DEFAULT_BLACK_LIMIT) +{ + mInitialized = initialize(); + mChipSize = (int)pow(2, mLevels); +}//QgsWaveletExtractor::QgsWaveletExtractor(QgsImageDataSet* image, unsigned int numPoints) + +QgsWaveletExtractor::QgsWaveletExtractor(QgsImageDataSet* image, int featureXSize, int featureYSize, double threshold): + mImage(image), + mRasterBand(0), + mThreshold(threshold), + mLimit(SAL_LIMIT), + mBlackLimit(DEFAULT_BLACK_LIMIT) +{ + setFeatureSize(featureXSize, featureYSize); + //Initialize + mInitialized = initialize(); +} + +void QgsWaveletExtractor::setFeatureSize(int xSize, int ySize) +{ + int fSize = MAX(xSize , ySize); + //Calculate the number of decomposition levels based on feature size; + mLevels = (int) ceil(log10((double) fSize) / log10((double) 2) ); + mChipSize = (int)pow(2, mLevels); +} + +bool QgsWaveletExtractor::initialize() +{ + if (mImage && !mImage->failed()) + { + + int xSize,ySize; + int biggestSize; + mRasterBand = rasterBand(); + mImage->imageSize(xSize, ySize); + if (xSize == 0 || ySize ==0) + { + QgsLogger::debug("Image has zero size",1, "qgswaveletextractor.cpp","QgsWaveletExtractor::initialize()"); + return false; + } + //Get the largest power of two as both width and height for the Haar algorithm + if (xSize > ySize) + { + biggestSize = xSize; + } else + { + biggestSize = ySize; + } + + double powerOfTwo = ceil(log10((double) biggestSize) / log10((double) 2) ); + mPaddedSize = (int) pow(2 , powerOfTwo); + return true; + } else { + QgsLogger::debug("Invalid QgsImageDataSet object",1,"qgswaveletextractor.cpp","QgsWaveletExtractor::initialize()"); + return false; + } +} + +QgsWaveletExtractor::~QgsWaveletExtractor() +{ +}//QgsWaveletExtractor::~QgsWaveletExtractor() + +//QgsGCPDataSet* +QList* QgsWaveletExtractor::extractFeatures() +{ + if (!mInitialized) + { + QgsLogger::debug("Wavelet not initialized",1,"qgswaveletextractor.cpp","QgsWaveletExtractor::extractFeatures()"); + return NULL; + } + + + QgsLogger::debug(QString("Levels: ") + QString::number(mLevels) ); + bool bProceed = true; + QList* result = NULL; + //QString message = "Using raster band "+ QString::number(rasterBand()); + // QgsLogger::debug(message,1,"qgswaveletextractor.cpp","QgsWaveletExtractor::extractFeatures()"); + for (int i = 1; i <= mLevels; ++i) + { + if (!decompose(i)) + { + QString message = "QgsWaveletExtractor::decompose("+ QString::number(i) + ") failed."; + QgsLogger::debug(message,1,"qgswaveletextractor.cpp","QgsWaveletExtractor::extractFeatures()"); + bProceed = false; + break; + } + } + if (bProceed) + { + result = reconstruct(); + } else { + result = NULL; + } + cleanUp(); + return result; +}//QgsWaveletExtractor::extractFeatures() + +bool QgsWaveletExtractor::initialized() +{ + return mInitialized; +} +//Finds the best rasterband to use if it hasn't already been set. +int QgsWaveletExtractor::rasterBand() +{ + if ( ! mImage ) + { + return 0; + } + if (mRasterBand > 0) + { + return mRasterBand; + } + int bands = mImage->rasterBands(); + if (2 <= bands) + { + return 2; //Prefer The Green band + } else if ( 1 == bands ) + { + return 1; + } else + { + return 0; + } + +} //QgsWaveletExtractor::rasterBand() + + +//Level 1 is done completely separate from the other levels. +//Although the algorithms are very similar, the separation is at the highest level, +//..to avoid having to evaluate the condition at each iteration. +bool QgsWaveletExtractor::decompose(int level) +{ + char message[100]; + char debug[200]; + + int datasize = (int) (mPaddedSize / pow(2,level)); + + long dataToWrite = datasize * sizeof(float); + + float* result = new float[datasize]; + std::string filename =generateTmpFileName(level); + std::ofstream out(filename.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); + + //QgsLogger::debug(QString("Created Temporary File: ") + filename.c_str() ); + int index = 0; + if (!out) + { + //char message[100]; + sprintf(message,"Failed to create temporary file %s",filename.c_str()); + QgsLogger::debug(QString(message),1,"qgswaveletextractor.cpp","QgsWaveletExtractor::decompose(int level)" ); + return false; + } + if (level == 1) //First level reads from the actual image + { + //assert(datasize == mPaddedSize / 2); + // QgsLogger::debug(QString("Starting level 1: ")); + for (int y = 0; y < datasize; ++y) + { + index = 0; + for (int x = 0; x < datasize; ++x) + { + int xcoord = x * 2; + int ycoord = y * 2; + double value[4]; + value[0] = readValue(xcoord, ycoord); + + value[1] = readValue(xcoord+1, ycoord); + value[2] = readValue(xcoord, ycoord+1); + value[3] = readValue(xcoord + 1, ycoord +1); + + float avg1 = (readValue(xcoord, ycoord ) + readValue(xcoord+1, ycoord ) ) / 2; + float avg2 = (readValue(xcoord, ycoord+1 ) + readValue(xcoord+1, ycoord+1 ) ) / 2; + + // printf("Values: %6.3f, %6.3f, %6.3f, %6.3f -Averages: %6.3f, %6.3f = %6.3f \n", value[0],value[1],value[2],value[3],avg1, avg2, (avg1 + avg2)/2); + // QgsLogger::debug(QString(debug)); + result[index++] = (avg1+avg2) / 2; + } + out.write((const char*) result, datasize * sizeof(float)); + } + // sprintf(message,"Completed Level 1"); + // QgsLogger::debug(QString(message),1,"qgswaveletextractor.cpp","QgsWaveletExtractor::decompose(int level)" ); + } else //All other levels read from the temp files. + { + std::string tempfile =generateTmpFileName(level - 1); + std::ifstream input(tempfile.c_str(), std::ios::in | std::ios::binary); //Previous level file to get the data + + if (!input) + { + char message[100]; + sprintf(message,"Failed to create temporary file %s",filename.c_str()); + QgsLogger::debug(QString(message),1,"qgswaveletextractor.cpp","QgsWaveletExtractor::decompose(int level)" ); + return false; + } + + input.seekg(0,std::ios::beg);//Put pointer back to begin. + + float* line1 = new float[datasize*2]; + float* line2 = new float[datasize*2]; + for (int y = 0; y < datasize; ++y) + { + index = 0; + input.read((char*) line1, dataToWrite * 2); //Previous level dataline is twice the length of this level + input.read((char*) line2, dataToWrite * 2); + for (int x = 0; x < datasize; ++x) + { + int xcoord = x * 2; + + float avg1 = (line1[xcoord] + line1[xcoord+1]) / 2; + float avg2 = (line2[xcoord] + line2[xcoord+1]) / 2; + //printf("Values: %6.3f, %6.3f, %6.3f, %6.3f -Averages: %6.3f, %6.3f = %6.3f \n",line1[xcoord],line1[xcoord+1],line2[xcoord],line2[xcoord+1],avg1, avg2, (avg1 + avg2)/2); + //QgsLogger::debug(debug); + result[index++] = (avg1+avg2) / 2; + } + out.write((const char*) result, dataToWrite); + } + input.close(); + + delete [] line1; + delete [] line2; + } + out.close(); + delete [] result; + return true; +}//QgsWaveletExtractor::decompose(); + +//QgsGCPDataSet* +QList* QgsWaveletExtractor::reconstruct() +{ + + // QgsLogger::debug("Reconstruction Started",1,"qgswaveletextractor.cpp","QgsWaveletExtractor::decompose(int level)" ); + int iDimension = (int) (mPaddedSize / pow(2,mLevels)); + // printf("iDimension: %d", iDimension); + //QgsLogger::debug(QString("Total salient points to extract:") + QString::number(iDimension*iDimension)); + int iDataSize = iDimension * iDimension * sizeof(float); + float *pAverages = new float[iDimension * iDimension]; + + // printf("Padded Size: %d iDimension: %d", (int)mPaddedSize,(int) iDimension ); + + float pValues[4]; + std::ifstream is(generateTmpFileName(mLevels).c_str(), std::ios::in | std::ios::binary); + if (!is) + { + QgsLogger::debug("Could not open highest level temp file",1,"qgswaveletextractor.cpp","QgsWaveletExtractor::reconstruct()"); + return NULL; + } + is.read((char*) pAverages,iDataSize); + if (is.fail()) + { + QgsLogger::debug("Highest level temp file is corrupt",1,"qgswaveletextractor.cpp","QgsWaveletExtractor::reconstruct()"); + return NULL; + } + is.close(); + //Create the GCP's + QgsSalientPoint *pGcp = new QgsSalientPoint[iDimension*iDimension]; + //initialize GCP's + for (int y = 0; y < iDimension; ++y) + { + for (int x = 0; x < iDimension; ++x) + { + pGcp[y*iDimension + x].setX(x); + pGcp[y*iDimension + x].setY(y); + + } + } + //float fAvg; + for (int level = mLevels - 1; level >= 0; --level) + { + int curDimension = (int) (mPaddedSize / pow(2,level)); + //int iOrigDim = (int) (mPaddedSize / pow(2,level-1)); + // printf("-------------------RECONSTRUCTION LEVEL %d \n",level); + std::string filename; + if (level > 0) + { + filename = generateTmpFileName(level); + is.open(filename.c_str(),std::ios::in | std::ios::binary); + } + for (int y = 0; y < iDimension; ++y)//Only work on selected points + { + float* line1; + float *line2; + for (int x = 0; x < iDimension; ++x) + { + float &fAvg = pAverages[y*iDimension + x]; + // printf("%d,%d Avg=%6.3f \n",x,y, fAvg); + QgsSalientPoint& gcp = pGcp[y*iDimension + x]; + int ycoord = (int)gcp.y() * 2; + int xcoord = (int)gcp.x() * 2; + + if (level == 0) //Get the previous level values + { + int iBand = rasterBand(); + pValues[0] = mImage->readValue(iBand, xcoord, ycoord); + pValues[1] = mImage->readValue(iBand, xcoord + 1, ycoord); + pValues[2] = mImage->readValue(iBand, xcoord, ycoord + 1); + pValues[3] = mImage->readValue(iBand, xcoord + 1, ycoord + 1); + } else + { + if (!is) { + char message[100]; + sprintf(message,"Failed to create temporary file %s",filename.c_str()); + QgsLogger::debug(QString(message),1,"qgswaveletextractor.cpp","QgsWaveletExtractor::reconstruct()" ); + + return NULL; + } + is.seekg( (ycoord*curDimension + xcoord) * sizeof(float)); //Get point in file where these coordinates are. + is.read((char*)pValues, 2 * sizeof(float));//Read two values + is.seekg( (curDimension - 2) * sizeof(float), std::ios_base::cur);//Move pointer on one line (minus the two floats just read). + is.read((char*) (&pValues[2]), 2 * sizeof(float)); + } + + + // printf("Values %6.3f, %6.3f, %6.3f, %6.3f \n", pValues[0], pValues[1], pValues[2],pValues[3]); + //Both cases: + int max = findMaxDev(pValues,fAvg); + + float sal = abs(fAvg - pValues[max]); + + fAvg = pValues[max]; + // printf("%d,%d New Avg=%6.3f \n",x,y, pAverages[y*iDimension + x]); + gcp.setSaliency(sal + gcp.saliency()); + int x, y; + switch (max) + { + case 0: + y = ycoord; + x = xcoord; + break; + case 1: + y = ycoord; + x= xcoord + 1; + break; + case 2: + y= ycoord + 1; + x = xcoord; + break; + case 3: + y = ycoord + 1; + x = xcoord + 1; + break; + } + gcp.setX(x); + gcp.setY(y); + } + } + is.close(); + } + QList* result = new QList(); + int count = 0; + for (int i = 0; i< iDimension * iDimension; ++i) + { + count ++; + QgsSalientPoint &point = pGcp[i]; + //Check whether the point falls within the bounds of the image. + if (point.x() < mImage->imageXSize() - mChipSize / 2 + && point.y() < mImage->imageYSize() - mChipSize / 2 + && point.saliency() > mThreshold + && point.x() > mChipSize / 2 + && point.y() > mChipSize / 2) + { + //Now Check if the point doesn't fall on a mask edge + int blackCount = 0; + for (int y = point.y() - mChipSize / 2; y < point.y() + mChipSize / 2; y++) + { + for (int x = point.x() - mChipSize / 2; x < point.x() + mChipSize / 2; x++) + { + double value = mImage->readValue(1, x, y); + if (abs(value) < DBL_EPSILON) + { + blackCount++; + } + } + } + float fracBlack = blackCount / (mChipSize * mChipSize); + if (fracBlack < mBlackLimit) + { + addPoint(result,pGcp[i]); + } + } + } +// printf("Internal list size: %d\n", count); + delete [] pAverages; + return result; +} + +//Get the highest deviating value of the four components of one coefficient +int QgsWaveletExtractor::findMaxDev(float* values, float avg) +{ + int max = 0; + float total = 0; + for (int i = 0; i < 4; ++i) + { + total +=values[i]; + if (abs(values[i] - avg) > abs(values[max] - avg)) + { + max = i; + } + // std::cout << values[i] << ", "; + } + // std::cout <imageXSize(); +// sprintf(message,"Image handle invalid %p", mImage); +// QgsLogger::debug(message); + + + if (x >= mImage->imageXSize() || y >= mImage->imageYSize()) + { + return 0.0; + } else + { + return mImage->readValue(mRasterBand,x,y); + } +} + +std::string QgsWaveletExtractor::generateTmpFileName(int level) +{ + std::stringstream stream; + //QgsLogger::debug(QString("Generating file for:") + mImage->filePath()); + char* filepath = mImage->filePath().toLatin1().data(); + stream << filepath; + stream << ".haar"<* list, QgsSalientPoint item) +{ + QList::iterator it = list->begin(); + for (; it != list->end() && item.saliency() < (*it).saliency();it++) + { + //Empty + } + list->insert(it , item); +} + +void QgsWaveletExtractor::setRasterBand(int band) +{ + if (mImage) + { + if (band < 1) + { + mRasterBand = 1; + } else if (band > mImage->rasterBands()) + { + mRasterBand = mImage->rasterBands(); + } else { + mRasterBand = band; + } + } +} + +void QgsWaveletExtractor::cleanUp() +{ + for (int i = 1; i <= mLevels; i++) + { + std::string filename = generateTmpFileName(i); + // printf("Deleting temp file %s\n", filename.c_str()); + + QFile tempfile(filename.c_str()); + if (tempfile.exists()) + { + // printf("Filename %s exists\n", filename.c_str()); + tempfile.remove(); + } + } +} + + Index: src/autogcp/qgsgcp.cpp =================================================================== --- src/autogcp/qgsgcp.cpp (revision 0) +++ src/autogcp/qgsgcp.cpp (revision 0) @@ -0,0 +1,129 @@ +/*************************************************************************** +qgsgcp.cpp - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsgcp.h" + +QgsGCP::QgsGCP(): + mChip(NULL), + mXRaw(0),mYRaw(0), + mXRef(0),mYRef(0), mZRef(0), + mCorrelationCoefficient(0.0) +{ +} + +QgsGCP::~QgsGCP() +{ + + if (mChip) + { + delete mChip; + } +} + +QgsGCP::QgsGCP(const QgsGCP& other): + mChip(NULL), + mXRaw(other.mXRaw),mYRaw(other.mYRaw), + mXRef(other.mXRef),mYRef(other.mYRef), mZRef(other.mZRef) +{ + +} + +const QgsGCP& QgsGCP::operator=(const QgsGCP& other) +{ + mChip = NULL; + mXRaw = other.mXRaw; + mYRaw =other.mYRaw; + mXRef = other.mXRef; + mYRef = other.mYRef; + mZRef =other.mZRef; +} + +bool QgsGCP::operator==(const QgsGCP& other) const +{ + return (mXRef == other.mXRef && mYRef == other.mYRef); +} + +double QgsGCP::refX() const +{ + return mXRef; +} + +void QgsGCP::setRefX(double value) +{ + mXRef = value; +} + +double QgsGCP::refY() const +{ + return mYRef; +} + +void QgsGCP::setRefY(double value) +{ + mYRef = value; +} + +double QgsGCP::refZ() const +{ + return mZRef; +} + +void QgsGCP::setRefZ(double value) +{ + mZRef = value; +} + +double QgsGCP::rawX() const +{ + return mXRaw; +} + +void QgsGCP::setRawX(double value) +{ + mXRaw = value; +} + +double QgsGCP::rawY() const +{ + return mYRaw; +} + +void QgsGCP::setRawY(double value) +{ + mYRaw = value; +} + +double QgsGCP::correlationCoefficient() const +{ + return mCorrelationCoefficient; +} + +void QgsGCP::setCorrelationCoefficient(double value) +{ + mCorrelationCoefficient = value; +} + +QgsImageDataSet* QgsGCP::gcpChip() const +{ + return mChip; +} + +void QgsGCP::setGcpChip(QgsImageDataSet* value) +{ + mChip = value; +} Index: src/autogcp/qgshasher.cpp =================================================================== --- src/autogcp/qgshasher.cpp (revision 0) +++ src/autogcp/qgshasher.cpp (revision 0) @@ -0,0 +1,82 @@ +/*************************************************************************** +qgshasher.cpp - A hash calculator used to generate hashes from strings and +files. +-------------------------------------- +Author: Christoph Stallmann +Date : 24-June-2010 +Date Modified: 08-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgshasher.h" + +QgsHasher::QgsHasher() +{ +} //QgsHasher::QgsHasher() + +QString QgsHasher::getStringHash(QString data, HashAlgorithm hash) +{ + QCryptographicHash *hasher; + if (hash == Md4) + { + hasher = new QCryptographicHash(QCryptographicHash::Md4); + }else if (hash == Sha1) + { + hasher = new QCryptographicHash(QCryptographicHash::Sha1); + }else + { + hasher = new QCryptographicHash(QCryptographicHash::Md5); + } + const char *dataArray; + QByteArray byteArray = data.toLatin1(); + dataArray = byteArray.data(); + hasher->addData(dataArray, data.length()); + + QByteArray resultArray = hasher->result(); + QString result(resultArray.toHex().constData()); + return result; +} //QString QgsHasher::getStringHash(QString data, HashAlgorithm hash) + +QString QgsHasher::getFileHash(QString data, HashAlgorithm hash, int numberOfBytes) +{ + QCryptographicHash *hasher; + if (hash == Md4) + { + hasher = new QCryptographicHash(QCryptographicHash::Md4); + }else if (hash == Sha1) + { + hasher = new QCryptographicHash(QCryptographicHash::Sha1); + }else + { + hasher = new QCryptographicHash(QCryptographicHash::Md5); + } + + QFile file(data); + + if(! file.exists()) + { + return "Error: File not found"; + } + if(! file.open(QIODevice::ReadOnly)) + { + return "Error: File could not be opened"; + } + if(file.size() < numberOfBytes || numberOfBytes < 0) + { + numberOfBytes = file.size(); //If more bytes or if a negative number of bytes are requested than the size of the file, only the size-number of bytes will be read + } + QByteArray byteArray = file.read(numberOfBytes); + file.close(); + hasher->addData(byteArray); + QByteArray resultArray = hasher->result(); + QString result(resultArray.toHex().constData()); + return result; +} //QString QgsHasher::getFileHash(QString data, HashAlgorithm hash, int numberOfBytes) Property changes on: src/autogcp/qgshasher.cpp ___________________________________________________________________ Added: svn:executable + * Index: src/autogcp/qgsprojectionmanager.h =================================================================== --- src/autogcp/qgsprojectionmanager.h (revision 0) +++ src/autogcp/qgsprojectionmanager.h (revision 0) @@ -0,0 +1,183 @@ +/*************************************************************************** +qgsprojectionmanager.cpp - The ProjectionManager class is responsible for the +projection of GCPs using the projection information either contained within the +Metadata of the image, or as specified by the user. +This class uses the GDAL Warp library to perform the projection on the provided +GCP chip. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +Author: Francois Maass +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSPROJECTIONMANAGER_H +#define QGSPROJECTIONMANAGER_H +#include +#include +#include +#include +#include +#include "qgsgcp.h" +#include "qgsimagedataset.h" +#include "qgslogger.h" + +/*! \brief Container for Projection Information + Struct serves as a container for all projection related information + needed to set projection definitions. + */ +struct PROJ_INFO +{ + + QString pGeographicCSName; + QString pProjectedCSName; + QString pVariantName; + QString pGeogName; + QString pDatumName; + QString pSpheroidName; + QString pPMName; + QString pAngularUnits; + double pStdP1; + double pStdP2; + double pCenterLat; + double pCenterLong; + double pFalseEasting; + double pFalseNorthing; + double pStandardParallel; + double pCentralMeridian; + double pPseudoStdParallelLat; + double pPseudoStdParallel1; + double pSatelliteHeight; + double pScale; + double pAzimuth; + double pRectToSkew; + double pLat1; + double pLong1; + double pLat2; + double pLong2; + double pLatitudeOfOrigin; + double pSemiMajor; + double pInvFlattening; + double pPMOffset; + double pConvertToRadians; + int pVariation; + int pZone; + int pNorth; + +}; + + +class QgsProjectionManager +{ +public: + /*! \brief QgsProjectionManager Constructor + Constructs a projection manager that will handle all projection related processes. + \param A pointer to the GDAL reference image dataset. + \param A pointer to the GDAL raw image dataset. + */ + QgsProjectionManager(QgsImageDataSet *refImageDataset, QgsImageDataSet *rawImageDataset); + /*! \brief QgsProjectionManager Constructor + Constructs a projection manager that will handle all projection related processes. + */ + QgsProjectionManager(); + /*! \brief Set the reference image dataset + Sets the reference image to be used for the projection as a QgsImageDataSet + \param A pointer to the GDAL reference image dataset. + */ + void setReferenceImage(QgsImageDataSet *refImageDataset); + /*! \brief Set the raw image dataset + Sets the raw image to be used for the projection as a QgsImageDataSet + \param A pointer to the GDAL raw image dataset. + */ + void setRawImage(QgsImageDataSet *rawImageDataset); + + /*! \brief Get the reference image dataset + Gets the reference image to be used for the projection as a QgsImageDataSet + */ + QgsImageDataSet* referenceImage(); + /*! \brief Get the reference image dataset + Gets the reference image to be used for the projection as a QgsImageDataSet + */ + QgsImageDataSet* rawImage(); + /*! \brief Static initializer for projection manager + Initializes the required projected- and geographic- Coordinate System data. + */ + void initializeMaps(); + /*! \brief QgsProjectionManager Destructor + */ + ~QgsProjectionManager(); + /*! \brief Notifier for error messages. + Notifies QGSLogger of error that occured. + \param The message describing the error. + */ + void notifyFailure(QString message); + + /*! \brief Project a single GCP between coordinate systems + A single GCP is projected between two defined coordinate systems as retrieved from + the raw- and reference image dataset provided with the constructor. This function handles + all the processes required to fully project the provided GCP chip. + Note: It is assumed that both datasets have valid projection definitions when called. + To check projection information, see QgsProjectionManager::checkProjectionInformation(...). + \param A pointer to the QgsImageDataSet containing the chip. + \param A pointer to the QgsImageDataSet in which the chip is to be returned + */ + bool projectGCPChip(QgsImageDataSet* chipIn, QgsImageDataSet* chipOut); + + /*! \brief Project a single GCP between coordinate systems + A single GCP is projected between two defined coordinate systems as retrieved from + the raw- and reference image dataset provided with the constructor. This function handles + all the processes required to fully project the provided GCP chip. + Note: It is assumed that both datasets have valid projection definitions when called. + To check projection information, see QgsProjectionManager::checkProjectionInformation(...). + \param A pointer to the QgsGCP object containing the extracted GCP chip. + */ + void projectGCP(QgsGCP *originalGCP); + /*! \brief Defines the warp options for projections + Warp Options are defined based on information extracted from the source and destination + datasets. + \param The source GDAL dataset (original coordinate system) + \param The destination GDAL dataset (desired coordinate system) + \param True if a GDAL progress bar should be printed to standard output. + */ + GDALWarpOptions* getWarpOptions(GDALDataset *srcDataset, GDALDataset *dstDataset, bool progressBar); + /*! \brief Warp operation that handles projection + The provided dataset is warped/projected using the projection options provided as well as + information extracted from the GDAL raw- and reference image datasets. + \param The warp options as defined by QgsProjectionManager::getWarpOptions(...). + \param The dataset to be projected + */ + void warpDatasets(GDALWarpOptions *pswops, GDALDataset *dstDataset); + /*! \brief Warp data destroyer + Cleans up all the additional data created for the projection process + \param The warp options as defined by QgsProjectionManager::getWarpOptions(...). + */ + void destroyWarpData(GDALWarpOptions *pswops); + /*! \brief Checks for availability and validity of projection definition strings. + The provided dataset is checked to see if it contains the projection definition string. + \param The dataset to be checked. + */ + bool checkProjectionInformation(QgsImageDataSet *imageDataset); + /*! \brief Sets the projection definition string + The projection definition string is derived from information contained in the projectionInfo + container based on the options provided, and assigned to the dataset. + \param The dataset to which the projection definition string is to be assigned. + \param The projection Information container. + */ + bool setProjectionInformation(QgsImageDataSet *imageDataset, PROJ_INFO *projectionInfo); +private: + GDALDataset *mRefDataset; + GDALDataset *mRawDataset; + bool mFail; + static bool init; + static QMap projectedCoordSystems; + static QMap geographicCoordSystems; + +}; +#endif //QGSPROJECTIONMANAGER_H Index: src/autogcp/qgssqlitedriver.cpp =================================================================== --- src/autogcp/qgssqlitedriver.cpp (revision 0) +++ src/autogcp/qgssqlitedriver.cpp (revision 0) @@ -0,0 +1,50 @@ +/*************************************************************************** +qgssqlitedriver.cpp - The Driver resposible for the SQLite database +connection +-------------------------------------- +Date : 02-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgssqlitedriver.h" + +QgsSqliteDriver::QgsSqliteDriver() +{ + mDatabase = QSqlDatabase::addDatabase("QSQLITE"); + mIsOpen = false; +} + +bool QgsSqliteDriver::openDatabase() +{ + if(!mIsOpen && !mName.isNull()) + { + mDatabase.setDatabaseName(mName); + mIsOpen = mDatabase.open(); + } + return mIsOpen; +} + +bool QgsSqliteDriver::openDatabase(const QString name) +{ + mName = name; + if(!mIsOpen) + { + mDatabase.setDatabaseName(mName); + mIsOpen = mDatabase.open(); + } + return mIsOpen; +} + +void QgsSqliteDriver::deleteDatabase() +{ + closeDatabase(); + QFile::remove(mName); +} \ No newline at end of file Index: src/autogcp/qgssqldriver.h =================================================================== --- src/autogcp/qgssqldriver.h (revision 0) +++ src/autogcp/qgssqldriver.h (revision 0) @@ -0,0 +1,46 @@ +/*************************************************************************** +qgssqlitedriver.h - The abstract driver resposible for the SQL database +connection +-------------------------------------- +Date : 02-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSSQLDRIVER_H +#define QGSSQLDRIVER_H +#include +#include +#include +#include +#include +#include +#include + +class QgsSqlDriver +{ + public: + virtual bool openDatabase() = 0;//Opens the database + void closeDatabase(); //Closes the database + virtual void deleteDatabase() = 0;//Deletes the database + bool reconnect(); //Closes the connection and opens it again + QSqlError lastError(); //Returns the last error if one occured + QSqlQuery executeQuery(const QString queryString); + QSqlRecord retrieveTable(const QString tableName); + QString name(); //The name of the database. For SQLite this is the file path + void setName(QString name); + bool isOpen(); //If the file is open + protected: + QString mName; //The file path to the database + QSqlDatabase mDatabase; //The database object + bool mIsOpen; //If the databse is open +}; + +#endif // QGSSQLDRIVER_H Index: src/autogcp/qgselevationmanager.cpp =================================================================== --- src/autogcp/qgselevationmanager.cpp (revision 0) +++ src/autogcp/qgselevationmanager.cpp (revision 0) @@ -0,0 +1,36 @@ +/*************************************************************************** +qgselevationmanager.cpp - The ElevationManager contains a Digital Elevation + Model of a specific reference image and allows sampling of the ground + elevation at different coordinates. This DEM is used in the orthorectification + process as well as chip projection. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgselevationmanager.h" + +QgsElevationManager::QgsElevationManager() +{ +} + +double QgsElevationManager::sampleHeight(int pX, int pY) +{ + return 0.0; +} + +void QgsElevationManager::openDEMFile(QString filePath) +{} + +QgsElevationManager::~QgsElevationManager() +{ + delete mElevation; +} Index: src/autogcp/CMakeLists.txt =================================================================== --- src/autogcp/CMakeLists.txt (revision 0) +++ src/autogcp/CMakeLists.txt (revision 0) @@ -0,0 +1,124 @@ + +SET(QGIS_AUTOGCP_SRCS + +qgsgcp.cpp +qgsimagedataset.cpp +qgsgcpdataset.cpp +qgsautogcpmanager.cpp +qgsdatarow.cpp +qgsdatasource.cpp +qgselevationmanager.cpp +qgsimageanalyzer.cpp +qgsorthorectification.cpp +qgsfeatureextractor.cpp +qgswaveletextractor.cpp +qgsimagechip.cpp +qgsprojectionmanager.cpp +qgscrosscorrelator.cpp +qgshasher.cpp +qgssqldriver.cpp +qgssqlitedriver.cpp +qgspostgresdriver.cpp +) + +SET(QGIS_AUTOGCP_MOC_HDRS + +qgsgcp.h +qgsautogcpmanager.h +qgsdatarow.h +qgsdatasource.h +qgselevationmanager.h +qgsgcpdataset.h +qgsimageanalyzer.h +qgsimagedataset.h +qgsorthorectification.h +qgsfeatureextractor.h +qgswaveletextractor.h +qgssalientpoint.h +qgsimagechip.h +qgsprojectionmanager.h +qgscrosscorrelator.h +qgshasher.h +qgssqldriver.h +qgssqlitedriver.h +qgspostgresdriver.h +) + +QT4_WRAP_CPP(QGIS_AUTOGCP_MOC_SRCS ${QGIS_AUTOGCP_MOC_HDRS}) + +INCLUDE_DIRECTORIES( + ${QT_QTUITOOLS_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/symbology-ng + ../core + ../core/composer + ../core/raster + ../core/renderer + ../core/symbology + ../core/symbology-ng + ${GDAL_INCLUDE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/../ui +) + +INCLUDE_DIRECTORIES(${GEOS_INCLUDE_DIR}) + +IF (WIN32) + IF (MSVC) + ADD_DEFINITIONS("-DGUI_EXPORT=__declspec(dllexport)") + ELSE (MSVC) + ADD_DEFINITIONS("-UGUI_EXPORT \"-DGUI_EXPORT=__declspec(dllexport)\"") + ENDIF (MSVC) +ENDIF (WIN32) + + +############################################################# +# qgis_gui library + + +ADD_LIBRARY(qgis_autogcp SHARED ${QGIS_AUTOGCP_SRCS} ${QGIS_AUTOGCP_MOC_SRCS}) + +SET_TARGET_PROPERTIES(qgis_autogcp PROPERTIES VERSION ${COMPLETE_VERSION} SOVERSION ${COMPLETE_VERSION}) + +TARGET_LINK_LIBRARIES(qgis_autogcp + qgis_core + ${QT_QTUITOOLS_LIBRARY} +) + + +IF (APPLE) + SET_TARGET_PROPERTIES(qgis_autogcp PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE ) +ENDIF (APPLE) + +INSTALL(TARGETS qgis_autogcp + RUNTIME DESTINATION ${QGIS_BIN_DIR} + LIBRARY DESTINATION ${QGIS_LIB_DIR} + ARCHIVE DESTINATION ${QGIS_LIB_DIR}) + +# for installing headers + +SET(QGIS_AUTOGCP_HDRS + +qgsautogcpmanager.h +qgsdatarow.h +qgsdatasource.h +qgselevationmanager.h +qgsgcp.h +qgsgcpdataset.h +qgsimageanalyzer.h +qgsimagedataset.h +qgsorthorectification.h +qgsfeatureextractor.h +qgssalientpoint.h +qgsimagechip.h +qgscrosscorrelator.h +qgsprojectionmanager.h +qgshasher.h +qgssqldriver.h +qgssqlitedriver.h +qgspostgresdriver.h +) + +INSTALL(CODE "MESSAGE(\"Installing AUTOGCP headers...\")") +INSTALL(FILES ${QGIS_AUTOGCP_HDRS} ${QGIS_AUTOGCP_MOC_HDRS} DESTINATION ${QGIS_INCLUDE_DIR}) + Index: src/autogcp/qgsgcpdataset.h =================================================================== --- src/autogcp/qgsgcpdataset.h (revision 0) +++ src/autogcp/qgsgcpdataset.h (revision 0) @@ -0,0 +1,67 @@ +/*************************************************************************** +qgsgcpdataset.cpp - This is a container class that represents an entire set of + GCP’s associated with a specific reference model or a specific extraction + and cross-referencing operation. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSGCPDATASET_H +#define QGSGCPDATASET_H + + +//****************Includes +#include //Internal container +#include "qgsgcp.h" + +class QgsGCPDataSet +{ +public: + /*! \brief QgsGCPDataSet constructor + Creates an empty GCP set. + */ + QgsGCPDataSet(); + /*! \brief QgsGCPDataSet destructor */ + virtual ~QgsGCPDataSet(); + /*! \brief Adds a GCP to this GCP set. + May add duplicate entries. + */ + void addGcp(QgsGCP* point); + /*! \brief Updates a GCP in this GCP set. + */ + void updateGcp(QgsGCP* oldPoint, QgsGCP* newPoint); + /*! \brief Removes a GCP from the set. + This removes the first GCP in the list with match reference x and y coordinates. + */ + void removeGcp(QgsGCP* point); + /*! \brief Gets the amount of GCP's in the list + */ + int size() const; + /*! \brief Removes all GCPs from this GCP set + */ + void clear(); + /*! \brief Returns the underlying QList + */ + const QList& constList() const; + /*! \brief Returns a copy of the underlying QList + */ + QList list(); +private: + typedef QList GcpList; + GcpList mList; + + //Functor used to order the list in descending order + //edit: Not used at the moment. + +}; + +#endif // QGSGCPDATASET_H Index: src/autogcp/qgserrorlist.cpp =================================================================== --- src/autogcp/qgserrorlist.cpp (revision 0) +++ src/autogcp/qgserrorlist.cpp (revision 0) @@ -0,0 +1,73 @@ +/*************************************************************************** +qgserrorlist.cpp - The QgsErrorList is a Singleton extension to the +QVector class that provides container functionality which is used to capture +and store any exceptions that may occur in other classes. +This allows errors or exceptions to be stored with extensive detail for use +by other classes or debugging purposes. +-------------------------------------- +Date : 12-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +Author: Francois Maass +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgserrorlist.h" + +QgsErrorList* QgsErrorList::onlyInstance = 0; + +QgsErrorList::QgsErrorList() : QVector() +{ + +} + +QgsErrorList* QgsErrorList::instance() +{ + if(onlyInstance == 0) + onlyInstance = new QgsErrorList; + return onlyInstance; + +} + +void QgsErrorList::reportError(QString message, QString classOccured, QString functionOccured, QString severity, bool printDebug) +{ + QgsError err; + err.setMessage(message); + err.setClassOccured(classOccured); + err.setFunctionOccured(functionOccured); + err.setSeverity(severity); + QVector::append(err); + + if(printDebug) + { + QString msg = classOccured + ": " + severity + " error. " + message; + QgsLogger::debug(msg.toLatin1().data()); + } +} + +QString QgsErrorList::lastError() +{ + QgsError &err = QVector::last(); + return composeMessage(err); +} + +void QgsErrorList::deleteLastError() +{ + QVector::erase(QVector::end() - 1); +} + +QString QgsErrorList::composeMessage(QgsError err) +{ + QString tmp("Error: \n"); + tmp += "Severity: " + err.severity() + "\n"; + tmp += "Message: " + err.message() + "\n"; + tmp += "Occured in Class: " + err.classOccured() + "\n"; + tmp += "Occured in Function: " + err.functionOccured() + "\n"; + return tmp; +} Index: src/autogcp/qgsimagechip.cpp =================================================================== --- src/autogcp/qgsimagechip.cpp (revision 0) +++ src/autogcp/qgsimagechip.cpp (revision 0) @@ -0,0 +1,57 @@ +#include "qgsimagechip.h" +#include "qgslogger.h" + +QgsImageChip::QgsImageChip(GDALDataset* dataset): + QgsImageDataSet(dataset), mData(NULL) +{ +} +QgsImageChip::QgsImageChip(const QgsImageChip& other):QgsImageDataSet(NULL), mData(NULL) +{ + +} + +const QgsImageChip& QgsImageChip::operator =(const QgsImageChip& other) +{ + +} + +QgsImageChip* QgsImageChip::createImageChip(int width, int height, GDALDataType type, int bands) +{ + char message[200]; + registerGdalDrivers(); + int chipDataSize = width * height * bands * (GDALGetDataTypeSize(type) / 8); + //printf("Allocate CHip data %d\n", chipDataSize); + //printf("%d, %d, %d, %d\n", width, height, bands, (GDALGetDataTypeSize(type) / 8)); + void* chipData = VSIMalloc(chipDataSize); + //printf("Allocated CHip data\n"); + if (!chipData) + { + sprintf(message, "Failed to allocate memory (%d Bytes) for GCP Chip data", chipDataSize); + QgsLogger::debug(message,1, "qgsimagechip.cpp","QgsImageChip::createImageChip()"); + return NULL; + } + char nameString[200]; + sprintf(nameString, + "MEM:::DATAPOINTER=%p,PIXELS=%d,LINES=%d,BANDS=%d,DATATYPE=%s", + chipData, width, height, bands, GDALGetDataTypeName(type)); + GDALDataset* ds = (GDALDataset*)GDALOpen(nameString,GA_Update); + if (! ds) + { + QgsLogger::debug("Cannot create In-Memory Chip dataset",1, "qgsimagechip.cpp","QgsImageChip::createImageChip()"); + return NULL; + } + + QgsImageChip* theChip = new QgsImageChip(ds); + theChip->mData = chipData; + return theChip; +} + +QgsImageChip::~QgsImageChip() +{ + +} +//Must delete here because the GDAL dataset still uses it at time of destruction. +void QgsImageChip::finalize() +{ + VSIFree(mData); +} Index: src/autogcp/qgspostgresdriver.h =================================================================== --- src/autogcp/qgspostgresdriver.h (revision 0) +++ src/autogcp/qgspostgresdriver.h (revision 0) @@ -0,0 +1,43 @@ +/*************************************************************************** +qgspostgresdriver.h - The Driver resposible for the PostgreSQL database +connection +-------------------------------------- +Date : 02-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSPOSTGRESDRIVER_H +#define QGSPOSTGRESDRIVER_H +#include "qgssqldriver.h" + +class QgsPostgresDriver : public QgsSqlDriver +{ +public: + QgsPostgresDriver(); + bool openDatabase(); //Opens the database + bool openDatabase(const QString name, const QString username, const QString password, const QString host); //Opens the database + void deleteDatabase(); //Deletes the database + QString username(); + void setUsername(const QString username); + QString password(); + void setPassword(const QString password); + QString host(); + void setHost(const QString host); + int port(); + void setPort(const int port); +private: + QString mUsername; + QString mPassword; + QString mHost; + int mPort; +}; + +#endif // QGSPOSTGRESDRIVER_H Index: src/autogcp/qgsimageanalyzer.cpp =================================================================== --- src/autogcp/qgsimageanalyzer.cpp (revision 0) +++ src/autogcp/qgsimageanalyzer.cpp (revision 0) @@ -0,0 +1,553 @@ +/*************************************************************************** +qgsimageanalyzer.cpp - The ImageAnalyzer class is responsible for the physical + analysis and processing of image data. This included detecting and extracting + GCP�s and GCP chips from images, as well as searching for these reference + GCP chips on a raw image. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsimageanalyzer.h" +#include "qgswaveletextractor.h" +#include "qgslogger.h" +#include "qgsimagechip.h" +#include "qgscrosscorrelator.h" +#ifndef MIN + #define MIN(x, y) \ + ((x < y) ? x : y) +#endif + +QgsImageAnalyzer::QgsImageAnalyzer(QgsImageDataSet* image): + mImageData(image), mChipType(CHIPTYPE), + mChipBandCount(DEFAULT_CHIP_BANDS) +{ + setChipSize(DEFAULT_CHIP_SIZE, DEFAULT_CHIP_SIZE); +} + + +//Doesn't own and therefore destroy mImageData. +QgsImageAnalyzer::~QgsImageAnalyzer() +{ +} + +QgsGCPDataSet* QgsImageAnalyzer::extractGcps(int amount) +{ + QgsLogger::debug("Analyzer Starting GCP extraction"); + if (!mImageData || mImageData->failed()) + { + QgsLogger::debug("Invalid image dataset"); + return false; + } + QgsWaveletExtractor* extractor = new QgsWaveletExtractor(mImageData,mChipSize.width, mChipSize.height); + extractor->setRasterBand(1); + QgsGCPDataSet* gcpset = new QgsGCPDataSet(); + QList* list = extractor->extractFeatures(); + printf("Features detected: %d\n", list->size()); + int dimension = (int) ceil(sqrt((double)amount)) + 1; + char debug[100]; + sprintf(debug, "Dividing image into %d X %d grids", dimension, dimension); + QgsLogger::debug(debug); + bool* occupied = new bool[dimension*dimension]; + + for (int i = 0; i< dimension * dimension; i++) + { + occupied[i] = false; + } + int sizeX, sizeY; + mImageData->imageSize(sizeX, sizeY); + + //TODO:Currenly just equal x-y grids regardless of resolution. + + double gridSizeX = sizeX / (double)dimension; + double gridSizeY = sizeY / (double) dimension; + + if (list) + { + QgsLogger::debug("Extracting GCP Chips"); + QList::iterator it = list->begin(); + + for (int count = 0;count < amount && it != list->end(); it++) + { + QgsSalientPoint& feature = (*it); + int pixX = feature.x(), pixY = feature.y(); + int gridX = (int) (pixX / gridSizeX); + int gridY = (int) (pixY / gridSizeY); + + if (!occupied[gridY*dimension +gridX])//Don't have a GCP in this grid yet + { + //printf("NEW GCP\n"); + QgsImageDataSet* chip = extractChip(feature, mChipSize.width, mChipSize.height, mChipBandCount, mChipType); + if (!chip) + { + QgsLogger::debug("Chip extraction failed",1, "qgsimageanalyzer.cpp","QgsImageAnalyzer::extractGcps()"); + } + QgsGCP* gcp = new QgsGCP(); + double geoX, geoY; + + mImageData->transformCoordinate(pixX, pixY, geoX, geoY, QgsImageDataSet::TM_PIXELGEO); + gcp->setRefX(geoX); + gcp->setRefY(geoY); + + gcp->setGcpChip(chip); + gcpset->addGcp(gcp); + + count++; + occupied[gridY*dimension +gridX] = true; + } + } + return gcpset; + } else { + QgsLogger::debug("NULL list returned by Wavelet",1, "qgsimageanalyzer.cpp","QgsImageAnalyzer::extractGcps()"); + return NULL; + } + +} + +//Matches each incoming GCP to point that most resembles it on the raw image +//If no match is found, the raw coordinates and correlation coefficient are set to -1 +QgsGCPDataSet* QgsImageAnalyzer::matchGcps(QgsGCPDataSet* gcpSet) +{ + QgsGCPDataSet* rawGcps = extractGcps(1000000); //TODO: do something about this number + QgsGrid* grid = new QgsGrid(32*4, mImageData); + grid->fillGrid(rawGcps); + + QList refList = gcpSet->list(); + for (int i = 0; i < refList.size(); i++) + { + //printf("i: %d\n", i); + QList rawList = grid->gridList(refList.at(i)); + if (rawList.size() > 0) + { + QgsGCP* best = rawList.at(0); + QgsCrossCorrelator* correlator = new QgsCrossCorrelator(refList.at(i)->gcpChip(), rawList.at(0)->gcpChip()); + best->setCorrelationCoefficient(correlator->correlationValue()); + //printf("i-2: %d\n", i); + for (int j = 0; j < rawList.size(); j++) + { + QgsCrossCorrelator* correlator = new QgsCrossCorrelator(refList.at(i)->gcpChip(), rawList.at(j)->gcpChip()); + rawList.at(j)->setCorrelationCoefficient(correlator->correlationValue()); + if (rawList.at(j)->correlationCoefficient() > best->correlationCoefficient()) + best = rawList.at(j); + } + //printf("i-3: %d\n", i); + refList.at(i)->setRawX(best->refX()); + refList.at(i)->setRawY(best->refY()); + refList.at(i)->setCorrelationCoefficient(best->correlationCoefficient()); + //printf("i-4: %d\n", i); + } + else + { + refList.at(i)->setRawX(-1); + refList.at(i)->setRawY(-1); + refList.at(i)->setCorrelationCoefficient(-1); + } + } + + return gcpSet; +} + +//********************DON'T REMOVE THIS COMMENTED METHOD!!!************************ +// +//*************************NEEDED FOR BENCHMARKING********************************* +// +/*typedef struct _ListItem + { + QgsSalientPoint point; + QgsImageDataSet* ds; + } _ListItem; + +QgsGCPDataSet* QgsImageAnalyzer::matchGcps(QgsGCPDataSet* gcpSet) +{ + QList gcpList = gcpSet->list(); + for (int i = 0; i < gcpSet->size(); i++) + { + QgsGCP* refGCP = gcpList[i]; + if (refGCP->gcpChip()) + { + double xGeo = refGCP->refX(); + double yGeo = refGCP->refY(); + int xPixel, yPixel; + mImageData->transformCoordinate(xPixel, yPixel, xGeo, yGeo,QgsImageDataSet::TM_GEOPIXEL); + QgsPoint sPoint = QgsPoint(xPixel+(refGCP->gcpChip()->imageXSize()/3), yPixel+(refGCP->gcpChip()->imageYSize()/3)); + + QgsImageDataSet* searchArea = extractChip(sPoint, (refGCP->gcpChip()->imageXSize()*4), (refGCP->gcpChip()->imageYSize()*4), mImageData->rasterBands()); + + //extract second search area!!! + + std::cout << "sPoint: " << sPoint << std::endl; + std::cout << "searchArea->rasterBands(): " << searchArea->rasterBands() << std::endl; + std::cout << "searchArea->imageXSize(): " << searchArea->imageXSize() << std::endl; + std::cout << "searchArea->imageYSize(): " << searchArea->imageYSize() << std::endl; + std::cout << "searchArea->readValue(1, ?, ?): " << searchArea->readValue(1, 20, 20) << std::endl; + + QgsWaveletExtractor* wave = new QgsWaveletExtractor(searchArea, 32, 32); + + QList* list = wave->extractFeatures(); + + int oldx = xPixel, oldy = yPixel; + + xPixel = 0; + yPixel = 0; + searchArea->transformCoordinate(xPixel, yPixel, xGeo, yGeo, QgsImageDataSet::TM_PIXELGEO); + mImageData->transformCoordinate(xPixel, yPixel, xGeo, yGeo, QgsImageDataSet::TM_GEOPIXEL); + QList<_ListItem> theChips; + QList::iterator pIt = list->begin(); + for (; pIt != list->end(); pIt++) + { + QgsSalientPoint& point = (*pIt); + point.setX(point.x() + xPixel); + point.setY(point.y() + yPixel); + + QgsImageDataSet* theChip = extractChip(point, (refGCP->gcpChip()->imageXSize()), (refGCP->gcpChip()->imageYSize()), mImageData->rasterBands()); + _ListItem item = {point, theChip}; + theChips.push_back(item); + + + } + printf("Ref: %d, %d SA: %d, %d, %d, %d\n",oldx, oldy, xPixel, yPixel, xPixel+96, yPixel+96 ); + for (int l = 0; l < list->size(); l++) + { + printf("Ref: %d, %d Candidate: %d, %d",oldx, oldy, (int)list->at(l).x(), (int)list->at(l).y() ); + if ( abs((int)list->at(l).x() - oldx ) < 10 && abs((int)list->at(l).y() - oldy ) < 10) + { + printf("**********"); + } + printf("\n"); + } + //printf("Search Area gcp's : %d\n",theChips.size()); + if(!theChips.isEmpty()) + { + QList<_ListItem>::iterator bestIndex = theChips.begin(); + double bestCC = 0.0; + QList<_ListItem>::iterator it; + for (it = theChips.begin(); it!= theChips.end(); it++) + if (it->ds) + { + QgsImageDataSet* chip = (*it).ds; + QgsCrossCorrelator* correlator = new QgsCrossCorrelator(refGCP->gcpChip(), chip); + double val; + if ( (val = correlator->correlationValue()) > bestCC) + { + bestCC = val; + bestIndex = it; + } + } + QgsSalientPoint& thePoint = (*bestIndex).point; + xPixel = (int)thePoint.x(); + yPixel = (int)thePoint.y(); + mImageData->transformCoordinate(xPixel, yPixel, xGeo, yGeo, QgsImageDataSet::TM_PIXELGEO); + gcpList.at(i)->setRawX(xGeo); + gcpList.at(i)->setRawY(yGeo); + } + else + { + QgsLogger::debug("Could not find GCPs in search area"); + return NULL; + } + } + + } + return gcpSet; +}*/ + +QgsImageDataSet* QgsImageAnalyzer::extractChip( QgsPoint& sourcePoint, int xPixels, int yLines, int bands, GDALDataType destType, QgsImageDataSet* dest) +{ + int chipXSize = xPixels; + int chipYSize = yLines; + int startX = (int)sourcePoint.x(); + int startY = (int)sourcePoint.y(); + //printf("Start X = %d, y = %d\n", startX, startY); + + GDALDataset* source = mImageData->gdalDataset(); + GDALDataType sourceType = source->GetRasterBand(1)->GetRasterDataType(); + + if (destType == UNKNOWN_TYPE) + { + destType = sourceType; + } + QgsImageDataSet* theChip = NULL; + if (0 >= bands) + { + bands = mImageData->rasterBands(); + } else + if (mImageData->rasterBands() < bands) + { + bands = mImageData->rasterBands(); + } + + if (dest) + { + theChip = dest; + if (chipXSize < theChip->imageXSize() || chipYSize < theChip->imageYSize()) + { + QgsLogger::debug("Destination dataset is too small for target chip extraction", 1, "qgsimageanalyzer.cpp","QgsImageAnalyzer::extractChip()"); + return NULL; + } + } else { + theChip = QgsImageChip::createImageChip(chipXSize, chipYSize,destType, bands); + if (!theChip) + { + QgsLogger::debug("Failed to create GCP chip",1, "qgsimageanalyzer.cpp","QgsImageAnalyzer::extractChip()"); + return NULL; + } + } + + GDALDataset* destDS = theChip->gdalDataset(); + + if (!source) + { + QgsLogger::debug("Invalid source. Cannot extract chips",1, "qgsimageanalyzer.cpp","QgsImageAnalyzer::extractChip()"); + return NULL; + } + int offsetX =startX - chipXSize / 2; + int offsetY = startY - chipYSize / 2; + if (offsetX < 0) + { + offsetX = 0; + } + if (offsetY <0) + { + offsetY = 0; + } + + if (offsetX + chipXSize > source->GetRasterXSize()) + { + offsetX = source->GetRasterXSize() - chipXSize; + } + if (offsetY + chipYSize > source->GetRasterYSize()) + { + offsetY = source->GetRasterYSize() - chipYSize; + } + + //If offsets below 0 now, it means chipsize is larger than source image. + if (offsetX < 0) + { + offsetX = 0; + chipXSize = source->GetRasterXSize(); + } + if (offsetY < 0) + { + offsetY = 0; + chipYSize = source->GetRasterYSize(); + } + //printf("Internal Offsets: %d, %d\n", offsetX, offsetY); + sourcePoint.setX(offsetX); + sourcePoint.setY(offsetY); + double geoTrans[6]; + source->GetGeoTransform(geoTrans); + //Geo X-offset + geoTrans[0] += offsetX * geoTrans[1] + offsetY * geoTrans[2]; + //Geo Y-offset + geoTrans[3] += offsetX * geoTrans[4] + offsetY * geoTrans[5]; + //meters/pixel Stays the same. + destDS->SetGeoTransform(geoTrans); + + //Temporary buffer with uniform datatype + void* buffer = VSIMalloc( chipXSize * chipYSize * sizeof(double)); + //rintf("Buffer size: %d\n", chipXSize * chipYSize * sizeof(double)); + try { + for (int i = 1; i <= bands; i++) + { + GDALRasterBand* srcBand = source->GetRasterBand(i); + GDALRasterBand* destBand = destDS->GetRasterBand(i); + char msg[100]; + CPLErr result; + char format[] = "Failed to %s image at band %d"; + if (CE_Failure == (result = srcBand->RasterIO(GF_Read, offsetX, offsetY, chipXSize, chipYSize, buffer, chipXSize, chipYSize, GDT_Float64,0,0 ))) + { + sprintf(msg, format, "read from source", i); + throw QString(msg); + break; + } + //printf("RESULT:%d\n",result); + if (CE_Failure == destBand->RasterIO(GF_Write, 0, 0, chipXSize, chipYSize, buffer, chipXSize, chipYSize, GDT_Float64,0,0 )) + { + sprintf(msg, format, "write to destination", i); + throw QString(msg); + } + } + } catch (QString ex) + { + QgsLogger::debug(ex,1, "qgsimageanalyzer.cpp","QgsImageAnalyzer::extractChip()"); + theChip = NULL; + } + VSIFree(buffer); + return theChip; +} + +const char* QgsImageAnalyzer::gdalDriver(char* buffer) const +{ + strcpy(buffer, "GTiff"); + return buffer; +} +void setDataValue(void* data,GDALDataType type, int index, double value) +{ + switch ( type ) + { + case GDT_Byte: + (( GByte * )data )[index] = ( GByte)value; + break; + case GDT_UInt16: + (( GUInt16 * )data )[index] = ( GUInt16)value; + break; + case GDT_Int16: + (( GInt16 * )data )[index] = ( GInt16 )value; + break; + case GDT_UInt32: + (( GUInt32 * )data )[index] = ( GUInt32 ) value; + break; + case GDT_Int32: + (( GInt32 * )data )[index] = ( GInt32 ) value; + break; + case GDT_Float32: + (( float * )data )[index] = (float) value; + break; + case GDT_Float64: + // val = (( double * )data )[index]; + (( double * )data )[index] = (double) value; + break; + default:; + // QgsLogger::warning( "GDAL data type is not supported" ); + } +}//void* QgsWaveletExtractor::dataIndex(void* data, int index) +double QgsImageAnalyzer::dataValue(void* data,GDALDataType type, int index) +{ + double value; + switch ( type ) + { + case GDT_Byte: + value = (double) (( GByte * )data )[index]; + break; + case GDT_UInt16: + value =( double ) (( GUInt16 * )data )[index]; + break; + case GDT_Int16: + value =( double) (( GInt16 * )data )[index]; + break; + case GDT_UInt32: + value =( double) (( GUInt32 * )data )[index]; + break; + case GDT_Int32: + value =( double) (( GInt32 * )data )[index]; + break; + case GDT_Float32: + value =( double) (( float * )data )[index]; + break; + case GDT_Float64: + // val = (( double * )data )[index]; + value =( double) (( double * )data )[index]; + break; + default: return 0.0; + // QgsLogger::warning( "GDAL data type is not supported" ); + }//switch(type) + // QgsLogger::debug(QString::number(imageXSize())); + return value; +} + +QgsImageAnalyzer::QgsGrid::QgsGrid(int bSize, QgsImageDataSet* img) +{ + blockSize = bSize; + mImageData = img; + + double dBlockSize = (double) blockSize; + double xD, yD; + xD = mImageData->imageXSize()/dBlockSize; + yD = mImageData->imageYSize()/dBlockSize; + + cols = ceil(xD); //47 + rows = ceil(yD); //27 + blocks = new GridBlock[rows*cols]; //1269 + for (int i = 0; i < (rows*cols); i++) + { + double dCols = cols; + double dRows = rows; + int x = (i%cols)*blockSize; + int y = (i/cols)*blockSize; + GridBlock block; + blocks[i] = block; + blocks[i].xBegin = x; + //if (i >= 1215 && i < 1235) printf("blocks[%d].xBegin: %d\n", i, blocks[i].xBegin); + blocks[i].yBegin = y; + //if (i >= 1215 && i < 1235) printf("blocks[%d].yBegin: %d\n", i, blocks[i].yBegin); + blocks[i].xEnd = MIN(blocks[i].xBegin + (blockSize-1), mImageData->imageXSize()); + blocks[i].yEnd = MIN(blocks[i].yBegin + (blockSize-1), mImageData->imageYSize()); + blocks[i].gcps = QList(); + } +} + +void QgsImageAnalyzer::QgsGrid::fillGrid(QgsGCPDataSet* gcpSet) +{ + int cell; + int col, row, xPixel, yPixel; + double xGeo, yGeo; + QList gcpList = gcpSet->list(); + for (int i = 0; i < gcpSet->size(); i++) + { + xGeo = gcpList.at(i)->refX(); + yGeo = gcpList.at(i)->refY(); + + mImageData->transformCoordinate(xPixel, yPixel, xGeo, yGeo,QgsImageDataSet::TM_GEOPIXEL); + + //get cell + col = floor(xPixel/blockSize); + row = floor(yPixel/blockSize); + cell = row*cols + col; + //add gcp to cell + blocks[cell].gcps.push_back(gcpList.at(i)); + + //check left, top and top-left cells + if ((xPixel-blockSize/2) < blocks[cell].xBegin && (xPixel-blockSize/2) >= 0 && ((yPixel-blockSize/2)) < blocks[cell].yBegin && (yPixel-blockSize/2) >= 0) + { + if (cell-1 >= 0) blocks[cell-1].gcps.push_back(gcpList.at(i)); + if (cell-cols >= 0) blocks[cell-cols].gcps.push_back(gcpList.at(i)); + if (cell-cols-1 >= 0) blocks[cell-cols-1].gcps.push_back(gcpList.at(i)); + } + else + { + if ((xPixel-blockSize/2) < blocks[cell].xBegin && xPixel-blockSize/2 >= 0) + if (cell-1 >= 0) blocks[cell-1].gcps.push_back(gcpList.at(i)); + else if (((yPixel-blockSize/2)) < blocks[cell].yBegin && yPixel-blockSize/2 >= 0) + { + if (cell-cols >=0 ) blocks[cell-cols].gcps.push_back(gcpList.at(i)); + } + } + + //check right, bottom and bottom-right cells + if ((xPixel+blockSize/2) > blocks[cell].xEnd && ((yPixel+blockSize/2)) > blocks[cell].yEnd) + { + if (cell+1 < rows*cols) blocks[cell+1].gcps.push_back(gcpList.at(i)); + if (cell+cols < rows*cols) blocks[cell+cols].gcps.push_back(gcpList.at(i)); + if (cell+cols+1 < rows*cols) blocks[cell+cols+1].gcps.push_back(gcpList.at(i)); + } + else + { + if ((xPixel+blockSize/2) > blocks[cell].xEnd && (xPixel+blockSize/2) <= mImageData->imageXSize()) + if (cell+1 < rows*cols) blocks[cell+1].gcps.push_back(gcpList.at(i)); + else if (((yPixel+blockSize/2)) > blocks[cell].yEnd && (yPixel+blockSize/2) <= mImageData->imageYSize()) + if (cell+cols < rows*cols) blocks[cell+cols].gcps.push_back(gcpList.at(i)); + } + + } +} + +QList QgsImageAnalyzer::QgsGrid::gridList(QgsGCP* refGcp) +{ + int xPixel, yPixel; + double xGeo, yGeo; + xGeo = refGcp->refX(); + yGeo = refGcp->refY(); + + mImageData->transformCoordinate(xPixel, yPixel, xGeo, yGeo,QgsImageDataSet::TM_GEOPIXEL); + int cell = (yPixel/blockSize)*cols + (xPixel/blockSize); + //printf("cell: %d\n", cell); + return blocks[cell].gcps; +} Index: src/autogcp/qgssensormodel.cpp =================================================================== --- src/autogcp/qgssensormodel.cpp (revision 0) +++ src/autogcp/qgssensormodel.cpp (revision 0) @@ -0,0 +1,33 @@ +/*************************************************************************** +qgssensormodel.cpp - +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgssensormodel.h" + +QgsSensorModel::QgsSensorModel() +{ +} + +void QgsSensorModel::projectGCP(QgsGCP gcp) +{ +} + +void QgsSensorModel::projectPoint(QPoint point) +{ + +} + +QgsSensorModel::~QgsSensorModel() +{ +} Index: src/autogcp/qgsdatasource.cpp =================================================================== --- src/autogcp/qgsdatasource.cpp (revision 0) +++ src/autogcp/qgsdatasource.cpp (revision 0) @@ -0,0 +1,303 @@ +/*************************************************************************** +qgsdatasource.cpp - The DataSource class is the data access layer between the + program logic and the database. For different installations of the system, + the DataSource may use a different Connector to interface with different + database engines. The DataSource performs operations such as constructing + mapping objects from database records, as well as the inverse of making these + objects persistent. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsdatasource.h" +#include + +QgsDataSource::QgsDataSource(const DatabaseType type, const QgsHasher::HashAlgorithm hashAlgorithm) +{ + mHashAlgorithm = hashAlgorithm; + mHasher = new QgsHasher(); + mType = type; +} + +bool QgsDataSource::createDatabase(const QString path) +{ + if(mType == SQLite) + { + return createSqliteDatabase(path); + }else + { + return false; + } +} + +bool QgsDataSource::createDatabase(const QString databseName, const QString username, const QString password, const QString host) +{ + if(mType == Postgres) + { + return createPostgresDatabase(databseName, username, password, host); + }else + { + return false; + } +} + +bool QgsDataSource::createSqliteDatabase(const QString path) +{ + try + { + mSqliteDriver = new QgsSqliteDriver(); + int hashLength; + if(mHashAlgorithm == QgsHasher::Md5 || mHashAlgorithm == QgsHasher::Md4) + { + hashLength = 32; + }else if (mHashAlgorithm == QgsHasher::Sha1) + { + hashLength = 40; + } + if(!mSqliteDriver->openDatabase(path)) + { + return false; + } + QString queryString = "CREATE TABLE image (\n"; + queryString += "\tid INTEGER PRIMARY KEY NOT NULL, \n"; + queryString += "\theight DECIMAL,\n"; + queryString += "\twidth DECIMAL,\n"; + queryString += "\thash char(" + QString::number(hashLength) + ")\n"; + queryString += ");\n"; + mSqliteDriver->executeQuery(queryString); + queryString = "CREATE TABLE gcpSet (\n"; + queryString += "\tid INTEGER PRIMARY KEY NOT NULL, \n"; + queryString += "\timage INTEGER,\n"; + queryString += "\tdateCreated DATE,\n"; + queryString += "\tFOREIGN KEY(image) REFERENCES image(id)\n"; + queryString += ");\n"; + mSqliteDriver->executeQuery(queryString); + queryString = "CREATE TABLE gcp (\n"; + queryString += "\tid INTEGER PRIMARY KEY NOT NULL, \n"; + queryString += "\trawX DECIMAL,\n"; + queryString += "\trawY DECIMAL,\n"; + queryString += "\trefX DECIMAL,\n"; + queryString += "\trefY DECIMAL,\n"; + queryString += "\trefZ DECIMAL,\n"; + queryString += "\tgcpChip BLOB,\n"; + queryString += "\tgcpSet INTEGER,\n"; + queryString += "\tFOREIGN KEY(gcpSet) REFERENCES gcpSet(id)\n"; + queryString += ");\n"; + mSqliteDriver->executeQuery(queryString); + return true; + }catch (QtConcurrent::Exception e) + { + return false; + } +} + +bool QgsDataSource::createPostgresDatabase(const QString databaseName, const QString username, const QString password, const QString host) +{ + try + { + mPostgresDriver = new QgsPostgresDriver(); + int hashLength; + if(mHashAlgorithm == QgsHasher::Md5 || mHashAlgorithm == QgsHasher::Md4) + { + hashLength = 32; + }else if (mHashAlgorithm == QgsHasher::Sha1) + { + hashLength = 40; + } + if(!mPostgresDriver->openDatabase(databaseName, username, password, host)) + { + return false; + } + QString queryString = "CREATE SEQUENCE imageId START 1;\nCREATE SEQUENCE gcpSetId START 1;\nCREATE SEQUENCE gcpID START 1;\n"; + mPostgresDriver->executeQuery(queryString); + queryString = "CREATE TABLE image (\n"; + queryString += "\tid INTEGER PRIMARY KEY NOT NULL, \n"; + queryString += "\theight DECIMAL,\n"; + queryString += "\twidth DECIMAL,\n"; + queryString += "\thash char(" + QString::number(hashLength) + ")\n"; + queryString += ");\n"; + mPostgresDriver->executeQuery(queryString); + queryString = "CREATE TABLE gcpSet (\n"; + queryString += "\tid INTEGER PRIMARY KEY NOT NULL, \n"; + queryString += "\timage INTEGER,\n"; + queryString += "\tdateCreated DATE,\n"; + queryString += "\tFOREIGN KEY(image) REFERENCES image(id)\n"; + queryString += ");\n"; + mPostgresDriver->executeQuery(queryString); + queryString = "CREATE TABLE gcp (\n"; + queryString += "\tid INTEGER PRIMARY KEY NOT NULL, \n"; + queryString += "\trawX DECIMAL,\n"; + queryString += "\trawY DECIMAL,\n"; + queryString += "\trefX DECIMAL,\n"; + queryString += "\trefY DECIMAL,\n"; + queryString += "\trefZ DECIMAL,\n"; + queryString += "\tgcpChip BYTEA,\n"; + queryString += "\tgcpSet INTEGER,\n"; + queryString += "\tFOREIGN KEY(gcpSet) REFERENCES gcpSet(id)\n"; + queryString += ");\n"; + mPostgresDriver->executeQuery(queryString); + return true; + }catch (QtConcurrent::Exception e) + { + return false; + } +} + +bool QgsDataSource::insertGcpSet(const QgsGCPDataSet *gcpSet, const QgsImageDataSet *refImage) +{ + try + { + if(mType == SQLite) + { + QString refHash = mHasher->getFileHash(refImage->filePath(), mHashAlgorithm, 1000000); + QString queryString = "INSERT INTO image (height, width, hash) VALUES ("; + queryString += QString::number(refImage->imageYSize()) + ", "; + queryString += QString::number(refImage->imageXSize()) + ", "; + queryString += "'" + refHash + "');"; + executeQuery(queryString); + queryString = "SELECT last_insert_rowid() AS imageId;"; + QSqlQuery result = executeQuery(queryString); + result.first(); + queryString = "INSERT INTO gcpSet (image, dateCreated) VALUES ("; + queryString += result.value(0).toString() + ", "; + queryString += "datetime('now'));"; + executeQuery(queryString); + queryString = "SELECT last_insert_rowid() AS imageId;"; + result = executeQuery(queryString); + result.first(); + QList set = gcpSet->constList(); + QString imageId = result.value(0).toString(); + for(int i = 0; i < set.size(); i++) + { + QgsGCP *gcp = set[i]; + queryString = "INSERT INTO gcp (rawX, rawY, refX, refY, refZ, gcpChip, gcpSet) VALUES ("; + queryString += QString::number(gcp->rawX()) + ", "; + queryString += QString::number(gcp->rawY()) + ", "; + queryString += QString::number(gcp->refX()) + ", "; + queryString += QString::number(gcp->refY()) + ", "; + queryString += QString::number(gcp->refZ()) + ", "; + queryString += "NULL, "; + queryString += imageId + ");"; + executeQuery(queryString); + } + }else + { + QString refHash = mHasher->getFileHash(refImage->filePath(), mHashAlgorithm, 1000000); + QString queryString = "INSERT INTO image (id , height, width, hash) VALUES (nextval('imageId'), "; + queryString += QString::number(refImage->imageYSize()) + ", "; + queryString += QString::number(refImage->imageXSize()) + ", "; + queryString += "'" + refHash + "');"; + executeQuery(queryString); + queryString = "INSERT INTO gcpSet (id, image, dateCreated) VALUES (nextval('gcpSetId'), "; + queryString += "currval('imageId'), "; + queryString += "CURRENT_TIMESTAMP);"; + QSqlQuery ss = executeQuery(queryString); + QMessageBox mm; + mm.setText("err: "+ss.lastError().text()); + mm.exec(); + QList set = gcpSet->constList(); + for(int i = 0; i < set.size(); i++) + { + QgsGCP *gcp = set[i]; + queryString = "INSERT INTO gcp (id, rawX, rawY, refX, refY, refZ, gcpChip, gcpSet) VALUES (nextval('gcpId'), "; + queryString += QString::number(gcp->rawX()) + ", "; + queryString += QString::number(gcp->rawY()) + ", "; + queryString += QString::number(gcp->refX()) + ", "; + queryString += QString::number(gcp->refY()) + ", "; + queryString += QString::number(gcp->refZ()) + ", "; + queryString += "NULL, "; + queryString += "currval('gcpSetId'));"; + executeQuery(queryString); + + } + } + return true; + }catch (QtConcurrent::Exception e) + { + return false; + } +} + +QgsGCPDataSet* QgsDataSource::selectByImage(const QgsImageDataSet *image) +{ + QString hash = mHasher->getFileHash(image->filePath(), mHashAlgorithm); + return selectByHash(hash); +} + +QgsGCPDataSet* QgsDataSource::selectByHash(const QString hash) +{ + QgsGCPDataSet *gcpDS = new QgsGCPDataSet(); + return gcpDS; +} + +QgsSqlDriver* QgsDataSource::driver() +{ + if(mType == SQLite) + { + return mSqliteDriver; + }else + { + return mPostgresDriver; + } +} + +void QgsDataSource::deleteDriver() +{ + if(mType == SQLite) + { + mSqliteDriver->deleteDatabase(); + }else + { + mPostgresDriver->deleteDatabase(); + } +} + +QgsHasher::HashAlgorithm QgsDataSource::hashAlgorithm() +{ + return mHashAlgorithm; +} + +void QgsDataSource::setHashAlogorithm(QgsHasher::HashAlgorithm hashAlgorithm) +{ + mHashAlgorithm = hashAlgorithm; +} + + + + + +QgsGCPDataSet QgsDataSource::selectByLocation(double latitude, double longitude, double window) +{ + QgsGCPDataSet gcpDS; + return gcpDS; +} + + + + + +QSqlQuery QgsDataSource::executeQuery(const QString query) +{ + QSqlQuery result; + if(mType == SQLite) + { + result = mSqliteDriver->executeQuery(query); + }else + { + result = mPostgresDriver->executeQuery(query); + } + return result; +} + +QgsDataSource::~QgsDataSource() +{ +} Index: src/autogcp/qgscrosscorrelator.h =================================================================== --- src/autogcp/qgscrosscorrelator.h (revision 0) +++ src/autogcp/qgscrosscorrelator.h (revision 0) @@ -0,0 +1,53 @@ +/*************************************************************************** +qgscrosscorrelator.cpp - This class handles the cross correlation of two +subimages. +-------------------------------------- +Date : 12-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSCROSSCORRELATOR_H +#define QGSCROSSCORRELATOR_H + +#include "qgsimagedataset.h" + +class QgsCrossCorrelator +{ +public: + /**\brief QgsCrossCorrelator Constructor + Constructs the correlator with the given chip images + */ + QgsCrossCorrelator(QgsImageDataSet* ref, QgsImageDataSet* raw); + /**\brief QgsCrossCorrelator Destructor + Destroys the QgsCrossCorrelator instance, releasing any owned resources. + */ + virtual ~QgsCrossCorrelator(); + + + + double correlationValue(); + typedef int Scheme; + static const Scheme GREY = 0; + static const Scheme RGB = 1; + static const Scheme CMYK = 2; + +private: + Scheme refConvert, rawConvert; + QgsImageDataSet* refChip, * rawChip; + double refAvg, rawAvg; + void calculateAverages(); + double calculateCC(); + double greyLevel(bool isRef, int x, int y); + int greyRefBand, redRefBand, blueRefBand, greenRefBand, cyanRefBand, magentaRefBand, yellowRefBand, blackRefBand; + int greyRawBand, redRawBand, blueRawBand, greenRawBand, cyanRawBand, magentaRawBand, yellowRawBand, blackRawBand; +}; + +#endif // QGSCROSSCORRELATOR_H Index: src/autogcp/qgsfeatureextractor.h =================================================================== --- src/autogcp/qgsfeatureextractor.h (revision 0) +++ src/autogcp/qgsfeatureextractor.h (revision 0) @@ -0,0 +1,16 @@ +#include "qgsgcpdataset.h" +#include + +/** +Abstract base class for detecting features / control points on an image +*/ +class QgsFeatureExtractor +{ +public: + virtual ~QgsFeatureExtractor(); + virtual QgsGCPDataSet* extractFeatures() = 0; +protected: + QgsFeatureExtractor(); +private: + +}; Index: src/autogcp/qgsimagedataset.h =================================================================== --- src/autogcp/qgsimagedataset.h (revision 0) +++ src/autogcp/qgsimagedataset.h (revision 0) @@ -0,0 +1,129 @@ +/*************************************************************************** +qgsimagedataset.cpp - This class contains all external data related to an image + including the sensor model associated to the particular image. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSIMAGEDATASET_H +#define QGSIMAGEDATASET_H + + + +#include +#include + +class QgsImageDataSet +{ +public: + + /**\brief QgsImageDataSet Constructor + Constructs the dataset with the given path and initializes all internal data + */ + QgsImageDataSet(QString path); + /**\brief QgsImageDataSet Constructor + Constructs the dataset with the given GDAL dataset. + */ + QgsImageDataSet(GDALDataset* dataset); + /**\brief QgsImageDataSet Destructor + Destroys the QgsImageDataSet instance, releasing any owned resources. + */ + virtual ~QgsImageDataSet(); + /**\brief Returns a pointer to the internal GDALDataset instance or NULL if initialization failed*/ + GDALDataset* gdalDataset(); + /**\brief Returns true if this object failed to initialize with the given file*/ + virtual bool failed() const; + /**\brief Returns the same as failed()*/ + bool operator!() const; + /*!\brief Gets the width and height of the raster image in pixels + Returns the width through the xSize reference parameter and the height through ySize. + If the image did not load or initialize correctly it does nothing. + Use failed() to check validity of the object. +**/ + void imageSize(int& xSize, int& ySize) const; + + int imageXSize() const; + int imageYSize() const; + + /*! \brief Gets the number of raster bands in the image. + Returns the number of rasterbands in the image or 0 if it hasn't been initialized. + */ + int rasterBands(); + + /*! \brief Reads the value of the image at a specified point + */ + double readValue( int band, int xPixel, int yLine); + /*! \brief Checks whether this object has initialized correctly + */ + operator bool() const; + QString filePath() const; + static const int TM_PIXELGEO = 0; //FROM PIXEL to GEO-COORDS + static const int TM_GEOPIXEL = 1;//FROM GEO to PIXEL COORDS + bool transformCoordinate(int& pixelX, int& pixelY, double& geoX, double& geoY,const int mode= TM_PIXELGEO) const; + static void registerGdalDrivers(); +protected: + QgsImageDataSet(){} + void setImageSize(int xSize, int ySize); +//Virtual methods + virtual GDALDataType dataType(int theBand) const; + /*! + \brief Reads a line from the specified raster band + Caller has ownership of the allocated memory and is responsible for deallocating it. + Returns NULL if an invalid band or line index is given. + */ + virtual void* readLine(int theBand, int line); + virtual void finalize() {} +private: + bool initialize(); + + void* dataIndex(void* data, int band, int index); +private: + template + struct DataBuffer + { + DataBuffer():currentBuffer(0) + { + for (int i =0; i< bufferCount; i++) + { + data[i] = 0; + line[i] = -1; + } + } + ~DataBuffer() + { + for (int i = 0; i < bufferCount; i++) + { + if (data[i]) + { + VSIFree(data[i]); + } + } + } + void* data[bufferCount]; + int line[bufferCount]; + int currentBuffer; + }; + + int mXSize; + int mYSize; + bool mFail; +//TODO: Or Not to do? What is mScale for again? + double mScale; + QString mFilePath; + + GDALDataset* mDataset; + + static const int mBufferCount = 2; + DataBuffer* mBuffers; +}; + +#endif // QGSIMAGEDATASET_H Index: src/autogcp/qgserror.h =================================================================== --- src/autogcp/qgserror.h (revision 0) +++ src/autogcp/qgserror.h (revision 0) @@ -0,0 +1,73 @@ +/*************************************************************************** +qgserrort.h - The QgsError class is used to describe an error that occured +during some stage of execution. Information about an error is captured here +and then stored in a QgsErrorList. +-------------------------------------- +Date : 12-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +Author: Francois Maass +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSERROR_H +#define QGSERROR_H + +#include +#include + +class QgsError +{ + public: + QgsError() + : mMessage(""),mClassOccured(""),mFunctionOccured(""),mErrorSeverity(0), mViewed(FALSE){}; + + ~QgsError() + {}; + + void setMessage(QString message) + { mMessage = message; }; + + void setClassOccured(QString classOccured) + { mClassOccured = classOccured; }; + + void setFunctionOccured(QString funcOccured) + { mFunctionOccured = funcOccured; }; + + void setSeverity(QString severity) + { mErrorSeverity = severity; }; + + void setViewed(bool viewed) + { mViewed = viewed; }; + + QString message() + { return mMessage; }; + + QString classOccured() + { return mClassOccured; }; + + QString functionOccured() + { return mFunctionOccured; }; + + QString severity() + { return mErrorSeverity; }; + + bool viewed() + { return mViewed; }; + + private: + QString mMessage; + QString mClassOccured; + QString mFunctionOccured; + QString mErrorSeverity; + bool mViewed; +}; + + +#endif //QGSERROR_H \ No newline at end of file Index: src/autogcp/qgsautogcpmanager.h =================================================================== --- src/autogcp/qgsautogcpmanager.h (revision 0) +++ src/autogcp/qgsautogcpmanager.h (revision 0) @@ -0,0 +1,118 @@ +/*************************************************************************** +qgsmanager.cpp - This class manages the operations that need to be performed by + the plug-in interface. Due to the clear separation of the core analysis + classes and the plugin-specific user interface classes, a bridge is required + between these different libraries. This class acts as the bridge, and removes + any business logic from the presentational duties of the UI classes. This is + done by delegating more specific operations to dedicated classes in the core + package. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +Modified: Francois Maass +Modification Date: 24/07/2010 +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSAUTOGCPMANAGER_H +#define QGSAUTOGCPMANAGER_H +#include "qgsgcpdataset.h" +#include "qgsimagedataset.h" +#include "qgsprojectionmanager.h" +#include +#include +#include +#include +#include + +struct IMAGE_INFO +{ + QString pFileName; + QString pFilePath; + QString pFileFormat; + QString pFileSize; + QString pRasterWidth; + QString pRasterHeight; + QString pOriginCoordinates; + QString pPixelSize; + QDateTime pDateCreated; + QDateTime pDateModified; + QDateTime pDateRead; + QString pRasterBands; + QString pProjectionInfo; +}; + +class QgsAutoGCPManager +{ +public: + QgsAutoGCPManager(); + /*! \brief Opens the sensed (raw) image to use + */ + bool openSensedImage(QString path); + /*! \brief Opens the reference (control) image to use + */ + bool openReferenceImage(QString path); + /*! \brief Sets the Sensor model string + The actual sensor model will be loaded from the registry using this string. + */ + void setSensorModel(QString sensorModel); + /*! \brief Sets the amount of GCP's to extract from the reference image. + */ + void setGcpCount(int count); + /*! \brief Empty the current set of GCPs + */ + void clearGcpSet(); + /*! \brief Performs the extraction of Ground Control Points from the reference image. + This class is the owner of the returned dataset and destroys it when itself is destroyed. + \return A pointer to the managed GCP set. + */ + QgsGCPDataSet* extractControlPoints(); + /*! \brief Matches the current set of owned GCP's to the raw image + This class is the owner of the returned dataset and destroys it when itself is destroyed. + \return A pointer to the managed GCP set, or NULL if the operation failed. + */ + QgsGCPDataSet* matchControlPoints(); + /*! \brief Gets a pointer to the managed GCP set + This class is the owner of the returned dataset and destroys it when itself is destroyed. + \return A pointer to the managed GCP set. + */ + QgsGCPDataSet* gcpSet(); + /*! \brief Returns the raw image. + Return a pointer to the QgsImageDataSet containing the raw image dataset. + */ + QgsImageDataSet* rawImage(){return mRawImage;} + /*! \brief Returns the reference image. + Return a pointer to the QgsImageDataSet containing the reference image dataset. + */ + QgsImageDataSet* referenceImage(){return mRefImage;} + /*! \brief QgsAutoGCPManager destructor. + Deallocates all datasets created from any operations. + */ + virtual ~QgsAutoGCPManager(); + + void projectGCPs(); + bool setProjection(QgsImageDataSet *imageDataset, PROJ_INFO *projectionInfo); + + bool exportGcpSet(QString path); + bool exportGcpSet(QgsGCPDataSet *gcpSet, QString path); + void addGcp(QgsGCP *gcp); + void updateGcp(QgsGCP *gcp); + void removeGcp(QgsGCP *gcp); + IMAGE_INFO imageInfo(QString path); + +private: + QgsImageDataSet* mRawImage; + QgsImageDataSet* mRefImage; + QgsGCPDataSet* mGcpSet; + QgsProjectionManager* mProjManager; + int mNumGcps; +}; + +#endif // QGSMANAGER_H Index: src/autogcp/qgsorthorectification.h =================================================================== --- src/autogcp/qgsorthorectification.h (revision 0) +++ src/autogcp/qgsorthorectification.h (revision 0) @@ -0,0 +1,38 @@ +/*************************************************************************** +qgsorthorectification.cpp - This class is used to perform actual ortho-correction on images using + a supplied GCPSet, a SensorModel and, optionally, a Digital Elevation Model +(DEM). +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSORTHORECTIFICATION_H +#define QGSORTHORECTIFICATION_H +#include "qgsimagedataset.h" +#include "qgsgcpdataset.h" + +#include "qgselevationmanager.h" + +class QgsOrthorectification +{ +public: + QgsOrthorectification(); + QgsImageDataSet* orthorectify(); + ~QgsOrthorectification(); +private: + QgsGCPDataSet* mGCPData; + + QgsElevationManager* mElevationModel; + QgsImageDataSet* mImageData; +}; + +#endif // QGSORTHORECTIFICATION_H Index: src/autogcp/qgsdatarow.h =================================================================== --- src/autogcp/qgsdatarow.h (revision 0) +++ src/autogcp/qgsdatarow.h (revision 0) @@ -0,0 +1,30 @@ +/*************************************************************************** +qgsdatarow.cpp - Represents each row of data stored in the Postgre and SQLite +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSDATAROW_H +#define QGSDATAROW_H +#include +#include +#include + +class QgsDataRow +{ +public: + QgsDataRow(); + QMap* values; + virtual ~QgsDataRow(); +}; + +#endif // QGSDATAROW_H Index: src/autogcp/qgsprojectionmanager.cpp =================================================================== --- src/autogcp/qgsprojectionmanager.cpp (revision 0) +++ src/autogcp/qgsprojectionmanager.cpp (revision 0) @@ -0,0 +1,708 @@ +/*************************************************************************** +qgsprojectionmanager.cpp - The ProjectionManager class is responsible for the +projection of GCPs using the projection information either contained within the +Metadata of the image, or as specified by the user. +This class uses the GDAL Warp library to perform the projection on the provided +GCP chip. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: Francois Maass +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsprojectionmanager.h" + +bool QgsProjectionManager::init = false; +QMap QgsProjectionManager::projectedCoordSystems; +QMap QgsProjectionManager::geographicCoordSystems; + +QgsProjectionManager::QgsProjectionManager(QgsImageDataSet *refImageDataset, QgsImageDataSet *rawImageDataset) +{ + if ((refImageDataset != NULL) && (rawImageDataset != NULL)) + { + + mRefDataset = refImageDataset->gdalDataset(); + mRawDataset = rawImageDataset->gdalDataset(); + if((mRefDataset) && (mRawDataset)) + { + mFail = false; + }else + { + mFail = true; + QgsLogger::debug("QGisProjectionManager cannot have NULL-valued datasets."); + } + + }else + { + mFail = true; + QgsLogger::debug("QGisProjectionManager cannot have NULL-valued datasets."); + } + if(!init) + { + initializeMaps(); + init = true; + } + +} + +QgsProjectionManager::QgsProjectionManager() +{ + mRefDataset = NULL; + mRawDataset = NULL; + mFail = false; + if(!init) + { + initializeMaps(); + init = true; + } + +} + +void QgsProjectionManager::setReferenceImage(QgsImageDataSet *refImageDataset) +{ + if(mRefDataset) + { + delete mRefDataset; + } + mRefDataset = refImageDataset->gdalDataset(); +} + +void QgsProjectionManager::setRawImage(QgsImageDataSet *rawImageDataset) +{ + if(mRawDataset) + { + delete mRawDataset; + } + mRawDataset = rawImageDataset->gdalDataset(); +} + +QgsImageDataSet* QgsProjectionManager::referenceImage() +{ + QgsImageDataSet *ds = new QgsImageDataSet(mRefDataset); + return ds; +} + +QgsImageDataSet* QgsProjectionManager::rawImage() +{ + QgsImageDataSet *ds = new QgsImageDataSet(mRawDataset); + return ds; +} + +void QgsProjectionManager::initializeMaps() +{ + //Populate projected coordinate systems map + projectedCoordSystems.insert("Albers Conic Equal Area", 1); + projectedCoordSystems.insert("Azimuthal Equidistant", 2); + projectedCoordSystems.insert("Bonne", 3); + projectedCoordSystems.insert("Cylindrical Equal Area", 4); + projectedCoordSystems.insert("Cassini-Soldner", 5); + projectedCoordSystems.insert("Equidistant Conic", 6); + projectedCoordSystems.insert("Eckert I-VI", 7); + projectedCoordSystems.insert("Equirectangular", 8); + projectedCoordSystems.insert("Equirectangular Generalized", 9); + projectedCoordSystems.insert("Gauss Schreiber Transverse Mercator", 10); + projectedCoordSystems.insert("Geostationary Satellite", 11); + projectedCoordSystems.insert("Goode Homolosine", 12); + projectedCoordSystems.insert("Gnomonic", 13); + projectedCoordSystems.insert("Gall Stereographic", 14); + projectedCoordSystems.insert("Hotine Oblique Mercator Using Azimuth", 15); + projectedCoordSystems.insert("Hotine Oblique Mercator Using Two Points", 16); + projectedCoordSystems.insert("International Map Of World Polycomic", 17); + projectedCoordSystems.insert("Krovak Oblique Conic Conformal", 18); + projectedCoordSystems.insert("Lambert Azimuthal Equal-Area", 19); + projectedCoordSystems.insert("Lambert Conformal Conic", 20); + projectedCoordSystems.insert("Lambert Conformal Conic 1SP", 21); + projectedCoordSystems.insert("Lambert Conformal Conic Belgium", 22); + projectedCoordSystems.insert("Miller Cylindrical", 23); + projectedCoordSystems.insert("Mercator", 24); + projectedCoordSystems.insert("Mollweide", 25); + projectedCoordSystems.insert("New Zealand Map Grid", 26); + projectedCoordSystems.insert("Orthographic", 27); + projectedCoordSystems.insert("Oblique Stereographic", 28); + projectedCoordSystems.insert("Polyconic", 29); + projectedCoordSystems.insert("Polar Stereographic", 30); + projectedCoordSystems.insert("Robinson", 31); + projectedCoordSystems.insert("Sinusoidal", 32); + projectedCoordSystems.insert("Swiss Oblique Cylindrical", 33); + projectedCoordSystems.insert("Stereographic", 34); + projectedCoordSystems.insert("Transverse Mercator", 35); + projectedCoordSystems.insert("Tunesia Mining Grid", 36); + projectedCoordSystems.insert("Transverse Mercator South Oriented", 37); + projectedCoordSystems.insert("Transverse Mercator Variant", 38); + projectedCoordSystems.insert("Two Point Equidistant", 39); + projectedCoordSystems.insert("UTM Projection", 40); + projectedCoordSystems.insert("Van Der Grinten", 41); + projectedCoordSystems.insert("Wagner I--VII", 42); + projectedCoordSystems.insert("None", 43); + +//Populate geographic "Well Known" coordinate systems map + geographicCoordSystems.insert("WGS84", 1); + geographicCoordSystems.insert("WGS72", 2); + geographicCoordSystems.insert("NAD27", 3); + geographicCoordSystems.insert("NAD83", 4); + geographicCoordSystems.insert("EPSG:N", 5); + geographicCoordSystems.insert("OTHER", 6); + +} + +QgsProjectionManager::~QgsProjectionManager() +{ + mRefDataset = NULL; + mRawDataset = NULL; + delete(mRefDataset); + delete(mRawDataset); +} + +void QgsProjectionManager::notifyFailure(QString message) +{ + mFail = true; + QgsLogger::debug(message); +} + +bool QgsProjectionManager::projectGCPChip(QgsImageDataSet* chipIn, QgsImageDataSet* chipOut) +{ + if(mFail) + { + QgsLogger::debug("Cannot execute QgsProjectionManager::projectGCP: QgsProjectionManager not properly constructed."); + return false; + } + + mFail = false; + + if(chipIn == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() - GCP IN pointer invalid!"); + return false; + } + + if(chipOut == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCPChip() - GCP OUT pointer invalid!"); + return false; + } + + GDALDriverH driver; + GDALDataType outDataType; + GDALDataset *outputDS; + + //Get the datatype from the first input band to create output datatype + outDataType = GDALGetRasterDataType(GDALGetRasterBand(mRefDataset, 1)); + + //Set the output driver to the same is the mRawDataset's driver + driver = mRawDataset->GetDriver(); + if(driver == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to get output driver."); + return false; + } + + //Set source and destination coordinate systems + const char *srcCoordSystem, *dstCoordSystem = NULL; + srcCoordSystem = GDALGetProjectionRef(mRefDataset); + + + if(srcCoordSystem == NULL || strlen(srcCoordSystem) <= 0) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to get projection definition from Reference Image Dataset"); + return false; + } + + dstCoordSystem = GDALGetProjectionRef(mRawDataset); + if(dstCoordSystem == NULL || strlen(dstCoordSystem) <= 0) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to get projection definition from Destination Image Dataset"); + return false; + } + + + //Create transformer and get approximate output bounds and resolution + void *transformArg; + + GDALDataset *chipdataset = chipIn->gdalDataset(); + + transformArg = GDALCreateGenImgProjTransformer(chipdataset, srcCoordSystem, NULL, dstCoordSystem, FALSE, 0 , 1); + if(transformArg == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to create transform arguments."); + return false; + } + + double dstGeoTransform[6]; + int nPixels = 0; + int nLines = 0; + CPLErr error; + //Returns the suggested size and resolution of output image, as well as the suggested pixelWidth(nPixels) and pixelHeight(nLines) + error = GDALSuggestedWarpOutput(chipdataset, GDALGenImgProjTransform, transformArg, dstGeoTransform, &nPixels, &nLines); + if(error != CE_None) + { + QgsLogger::debug("QgsProjectionManager::projectGCPChip() could not determine suggested transformation"); + return false; + } + GDALDestroyGenImgProjTransformer(transformArg); + + //Create output file --->>>>>>>><<<<<<<<--- + + int chipDatasize = nPixels * nLines * GDALGetRasterCount(mRefDataset) * (GDALGetDataTypeSize(outDataType) / 8); + void *chipData = CPLMalloc(chipDatasize); + if(!chipData) + { + QgsLogger::debug("QgsProjectionManager::projectGCPChip() failed to create output chipData."); + return false; + } + char nameString[200]; + sprintf(nameString, "MEM:::DATAPOINTER=%p,PIXELS=%d,LINES=%d,BANDS=%d,DATATYPE=%s", + chipData, nPixels, nLines, GDALGetRasterCount(mRefDataset), GDALGetDataTypeName(outDataType)); + +-- outputDS = chipOut->gdalDataset(); + if(outputDS == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCPChip() failed to create output datastet."); + return false; + } + + //Set Projection info for new image + GDALSetProjection(outputDS, dstCoordSystem); + + GDALSetGeoTransform(outputDS, dstGeoTransform); + + //Set color table if it is available and required + GDALColorTableH colorTable; + colorTable = GDALGetRasterColorTable(GDALGetRasterBand(mRefDataset, 1)); + if(colorTable != NULL) + GDALSetRasterColorTable(GDALGetRasterBand(outputDS,1), colorTable); + + //Get the warp options + GDALWarpOptions *warpOptions = getWarpOptions(mRefDataset, outputDS, true); + + //Start the warp operation + warpDatasets(warpOptions, outputDS); + + //cleanup process + destroyWarpData(warpOptions); + + } + +void QgsProjectionManager::projectGCP(QgsGCP *originalGCP) +{ + if(mFail) + { + QgsLogger::debug("Cannot execute QgsProjectionManager::projectGCP: QgsProjectionManager not properly constructed."); + return; + } + + if(originalGCP == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() - GCP pointer invalid!"); + return; + } + + GDALDriverH driver; + GDALDataType outDataType; + GDALDataset *outputDS; + + //Get the datatype from the first input band to create output datatype + outDataType = GDALGetRasterDataType(GDALGetRasterBand(mRefDataset, 1)); + + //Set the output driver to the same is the mRawDataset's driver + driver = mRawDataset->GetDriver(); + if(driver == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to get output driver."); + return; + } + + //Set source and destination coordinate systems + const char *srcCoordSystem, *dstCoordSystem = NULL; + srcCoordSystem = GDALGetProjectionRef(mRefDataset); + + + if(srcCoordSystem == NULL || strlen(srcCoordSystem) <= 0) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to get projection definition from Reference Image Dataset"); + return; + } + + dstCoordSystem = GDALGetProjectionRef(mRawDataset); + if(dstCoordSystem == NULL || strlen(dstCoordSystem) <= 0) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to get projection definition from Destination Image Dataset"); + return; + } + + + //Create transformer and get approximate output bounds and resolution + void *transformArg; + QgsImageDataSet *gcpImageDS = originalGCP->gcpChip(); + + + if(gcpImageDS == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() - GCP Chip datset empty (NULL POINTER)"); + return; + } + GDALDataset *chipdataset = gcpImageDS->gdalDataset(); + + + transformArg = GDALCreateGenImgProjTransformer(chipdataset, srcCoordSystem, NULL, dstCoordSystem, FALSE, 0 , 1); + if(transformArg == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to create transform arguments."); + return; + } + + double dstGeoTransform[6]; + int nPixels = 0; + int nLines = 0; + CPLErr error; + //Returns the suggested size and resolution of output image, as well as the suggested pixelWidth(nPixels) and pixelHeight(nLines) + error = GDALSuggestedWarpOutput(gcpImageDS->gdalDataset(), GDALGenImgProjTransform, transformArg, dstGeoTransform, &nPixels, &nLines); + if(error != CE_None) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() could not determine suggested transformation"); + return; + } + GDALDestroyGenImgProjTransformer(transformArg); + + //Create output file --->>>>>>>><<<<<<<<--- + + int chipDatasize = nPixels * nLines * GDALGetRasterCount(mRefDataset) * (GDALGetDataTypeSize(outDataType) / 8); + void *chipData = CPLMalloc(chipDatasize); + if(!chipData) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to create output chipData."); + return; + } + char nameString[200]; + sprintf(nameString, "MEM:::DATAPOINTER=%p,PIXELS=%d,LINES=%d,BANDS=%d,DATATYPE=%s", + chipData, nPixels, nLines, GDALGetRasterCount(mRefDataset), GDALGetDataTypeName(outDataType)); + + outputDS = (GDALDataset *) GDALOpen(nameString, GA_Update); + if(outputDS == NULL) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to create output datastet."); + return; + } + + //Set Projection info for new image + GDALSetProjection(outputDS, dstCoordSystem); + + GDALSetGeoTransform(outputDS, dstGeoTransform); + + //Set color table if it is available and required + GDALColorTableH colorTable; + colorTable = GDALGetRasterColorTable(GDALGetRasterBand(mRefDataset, 1)); + if(colorTable != NULL) + GDALSetRasterColorTable(GDALGetRasterBand(outputDS,1), colorTable); + + //Get the warp options + GDALWarpOptions *warpOptions = getWarpOptions(mRefDataset, outputDS, true); + + //Start the warp operation + warpDatasets(warpOptions, outputDS); + + //cleanup process + destroyWarpData(warpOptions); + + //Set output chip + QgsImageDataSet *outputQgsDataset; + outputQgsDataset = new QgsImageDataSet(outputDS); + originalGCP->setGcpChip(outputQgsDataset); +} + +GDALWarpOptions* QgsProjectionManager::getWarpOptions(GDALDataset *srcDataset, GDALDataset *dstDataset, bool progressBar) +{ + GDALWarpOptions *pswops = GDALCreateWarpOptions(); + //set src and dst datasets + pswops->hSrcDS = srcDataset; + pswops->hDstDS = dstDataset; + + //set Band options for src and dst datasets + pswops->nBandCount = 1; + pswops->panSrcBands = (int *) CPLMalloc(sizeof(int) * pswops->nBandCount); + pswops->panSrcBands[0] = 1; + pswops->panDstBands = (int *) CPLMalloc(sizeof(int) * pswops->nBandCount); + pswops->panDstBands[0] = 1; + + //Optional: Use GDALTermProgress bar for console applications + if(progressBar) + pswops->pfnProgress = GDALTermProgress; + + //Set transformers: + //GenImgProjTransformer does a three stage geo-transformation: + //1. Source pixel/line coordinates to source image georeferenced coordinates using GeoTransformation + //2. Change projections from source coordinate system to destination coordinate system + //3. Convert from destination image georeferenced coordinates to destination image coordinates + pswops->pTransformerArg = GDALCreateGenImgProjTransformer(srcDataset, GDALGetProjectionRef(srcDataset),dstDataset,GDALGetProjectionRef(dstDataset), FALSE, 0.0, 1); + pswops->pfnTransformer = GDALGenImgProjTransform; + + return pswops; +} + +void QgsProjectionManager::warpDatasets(GDALWarpOptions *pswops, GDALDataset *dstDataset) +{ + GDALWarpOperation warpOp; + CPLErr err; + warpOp.Initialize(pswops); + err = warpOp.ChunkAndWarpImage(0, 0, GDALGetRasterXSize(dstDataset), GDALGetRasterYSize(dstDataset)); + if(err != CE_None) + { + QgsLogger::debug("QgsProjectionManager::projectGCP() failed to warp datasets."); + } +} + + +void QgsProjectionManager::destroyWarpData(GDALWarpOptions *pswops) +{ + GDALDestroyGenImgProjTransformer(pswops->pTransformerArg); + GDALDestroyWarpOptions(pswops); +} + + +bool QgsProjectionManager::checkProjectionInformation(QgsImageDataSet *imageDataset) +{ + GDALDataset *dataset = imageDataset->gdalDataset(); + if(!dataset) + { + QgsLogger::debug("Invalid dataset passed to QgsProjectionManager::checkProjectionInformation(GDALDataset*)."); + return false; + } + + const char *imageProjInfo = dataset->GetProjectionRef(); + if(0 == strcmp("",imageProjInfo)) + { + return false; + } + return true; + +} + +bool QgsProjectionManager::setProjectionInformation(QgsImageDataSet *imageDataset, PROJ_INFO *projectionInfo) +{ + if(!init) + { + initializeMaps(); + init = true; + } + + mFail = false; + if(mFail) + { + QgsLogger::debug("Cannot execute QgsProjectionManager::projectGCP: QgsProjectionManager not properly constructed."); + return false; + } + PROJ_INFO& projInfo = *projectionInfo; + + char *projDefinition = NULL; + OGRSpatialReference ogrSRef; + OGRErr error = OGRERR_NONE; + int projectedId = 0; + int geographicId = 0; + + if((projectedCoordSystems.contains(projInfo.pProjectedCSName)) && (geographicCoordSystems.contains(projInfo.pGeographicCSName))) + { + projectedId = projectedCoordSystems.value(projInfo.pProjectedCSName); + geographicId = geographicCoordSystems.value(projInfo.pGeographicCSName); + } +else + { + QgsLogger::debug("QgsProjectionManager::setProjectionInformation - Could not find specified projections."); + mFail = true; + return false; + } +projectedId = 40; +geographicId = 1; + +//Set Projected Coordinate System + switch(projectedId) + { + case 1: //ALbers Conical Equal Area + error = ogrSRef.SetACEA(projInfo.pStdP1, projInfo.pStdP2, projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 2: //Azimuthal Equidistant + error = ogrSRef.SetAE(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 3: //Bonne + error = ogrSRef.SetBonne(projInfo.pStdP1, projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 4: //Cylindrical Equal Area + error = ogrSRef.SetCEA(projInfo.pStdP1, projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 5: //Cassini-Soldner + error = ogrSRef.SetCS(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 6: //Equidistant Conic + error = ogrSRef.SetEC(projInfo.pStdP1, projInfo.pStdP2, projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 7: //Eckert I-VI + error = ogrSRef.SetEckert(projInfo.pVariation, projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 8: //Equirectangular + error = ogrSRef.SetEquirectangular(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 9: //Equirectangular Generalized + error = ogrSRef.SetEquirectangular2(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pPseudoStdParallel1, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 10: //Gauss Schreiber Transverse Mercator + error = ogrSRef.SetGaussSchreiberTMercator(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 11: //Geostationary Satellite + error = ogrSRef.SetGEOS(projInfo.pCentralMeridian, projInfo.pSatelliteHeight, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 12: //Goode Homolosine + error = ogrSRef.SetGH(projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 13: //Gnomonic + error = ogrSRef.SetGnomonic(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 14: //Gall Stereographic + error = ogrSRef.SetGS(projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 15: //Hotine Oblique Mercator Using Azimuth + error = ogrSRef.SetHOM(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pAzimuth, projInfo.pRectToSkew, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 16: //Hotine Oblique Mercator Using Two Points + error = ogrSRef.SetHOM2PNO(projInfo.pCenterLat, projInfo.pLat1, projInfo.pLong1, projInfo.pLat2, projInfo.pLong2, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 17: //International Map or the World Polyconic + error = ogrSRef.SetIWMPolyconic(projInfo.pLat1, projInfo.pLat2, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 18: //Krovak Oblique Conic Conformal + error = ogrSRef.SetKrovak(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pAzimuth, projInfo.pPseudoStdParallelLat, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 19: //Lambert Azimuthal Equal-Area + error = ogrSRef.SetLAEA(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 20: //Lambert Conformal Conic + error = ogrSRef.SetLCC(projInfo.pStdP1, projInfo.pStdP2, projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 21: //Lambert Conformal Conic 1SP + error = ogrSRef.SetLCC1SP(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 22: //Lambert Conformal Belgium + error = ogrSRef.SetLCCB(projInfo.pStdP1, projInfo.pStdP2, projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 23: //Miller Cylindrical + error = ogrSRef.SetMC(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 24: //Mercator + error = ogrSRef.SetMercator(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 25: //Mollweide + error = ogrSRef.SetMollweide(projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 26: //New Zealand Map Grid + error = ogrSRef.SetNZMG(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 27: //Orthographic + error = ogrSRef.SetOrthographic(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 28: //Oblique Stereographic + error = ogrSRef.SetOS(projInfo.pLatitudeOfOrigin, projInfo.pCentralMeridian, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 29: //Polyconic + error = ogrSRef.SetPolyconic(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 30: //Polar Stereographic + error = ogrSRef.SetPS(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 31: //Robinson + error = ogrSRef.SetRobinson(projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 32: //Sinusoidal + error = ogrSRef.SetSinusoidal(projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 33: //Swiss Oblique Cylindrical + error = ogrSRef.SetSOC(projInfo.pLatitudeOfOrigin, projInfo.pCentralMeridian, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 34: //Stereographic + error = ogrSRef.SetStereographic(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 35: //Transverse Mercator + error = ogrSRef.SetTM(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 36: //Tunesia Mining Grid + error = ogrSRef.SetTMG(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 37: //Transverse Mercator South Oriented + error = ogrSRef.SetTMSO(projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 38: //Transverse Mercator Variant + error = ogrSRef.SetTMVariant(projInfo.pVariantName.toLatin1().data(), projInfo.pCenterLat, projInfo.pCenterLong, projInfo.pScale, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 39: //Two Point Equidistant + error = ogrSRef.SetTPED(projInfo.pLat1, projInfo.pLong1, projInfo.pLat2, projInfo.pLong2, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 40: //UTM + error = ogrSRef.SetUTM(projInfo.pZone, projInfo.pNorth); + break; + case 41: //Van Der Grinten + error = ogrSRef.SetVDG(projInfo.pCenterLong, projInfo.pFalseEasting, projInfo.pFalseNorthing); + break; + case 42: //Wagner I -- VII + error = ogrSRef.SetWagner(projInfo.pVariation, projInfo.pCenterLat, projInfo.pFalseEasting, projInfo.pFalseNorthing); + } + + if(error != OGRERR_NONE) + { + mFail = true; + QgsLogger::debug("QgsProjectionManager::SetProjection could not set Projected Coordinate System."); + return false; + } + + //Set Geographic Coordinate System + switch(geographicId) + { + case 1: + error = ogrSRef.SetWellKnownGeogCS("WGS84"); + break; + case 2: + error = ogrSRef.SetWellKnownGeogCS("WGS72"); + break; + case 3: + error = ogrSRef.SetWellKnownGeogCS("NAD27"); + break; + case 4: + error = ogrSRef.SetWellKnownGeogCS("NAD83"); + break; + case 5: + error = ogrSRef.SetWellKnownGeogCS("EPSG:N"); + break; + case 6: + error = ogrSRef.SetGeogCS(projInfo.pGeogName.toLatin1().data(), projInfo.pDatumName.toLatin1().data(), projInfo.pSpheroidName.toLatin1().data(), projInfo.pSemiMajor, projInfo.pInvFlattening, projInfo.pPMName.toLatin1().data(), projInfo.pPMOffset, projInfo.pAngularUnits.toLatin1().data(), projInfo.pConvertToRadians); + } + + if(error != OGRERR_NONE) + { + mFail = true; + QgsLogger::debug("QgsProjectionManager::SetProjection could not set Geographic Coordinate System."); + return false; + } + + //Export to char* and assign projection to Dataset. + error = ogrSRef.exportToWkt(&projDefinition); + + if(error != OGRERR_NONE) + { + mFail = true; + QgsLogger::debug("QgsProjectionManager::SetProjection could not export Projection Definition."); + return false; + } + + GDALDataset *dataset = imageDataset->gdalDataset(); + + if(dataset->SetProjection(projDefinition) != CE_None) + { + QgsLogger::debug("QgsProjectionManager::SetProjection failed to set projection to dataset provided."); + mFail = true; + return false; + } + return true; +} + Index: src/autogcp/qgswaveletextractor.h =================================================================== --- src/autogcp/qgswaveletextractor.h (revision 0) +++ src/autogcp/qgswaveletextractor.h (revision 0) @@ -0,0 +1,104 @@ +/*************************************************************************** +Date : 07-May-2010 +Author : James Meyer +Copyright : (C) 2010 by FoxHat Solutions +Email : jamesmeyerx@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +//#include "qgsfeatureextractor.h" +//#include + +#include +#include +#include +#include "qgssalientpoint.h" +#include "qgsgcpdataset.h" +#include "qgsimagedataset.h" +#define DEFAULT_LEVELS 5 +#define SALIENCY_LIMIT 1 +#define SAL_LIMIT 175 +#define DEFAULT_BLACK_LIMIT 0.5f +/*! \brief The class uses the Haar Wavelet transform to detect salient features on an image dataset. +The Haar transform decomposes the image into different resolution representations of the image by calculating averages. +*/ +class QgsWaveletExtractor// : public QgsFeatureExtractor +{ +public: + /*! \brief QgsWaveletExtractor Constructor. + Initializes the wavelet extractor with the given image and default feature size. + */ + QgsWaveletExtractor(QgsImageDataSet* image, double threshold = 1.0); + + /*! \brief QgsWaveletExtractor Constructor. + Initializes the extractor with the given dataset and feature size. + */ + QgsWaveletExtractor(QgsImageDataSet* image, int featureXSize, int featureYSize, double threshold = 1.0); + + /*! \brief QgsWaveletExtractor destructor + This does not free the QgsImageDataSet object or any GCP data retrieved. + */ + ~QgsWaveletExtractor(); + + /*! \brief performs the extraction of salient points from the image. + The points contain the pixel coordinates and saliency value. + This method is guaranteed to extract at least the number of GCP's required, but will likely extract more. + The GCP's are ordered in decreasing order of saliency value (i.e. Sharpest points are first). + The caller of this function is responsible for dealocating the data. + */ + QList* extractFeatures(); + + + /*! \brief Checks wether this extractor initialized correctly and is ready for extraction. + If this method returns false, a likely reason is that the underlying image is invalid. + */ + bool initialized(); + + /*! \brief Sets the raster band to use for feature extraction + NB: Band numbers are indexed from 1. + */ + void setRasterBand(int band); + + /*! \brief Sets the size of the salient features to find. + */ + void setFeatureSize(int xSize, int ySize); +private: + bool initialize(); + void addPoint(QList* list, QgsSalientPoint item); + int rasterBand(); + void cleanUp(); + /*! \brief Does the Haar wavelet decomposition of a single level. + Writes each average coefficient as a float to a temporary file which will be read by the next level of decomposition. + \return Returns true if the decomposition succeeded. False otherwise + This method will fail if the previous levels have not been completed. + */ + bool decompose(int level); + /*! \brief Performs the wavelet reconstuction to identify the salient points. + \return If the reconstruction succeeds a pointer to QgsGCPDataSet containing the salient points is returned. Otherwise it returns an empty QgsGCPDataSet. + */ + QList* reconstruct(); +//QgsGCPDataSet* reconstruct(); + float readValue(int x, int y); +/*! \brief Generates the temporary decomposition filename. +*/ + std::string generateTmpFileName(int level); + /*! \brief Finds the value that is furthest from the specified average + Helper method called in reconstruct() + */ + int findMaxDev(float* values,float avg); + //void* readData() {};//Not used yet +private: + QgsImageDataSet* mImage; + int mPaddedSize; + int mLevels, mChipSize; + int mRasterBand; + bool mInitialized; + float mBlackLimit; + double mThreshold, mLimit; +}; Index: src/autogcp/qgssqldriver.cpp =================================================================== --- src/autogcp/qgssqldriver.cpp (revision 0) +++ src/autogcp/qgssqldriver.cpp (revision 0) @@ -0,0 +1,64 @@ +/*************************************************************************** +qgssqlitedriver.cpp - The abstract driver resposible for the SQL database +connection +-------------------------------------- +Date : 02-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgssqldriver.h" + +void QgsSqlDriver::closeDatabase() +{ + mDatabase.close(); + mIsOpen = false; +} + +bool QgsSqlDriver::reconnect() +{ + closeDatabase(); + return openDatabase(); +} + +QSqlError QgsSqlDriver::lastError() +{ + return mDatabase.lastError(); +} + +QSqlQuery QgsSqlDriver::executeQuery(const QString queryString) +{ + if(mIsOpen) + { + return mDatabase.exec(queryString); + } + QSqlQuery query; + return query; +} + +QSqlRecord QgsSqlDriver::retrieveTable(const QString tableName) +{ + return mDatabase.record(tableName); +} + +QString QgsSqlDriver::name() +{ + return mName; +} + +void QgsSqlDriver::setName(QString name) +{ + mName = name; +} + +bool QgsSqlDriver::isOpen() +{ + return mIsOpen; +} \ No newline at end of file Index: src/autogcp/qgsgcp.h =================================================================== --- src/autogcp/qgsgcp.h (revision 0) +++ src/autogcp/qgsgcp.h (revision 0) @@ -0,0 +1,51 @@ +/*************************************************************************** +qgsgcp.cpp - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSGCP_H +#define QGSGCP_H +#include "qgsimagedataset.h" +class QgsGCP +{ +public: + QgsGCP(); + QgsGCP(const QgsGCP& other); + ~QgsGCP(); + const QgsGCP& operator=(const QgsGCP& other); + bool operator==(const QgsGCP& other) const; + double refX() const; + void setRefX(double value); + double refY() const; + void setRefY(double value); + double refZ() const; + void setRefZ(double value); + double rawX() const; + void setRawX(double value); + double rawY() const; + void setRawY(double value); + double correlationCoefficient() const; + void setCorrelationCoefficient(double value); + QgsImageDataSet* gcpChip() const; + void setGcpChip(QgsImageDataSet* value); +private: + double mXRaw, mYRaw, mXRef, mYRef, mZRef; + double mCorrelationCoefficient; + QgsImageDataSet* mChip; + +}; + +#endif // QGSGCP_H Index: src/autogcp/qgssalientpoint.h =================================================================== --- src/autogcp/qgssalientpoint.h (revision 0) +++ src/autogcp/qgssalientpoint.h (revision 0) @@ -0,0 +1,51 @@ +/************************************************************************** +qgsgcp.cpp - A Ground Control Point (GCP) abstraction contains information about + a specific GCP such as the reference and associated raw coordinates of this + GCP, as well as additional elevation and other information. This object is + also the container for the GCP chip data. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Author: James Meyer +Email : jamesmeyerx@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSSALIENTPOINT_H +#define QGSSALIENTPOINT_H + +#include "qgspoint.h" +/*! + This class represents any point of interest on a two-dimensional raster image. +*/ +class QgsSalientPoint : public QgsPoint +{ + public: + /*! \brief QgsSalientPoint constructor + constructs a feature point at the given x, y coordinates and optionally a saliency value. + */ + QgsSalientPoint(double x = 0, double y = 0, double theSaliency = 0): + QgsPoint(x,y), + mSaliency(theSaliency) + { + } + + /*! \brief Gets the Saliency value of this feature. + */ + double saliency()const { return mSaliency; } + + /*! \brief Sets the Saliency value of this feature. + */ + void setSaliency(double value) { mSaliency = value; } + + private: + double mSaliency; +}; + +#endif // QGSSALIENTPOINT_H Index: src/autogcp/qgshasher.h =================================================================== --- src/autogcp/qgshasher.h (revision 0) +++ src/autogcp/qgshasher.h (revision 0) @@ -0,0 +1,70 @@ +/*************************************************************************** +qgshasher.h - A hash calculator used to generate hashes from strings and +files. +-------------------------------------- +Author: Christoph Stallmann +Date : 24-June-2010 +Date Modified: 08-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSHASHER_H +#define QGSHASHER_H + +#include +#include +#include +#include + +class QgsHasher +{ + public: + + /** + * Options for the hash algorithm to be used. + **/ + enum HashAlgorithm + { + Md4, + Md5, + Sha1 + }; + + /** + * Default constructor for the class. + **/ + QgsHasher(); + + /** + * Calculates the hash for a string. + * + * @param data - The string used for the hash calculation. + * @param hash - Specifies the hash algorithm. Md5 is given as default hash algorithm. + * + * @return A string containing the hash. + * + **/ + QString getStringHash(QString data, HashAlgorithm hash = Md5); + + /** + * Calculates the hash for a file. + * + * @param data - The path of the file to be used for the hash calculation. + * @param hash - Specifies the hash algorithm. Md5 is given as default hash algorithm. + * @param numberOfBytes - Specefies the number of bytes to be read from the file, used for the hash calculation. -1 is given as default and used to read the whole file. + * + * @return A string containing the hash + * + **/ + QString getFileHash(QString data, HashAlgorithm hash = Md5, int numberOfBytes = -1); +}; + +#endif // QGSHASHER_H Property changes on: src/autogcp/qgshasher.h ___________________________________________________________________ Added: svn:executable + * Index: src/autogcp/qgsgcpdataset.cpp =================================================================== --- src/autogcp/qgsgcpdataset.cpp (revision 0) +++ src/autogcp/qgsgcpdataset.cpp (revision 0) @@ -0,0 +1,86 @@ +/*************************************************************************** +qgsgcpdataset.cpp - This is a container class that represents an entire set of + GCP’s associated with a specific reference model or a specific extraction + and cross-referencing operation. +-------------------------------------- +Date : 07-May-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgsgcpdataset.h" + +QgsGCPDataSet::QgsGCPDataSet() +{ +} + +QgsGCPDataSet::~QgsGCPDataSet() +{ + +} + + +//Adds the GCP's in descending order of error value +void QgsGCPDataSet::addGcp(QgsGCP* point) +{ + mList.append( point); +} +void QgsGCPDataSet::removeGcp(QgsGCP* point) +{ + GcpList::iterator it = mList.begin(); + for (; it != mList.end();it++) + { + if ( (*it) == point) + { + mList.erase(it); + break; + } + } +} +//Sorts all GCP's in descending order of error values +/*void QgsGCPDataSet::sort() +{ + DescErrorCompare comp; + mList.sort(comp); +}*/ + +void QgsGCPDataSet::updateGcp(QgsGCP* oldPoint, QgsGCP* newPoint) +{ + GcpList::iterator it = mList.begin(); + for (; it != mList.end();it++) + { + if ((*it) == oldPoint) + { + (*it) = newPoint; + break; + } + } +} + +void QgsGCPDataSet::clear() +{ + mList.clear(); +} + + +int QgsGCPDataSet::size() const +{ + return mList.size(); +} + +const QList& QgsGCPDataSet::constList() const +{ + return mList; +} + +QList QgsGCPDataSet::list() +{ + return mList; +} Index: src/autogcp/qgspostgresdriver.cpp =================================================================== --- src/autogcp/qgspostgresdriver.cpp (revision 0) +++ src/autogcp/qgspostgresdriver.cpp (revision 0) @@ -0,0 +1,107 @@ +/*************************************************************************** +qgspostgresdriver.cpp - The Driver resposible for the PostgreSQL database +connection +-------------------------------------- +Date : 02-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#include "qgspostgresdriver.h" +#include + +QgsPostgresDriver::QgsPostgresDriver() +{ + mDatabase = QSqlDatabase::addDatabase("QPSQL"); + mIsOpen = false; +} + +bool QgsPostgresDriver::openDatabase() +{ + if(!mIsOpen && !mName.isNull() && !mHost.isNull() && !mUsername.isNull() && !mPassword.isNull()) + { + mDatabase.setHostName(mHost); + mDatabase.setUserName(mUsername); //sudo apt-get install postgres -> sudo -u postgres psql postgres -> \password postgres -> + mDatabase.setPassword(mPassword); + mDatabase.setDatabaseName(mName); + QSqlQuery query(mDatabase); + query.exec("CREATE DATABASE IF NOT EXISTS "+mName); + query.exec("USE "+mName); + mIsOpen = mDatabase.open(); + } + return mIsOpen; +} + +bool QgsPostgresDriver::openDatabase(const QString name, const QString username, const QString password, const QString host) +{ + mName = name; + mUsername = username; + mPassword = password; + mHost = host; + if(!mIsOpen) + { + mDatabase.setHostName(mHost); + mDatabase.setUserName(mUsername); //sudo apt-get install postgres -> sudo -u postgres psql postgres -> \password postgres -> + mDatabase.setPassword(mPassword); + mIsOpen = mDatabase.open(); + QSqlQuery query(mDatabase); + query.exec("CREATE DATABASE "+mName+";"); + mDatabase.setDatabaseName(mName); + mIsOpen = mDatabase.open(); + } + return mIsOpen; +} + +void QgsPostgresDriver::deleteDatabase() +{ + closeDatabase(); + QSqlQuery query(mDatabase); + query.exec("DROP DATABASE "+mName+";"); +} + +QString QgsPostgresDriver::username() +{ + return mUsername; +} + +void QgsPostgresDriver::setUsername(const QString username) +{ + mUsername = username; +} + +QString QgsPostgresDriver::password() +{ + return mPassword; +} + +void QgsPostgresDriver::setPassword(const QString password) +{ + mPassword = password; +} + +QString QgsPostgresDriver::host() +{ + return mHost; +} + +void QgsPostgresDriver::setHost(const QString host) +{ + mHost = host; +} + +int QgsPostgresDriver::port() +{ + return mPort; +} + +void QgsPostgresDriver::setPort(const int port) +{ + mPort = port; +} \ No newline at end of file Index: src/autogcp/qgssqlitedriver.h =================================================================== --- src/autogcp/qgssqlitedriver.h (revision 0) +++ src/autogcp/qgssqlitedriver.h (revision 0) @@ -0,0 +1,30 @@ +/*************************************************************************** +qgssqlitedriver.h - The driver resposible for the SQLite database +connection +-------------------------------------- +Date : 02-July-2010 +Copyright : (C) 2010 by FoxHat Solutions +Email : foxhat.solutions@gmail.com +/*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +***************************************************************************/ + +#ifndef QGSSQLITEDRIVER_H +#define QGSSQLITEDRIVER_H +#include "qgssqldriver.h" + +class QgsSqliteDriver : public QgsSqlDriver +{ + public: + QgsSqliteDriver(); + bool openDatabase(); //Opens the database + bool openDatabase(const QString name); //Opens the database + void deleteDatabase(); //Deletes the database +}; + +#endif // QGSSQLITEDRIVER_H Index: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt (revision 14199) +++ src/CMakeLists.txt (working copy) @@ -1,4 +1,4 @@ -SUBDIRS(core analysis ui gui app providers plugins helpviewer) +SUBDIRS(core analysis ui gui app providers plugins helpviewer autogcp) IF (WITH_BINDINGS) SUBDIRS(python)