mirror of
https://github.com/storytold/LiveScan3D.git
synced 2026-10-09 00:09:58 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
|
||||
#include "nanoflann.h"
|
||||
|
||||
#if defined(ICP_DLL_EXPORTS) // inside DLL
|
||||
# define ICP_API __declspec(dllexport)
|
||||
#else // outside DLL
|
||||
# define ICP_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct Point3f
|
||||
{
|
||||
float X, Y, Z;
|
||||
};
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
struct PointCloud
|
||||
{
|
||||
std::vector<Point3f> pts;
|
||||
|
||||
// Must return the number of data points
|
||||
inline size_t kdtree_get_point_count() const { return pts.size(); }
|
||||
// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
|
||||
inline float kdtree_distance(const float *p1, const size_t idx_p2, size_t /*size*/) const
|
||||
{
|
||||
const float d0 = p1[0] - pts[idx_p2].X;
|
||||
const float d1 = p1[1] - pts[idx_p2].Y;
|
||||
const float d2 = p1[2] - pts[idx_p2].Z;
|
||||
|
||||
return d0*d0 + d1*d1 + d2*d2;
|
||||
}
|
||||
// Returns the dim'th component of the idx'th point in the class:
|
||||
// Since this is inlined and the "dim" argument is typically an immediate value, the
|
||||
// "if/else's" are actually solved at compile time.
|
||||
inline float kdtree_get_pt(const size_t idx, int dim) const
|
||||
{
|
||||
if (dim == 0) return pts[idx].X;
|
||||
else if (dim == 1) return pts[idx].Y;
|
||||
else return pts[idx].Z;
|
||||
}
|
||||
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
|
||||
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
|
||||
// Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
|
||||
template <class BBOX>
|
||||
bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
extern "C" ICP_API float __stdcall ICP(Point3f *verts1, Point3f *verts2, int nVerts1, int nVerts2, float *R, float *t, int maxIter = 10);
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "marker.h"
|
||||
#include "utils.h"
|
||||
|
||||
vector<float> RotatePoint(vector<float> &point, std::vector<std::vector<float>> &R);
|
||||
vector<float> InverseRotatePoint(vector<float> &point, std::vector<std::vector<float>> &R);
|
||||
|
||||
struct MarkerPose
|
||||
{
|
||||
int markerId;
|
||||
float R[3][3];
|
||||
float t[3];
|
||||
};
|
||||
|
||||
class Calibration
|
||||
{
|
||||
public:
|
||||
vector<float> worldT;
|
||||
vector<vector<float>> worldR;
|
||||
int iUsedMarkerId;
|
||||
|
||||
vector<float> cameraT;
|
||||
vector<vector<float>> cameraR;
|
||||
|
||||
vector<MarkerPose> markerPoses;
|
||||
|
||||
bool bCalibrated;
|
||||
|
||||
Calibration();
|
||||
~Calibration();
|
||||
|
||||
bool Calibrate(RGB *pBuffer, Point3f *pCameraCoordinates, int cColorWidth, int cColorHeight);
|
||||
private:
|
||||
IMarker *pDetector;
|
||||
int nSampleCounter;
|
||||
int nRequiredSamples;
|
||||
|
||||
vector<vector<Point3f>> marker3DSamples;
|
||||
|
||||
void Procrustes(MarkerInfo &marker, vector<Point3f> &markerInWorld, vector<float> &markerT, vector<vector<float>> &markerR);
|
||||
bool GetMarkerCorners3D(vector<Point3f> &marker3D, MarkerInfo &marker, Point3f *pCameraCoordinates, int cColorWidth, int cColorHeight);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "nanoflann.h"
|
||||
#include "utils.h"
|
||||
|
||||
struct KNNeighborsResult
|
||||
{
|
||||
std::vector<size_t> neighbors;
|
||||
std::vector<float> distances;
|
||||
float kDistance;
|
||||
};
|
||||
|
||||
struct PointCloud
|
||||
{
|
||||
std::vector<Point3f> pts;
|
||||
|
||||
// Must return the number of data points
|
||||
inline size_t kdtree_get_point_count() const { return pts.size(); }
|
||||
// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
|
||||
inline float kdtree_distance(const float *p1, const size_t idx_p2, size_t /*size*/) const
|
||||
{
|
||||
const float d0 = p1[0] - pts[idx_p2].X;
|
||||
const float d1 = p1[1] - pts[idx_p2].Y;
|
||||
const float d2 = p1[2] - pts[idx_p2].Z;
|
||||
|
||||
return d0*d0 + d1*d1 + d2*d2;
|
||||
}
|
||||
// Returns the dim'th component of the idx'th point in the class:
|
||||
// Since this is inlined and the "dim" argument is typically an immediate value, the
|
||||
// "if/else's" are actually solved at compile time.
|
||||
inline float kdtree_get_pt(const size_t idx, int dim) const
|
||||
{
|
||||
if (dim == 0) return pts[idx].X;
|
||||
else if (dim == 1) return pts[idx].Y;
|
||||
else return pts[idx].Z;
|
||||
}
|
||||
// Optional bounding-box computation: return false to default to a standard bbox computation loop.
|
||||
// Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
|
||||
// Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
|
||||
template <class BBOX>
|
||||
bool kdtree_get_bbox(BBOX& /*bb*/) const { return false; }
|
||||
};
|
||||
|
||||
typedef nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<float, PointCloud>, PointCloud, 3> kdTree;
|
||||
|
||||
void filter(std::vector<Point3f> &vertices, std::vector<RGB> &colors, int k = 10, float maxDist = 0.01);
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
class ICapture
|
||||
{
|
||||
public:
|
||||
ICapture();
|
||||
~ICapture();
|
||||
|
||||
virtual bool Initialize() = 0;
|
||||
virtual bool AcquireFrame() = 0;
|
||||
virtual void MapDepthFrameToCameraSpace(Point3f *pCameraSpacePoints) = 0;
|
||||
virtual void MapColorFrameToCameraSpace(Point3f *pCameraSpacePoints) = 0;
|
||||
virtual void MapDepthFrameToColorSpace(Point2f *pColorSpacePoints) = 0;
|
||||
virtual void MapColorFrameToDepthSpace(Point2f *pDepthSpacePoints) = 0;
|
||||
|
||||
bool bInitialized;
|
||||
|
||||
int nColorFrameHeight, nColorFrameWidth;
|
||||
int nDepthFrameHeight, nDepthFrameWidth;
|
||||
|
||||
UINT16 *pDepth;
|
||||
RGB *pColorRGBX;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
//struktura przechowywuj¹ca wszystkie dane markera
|
||||
typedef struct MarkerStruct
|
||||
{
|
||||
int id;
|
||||
//po³o¿enie naro¿ników markera w obrazie
|
||||
std::vector<Point2f> corners;
|
||||
//te same punkty w uk³adzie wspó³rzêdnych markera
|
||||
std::vector<Point3f> points;
|
||||
|
||||
MarkerStruct()
|
||||
{
|
||||
id = -1;
|
||||
}
|
||||
|
||||
MarkerStruct(int id, std::vector<Point2f> corners, std::vector<Point3f> points)
|
||||
{
|
||||
this->id = id;
|
||||
|
||||
this->corners = corners;
|
||||
this->points = points;
|
||||
}
|
||||
} MarkerInfo;
|
||||
|
||||
class IMarker
|
||||
{
|
||||
public:
|
||||
IMarker() {};
|
||||
|
||||
//znajduje wszystkie markery w obrazie i zapisuje je w zmiennej markers
|
||||
virtual bool GetMarker(RGB *img, int height, int width, MarkerInfo &marker) = 0;
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="ImageRenderer.h" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Manages the drawing of image data
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d2d1.h>
|
||||
|
||||
class ImageRenderer
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
ImageRenderer();
|
||||
|
||||
/// <summary>
|
||||
/// Destructor
|
||||
/// </summary>
|
||||
virtual ~ImageRenderer();
|
||||
|
||||
/// <summary>
|
||||
/// Set the window to draw to as well as the video format
|
||||
/// Implied bits per pixel is 32
|
||||
/// </summary>
|
||||
/// <param name="hWnd">window to draw to</param>
|
||||
/// <param name="pD2DFactory">already created D2D factory object</param>
|
||||
/// <param name="sourceWidth">width (in pixels) of image data to be drawn</param>
|
||||
/// <param name="sourceHeight">height (in pixels) of image data to be drawn</param>
|
||||
/// <param name="sourceStride">length (in bytes) of a single scanline</param>
|
||||
/// <returns>indicates success or failure</returns>
|
||||
HRESULT Initialize(HWND hwnd, ID2D1Factory* pD2DFactory, int sourceWidth, int sourceHeight, int sourceStride);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a 32 bit per pixel image of previously specified width, height, and stride to the associated hwnd
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data in RGBX format</param>
|
||||
/// <param name="cbImage">size of image data in bytes</param>
|
||||
/// <returns>indicates success or failure</returns>
|
||||
HRESULT Draw(BYTE* pImage, unsigned long cbImage);
|
||||
|
||||
private:
|
||||
HWND m_hWnd;
|
||||
|
||||
// Format information
|
||||
UINT m_sourceHeight;
|
||||
UINT m_sourceWidth;
|
||||
LONG m_sourceStride;
|
||||
|
||||
// Direct2D
|
||||
ID2D1Factory* m_pD2DFactory;
|
||||
ID2D1HwndRenderTarget* m_pRenderTarget;
|
||||
ID2D1Bitmap* m_pBitmap;
|
||||
|
||||
/// <summary>
|
||||
/// Ensure necessary Direct2d resources are created
|
||||
/// </summary>
|
||||
/// <returns>indicates success or failure</returns>
|
||||
HRESULT EnsureResources();
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of Direct2d resources
|
||||
/// </summary>
|
||||
void DiscardResources();
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ICapture.h"
|
||||
#include "Kinect.h"
|
||||
#include "utils.h"
|
||||
|
||||
class KinectCapture : public ICapture
|
||||
{
|
||||
public:
|
||||
KinectCapture();
|
||||
~KinectCapture();
|
||||
|
||||
bool Initialize();
|
||||
bool AcquireFrame();
|
||||
void MapDepthFrameToCameraSpace(Point3f *pCameraSpacePoints);
|
||||
void MapColorFrameToCameraSpace(Point3f *pCameraSpacePoints);
|
||||
void MapDepthFrameToColorSpace(Point2f *pColorSpacePoints);
|
||||
void MapColorFrameToDepthSpace(Point2f *pDepthSpacePoints);
|
||||
private:
|
||||
ICoordinateMapper* pCoordinateMapper;
|
||||
IKinectSensor* pKinectSensor;
|
||||
IMultiSourceFrameReader* pMultiSourceFrameReader;
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include "resource.h"
|
||||
#include "ImageRenderer.h"
|
||||
#include "SocketCS.h"
|
||||
#include "calibration.h"
|
||||
#include "utils.h"
|
||||
#include "KinectCapture.h"
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
class LiveScanClient
|
||||
{
|
||||
public:
|
||||
LiveScanClient();
|
||||
~LiveScanClient();
|
||||
|
||||
|
||||
static LRESULT CALLBACK MessageRouter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
int Run(HINSTANCE hInstance, int nCmdShow);
|
||||
|
||||
bool m_bSocketThread;
|
||||
private:
|
||||
Calibration calibration;
|
||||
|
||||
bool m_bCalibrate;
|
||||
bool m_bFilter;
|
||||
|
||||
ICapture *pCapture;
|
||||
|
||||
int m_nFilterNeighbors;
|
||||
float m_fFilterThreshold;
|
||||
|
||||
bool m_bCaptureFrame;
|
||||
bool m_bConnected;
|
||||
bool m_bConfirmCaptured;
|
||||
bool m_bConfirmCalibrated;
|
||||
bool m_bShowDepth;
|
||||
|
||||
SocketClient *m_pClientSocket;
|
||||
std::vector<float> m_vBounds;
|
||||
|
||||
std::vector<Point3f> m_vLastFrameVertices;
|
||||
std::vector<RGB> m_vLastFrameRGB;
|
||||
std::vector<std::vector<Point3f>> m_vGatheredVertices;
|
||||
std::vector<std::vector<RGB>> m_vGatheredRGBPoints;
|
||||
|
||||
HWND m_hWnd;
|
||||
INT64 m_nLastCounter;
|
||||
double m_fFreq;
|
||||
INT64 m_nNextStatusTime;
|
||||
DWORD m_nFramesSinceUpdate;
|
||||
|
||||
Point3f* m_pCameraSpaceCoordinates;
|
||||
Point2f* m_pColorCoordinates;
|
||||
|
||||
// Direct2D
|
||||
ImageRenderer* m_pDrawColor;
|
||||
ID2D1Factory* m_pD2DFactory;
|
||||
RGB* m_pDepthRGBX;
|
||||
|
||||
void UpdateFrame();
|
||||
void ProcessColor(RGB* pBuffer, int nWidth, int nHeight);
|
||||
void ProcessDepth(const UINT16* pBuffer, int nHeight, int nWidth);
|
||||
|
||||
bool SetStatusMessage(_In_z_ WCHAR* szMessage, DWORD nShowTimeMsec, bool bForce);
|
||||
|
||||
void HandleSocket();
|
||||
void SocketThreadFunction();
|
||||
void StoreFrame(Point3f *vertices, Point2f *mapping, RGB *color);
|
||||
void ShowFPS();
|
||||
void ReadIPFromFile();
|
||||
void WriteIPToFile();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "utils.h"
|
||||
#include "IMarker.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class MarkerDetector : public IMarker
|
||||
{
|
||||
public:
|
||||
MarkerDetector();
|
||||
|
||||
bool GetMarker(RGB *img, int height, int width, MarkerInfo &marker);
|
||||
private:
|
||||
int nMarkerCorners;
|
||||
vector<cv::Point2f> vPts;
|
||||
|
||||
int nMinSize;
|
||||
int nMaxSize;
|
||||
int nThreshold;
|
||||
double dApproxPolyCoef;
|
||||
double dMarkerFrame;
|
||||
bool bDraw;
|
||||
|
||||
bool GetMarker(cv::Mat &img, MarkerInfo &marker);
|
||||
bool OrderCorners(vector<cv::Point2f> &corners);
|
||||
int GetCode(cv::Mat &img, vector<cv::Point2f> points, vector<cv::Point2f> corners);
|
||||
void CornersSubPix(vector<cv::Point2f> &corners, vector<cv::Point> contour, bool order);
|
||||
cv::Point2f GetIntersection(cv::Vec4f lin1, cv::Vec4f lin2);
|
||||
void GetMarkerPoints(vector<Point3f> &pts);
|
||||
void GetMarkerPointsForWarp(vector<cv::Point2f> &pts);
|
||||
double GetMarkerArea(MarkerInfo &marker);
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (C) 2015 Marek Kowalski (M.Kowalski@ire.pw.edu.pl), Jacek Naruniec (J.Naruniec@ire.pw.edu.pl)
|
||||
// License: MIT Software License See LICENSE.txt for the full license.
|
||||
|
||||
// If you use this software in your research, then please use the following citation:
|
||||
|
||||
// Kowalski, M.; Naruniec, J.; Daniluk, M.: "LiveScan3D: A Fast and Inexpensive 3D Data
|
||||
// Acquisition System for Multiple Kinect v2 Sensors". in 3D Vision (3DV), 2015 International Conference on, Lyon, France, 2015
|
||||
|
||||
// @INPROCEEDINGS{Kowalski15,
|
||||
// author={Kowalski, M. and Naruniec, J. and Daniluk, M.},
|
||||
// booktitle={3D Vision (3DV), 2015 International Conference on},
|
||||
// title={LiveScan3D: A Fast and Inexpensive 3D Data Acquisition System for Multiple Kinect v2 Sensors},
|
||||
// year={2015},
|
||||
// }
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum INCOMING_MESSAGE_TYPE
|
||||
{
|
||||
MSG_CAPTURE_FRAME,
|
||||
MSG_CALIBRATE,
|
||||
MSG_RECEIVE_SETTINGS,
|
||||
MSG_REQUEST_STORED_FRAME,
|
||||
MSG_REQUEST_LAST_FRAME,
|
||||
MSG_RECEIVE_CALIBRATION,
|
||||
MSG_CLEAR_STORED_FRAMES
|
||||
};
|
||||
|
||||
enum OUTGOING_MESSAGE_TYPE
|
||||
{
|
||||
MSG_CONFIRM_CAPTURED,
|
||||
MSG_CONFIRM_CALIBRATED,
|
||||
MSG_STORED_FRAME,
|
||||
MSG_LAST_FRAME
|
||||
};
|
||||
|
||||
typedef struct Point3f
|
||||
{
|
||||
Point3f()
|
||||
{
|
||||
this->X = 0;
|
||||
this->Y = 0;
|
||||
this->Z = 0;
|
||||
}
|
||||
Point3f(float X, float Y, float Z)
|
||||
{
|
||||
this->X = X;
|
||||
this->Y = Y;
|
||||
this->Z = Z;
|
||||
}
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
} Point3f;
|
||||
|
||||
typedef struct Point2f
|
||||
{
|
||||
Point2f()
|
||||
{
|
||||
this->X = 0;
|
||||
this->Y = 0;
|
||||
}
|
||||
Point2f(float X, float Y)
|
||||
{
|
||||
this->X = X;
|
||||
this->Y = Y;
|
||||
}
|
||||
float X;
|
||||
float Y;
|
||||
} Point2f;
|
||||
|
||||
typedef struct RGB
|
||||
{
|
||||
BYTE rgbBlue;
|
||||
BYTE rgbGreen;
|
||||
BYTE rgbRed;
|
||||
BYTE rgbReserved;
|
||||
} RGB;
|
||||
|
||||
Point3f RotatePoint(Point3f &point, std::vector<std::vector<float>> &R);
|
||||
Point3f InverseRotatePoint(Point3f &point, std::vector<std::vector<float>> &R);
|
||||
+1391
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_CV_H__
|
||||
#define __OPENCV_OLD_CV_H__
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define CV_DO_PRAGMA(x) __pragma(x)
|
||||
#define __CVSTR2__(x) #x
|
||||
#define __CVSTR1__(x) __CVSTR2__(x)
|
||||
#define __CVMSVCLOC__ __FILE__ "("__CVSTR1__(__LINE__)") : "
|
||||
#define CV_MSG_PRAGMA(_msg) CV_DO_PRAGMA(message (__CVMSVCLOC__ _msg))
|
||||
#elif defined(__GNUC__)
|
||||
#define CV_DO_PRAGMA(x) _Pragma (#x)
|
||||
#define CV_MSG_PRAGMA(_msg) CV_DO_PRAGMA(message (_msg))
|
||||
#else
|
||||
#define CV_DO_PRAGMA(x)
|
||||
#define CV_MSG_PRAGMA(_msg)
|
||||
#endif
|
||||
#define CV_WARNING(x) CV_MSG_PRAGMA("Warning: " #x)
|
||||
|
||||
//CV_WARNING("This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module")
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/flann/flann.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/legacy/compat.hpp"
|
||||
|
||||
#if !defined(CV_IMPL)
|
||||
#define CV_IMPL extern "C"
|
||||
#endif //CV_IMPL
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#include "opencv2/core/internal.hpp"
|
||||
#endif //__cplusplus
|
||||
|
||||
#endif // __OPENCV_OLD_CV_H_
|
||||
@@ -0,0 +1,52 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_CV_HPP__
|
||||
#define __OPENCV_OLD_CV_HPP__
|
||||
|
||||
//#if defined(__GNUC__)
|
||||
//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
|
||||
//#endif
|
||||
|
||||
#include <cv.h>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_AUX_H__
|
||||
#define __OPENCV_OLD_AUX_H__
|
||||
|
||||
//#if defined(__GNUC__)
|
||||
//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
|
||||
//#endif
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc_c.h"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
#include "opencv2/video/background_segm.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/calib3d/calib3d.hpp"
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
#include "opencv2/legacy/legacy.hpp"
|
||||
#include "opencv2/legacy/compat.hpp"
|
||||
#include "opencv2/legacy/blobtrack.hpp"
|
||||
#include "opencv2/contrib/contrib.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
/* End of file. */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_AUX_HPP__
|
||||
#define __OPENCV_OLD_AUX_HPP__
|
||||
|
||||
//#if defined(__GNUC__)
|
||||
//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
|
||||
//#endif
|
||||
|
||||
#include <cvaux.h>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to
|
||||
// this license. If you do not agree to this license, do not download,
|
||||
// install, copy or use the software.
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2008, Google, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation or contributors may not be used to endorse
|
||||
// or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is"
|
||||
// and any express or implied warranties, including, but not limited to, the
|
||||
// implied warranties of merchantability and fitness for a particular purpose
|
||||
// are disclaimed. In no event shall the Intel Corporation or contributors be
|
||||
// liable for any direct, indirect, incidental, special, exemplary, or
|
||||
// consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
|
||||
|
||||
#ifndef __OPENCV_OLD_WIMAGE_HPP__
|
||||
#define __OPENCV_OLD_WIMAGE_HPP__
|
||||
|
||||
#include "opencv2/core/wimage.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_CXCORE_H__
|
||||
#define __OPENCV_OLD_CXCORE_H__
|
||||
|
||||
//#if defined(__GNUC__)
|
||||
//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
|
||||
//#endif
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,52 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_CXCORE_HPP__
|
||||
#define __OPENCV_OLD_CXCORE_HPP__
|
||||
|
||||
//#if defined(__GNUC__)
|
||||
//#warning "This is a deprecated opencv header provided for compatibility. Please include a header from a corresponding opencv module"
|
||||
//#endif
|
||||
|
||||
#include <cxcore.h>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_EIGEN_HPP__
|
||||
#define __OPENCV_OLD_EIGEN_HPP__
|
||||
|
||||
#include "opencv2/core/eigen.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef __OPENCV_OLD_CXMISC_H__
|
||||
#define __OPENCV_OLD_CXMISC_H__
|
||||
|
||||
#include "opencv2/core/internal.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_HIGHGUI_H__
|
||||
#define __OPENCV_OLD_HIGHGUI_H__
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/highgui/highgui_c.h"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
//
|
||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OLD_ML_H__
|
||||
#define __OPENCV_OLD_ML_H__
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/ml/ml.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,751 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_CALIB3D_HPP__
|
||||
#define __OPENCV_CALIB3D_HPP__
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/****************************************************************************************\
|
||||
* Camera Calibration, Pose Estimation and Stereo *
|
||||
\****************************************************************************************/
|
||||
|
||||
typedef struct CvPOSITObject CvPOSITObject;
|
||||
|
||||
/* Allocates and initializes CvPOSITObject structure before doing cvPOSIT */
|
||||
CVAPI(CvPOSITObject*) cvCreatePOSITObject( CvPoint3D32f* points, int point_count );
|
||||
|
||||
|
||||
/* Runs POSIT (POSe from ITeration) algorithm for determining 3d position of
|
||||
an object given its model and projection in a weak-perspective case */
|
||||
CVAPI(void) cvPOSIT( CvPOSITObject* posit_object, CvPoint2D32f* image_points,
|
||||
double focal_length, CvTermCriteria criteria,
|
||||
float* rotation_matrix, float* translation_vector);
|
||||
|
||||
/* Releases CvPOSITObject structure */
|
||||
CVAPI(void) cvReleasePOSITObject( CvPOSITObject** posit_object );
|
||||
|
||||
/* updates the number of RANSAC iterations */
|
||||
CVAPI(int) cvRANSACUpdateNumIters( double p, double err_prob,
|
||||
int model_points, int max_iters );
|
||||
|
||||
CVAPI(void) cvConvertPointsHomogeneous( const CvMat* src, CvMat* dst );
|
||||
|
||||
/* Calculates fundamental matrix given a set of corresponding points */
|
||||
#define CV_FM_7POINT 1
|
||||
#define CV_FM_8POINT 2
|
||||
|
||||
#define CV_LMEDS 4
|
||||
#define CV_RANSAC 8
|
||||
|
||||
#define CV_FM_LMEDS_ONLY CV_LMEDS
|
||||
#define CV_FM_RANSAC_ONLY CV_RANSAC
|
||||
#define CV_FM_LMEDS CV_LMEDS
|
||||
#define CV_FM_RANSAC CV_RANSAC
|
||||
|
||||
enum
|
||||
{
|
||||
CV_ITERATIVE = 0,
|
||||
CV_EPNP = 1, // F.Moreno-Noguer, V.Lepetit and P.Fua "EPnP: Efficient Perspective-n-Point Camera Pose Estimation"
|
||||
CV_P3P = 2 // X.S. Gao, X.-R. Hou, J. Tang, H.-F. Chang; "Complete Solution Classification for the Perspective-Three-Point Problem"
|
||||
};
|
||||
|
||||
CVAPI(int) cvFindFundamentalMat( const CvMat* points1, const CvMat* points2,
|
||||
CvMat* fundamental_matrix,
|
||||
int method CV_DEFAULT(CV_FM_RANSAC),
|
||||
double param1 CV_DEFAULT(3.), double param2 CV_DEFAULT(0.99),
|
||||
CvMat* status CV_DEFAULT(NULL) );
|
||||
|
||||
/* For each input point on one of images
|
||||
computes parameters of the corresponding
|
||||
epipolar line on the other image */
|
||||
CVAPI(void) cvComputeCorrespondEpilines( const CvMat* points,
|
||||
int which_image,
|
||||
const CvMat* fundamental_matrix,
|
||||
CvMat* correspondent_lines );
|
||||
|
||||
/* Triangulation functions */
|
||||
|
||||
CVAPI(void) cvTriangulatePoints(CvMat* projMatr1, CvMat* projMatr2,
|
||||
CvMat* projPoints1, CvMat* projPoints2,
|
||||
CvMat* points4D);
|
||||
|
||||
CVAPI(void) cvCorrectMatches(CvMat* F, CvMat* points1, CvMat* points2,
|
||||
CvMat* new_points1, CvMat* new_points2);
|
||||
|
||||
|
||||
/* Computes the optimal new camera matrix according to the free scaling parameter alpha:
|
||||
alpha=0 - only valid pixels will be retained in the undistorted image
|
||||
alpha=1 - all the source image pixels will be retained in the undistorted image
|
||||
*/
|
||||
CVAPI(void) cvGetOptimalNewCameraMatrix( const CvMat* camera_matrix,
|
||||
const CvMat* dist_coeffs,
|
||||
CvSize image_size, double alpha,
|
||||
CvMat* new_camera_matrix,
|
||||
CvSize new_imag_size CV_DEFAULT(cvSize(0,0)),
|
||||
CvRect* valid_pixel_ROI CV_DEFAULT(0),
|
||||
int center_principal_point CV_DEFAULT(0));
|
||||
|
||||
/* Converts rotation vector to rotation matrix or vice versa */
|
||||
CVAPI(int) cvRodrigues2( const CvMat* src, CvMat* dst,
|
||||
CvMat* jacobian CV_DEFAULT(0) );
|
||||
|
||||
/* Finds perspective transformation between the object plane and image (view) plane */
|
||||
CVAPI(int) cvFindHomography( const CvMat* src_points,
|
||||
const CvMat* dst_points,
|
||||
CvMat* homography,
|
||||
int method CV_DEFAULT(0),
|
||||
double ransacReprojThreshold CV_DEFAULT(3),
|
||||
CvMat* mask CV_DEFAULT(0));
|
||||
|
||||
/* Computes RQ decomposition for 3x3 matrices */
|
||||
CVAPI(void) cvRQDecomp3x3( const CvMat *matrixM, CvMat *matrixR, CvMat *matrixQ,
|
||||
CvMat *matrixQx CV_DEFAULT(NULL),
|
||||
CvMat *matrixQy CV_DEFAULT(NULL),
|
||||
CvMat *matrixQz CV_DEFAULT(NULL),
|
||||
CvPoint3D64f *eulerAngles CV_DEFAULT(NULL));
|
||||
|
||||
/* Computes projection matrix decomposition */
|
||||
CVAPI(void) cvDecomposeProjectionMatrix( const CvMat *projMatr, CvMat *calibMatr,
|
||||
CvMat *rotMatr, CvMat *posVect,
|
||||
CvMat *rotMatrX CV_DEFAULT(NULL),
|
||||
CvMat *rotMatrY CV_DEFAULT(NULL),
|
||||
CvMat *rotMatrZ CV_DEFAULT(NULL),
|
||||
CvPoint3D64f *eulerAngles CV_DEFAULT(NULL));
|
||||
|
||||
/* Computes d(AB)/dA and d(AB)/dB */
|
||||
CVAPI(void) cvCalcMatMulDeriv( const CvMat* A, const CvMat* B, CvMat* dABdA, CvMat* dABdB );
|
||||
|
||||
/* Computes r3 = rodrigues(rodrigues(r2)*rodrigues(r1)),
|
||||
t3 = rodrigues(r2)*t1 + t2 and the respective derivatives */
|
||||
CVAPI(void) cvComposeRT( const CvMat* _rvec1, const CvMat* _tvec1,
|
||||
const CvMat* _rvec2, const CvMat* _tvec2,
|
||||
CvMat* _rvec3, CvMat* _tvec3,
|
||||
CvMat* dr3dr1 CV_DEFAULT(0), CvMat* dr3dt1 CV_DEFAULT(0),
|
||||
CvMat* dr3dr2 CV_DEFAULT(0), CvMat* dr3dt2 CV_DEFAULT(0),
|
||||
CvMat* dt3dr1 CV_DEFAULT(0), CvMat* dt3dt1 CV_DEFAULT(0),
|
||||
CvMat* dt3dr2 CV_DEFAULT(0), CvMat* dt3dt2 CV_DEFAULT(0) );
|
||||
|
||||
/* Projects object points to the view plane using
|
||||
the specified extrinsic and intrinsic camera parameters */
|
||||
CVAPI(void) cvProjectPoints2( const CvMat* object_points, const CvMat* rotation_vector,
|
||||
const CvMat* translation_vector, const CvMat* camera_matrix,
|
||||
const CvMat* distortion_coeffs, CvMat* image_points,
|
||||
CvMat* dpdrot CV_DEFAULT(NULL), CvMat* dpdt CV_DEFAULT(NULL),
|
||||
CvMat* dpdf CV_DEFAULT(NULL), CvMat* dpdc CV_DEFAULT(NULL),
|
||||
CvMat* dpddist CV_DEFAULT(NULL),
|
||||
double aspect_ratio CV_DEFAULT(0));
|
||||
|
||||
/* Finds extrinsic camera parameters from
|
||||
a few known corresponding point pairs and intrinsic parameters */
|
||||
CVAPI(void) cvFindExtrinsicCameraParams2( const CvMat* object_points,
|
||||
const CvMat* image_points,
|
||||
const CvMat* camera_matrix,
|
||||
const CvMat* distortion_coeffs,
|
||||
CvMat* rotation_vector,
|
||||
CvMat* translation_vector,
|
||||
int use_extrinsic_guess CV_DEFAULT(0) );
|
||||
|
||||
/* Computes initial estimate of the intrinsic camera parameters
|
||||
in case of planar calibration target (e.g. chessboard) */
|
||||
CVAPI(void) cvInitIntrinsicParams2D( const CvMat* object_points,
|
||||
const CvMat* image_points,
|
||||
const CvMat* npoints, CvSize image_size,
|
||||
CvMat* camera_matrix,
|
||||
double aspect_ratio CV_DEFAULT(1.) );
|
||||
|
||||
#define CV_CALIB_CB_ADAPTIVE_THRESH 1
|
||||
#define CV_CALIB_CB_NORMALIZE_IMAGE 2
|
||||
#define CV_CALIB_CB_FILTER_QUADS 4
|
||||
#define CV_CALIB_CB_FAST_CHECK 8
|
||||
|
||||
// Performs a fast check if a chessboard is in the input image. This is a workaround to
|
||||
// a problem of cvFindChessboardCorners being slow on images with no chessboard
|
||||
// - src: input image
|
||||
// - size: chessboard size
|
||||
// Returns 1 if a chessboard can be in this image and findChessboardCorners should be called,
|
||||
// 0 if there is no chessboard, -1 in case of error
|
||||
CVAPI(int) cvCheckChessboard(IplImage* src, CvSize size);
|
||||
|
||||
/* Detects corners on a chessboard calibration pattern */
|
||||
CVAPI(int) cvFindChessboardCorners( const void* image, CvSize pattern_size,
|
||||
CvPoint2D32f* corners,
|
||||
int* corner_count CV_DEFAULT(NULL),
|
||||
int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) );
|
||||
|
||||
/* Draws individual chessboard corners or the whole chessboard detected */
|
||||
CVAPI(void) cvDrawChessboardCorners( CvArr* image, CvSize pattern_size,
|
||||
CvPoint2D32f* corners,
|
||||
int count, int pattern_was_found );
|
||||
|
||||
#define CV_CALIB_USE_INTRINSIC_GUESS 1
|
||||
#define CV_CALIB_FIX_ASPECT_RATIO 2
|
||||
#define CV_CALIB_FIX_PRINCIPAL_POINT 4
|
||||
#define CV_CALIB_ZERO_TANGENT_DIST 8
|
||||
#define CV_CALIB_FIX_FOCAL_LENGTH 16
|
||||
#define CV_CALIB_FIX_K1 32
|
||||
#define CV_CALIB_FIX_K2 64
|
||||
#define CV_CALIB_FIX_K3 128
|
||||
#define CV_CALIB_FIX_K4 2048
|
||||
#define CV_CALIB_FIX_K5 4096
|
||||
#define CV_CALIB_FIX_K6 8192
|
||||
#define CV_CALIB_RATIONAL_MODEL 16384
|
||||
|
||||
/* Finds intrinsic and extrinsic camera parameters
|
||||
from a few views of known calibration pattern */
|
||||
CVAPI(double) cvCalibrateCamera2( const CvMat* object_points,
|
||||
const CvMat* image_points,
|
||||
const CvMat* point_counts,
|
||||
CvSize image_size,
|
||||
CvMat* camera_matrix,
|
||||
CvMat* distortion_coeffs,
|
||||
CvMat* rotation_vectors CV_DEFAULT(NULL),
|
||||
CvMat* translation_vectors CV_DEFAULT(NULL),
|
||||
int flags CV_DEFAULT(0),
|
||||
CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria(
|
||||
CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)) );
|
||||
|
||||
/* Computes various useful characteristics of the camera from the data computed by
|
||||
cvCalibrateCamera2 */
|
||||
CVAPI(void) cvCalibrationMatrixValues( const CvMat *camera_matrix,
|
||||
CvSize image_size,
|
||||
double aperture_width CV_DEFAULT(0),
|
||||
double aperture_height CV_DEFAULT(0),
|
||||
double *fovx CV_DEFAULT(NULL),
|
||||
double *fovy CV_DEFAULT(NULL),
|
||||
double *focal_length CV_DEFAULT(NULL),
|
||||
CvPoint2D64f *principal_point CV_DEFAULT(NULL),
|
||||
double *pixel_aspect_ratio CV_DEFAULT(NULL));
|
||||
|
||||
#define CV_CALIB_FIX_INTRINSIC 256
|
||||
#define CV_CALIB_SAME_FOCAL_LENGTH 512
|
||||
|
||||
/* Computes the transformation from one camera coordinate system to another one
|
||||
from a few correspondent views of the same calibration target. Optionally, calibrates
|
||||
both cameras */
|
||||
CVAPI(double) cvStereoCalibrate( const CvMat* object_points, const CvMat* image_points1,
|
||||
const CvMat* image_points2, const CvMat* npoints,
|
||||
CvMat* camera_matrix1, CvMat* dist_coeffs1,
|
||||
CvMat* camera_matrix2, CvMat* dist_coeffs2,
|
||||
CvSize image_size, CvMat* R, CvMat* T,
|
||||
CvMat* E CV_DEFAULT(0), CvMat* F CV_DEFAULT(0),
|
||||
CvTermCriteria term_crit CV_DEFAULT(cvTermCriteria(
|
||||
CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6)),
|
||||
int flags CV_DEFAULT(CV_CALIB_FIX_INTRINSIC));
|
||||
|
||||
#define CV_CALIB_ZERO_DISPARITY 1024
|
||||
|
||||
/* Computes 3D rotations (+ optional shift) for each camera coordinate system to make both
|
||||
views parallel (=> to make all the epipolar lines horizontal or vertical) */
|
||||
CVAPI(void) cvStereoRectify( const CvMat* camera_matrix1, const CvMat* camera_matrix2,
|
||||
const CvMat* dist_coeffs1, const CvMat* dist_coeffs2,
|
||||
CvSize image_size, const CvMat* R, const CvMat* T,
|
||||
CvMat* R1, CvMat* R2, CvMat* P1, CvMat* P2,
|
||||
CvMat* Q CV_DEFAULT(0),
|
||||
int flags CV_DEFAULT(CV_CALIB_ZERO_DISPARITY),
|
||||
double alpha CV_DEFAULT(-1),
|
||||
CvSize new_image_size CV_DEFAULT(cvSize(0,0)),
|
||||
CvRect* valid_pix_ROI1 CV_DEFAULT(0),
|
||||
CvRect* valid_pix_ROI2 CV_DEFAULT(0));
|
||||
|
||||
/* Computes rectification transformations for uncalibrated pair of images using a set
|
||||
of point correspondences */
|
||||
CVAPI(int) cvStereoRectifyUncalibrated( const CvMat* points1, const CvMat* points2,
|
||||
const CvMat* F, CvSize img_size,
|
||||
CvMat* H1, CvMat* H2,
|
||||
double threshold CV_DEFAULT(5));
|
||||
|
||||
|
||||
|
||||
/* stereo correspondence parameters and functions */
|
||||
|
||||
#define CV_STEREO_BM_NORMALIZED_RESPONSE 0
|
||||
#define CV_STEREO_BM_XSOBEL 1
|
||||
|
||||
/* Block matching algorithm structure */
|
||||
typedef struct CvStereoBMState
|
||||
{
|
||||
// pre-filtering (normalization of input images)
|
||||
int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now
|
||||
int preFilterSize; // averaging window size: ~5x5..21x21
|
||||
int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap]
|
||||
|
||||
// correspondence using Sum of Absolute Difference (SAD)
|
||||
int SADWindowSize; // ~5x5..21x21
|
||||
int minDisparity; // minimum disparity (can be negative)
|
||||
int numberOfDisparities; // maximum disparity - minimum disparity (> 0)
|
||||
|
||||
// post-filtering
|
||||
int textureThreshold; // the disparity is only computed for pixels
|
||||
// with textured enough neighborhood
|
||||
int uniquenessRatio; // accept the computed disparity d* only if
|
||||
// SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.)
|
||||
// for any d != d*+/-1 within the search range.
|
||||
int speckleWindowSize; // disparity variation window
|
||||
int speckleRange; // acceptable range of variation in window
|
||||
|
||||
int trySmallerWindows; // if 1, the results may be more accurate,
|
||||
// at the expense of slower processing
|
||||
CvRect roi1, roi2;
|
||||
int disp12MaxDiff;
|
||||
|
||||
// temporary buffers
|
||||
CvMat* preFilteredImg0;
|
||||
CvMat* preFilteredImg1;
|
||||
CvMat* slidingSumBuf;
|
||||
CvMat* cost;
|
||||
CvMat* disp;
|
||||
} CvStereoBMState;
|
||||
|
||||
#define CV_STEREO_BM_BASIC 0
|
||||
#define CV_STEREO_BM_FISH_EYE 1
|
||||
#define CV_STEREO_BM_NARROW 2
|
||||
|
||||
CVAPI(CvStereoBMState*) cvCreateStereoBMState(int preset CV_DEFAULT(CV_STEREO_BM_BASIC),
|
||||
int numberOfDisparities CV_DEFAULT(0));
|
||||
|
||||
CVAPI(void) cvReleaseStereoBMState( CvStereoBMState** state );
|
||||
|
||||
CVAPI(void) cvFindStereoCorrespondenceBM( const CvArr* left, const CvArr* right,
|
||||
CvArr* disparity, CvStereoBMState* state );
|
||||
|
||||
CVAPI(CvRect) cvGetValidDisparityROI( CvRect roi1, CvRect roi2, int minDisparity,
|
||||
int numberOfDisparities, int SADWindowSize );
|
||||
|
||||
CVAPI(void) cvValidateDisparity( CvArr* disparity, const CvArr* cost,
|
||||
int minDisparity, int numberOfDisparities,
|
||||
int disp12MaxDiff CV_DEFAULT(1) );
|
||||
|
||||
/* Reprojects the computed disparity image to the 3D space using the specified 4x4 matrix */
|
||||
CVAPI(void) cvReprojectImageTo3D( const CvArr* disparityImage,
|
||||
CvArr* _3dImage, const CvMat* Q,
|
||||
int handleMissingValues CV_DEFAULT(0) );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
class CV_EXPORTS CvLevMarq
|
||||
{
|
||||
public:
|
||||
CvLevMarq();
|
||||
CvLevMarq( int nparams, int nerrs, CvTermCriteria criteria=
|
||||
cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),
|
||||
bool completeSymmFlag=false );
|
||||
~CvLevMarq();
|
||||
void init( int nparams, int nerrs, CvTermCriteria criteria=
|
||||
cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,DBL_EPSILON),
|
||||
bool completeSymmFlag=false );
|
||||
bool update( const CvMat*& param, CvMat*& J, CvMat*& err );
|
||||
bool updateAlt( const CvMat*& param, CvMat*& JtJ, CvMat*& JtErr, double*& errNorm );
|
||||
|
||||
void clear();
|
||||
void step();
|
||||
enum { DONE=0, STARTED=1, CALC_J=2, CHECK_ERR=3 };
|
||||
|
||||
cv::Ptr<CvMat> mask;
|
||||
cv::Ptr<CvMat> prevParam;
|
||||
cv::Ptr<CvMat> param;
|
||||
cv::Ptr<CvMat> J;
|
||||
cv::Ptr<CvMat> err;
|
||||
cv::Ptr<CvMat> JtJ;
|
||||
cv::Ptr<CvMat> JtJN;
|
||||
cv::Ptr<CvMat> JtErr;
|
||||
cv::Ptr<CvMat> JtJV;
|
||||
cv::Ptr<CvMat> JtJW;
|
||||
double prevErrNorm, errNorm;
|
||||
int lambdaLg10;
|
||||
CvTermCriteria criteria;
|
||||
int state;
|
||||
int iters;
|
||||
bool completeSymmFlag;
|
||||
};
|
||||
|
||||
namespace cv
|
||||
{
|
||||
//! converts rotation vector to rotation matrix or vice versa using Rodrigues transformation
|
||||
CV_EXPORTS_W void Rodrigues(InputArray src, OutputArray dst, OutputArray jacobian=noArray());
|
||||
|
||||
//! type of the robust estimation algorithm
|
||||
enum
|
||||
{
|
||||
LMEDS=CV_LMEDS, //!< least-median algorithm
|
||||
RANSAC=CV_RANSAC //!< RANSAC algorithm
|
||||
};
|
||||
|
||||
//! computes the best-fit perspective transformation mapping srcPoints to dstPoints.
|
||||
CV_EXPORTS_W Mat findHomography( InputArray srcPoints, InputArray dstPoints,
|
||||
int method=0, double ransacReprojThreshold=3,
|
||||
OutputArray mask=noArray());
|
||||
|
||||
//! variant of findHomography for backward compatibility
|
||||
CV_EXPORTS Mat findHomography( InputArray srcPoints, InputArray dstPoints,
|
||||
OutputArray mask, int method=0, double ransacReprojThreshold=3);
|
||||
|
||||
//! Computes RQ decomposition of 3x3 matrix
|
||||
CV_EXPORTS_W Vec3d RQDecomp3x3( InputArray src, OutputArray mtxR, OutputArray mtxQ,
|
||||
OutputArray Qx=noArray(),
|
||||
OutputArray Qy=noArray(),
|
||||
OutputArray Qz=noArray());
|
||||
|
||||
//! Decomposes the projection matrix into camera matrix and the rotation martix and the translation vector
|
||||
CV_EXPORTS_W void decomposeProjectionMatrix( InputArray projMatrix, OutputArray cameraMatrix,
|
||||
OutputArray rotMatrix, OutputArray transVect,
|
||||
OutputArray rotMatrixX=noArray(),
|
||||
OutputArray rotMatrixY=noArray(),
|
||||
OutputArray rotMatrixZ=noArray(),
|
||||
OutputArray eulerAngles=noArray() );
|
||||
|
||||
//! computes derivatives of the matrix product w.r.t each of the multiplied matrix coefficients
|
||||
CV_EXPORTS_W void matMulDeriv( InputArray A, InputArray B,
|
||||
OutputArray dABdA,
|
||||
OutputArray dABdB );
|
||||
|
||||
//! composes 2 [R|t] transformations together. Also computes the derivatives of the result w.r.t the arguments
|
||||
CV_EXPORTS_W void composeRT( InputArray rvec1, InputArray tvec1,
|
||||
InputArray rvec2, InputArray tvec2,
|
||||
OutputArray rvec3, OutputArray tvec3,
|
||||
OutputArray dr3dr1=noArray(), OutputArray dr3dt1=noArray(),
|
||||
OutputArray dr3dr2=noArray(), OutputArray dr3dt2=noArray(),
|
||||
OutputArray dt3dr1=noArray(), OutputArray dt3dt1=noArray(),
|
||||
OutputArray dt3dr2=noArray(), OutputArray dt3dt2=noArray() );
|
||||
|
||||
//! projects points from the model coordinate space to the image coordinates. Also computes derivatives of the image coordinates w.r.t the intrinsic and extrinsic camera parameters
|
||||
CV_EXPORTS_W void projectPoints( InputArray objectPoints,
|
||||
InputArray rvec, InputArray tvec,
|
||||
InputArray cameraMatrix, InputArray distCoeffs,
|
||||
OutputArray imagePoints,
|
||||
OutputArray jacobian=noArray(),
|
||||
double aspectRatio=0 );
|
||||
|
||||
//! computes the camera pose from a few 3D points and the corresponding projections. The outliers are not handled.
|
||||
enum
|
||||
{
|
||||
ITERATIVE=CV_ITERATIVE,
|
||||
EPNP=CV_EPNP,
|
||||
P3P=CV_P3P
|
||||
};
|
||||
CV_EXPORTS_W bool solvePnP( InputArray objectPoints, InputArray imagePoints,
|
||||
InputArray cameraMatrix, InputArray distCoeffs,
|
||||
OutputArray rvec, OutputArray tvec,
|
||||
bool useExtrinsicGuess=false, int flags=ITERATIVE);
|
||||
|
||||
//! computes the camera pose from a few 3D points and the corresponding projections. The outliers are possible.
|
||||
CV_EXPORTS_W void solvePnPRansac( InputArray objectPoints,
|
||||
InputArray imagePoints,
|
||||
InputArray cameraMatrix,
|
||||
InputArray distCoeffs,
|
||||
OutputArray rvec,
|
||||
OutputArray tvec,
|
||||
bool useExtrinsicGuess = false,
|
||||
int iterationsCount = 100,
|
||||
float reprojectionError = 8.0,
|
||||
int minInliersCount = 100,
|
||||
OutputArray inliers = noArray(),
|
||||
int flags = ITERATIVE);
|
||||
|
||||
//! initializes camera matrix from a few 3D points and the corresponding projections.
|
||||
CV_EXPORTS_W Mat initCameraMatrix2D( InputArrayOfArrays objectPoints,
|
||||
InputArrayOfArrays imagePoints,
|
||||
Size imageSize, double aspectRatio=1. );
|
||||
|
||||
enum { CALIB_CB_ADAPTIVE_THRESH = 1, CALIB_CB_NORMALIZE_IMAGE = 2,
|
||||
CALIB_CB_FILTER_QUADS = 4, CALIB_CB_FAST_CHECK = 8 };
|
||||
|
||||
//! finds checkerboard pattern of the specified size in the image
|
||||
CV_EXPORTS_W bool findChessboardCorners( InputArray image, Size patternSize,
|
||||
OutputArray corners,
|
||||
int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE );
|
||||
|
||||
//! finds subpixel-accurate positions of the chessboard corners
|
||||
CV_EXPORTS bool find4QuadCornerSubpix(InputArray img, InputOutputArray corners, Size region_size);
|
||||
|
||||
//! draws the checkerboard pattern (found or partly found) in the image
|
||||
CV_EXPORTS_W void drawChessboardCorners( InputOutputArray image, Size patternSize,
|
||||
InputArray corners, bool patternWasFound );
|
||||
|
||||
enum { CALIB_CB_SYMMETRIC_GRID = 1, CALIB_CB_ASYMMETRIC_GRID = 2,
|
||||
CALIB_CB_CLUSTERING = 4 };
|
||||
|
||||
//! finds circles' grid pattern of the specified size in the image
|
||||
CV_EXPORTS_W bool findCirclesGrid( InputArray image, Size patternSize,
|
||||
OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID,
|
||||
const Ptr<FeatureDetector> &blobDetector = new SimpleBlobDetector());
|
||||
|
||||
//! the deprecated function. Use findCirclesGrid() instead of it.
|
||||
CV_EXPORTS_W bool findCirclesGridDefault( InputArray image, Size patternSize,
|
||||
OutputArray centers, int flags=CALIB_CB_SYMMETRIC_GRID );
|
||||
enum
|
||||
{
|
||||
CALIB_USE_INTRINSIC_GUESS = CV_CALIB_USE_INTRINSIC_GUESS,
|
||||
CALIB_FIX_ASPECT_RATIO = CV_CALIB_FIX_ASPECT_RATIO,
|
||||
CALIB_FIX_PRINCIPAL_POINT = CV_CALIB_FIX_PRINCIPAL_POINT,
|
||||
CALIB_ZERO_TANGENT_DIST = CV_CALIB_ZERO_TANGENT_DIST,
|
||||
CALIB_FIX_FOCAL_LENGTH = CV_CALIB_FIX_FOCAL_LENGTH,
|
||||
CALIB_FIX_K1 = CV_CALIB_FIX_K1,
|
||||
CALIB_FIX_K2 = CV_CALIB_FIX_K2,
|
||||
CALIB_FIX_K3 = CV_CALIB_FIX_K3,
|
||||
CALIB_FIX_K4 = CV_CALIB_FIX_K4,
|
||||
CALIB_FIX_K5 = CV_CALIB_FIX_K5,
|
||||
CALIB_FIX_K6 = CV_CALIB_FIX_K6,
|
||||
CALIB_RATIONAL_MODEL = CV_CALIB_RATIONAL_MODEL,
|
||||
// only for stereo
|
||||
CALIB_FIX_INTRINSIC = CV_CALIB_FIX_INTRINSIC,
|
||||
CALIB_SAME_FOCAL_LENGTH = CV_CALIB_SAME_FOCAL_LENGTH,
|
||||
// for stereo rectification
|
||||
CALIB_ZERO_DISPARITY = CV_CALIB_ZERO_DISPARITY
|
||||
};
|
||||
|
||||
//! finds intrinsic and extrinsic camera parameters from several fews of a known calibration pattern.
|
||||
CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,
|
||||
InputArrayOfArrays imagePoints,
|
||||
Size imageSize,
|
||||
CV_OUT InputOutputArray cameraMatrix,
|
||||
CV_OUT InputOutputArray distCoeffs,
|
||||
OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
|
||||
int flags=0, TermCriteria criteria = TermCriteria(
|
||||
TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON) );
|
||||
|
||||
//! computes several useful camera characteristics from the camera matrix, camera frame resolution and the physical sensor size.
|
||||
CV_EXPORTS_W void calibrationMatrixValues( InputArray cameraMatrix,
|
||||
Size imageSize,
|
||||
double apertureWidth,
|
||||
double apertureHeight,
|
||||
CV_OUT double& fovx,
|
||||
CV_OUT double& fovy,
|
||||
CV_OUT double& focalLength,
|
||||
CV_OUT Point2d& principalPoint,
|
||||
CV_OUT double& aspectRatio );
|
||||
|
||||
//! finds intrinsic and extrinsic parameters of a stereo camera
|
||||
CV_EXPORTS_W double stereoCalibrate( InputArrayOfArrays objectPoints,
|
||||
InputArrayOfArrays imagePoints1,
|
||||
InputArrayOfArrays imagePoints2,
|
||||
CV_OUT InputOutputArray cameraMatrix1,
|
||||
CV_OUT InputOutputArray distCoeffs1,
|
||||
CV_OUT InputOutputArray cameraMatrix2,
|
||||
CV_OUT InputOutputArray distCoeffs2,
|
||||
Size imageSize, OutputArray R,
|
||||
OutputArray T, OutputArray E, OutputArray F,
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6),
|
||||
int flags=CALIB_FIX_INTRINSIC );
|
||||
|
||||
|
||||
//! computes the rectification transformation for a stereo camera from its intrinsic and extrinsic parameters
|
||||
CV_EXPORTS_W void stereoRectify( InputArray cameraMatrix1, InputArray distCoeffs1,
|
||||
InputArray cameraMatrix2, InputArray distCoeffs2,
|
||||
Size imageSize, InputArray R, InputArray T,
|
||||
OutputArray R1, OutputArray R2,
|
||||
OutputArray P1, OutputArray P2,
|
||||
OutputArray Q, int flags=CALIB_ZERO_DISPARITY,
|
||||
double alpha=-1, Size newImageSize=Size(),
|
||||
CV_OUT Rect* validPixROI1=0, CV_OUT Rect* validPixROI2=0 );
|
||||
|
||||
//! computes the rectification transformation for an uncalibrated stereo camera (zero distortion is assumed)
|
||||
CV_EXPORTS_W bool stereoRectifyUncalibrated( InputArray points1, InputArray points2,
|
||||
InputArray F, Size imgSize,
|
||||
OutputArray H1, OutputArray H2,
|
||||
double threshold=5 );
|
||||
|
||||
//! computes the rectification transformations for 3-head camera, where all the heads are on the same line.
|
||||
CV_EXPORTS_W float rectify3Collinear( InputArray cameraMatrix1, InputArray distCoeffs1,
|
||||
InputArray cameraMatrix2, InputArray distCoeffs2,
|
||||
InputArray cameraMatrix3, InputArray distCoeffs3,
|
||||
InputArrayOfArrays imgpt1, InputArrayOfArrays imgpt3,
|
||||
Size imageSize, InputArray R12, InputArray T12,
|
||||
InputArray R13, InputArray T13,
|
||||
OutputArray R1, OutputArray R2, OutputArray R3,
|
||||
OutputArray P1, OutputArray P2, OutputArray P3,
|
||||
OutputArray Q, double alpha, Size newImgSize,
|
||||
CV_OUT Rect* roi1, CV_OUT Rect* roi2, int flags );
|
||||
|
||||
//! returns the optimal new camera matrix
|
||||
CV_EXPORTS_W Mat getOptimalNewCameraMatrix( InputArray cameraMatrix, InputArray distCoeffs,
|
||||
Size imageSize, double alpha, Size newImgSize=Size(),
|
||||
CV_OUT Rect* validPixROI=0, bool centerPrincipalPoint=false);
|
||||
|
||||
//! converts point coordinates from normal pixel coordinates to homogeneous coordinates ((x,y)->(x,y,1))
|
||||
CV_EXPORTS_W void convertPointsToHomogeneous( InputArray src, OutputArray dst );
|
||||
|
||||
//! converts point coordinates from homogeneous to normal pixel coordinates ((x,y,z)->(x/z, y/z))
|
||||
CV_EXPORTS_W void convertPointsFromHomogeneous( InputArray src, OutputArray dst );
|
||||
|
||||
//! for backward compatibility
|
||||
CV_EXPORTS void convertPointsHomogeneous( InputArray src, OutputArray dst );
|
||||
|
||||
//! the algorithm for finding fundamental matrix
|
||||
enum
|
||||
{
|
||||
FM_7POINT = CV_FM_7POINT, //!< 7-point algorithm
|
||||
FM_8POINT = CV_FM_8POINT, //!< 8-point algorithm
|
||||
FM_LMEDS = CV_FM_LMEDS, //!< least-median algorithm
|
||||
FM_RANSAC = CV_FM_RANSAC //!< RANSAC algorithm
|
||||
};
|
||||
|
||||
//! finds fundamental matrix from a set of corresponding 2D points
|
||||
CV_EXPORTS_W Mat findFundamentalMat( InputArray points1, InputArray points2,
|
||||
int method=FM_RANSAC,
|
||||
double param1=3., double param2=0.99,
|
||||
OutputArray mask=noArray());
|
||||
|
||||
//! variant of findFundamentalMat for backward compatibility
|
||||
CV_EXPORTS Mat findFundamentalMat( InputArray points1, InputArray points2,
|
||||
OutputArray mask, int method=FM_RANSAC,
|
||||
double param1=3., double param2=0.99);
|
||||
|
||||
//! finds coordinates of epipolar lines corresponding the specified points
|
||||
CV_EXPORTS_W void computeCorrespondEpilines( InputArray points,
|
||||
int whichImage, InputArray F,
|
||||
OutputArray lines );
|
||||
|
||||
CV_EXPORTS_W void triangulatePoints( InputArray projMatr1, InputArray projMatr2,
|
||||
InputArray projPoints1, InputArray projPoints2,
|
||||
OutputArray points4D );
|
||||
|
||||
CV_EXPORTS_W void correctMatches( InputArray F, InputArray points1, InputArray points2,
|
||||
OutputArray newPoints1, OutputArray newPoints2 );
|
||||
|
||||
template<> CV_EXPORTS void Ptr<CvStereoBMState>::delete_obj();
|
||||
|
||||
/*!
|
||||
Block Matching Stereo Correspondence Algorithm
|
||||
|
||||
The class implements BM stereo correspondence algorithm by K. Konolige.
|
||||
*/
|
||||
class CV_EXPORTS_W StereoBM
|
||||
{
|
||||
public:
|
||||
enum { PREFILTER_NORMALIZED_RESPONSE = 0, PREFILTER_XSOBEL = 1,
|
||||
BASIC_PRESET=0, FISH_EYE_PRESET=1, NARROW_PRESET=2 };
|
||||
|
||||
//! the default constructor
|
||||
CV_WRAP StereoBM();
|
||||
//! the full constructor taking the camera-specific preset, number of disparities and the SAD window size
|
||||
CV_WRAP StereoBM(int preset, int ndisparities=0, int SADWindowSize=21);
|
||||
//! the method that reinitializes the state. The previous content is destroyed
|
||||
void init(int preset, int ndisparities=0, int SADWindowSize=21);
|
||||
//! the stereo correspondence operator. Finds the disparity for the specified rectified stereo pair
|
||||
CV_WRAP_AS(compute) void operator()( InputArray left, InputArray right,
|
||||
OutputArray disparity, int disptype=CV_16S );
|
||||
|
||||
//! pointer to the underlying CvStereoBMState
|
||||
Ptr<CvStereoBMState> state;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
Semi-Global Block Matching Stereo Correspondence Algorithm
|
||||
|
||||
The class implements the original SGBM stereo correspondence algorithm by H. Hirschmuller and some its modification.
|
||||
*/
|
||||
class CV_EXPORTS_W StereoSGBM
|
||||
{
|
||||
public:
|
||||
enum { DISP_SHIFT=4, DISP_SCALE = (1<<DISP_SHIFT) };
|
||||
|
||||
//! the default constructor
|
||||
CV_WRAP StereoSGBM();
|
||||
|
||||
//! the full constructor taking all the necessary algorithm parameters
|
||||
CV_WRAP StereoSGBM(int minDisparity, int numDisparities, int SADWindowSize,
|
||||
int P1=0, int P2=0, int disp12MaxDiff=0,
|
||||
int preFilterCap=0, int uniquenessRatio=0,
|
||||
int speckleWindowSize=0, int speckleRange=0,
|
||||
bool fullDP=false);
|
||||
//! the destructor
|
||||
virtual ~StereoSGBM();
|
||||
|
||||
//! the stereo correspondence operator that computes disparity map for the specified rectified stereo pair
|
||||
CV_WRAP_AS(compute) virtual void operator()(InputArray left, InputArray right,
|
||||
OutputArray disp);
|
||||
|
||||
CV_PROP_RW int minDisparity;
|
||||
CV_PROP_RW int numberOfDisparities;
|
||||
CV_PROP_RW int SADWindowSize;
|
||||
CV_PROP_RW int preFilterCap;
|
||||
CV_PROP_RW int uniquenessRatio;
|
||||
CV_PROP_RW int P1;
|
||||
CV_PROP_RW int P2;
|
||||
CV_PROP_RW int speckleWindowSize;
|
||||
CV_PROP_RW int speckleRange;
|
||||
CV_PROP_RW int disp12MaxDiff;
|
||||
CV_PROP_RW bool fullDP;
|
||||
|
||||
protected:
|
||||
Mat buffer;
|
||||
};
|
||||
|
||||
//! filters off speckles (small regions of incorrectly computed disparity)
|
||||
CV_EXPORTS_W void filterSpeckles( InputOutputArray img, double newVal, int maxSpeckleSize, double maxDiff,
|
||||
InputOutputArray buf=noArray() );
|
||||
|
||||
//! computes valid disparity ROI from the valid ROIs of the rectified images (that are returned by cv::stereoRectify())
|
||||
CV_EXPORTS_W Rect getValidDisparityROI( Rect roi1, Rect roi2,
|
||||
int minDisparity, int numberOfDisparities,
|
||||
int SADWindowSize );
|
||||
|
||||
//! validates disparity using the left-right check. The matrix "cost" should be computed by the stereo correspondence algorithm
|
||||
CV_EXPORTS_W void validateDisparity( InputOutputArray disparity, InputArray cost,
|
||||
int minDisparity, int numberOfDisparities,
|
||||
int disp12MaxDisp=1 );
|
||||
|
||||
//! reprojects disparity image to 3D: (x,y,d)->(X,Y,Z) using the matrix Q returned by cv::stereoRectify
|
||||
CV_EXPORTS_W void reprojectImageTo3D( InputArray disparity,
|
||||
OutputArray _3dImage, InputArray Q,
|
||||
bool handleMissingValues=false,
|
||||
int ddepth=-1 );
|
||||
|
||||
CV_EXPORTS_W int estimateAffine3D(InputArray src, InputArray dst,
|
||||
OutputArray out, OutputArray inliers,
|
||||
double ransacThreshold=3, double confidence=0.99);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,985 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_CONTRIB_HPP__
|
||||
#define __OPENCV_CONTRIB_HPP__
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/objdetect/objdetect.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/****************************************************************************************\
|
||||
* Adaptive Skin Detector *
|
||||
\****************************************************************************************/
|
||||
|
||||
class CV_EXPORTS CvAdaptiveSkinDetector
|
||||
{
|
||||
private:
|
||||
enum {
|
||||
GSD_HUE_LT = 3,
|
||||
GSD_HUE_UT = 33,
|
||||
GSD_INTENSITY_LT = 15,
|
||||
GSD_INTENSITY_UT = 250
|
||||
};
|
||||
|
||||
class CV_EXPORTS Histogram
|
||||
{
|
||||
private:
|
||||
enum {
|
||||
HistogramSize = (GSD_HUE_UT - GSD_HUE_LT + 1)
|
||||
};
|
||||
|
||||
protected:
|
||||
int findCoverageIndex(double surfaceToCover, int defaultValue = 0);
|
||||
|
||||
public:
|
||||
CvHistogram *fHistogram;
|
||||
Histogram();
|
||||
virtual ~Histogram();
|
||||
|
||||
void findCurveThresholds(int &x1, int &x2, double percent = 0.05);
|
||||
void mergeWith(Histogram *source, double weight);
|
||||
};
|
||||
|
||||
int nStartCounter, nFrameCount, nSkinHueLowerBound, nSkinHueUpperBound, nMorphingMethod, nSamplingDivider;
|
||||
double fHistogramMergeFactor, fHuePercentCovered;
|
||||
Histogram histogramHueMotion, skinHueHistogram;
|
||||
IplImage *imgHueFrame, *imgSaturationFrame, *imgLastGrayFrame, *imgMotionFrame, *imgFilteredFrame;
|
||||
IplImage *imgShrinked, *imgTemp, *imgGrayFrame, *imgHSVFrame;
|
||||
|
||||
protected:
|
||||
void initData(IplImage *src, int widthDivider, int heightDivider);
|
||||
void adaptiveFilter();
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
MORPHING_METHOD_NONE = 0,
|
||||
MORPHING_METHOD_ERODE = 1,
|
||||
MORPHING_METHOD_ERODE_ERODE = 2,
|
||||
MORPHING_METHOD_ERODE_DILATE = 3
|
||||
};
|
||||
|
||||
CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE);
|
||||
virtual ~CvAdaptiveSkinDetector();
|
||||
|
||||
virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask);
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
* Fuzzy MeanShift Tracker *
|
||||
\****************************************************************************************/
|
||||
|
||||
class CV_EXPORTS CvFuzzyPoint {
|
||||
public:
|
||||
double x, y, value;
|
||||
|
||||
CvFuzzyPoint(double _x, double _y);
|
||||
};
|
||||
|
||||
class CV_EXPORTS CvFuzzyCurve {
|
||||
private:
|
||||
std::vector<CvFuzzyPoint> points;
|
||||
double value, centre;
|
||||
|
||||
bool between(double x, double x1, double x2);
|
||||
|
||||
public:
|
||||
CvFuzzyCurve();
|
||||
~CvFuzzyCurve();
|
||||
|
||||
void setCentre(double _centre);
|
||||
double getCentre();
|
||||
void clear();
|
||||
void addPoint(double x, double y);
|
||||
double calcValue(double param);
|
||||
double getValue();
|
||||
void setValue(double _value);
|
||||
};
|
||||
|
||||
class CV_EXPORTS CvFuzzyFunction {
|
||||
public:
|
||||
std::vector<CvFuzzyCurve> curves;
|
||||
|
||||
CvFuzzyFunction();
|
||||
~CvFuzzyFunction();
|
||||
void addCurve(CvFuzzyCurve *curve, double value = 0);
|
||||
void resetValues();
|
||||
double calcValue();
|
||||
CvFuzzyCurve *newCurve();
|
||||
};
|
||||
|
||||
class CV_EXPORTS CvFuzzyRule {
|
||||
private:
|
||||
CvFuzzyCurve *fuzzyInput1, *fuzzyInput2;
|
||||
CvFuzzyCurve *fuzzyOutput;
|
||||
public:
|
||||
CvFuzzyRule();
|
||||
~CvFuzzyRule();
|
||||
void setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1);
|
||||
double calcValue(double param1, double param2);
|
||||
CvFuzzyCurve *getOutputCurve();
|
||||
};
|
||||
|
||||
class CV_EXPORTS CvFuzzyController {
|
||||
private:
|
||||
std::vector<CvFuzzyRule*> rules;
|
||||
public:
|
||||
CvFuzzyController();
|
||||
~CvFuzzyController();
|
||||
void addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1);
|
||||
double calcOutput(double param1, double param2);
|
||||
};
|
||||
|
||||
class CV_EXPORTS CvFuzzyMeanShiftTracker
|
||||
{
|
||||
private:
|
||||
class FuzzyResizer
|
||||
{
|
||||
private:
|
||||
CvFuzzyFunction iInput, iOutput;
|
||||
CvFuzzyController fuzzyController;
|
||||
public:
|
||||
FuzzyResizer();
|
||||
int calcOutput(double edgeDensity, double density);
|
||||
};
|
||||
|
||||
class SearchWindow
|
||||
{
|
||||
public:
|
||||
FuzzyResizer *fuzzyResizer;
|
||||
int x, y;
|
||||
int width, height, maxWidth, maxHeight, ellipseHeight, ellipseWidth;
|
||||
int ldx, ldy, ldw, ldh, numShifts, numIters;
|
||||
int xGc, yGc;
|
||||
long m00, m01, m10, m11, m02, m20;
|
||||
double ellipseAngle;
|
||||
double density;
|
||||
unsigned int depthLow, depthHigh;
|
||||
int verticalEdgeLeft, verticalEdgeRight, horizontalEdgeTop, horizontalEdgeBottom;
|
||||
|
||||
SearchWindow();
|
||||
~SearchWindow();
|
||||
void setSize(int _x, int _y, int _width, int _height);
|
||||
void initDepthValues(IplImage *maskImage, IplImage *depthMap);
|
||||
bool shift();
|
||||
void extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth);
|
||||
void getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);
|
||||
void getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);
|
||||
void getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);
|
||||
bool meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth);
|
||||
};
|
||||
|
||||
public:
|
||||
enum TrackingState
|
||||
{
|
||||
tsNone = 0,
|
||||
tsSearching = 1,
|
||||
tsTracking = 2,
|
||||
tsSetWindow = 3,
|
||||
tsDisabled = 10
|
||||
};
|
||||
|
||||
enum ResizeMethod {
|
||||
rmEdgeDensityLinear = 0,
|
||||
rmEdgeDensityFuzzy = 1,
|
||||
rmInnerDensity = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
MinKernelMass = 1000
|
||||
};
|
||||
|
||||
SearchWindow kernel;
|
||||
int searchMode;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
MaxMeanShiftIteration = 5,
|
||||
MaxSetSizeIteration = 5
|
||||
};
|
||||
|
||||
void findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth);
|
||||
|
||||
public:
|
||||
CvFuzzyMeanShiftTracker();
|
||||
~CvFuzzyMeanShiftTracker();
|
||||
|
||||
void track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass = MinKernelMass);
|
||||
};
|
||||
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class CV_EXPORTS Octree
|
||||
{
|
||||
public:
|
||||
struct Node
|
||||
{
|
||||
Node() {}
|
||||
int begin, end;
|
||||
float x_min, x_max, y_min, y_max, z_min, z_max;
|
||||
int maxLevels;
|
||||
bool isLeaf;
|
||||
int children[8];
|
||||
};
|
||||
|
||||
Octree();
|
||||
Octree( const vector<Point3f>& points, int maxLevels = 10, int minPoints = 20 );
|
||||
virtual ~Octree();
|
||||
|
||||
virtual void buildTree( const vector<Point3f>& points, int maxLevels = 10, int minPoints = 20 );
|
||||
virtual void getPointsWithinSphere( const Point3f& center, float radius,
|
||||
vector<Point3f>& points ) const;
|
||||
const vector<Node>& getNodes() const { return nodes; }
|
||||
private:
|
||||
int minPoints;
|
||||
vector<Point3f> points;
|
||||
vector<Node> nodes;
|
||||
|
||||
virtual void buildNext(size_t node_ind);
|
||||
};
|
||||
|
||||
|
||||
class CV_EXPORTS Mesh3D
|
||||
{
|
||||
public:
|
||||
struct EmptyMeshException {};
|
||||
|
||||
Mesh3D();
|
||||
Mesh3D(const vector<Point3f>& vtx);
|
||||
~Mesh3D();
|
||||
|
||||
void buildOctree();
|
||||
void clearOctree();
|
||||
float estimateResolution(float tryRatio = 0.1f);
|
||||
void computeNormals(float normalRadius, int minNeighbors = 20);
|
||||
void computeNormals(const vector<int>& subset, float normalRadius, int minNeighbors = 20);
|
||||
|
||||
void writeAsVrml(const String& file, const vector<Scalar>& colors = vector<Scalar>()) const;
|
||||
|
||||
vector<Point3f> vtx;
|
||||
vector<Point3f> normals;
|
||||
float resolution;
|
||||
Octree octree;
|
||||
|
||||
const static Point3f allzero;
|
||||
};
|
||||
|
||||
class CV_EXPORTS SpinImageModel
|
||||
{
|
||||
public:
|
||||
|
||||
/* model parameters, leave unset for default or auto estimate */
|
||||
float normalRadius;
|
||||
int minNeighbors;
|
||||
|
||||
float binSize;
|
||||
int imageWidth;
|
||||
|
||||
float lambda;
|
||||
float gamma;
|
||||
|
||||
float T_GeometriccConsistency;
|
||||
float T_GroupingCorespondances;
|
||||
|
||||
/* public interface */
|
||||
SpinImageModel();
|
||||
explicit SpinImageModel(const Mesh3D& mesh);
|
||||
~SpinImageModel();
|
||||
|
||||
void setLogger(std::ostream* log);
|
||||
void selectRandomSubset(float ratio);
|
||||
void setSubset(const vector<int>& subset);
|
||||
void compute();
|
||||
|
||||
void match(const SpinImageModel& scene, vector< vector<Vec2i> >& result);
|
||||
|
||||
Mat packRandomScaledSpins(bool separateScale = false, size_t xCount = 10, size_t yCount = 10) const;
|
||||
|
||||
size_t getSpinCount() const { return spinImages.rows; }
|
||||
Mat getSpinImage(size_t index) const { return spinImages.row((int)index); }
|
||||
const Point3f& getSpinVertex(size_t index) const { return mesh.vtx[subset[index]]; }
|
||||
const Point3f& getSpinNormal(size_t index) const { return mesh.normals[subset[index]]; }
|
||||
|
||||
const Mesh3D& getMesh() const { return mesh; }
|
||||
Mesh3D& getMesh() { return mesh; }
|
||||
|
||||
/* static utility functions */
|
||||
static bool spinCorrelation(const Mat& spin1, const Mat& spin2, float lambda, float& result);
|
||||
|
||||
static Point2f calcSpinMapCoo(const Point3f& point, const Point3f& vertex, const Point3f& normal);
|
||||
|
||||
static float geometricConsistency(const Point3f& pointScene1, const Point3f& normalScene1,
|
||||
const Point3f& pointModel1, const Point3f& normalModel1,
|
||||
const Point3f& pointScene2, const Point3f& normalScene2,
|
||||
const Point3f& pointModel2, const Point3f& normalModel2);
|
||||
|
||||
static float groupingCreteria(const Point3f& pointScene1, const Point3f& normalScene1,
|
||||
const Point3f& pointModel1, const Point3f& normalModel1,
|
||||
const Point3f& pointScene2, const Point3f& normalScene2,
|
||||
const Point3f& pointModel2, const Point3f& normalModel2,
|
||||
float gamma);
|
||||
protected:
|
||||
void defaultParams();
|
||||
|
||||
void matchSpinToModel(const Mat& spin, vector<int>& indeces,
|
||||
vector<float>& corrCoeffs, bool useExtremeOutliers = true) const;
|
||||
|
||||
void repackSpinImages(const vector<uchar>& mask, Mat& spinImages, bool reAlloc = true) const;
|
||||
|
||||
vector<int> subset;
|
||||
Mesh3D mesh;
|
||||
Mat spinImages;
|
||||
std::ostream* out;
|
||||
};
|
||||
|
||||
class CV_EXPORTS TickMeter
|
||||
{
|
||||
public:
|
||||
TickMeter();
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
int64 getTimeTicks() const;
|
||||
double getTimeMicro() const;
|
||||
double getTimeMilli() const;
|
||||
double getTimeSec() const;
|
||||
int64 getCounter() const;
|
||||
|
||||
void reset();
|
||||
private:
|
||||
int64 counter;
|
||||
int64 sumTime;
|
||||
int64 startTime;
|
||||
};
|
||||
|
||||
CV_EXPORTS std::ostream& operator<<(std::ostream& out, const TickMeter& tm);
|
||||
|
||||
class CV_EXPORTS SelfSimDescriptor
|
||||
{
|
||||
public:
|
||||
SelfSimDescriptor();
|
||||
SelfSimDescriptor(int _ssize, int _lsize,
|
||||
int _startDistanceBucket=DEFAULT_START_DISTANCE_BUCKET,
|
||||
int _numberOfDistanceBuckets=DEFAULT_NUM_DISTANCE_BUCKETS,
|
||||
int _nangles=DEFAULT_NUM_ANGLES);
|
||||
SelfSimDescriptor(const SelfSimDescriptor& ss);
|
||||
virtual ~SelfSimDescriptor();
|
||||
SelfSimDescriptor& operator = (const SelfSimDescriptor& ss);
|
||||
|
||||
size_t getDescriptorSize() const;
|
||||
Size getGridSize( Size imgsize, Size winStride ) const;
|
||||
|
||||
virtual void compute(const Mat& img, vector<float>& descriptors, Size winStride=Size(),
|
||||
const vector<Point>& locations=vector<Point>()) const;
|
||||
virtual void computeLogPolarMapping(Mat& mappingMask) const;
|
||||
virtual void SSD(const Mat& img, Point pt, Mat& ssd) const;
|
||||
|
||||
int smallSize;
|
||||
int largeSize;
|
||||
int startDistanceBucket;
|
||||
int numberOfDistanceBuckets;
|
||||
int numberOfAngles;
|
||||
|
||||
enum { DEFAULT_SMALL_SIZE = 5, DEFAULT_LARGE_SIZE = 41,
|
||||
DEFAULT_NUM_ANGLES = 20, DEFAULT_START_DISTANCE_BUCKET = 3,
|
||||
DEFAULT_NUM_DISTANCE_BUCKETS = 7 };
|
||||
};
|
||||
|
||||
|
||||
typedef bool (*BundleAdjustCallback)(int iteration, double norm_error, void* user_data);
|
||||
|
||||
class CV_EXPORTS LevMarqSparse {
|
||||
public:
|
||||
LevMarqSparse();
|
||||
LevMarqSparse(int npoints, // number of points
|
||||
int ncameras, // number of cameras
|
||||
int nPointParams, // number of params per one point (3 in case of 3D points)
|
||||
int nCameraParams, // number of parameters per one camera
|
||||
int nErrParams, // number of parameters in measurement vector
|
||||
// for 1 point at one camera (2 in case of 2D projections)
|
||||
Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras
|
||||
// 1 - point is visible for the camera, 0 - invisible
|
||||
Mat& P0, // starting vector of parameters, first cameras then points
|
||||
Mat& X, // measurements, in order of visibility. non visible cases are skipped
|
||||
TermCriteria criteria, // termination criteria
|
||||
|
||||
// callback for estimation of Jacobian matrices
|
||||
void (CV_CDECL * fjac)(int i, int j, Mat& point_params,
|
||||
Mat& cam_params, Mat& A, Mat& B, void* data),
|
||||
// callback for estimation of backprojection errors
|
||||
void (CV_CDECL * func)(int i, int j, Mat& point_params,
|
||||
Mat& cam_params, Mat& estim, void* data),
|
||||
void* data, // user-specific data passed to the callbacks
|
||||
BundleAdjustCallback cb, void* user_data
|
||||
);
|
||||
|
||||
virtual ~LevMarqSparse();
|
||||
|
||||
virtual void run( int npoints, // number of points
|
||||
int ncameras, // number of cameras
|
||||
int nPointParams, // number of params per one point (3 in case of 3D points)
|
||||
int nCameraParams, // number of parameters per one camera
|
||||
int nErrParams, // number of parameters in measurement vector
|
||||
// for 1 point at one camera (2 in case of 2D projections)
|
||||
Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras
|
||||
// 1 - point is visible for the camera, 0 - invisible
|
||||
Mat& P0, // starting vector of parameters, first cameras then points
|
||||
Mat& X, // measurements, in order of visibility. non visible cases are skipped
|
||||
TermCriteria criteria, // termination criteria
|
||||
|
||||
// callback for estimation of Jacobian matrices
|
||||
void (CV_CDECL * fjac)(int i, int j, Mat& point_params,
|
||||
Mat& cam_params, Mat& A, Mat& B, void* data),
|
||||
// callback for estimation of backprojection errors
|
||||
void (CV_CDECL * func)(int i, int j, Mat& point_params,
|
||||
Mat& cam_params, Mat& estim, void* data),
|
||||
void* data // user-specific data passed to the callbacks
|
||||
);
|
||||
|
||||
virtual void clear();
|
||||
|
||||
// useful function to do simple bundle adjustment tasks
|
||||
static void bundleAdjust(vector<Point3d>& points, // positions of points in global coordinate system (input and output)
|
||||
const vector<vector<Point2d> >& imagePoints, // projections of 3d points for every camera
|
||||
const vector<vector<int> >& visibility, // visibility of 3d points for every camera
|
||||
vector<Mat>& cameraMatrix, // intrinsic matrices of all cameras (input and output)
|
||||
vector<Mat>& R, // rotation matrices of all cameras (input and output)
|
||||
vector<Mat>& T, // translation vector of all cameras (input and output)
|
||||
vector<Mat>& distCoeffs, // distortion coefficients of all cameras (input and output)
|
||||
const TermCriteria& criteria=
|
||||
TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON),
|
||||
BundleAdjustCallback cb = 0, void* user_data = 0);
|
||||
|
||||
public:
|
||||
virtual void optimize(CvMat &_vis); //main function that runs minimization
|
||||
|
||||
//iteratively asks for measurement for visible camera-point pairs
|
||||
void ask_for_proj(CvMat &_vis,bool once=false);
|
||||
//iteratively asks for Jacobians for every camera_point pair
|
||||
void ask_for_projac(CvMat &_vis);
|
||||
|
||||
CvMat* err; //error X-hX
|
||||
double prevErrNorm, errNorm;
|
||||
double lambda;
|
||||
CvTermCriteria criteria;
|
||||
int iters;
|
||||
|
||||
CvMat** U; //size of array is equal to number of cameras
|
||||
CvMat** V; //size of array is equal to number of points
|
||||
CvMat** inv_V_star; //inverse of V*
|
||||
|
||||
CvMat** A;
|
||||
CvMat** B;
|
||||
CvMat** W;
|
||||
|
||||
CvMat* X; //measurement
|
||||
CvMat* hX; //current measurement extimation given new parameter vector
|
||||
|
||||
CvMat* prevP; //current already accepted parameter.
|
||||
CvMat* P; // parameters used to evaluate function with new params
|
||||
// this parameters may be rejected
|
||||
|
||||
CvMat* deltaP; //computed increase of parameters (result of normal system solution )
|
||||
|
||||
CvMat** ea; // sum_i AijT * e_ij , used as right part of normal equation
|
||||
// length of array is j = number of cameras
|
||||
CvMat** eb; // sum_j BijT * e_ij , used as right part of normal equation
|
||||
// length of array is i = number of points
|
||||
|
||||
CvMat** Yj; //length of array is i = num_points
|
||||
|
||||
CvMat* S; //big matrix of block Sjk , each block has size num_cam_params x num_cam_params
|
||||
|
||||
CvMat* JtJ_diag; //diagonal of JtJ, used to backup diagonal elements before augmentation
|
||||
|
||||
CvMat* Vis_index; // matrix which element is index of measurement for point i and camera j
|
||||
|
||||
int num_cams;
|
||||
int num_points;
|
||||
int num_err_param;
|
||||
int num_cam_param;
|
||||
int num_point_param;
|
||||
|
||||
//target function and jacobian pointers, which needs to be initialized
|
||||
void (*fjac)(int i, int j, Mat& point_params, Mat& cam_params, Mat& A, Mat& B, void* data);
|
||||
void (*func)(int i, int j, Mat& point_params, Mat& cam_params, Mat& estim, void* data);
|
||||
|
||||
void* data;
|
||||
|
||||
BundleAdjustCallback cb;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
CV_EXPORTS_W int chamerMatching( Mat& img, Mat& templ,
|
||||
CV_OUT vector<vector<Point> >& results, CV_OUT vector<float>& cost,
|
||||
double templScale=1, int maxMatches = 20,
|
||||
double minMatchDistance = 1.0, int padX = 3,
|
||||
int padY = 3, int scales = 5, double minScale = 0.6, double maxScale = 1.6,
|
||||
double orientationWeight = 0.5, double truncate = 20);
|
||||
|
||||
|
||||
class CV_EXPORTS_W StereoVar
|
||||
{
|
||||
public:
|
||||
// Flags
|
||||
enum {USE_INITIAL_DISPARITY = 1, USE_EQUALIZE_HIST = 2, USE_SMART_ID = 4, USE_AUTO_PARAMS = 8, USE_MEDIAN_FILTERING = 16};
|
||||
enum {CYCLE_O, CYCLE_V};
|
||||
enum {PENALIZATION_TICHONOV, PENALIZATION_CHARBONNIER, PENALIZATION_PERONA_MALIK};
|
||||
|
||||
//! the default constructor
|
||||
CV_WRAP StereoVar();
|
||||
|
||||
//! the full constructor taking all the necessary algorithm parameters
|
||||
CV_WRAP StereoVar(int levels, double pyrScale, int nIt, int minDisp, int maxDisp, int poly_n, double poly_sigma, float fi, float lambda, int penalization, int cycle, int flags);
|
||||
|
||||
//! the destructor
|
||||
virtual ~StereoVar();
|
||||
|
||||
//! the stereo correspondence operator that computes disparity map for the specified rectified stereo pair
|
||||
CV_WRAP_AS(compute) virtual void operator()(const Mat& left, const Mat& right, CV_OUT Mat& disp);
|
||||
|
||||
CV_PROP_RW int levels;
|
||||
CV_PROP_RW double pyrScale;
|
||||
CV_PROP_RW int nIt;
|
||||
CV_PROP_RW int minDisp;
|
||||
CV_PROP_RW int maxDisp;
|
||||
CV_PROP_RW int poly_n;
|
||||
CV_PROP_RW double poly_sigma;
|
||||
CV_PROP_RW float fi;
|
||||
CV_PROP_RW float lambda;
|
||||
CV_PROP_RW int penalization;
|
||||
CV_PROP_RW int cycle;
|
||||
CV_PROP_RW int flags;
|
||||
|
||||
private:
|
||||
void autoParams();
|
||||
void FMG(Mat &I1, Mat &I2, Mat &I2x, Mat &u, int level);
|
||||
void VCycle_MyFAS(Mat &I1_h, Mat &I2_h, Mat &I2x_h, Mat &u_h, int level);
|
||||
void VariationalSolver(Mat &I1_h, Mat &I2_h, Mat &I2x_h, Mat &u_h, int level);
|
||||
};
|
||||
|
||||
CV_EXPORTS void polyfit(const Mat& srcx, const Mat& srcy, Mat& dst, int order);
|
||||
|
||||
class CV_EXPORTS Directory
|
||||
{
|
||||
public:
|
||||
static std::vector<std::string> GetListFiles ( const std::string& path, const std::string & exten = "*", bool addPath = true );
|
||||
static std::vector<std::string> GetListFilesR ( const std::string& path, const std::string & exten = "*", bool addPath = true );
|
||||
static std::vector<std::string> GetListFolders( const std::string& path, const std::string & exten = "*", bool addPath = true );
|
||||
};
|
||||
|
||||
/*
|
||||
* Generation of a set of different colors by the following way:
|
||||
* 1) generate more then need colors (in "factor" times) in RGB,
|
||||
* 2) convert them to Lab,
|
||||
* 3) choose the needed count of colors from the set that are more different from
|
||||
* each other,
|
||||
* 4) convert the colors back to RGB
|
||||
*/
|
||||
CV_EXPORTS void generateColors( std::vector<Scalar>& colors, size_t count, size_t factor=100 );
|
||||
|
||||
|
||||
/*
|
||||
* Estimate the rigid body motion from frame0 to frame1. The method is based on the paper
|
||||
* "Real-Time Visual Odometry from Dense RGB-D Images", F. Steinbucker, J. Strum, D. Cremers, ICCV, 2011.
|
||||
*/
|
||||
enum { ROTATION = 1,
|
||||
TRANSLATION = 2,
|
||||
RIGID_BODY_MOTION = 4
|
||||
};
|
||||
CV_EXPORTS bool RGBDOdometry( Mat& Rt, const Mat& initRt,
|
||||
const Mat& image0, const Mat& depth0, const Mat& mask0,
|
||||
const Mat& image1, const Mat& depth1, const Mat& mask1,
|
||||
const Mat& cameraMatrix, float minDepth=0.f, float maxDepth=4.f, float maxDepthDiff=0.07f,
|
||||
const std::vector<int>& iterCounts=std::vector<int>(),
|
||||
const std::vector<float>& minGradientMagnitudes=std::vector<float>(),
|
||||
int transformType=RIGID_BODY_MOTION );
|
||||
|
||||
/**
|
||||
*Bilinear interpolation technique.
|
||||
*
|
||||
*The value of a desired cortical pixel is obtained through a bilinear interpolation of the values
|
||||
*of the four nearest neighbouring Cartesian pixels to the center of the RF.
|
||||
*The same principle is applied to the inverse transformation.
|
||||
*
|
||||
*More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5
|
||||
*/
|
||||
class CV_EXPORTS LogPolar_Interp
|
||||
{
|
||||
public:
|
||||
|
||||
LogPolar_Interp() {}
|
||||
|
||||
/**
|
||||
*Constructor
|
||||
*\param w the width of the input image
|
||||
*\param h the height of the input image
|
||||
*\param center the transformation center: where the output precision is maximal
|
||||
*\param R the number of rings of the cortical image (default value 70 pixel)
|
||||
*\param ro0 the radius of the blind spot (default value 3 pixel)
|
||||
*\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle.
|
||||
* \a 0 means that the retinal image is computed within the inscribed circle.
|
||||
*\param S the number of sectors of the cortical image (default value 70 pixel).
|
||||
* Its value is usually internally computed to obtain a pixel aspect ratio equals to 1.
|
||||
*\param sp \a 1 (default value) means that the parameter \a S is internally computed.
|
||||
* \a 0 means that the parameter \a S is provided by the user.
|
||||
*/
|
||||
LogPolar_Interp(int w, int h, Point2i center, int R=70, double ro0=3.0,
|
||||
int interp=INTER_LINEAR, int full=1, int S=117, int sp=1);
|
||||
/**
|
||||
*Transformation from Cartesian image to cortical (log-polar) image.
|
||||
*\param source the Cartesian image
|
||||
*\return the transformed image (cortical image)
|
||||
*/
|
||||
const Mat to_cortical(const Mat &source);
|
||||
/**
|
||||
*Transformation from cortical image to retinal (inverse log-polar) image.
|
||||
*\param source the cortical image
|
||||
*\return the transformed image (retinal image)
|
||||
*/
|
||||
const Mat to_cartesian(const Mat &source);
|
||||
/**
|
||||
*Destructor
|
||||
*/
|
||||
~LogPolar_Interp();
|
||||
|
||||
protected:
|
||||
|
||||
Mat Rsri;
|
||||
Mat Csri;
|
||||
|
||||
int S, R, M, N;
|
||||
int top, bottom,left,right;
|
||||
double ro0, romax, a, q;
|
||||
int interp;
|
||||
|
||||
Mat ETAyx;
|
||||
Mat CSIyx;
|
||||
|
||||
void create_map(int M, int N, int R, int S, double ro0);
|
||||
};
|
||||
|
||||
/**
|
||||
*Overlapping circular receptive fields technique
|
||||
*
|
||||
*The Cartesian plane is divided in two regions: the fovea and the periphery.
|
||||
*The fovea (oversampling) is handled by using the bilinear interpolation technique described above, whereas in
|
||||
*the periphery we use the overlapping Gaussian circular RFs.
|
||||
*
|
||||
*More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5
|
||||
*/
|
||||
class CV_EXPORTS LogPolar_Overlapping
|
||||
{
|
||||
public:
|
||||
LogPolar_Overlapping() {}
|
||||
|
||||
/**
|
||||
*Constructor
|
||||
*\param w the width of the input image
|
||||
*\param h the height of the input image
|
||||
*\param center the transformation center: where the output precision is maximal
|
||||
*\param R the number of rings of the cortical image (default value 70 pixel)
|
||||
*\param ro0 the radius of the blind spot (default value 3 pixel)
|
||||
*\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle.
|
||||
* \a 0 means that the retinal image is computed within the inscribed circle.
|
||||
*\param S the number of sectors of the cortical image (default value 70 pixel).
|
||||
* Its value is usually internally computed to obtain a pixel aspect ratio equals to 1.
|
||||
*\param sp \a 1 (default value) means that the parameter \a S is internally computed.
|
||||
* \a 0 means that the parameter \a S is provided by the user.
|
||||
*/
|
||||
LogPolar_Overlapping(int w, int h, Point2i center, int R=70,
|
||||
double ro0=3.0, int full=1, int S=117, int sp=1);
|
||||
/**
|
||||
*Transformation from Cartesian image to cortical (log-polar) image.
|
||||
*\param source the Cartesian image
|
||||
*\return the transformed image (cortical image)
|
||||
*/
|
||||
const Mat to_cortical(const Mat &source);
|
||||
/**
|
||||
*Transformation from cortical image to retinal (inverse log-polar) image.
|
||||
*\param source the cortical image
|
||||
*\return the transformed image (retinal image)
|
||||
*/
|
||||
const Mat to_cartesian(const Mat &source);
|
||||
/**
|
||||
*Destructor
|
||||
*/
|
||||
~LogPolar_Overlapping();
|
||||
|
||||
protected:
|
||||
|
||||
Mat Rsri;
|
||||
Mat Csri;
|
||||
vector<int> Rsr;
|
||||
vector<int> Csr;
|
||||
vector<double> Wsr;
|
||||
|
||||
int S, R, M, N, ind1;
|
||||
int top, bottom,left,right;
|
||||
double ro0, romax, a, q;
|
||||
|
||||
struct kernel
|
||||
{
|
||||
kernel() { w = 0; }
|
||||
vector<double> weights;
|
||||
int w;
|
||||
};
|
||||
|
||||
Mat ETAyx;
|
||||
Mat CSIyx;
|
||||
vector<kernel> w_ker_2D;
|
||||
|
||||
void create_map(int M, int N, int R, int S, double ro0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjacent receptive fields technique
|
||||
*
|
||||
*All the Cartesian pixels, whose coordinates in the cortical domain share the same integer part, are assigned to the same RF.
|
||||
*The precision of the boundaries of the RF can be improved by breaking each pixel into subpixels and assigning each of them to the correct RF.
|
||||
*This technique is implemented from: Traver, V., Pla, F.: Log-polar mapping template design: From task-level requirements
|
||||
*to geometry parameters. Image Vision Comput. 26(10) (2008) 1354-1370
|
||||
*
|
||||
*More details can be found in http://dx.doi.org/10.1007/978-3-642-23968-7_5
|
||||
*/
|
||||
class CV_EXPORTS LogPolar_Adjacent
|
||||
{
|
||||
public:
|
||||
LogPolar_Adjacent() {}
|
||||
|
||||
/**
|
||||
*Constructor
|
||||
*\param w the width of the input image
|
||||
*\param h the height of the input image
|
||||
*\param center the transformation center: where the output precision is maximal
|
||||
*\param R the number of rings of the cortical image (default value 70 pixel)
|
||||
*\param ro0 the radius of the blind spot (default value 3 pixel)
|
||||
*\param smin the size of the subpixel (default value 0.25 pixel)
|
||||
*\param full \a 1 (default value) means that the retinal image (the inverse transform) is computed within the circumscribing circle.
|
||||
* \a 0 means that the retinal image is computed within the inscribed circle.
|
||||
*\param S the number of sectors of the cortical image (default value 70 pixel).
|
||||
* Its value is usually internally computed to obtain a pixel aspect ratio equals to 1.
|
||||
*\param sp \a 1 (default value) means that the parameter \a S is internally computed.
|
||||
* \a 0 means that the parameter \a S is provided by the user.
|
||||
*/
|
||||
LogPolar_Adjacent(int w, int h, Point2i center, int R=70, double ro0=3.0, double smin=0.25, int full=1, int S=117, int sp=1);
|
||||
/**
|
||||
*Transformation from Cartesian image to cortical (log-polar) image.
|
||||
*\param source the Cartesian image
|
||||
*\return the transformed image (cortical image)
|
||||
*/
|
||||
const Mat to_cortical(const Mat &source);
|
||||
/**
|
||||
*Transformation from cortical image to retinal (inverse log-polar) image.
|
||||
*\param source the cortical image
|
||||
*\return the transformed image (retinal image)
|
||||
*/
|
||||
const Mat to_cartesian(const Mat &source);
|
||||
/**
|
||||
*Destructor
|
||||
*/
|
||||
~LogPolar_Adjacent();
|
||||
|
||||
protected:
|
||||
struct pixel
|
||||
{
|
||||
pixel() { u = v = 0; a = 0.; }
|
||||
int u;
|
||||
int v;
|
||||
double a;
|
||||
};
|
||||
int S, R, M, N;
|
||||
int top, bottom,left,right;
|
||||
double ro0, romax, a, q;
|
||||
vector<vector<pixel> > L;
|
||||
vector<double> A;
|
||||
|
||||
void subdivide_recursively(double x, double y, int i, int j, double length, double smin);
|
||||
bool get_uv(double x, double y, int&u, int&v);
|
||||
void create_map(int M, int N, int R, int S, double ro0, double smin);
|
||||
};
|
||||
|
||||
CV_EXPORTS Mat subspaceProject(InputArray W, InputArray mean, InputArray src);
|
||||
CV_EXPORTS Mat subspaceReconstruct(InputArray W, InputArray mean, InputArray src);
|
||||
|
||||
class CV_EXPORTS LDA
|
||||
{
|
||||
public:
|
||||
// Initializes a LDA with num_components (default 0) and specifies how
|
||||
// samples are aligned (default dataAsRow=true).
|
||||
LDA(int num_components = 0) :
|
||||
_num_components(num_components) {};
|
||||
|
||||
// Initializes and performs a Discriminant Analysis with Fisher's
|
||||
// Optimization Criterion on given data in src and corresponding labels
|
||||
// in labels. If 0 (or less) number of components are given, they are
|
||||
// automatically determined for given data in computation.
|
||||
LDA(const Mat& src, vector<int> labels,
|
||||
int num_components = 0) :
|
||||
_num_components(num_components)
|
||||
{
|
||||
this->compute(src, labels); //! compute eigenvectors and eigenvalues
|
||||
}
|
||||
|
||||
// Initializes and performs a Discriminant Analysis with Fisher's
|
||||
// Optimization Criterion on given data in src and corresponding labels
|
||||
// in labels. If 0 (or less) number of components are given, they are
|
||||
// automatically determined for given data in computation.
|
||||
LDA(InputArrayOfArrays src, InputArray labels,
|
||||
int num_components = 0) :
|
||||
_num_components(num_components)
|
||||
{
|
||||
this->compute(src, labels); //! compute eigenvectors and eigenvalues
|
||||
}
|
||||
|
||||
// Serializes this object to a given filename.
|
||||
void save(const string& filename) const;
|
||||
|
||||
// Deserializes this object from a given filename.
|
||||
void load(const string& filename);
|
||||
|
||||
// Serializes this object to a given cv::FileStorage.
|
||||
void save(FileStorage& fs) const;
|
||||
|
||||
// Deserializes this object from a given cv::FileStorage.
|
||||
void load(const FileStorage& node);
|
||||
|
||||
// Destructor.
|
||||
~LDA() {}
|
||||
|
||||
//! Compute the discriminants for data in src and labels.
|
||||
void compute(InputArrayOfArrays src, InputArray labels);
|
||||
|
||||
// Projects samples into the LDA subspace.
|
||||
Mat project(InputArray src);
|
||||
|
||||
// Reconstructs projections from the LDA subspace.
|
||||
Mat reconstruct(InputArray src);
|
||||
|
||||
// Returns the eigenvectors of this LDA.
|
||||
Mat eigenvectors() const { return _eigenvectors; };
|
||||
|
||||
// Returns the eigenvalues of this LDA.
|
||||
Mat eigenvalues() const { return _eigenvalues; }
|
||||
|
||||
protected:
|
||||
bool _dataAsRow;
|
||||
int _num_components;
|
||||
Mat _eigenvectors;
|
||||
Mat _eigenvalues;
|
||||
|
||||
void lda(InputArrayOfArrays src, InputArray labels);
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W FaceRecognizer : public Algorithm
|
||||
{
|
||||
public:
|
||||
//! virtual destructor
|
||||
virtual ~FaceRecognizer() {}
|
||||
|
||||
// Trains a FaceRecognizer.
|
||||
CV_WRAP virtual void train(InputArrayOfArrays src, InputArray labels) = 0;
|
||||
|
||||
// Updates a FaceRecognizer.
|
||||
CV_WRAP void update(InputArrayOfArrays src, InputArray labels);
|
||||
|
||||
// Gets a prediction from a FaceRecognizer.
|
||||
virtual int predict(InputArray src) const = 0;
|
||||
|
||||
// Predicts the label and confidence for a given sample.
|
||||
CV_WRAP virtual void predict(InputArray src, CV_OUT int &label, CV_OUT double &confidence) const = 0;
|
||||
|
||||
// Serializes this object to a given filename.
|
||||
CV_WRAP virtual void save(const string& filename) const;
|
||||
|
||||
// Deserializes this object from a given filename.
|
||||
CV_WRAP virtual void load(const string& filename);
|
||||
|
||||
// Serializes this object to a given cv::FileStorage.
|
||||
virtual void save(FileStorage& fs) const = 0;
|
||||
|
||||
// Deserializes this object from a given cv::FileStorage.
|
||||
virtual void load(const FileStorage& fs) = 0;
|
||||
|
||||
};
|
||||
|
||||
CV_EXPORTS_W Ptr<FaceRecognizer> createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX);
|
||||
CV_EXPORTS_W Ptr<FaceRecognizer> createFisherFaceRecognizer(int num_components = 0, double threshold = DBL_MAX);
|
||||
CV_EXPORTS_W Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius=1, int neighbors=8,
|
||||
int grid_x=8, int grid_y=8, double threshold = DBL_MAX);
|
||||
|
||||
enum
|
||||
{
|
||||
COLORMAP_AUTUMN = 0,
|
||||
COLORMAP_BONE = 1,
|
||||
COLORMAP_JET = 2,
|
||||
COLORMAP_WINTER = 3,
|
||||
COLORMAP_RAINBOW = 4,
|
||||
COLORMAP_OCEAN = 5,
|
||||
COLORMAP_SUMMER = 6,
|
||||
COLORMAP_SPRING = 7,
|
||||
COLORMAP_COOL = 8,
|
||||
COLORMAP_HSV = 9,
|
||||
COLORMAP_PINK = 10,
|
||||
COLORMAP_HOT = 11
|
||||
};
|
||||
|
||||
CV_EXPORTS_W void applyColorMap(InputArray src, OutputArray dst, int colormap);
|
||||
|
||||
CV_EXPORTS bool initModule_contrib();
|
||||
}
|
||||
|
||||
#include "opencv2/contrib/retina.hpp"
|
||||
|
||||
#include "opencv2/contrib/openfabmap.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(ANDROID)
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/objdetect/objdetect.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
class DetectionBasedTracker
|
||||
{
|
||||
public:
|
||||
struct Parameters
|
||||
{
|
||||
int minObjectSize;
|
||||
int maxObjectSize;
|
||||
double scaleFactor;
|
||||
int maxTrackLifetime;
|
||||
int minNeighbors;
|
||||
int minDetectionPeriod; //the minimal time between run of the big object detector (on the whole frame) in ms (1000 mean 1 sec), default=0
|
||||
|
||||
Parameters();
|
||||
};
|
||||
|
||||
DetectionBasedTracker(const std::string& cascadeFilename, const Parameters& params);
|
||||
virtual ~DetectionBasedTracker();
|
||||
|
||||
virtual bool run();
|
||||
virtual void stop();
|
||||
virtual void resetTracking();
|
||||
|
||||
virtual void process(const cv::Mat& imageGray);
|
||||
|
||||
bool setParameters(const Parameters& params);
|
||||
const Parameters& getParameters();
|
||||
|
||||
|
||||
typedef std::pair<cv::Rect, int> Object;
|
||||
virtual void getObjects(std::vector<cv::Rect>& result) const;
|
||||
virtual void getObjects(std::vector<Object>& result) const;
|
||||
|
||||
protected:
|
||||
class SeparateDetectionWork;
|
||||
cv::Ptr<SeparateDetectionWork> separateDetectionWork;
|
||||
friend void* workcycleObjectDetectorFunction(void* p);
|
||||
|
||||
|
||||
struct InnerParameters
|
||||
{
|
||||
int numLastPositionsToTrack;
|
||||
int numStepsToWaitBeforeFirstShow;
|
||||
int numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown;
|
||||
int numStepsToShowWithoutDetecting;
|
||||
|
||||
float coeffTrackingWindowSize;
|
||||
float coeffObjectSizeToTrack;
|
||||
float coeffObjectSpeedUsingInPrediction;
|
||||
|
||||
InnerParameters();
|
||||
};
|
||||
Parameters parameters;
|
||||
InnerParameters innerParameters;
|
||||
|
||||
struct TrackedObject
|
||||
{
|
||||
typedef std::vector<cv::Rect> PositionsVector;
|
||||
|
||||
PositionsVector lastPositions;
|
||||
|
||||
int numDetectedFrames;
|
||||
int numFramesNotDetected;
|
||||
int id;
|
||||
|
||||
TrackedObject(const cv::Rect& rect):numDetectedFrames(1), numFramesNotDetected(0)
|
||||
{
|
||||
lastPositions.push_back(rect);
|
||||
id=getNextId();
|
||||
};
|
||||
|
||||
static int getNextId()
|
||||
{
|
||||
static int _id=0;
|
||||
return _id++;
|
||||
}
|
||||
};
|
||||
|
||||
int numTrackedSteps;
|
||||
std::vector<TrackedObject> trackedObjects;
|
||||
|
||||
std::vector<float> weightsPositionsSmoothing;
|
||||
std::vector<float> weightsSizesSmoothing;
|
||||
|
||||
cv::CascadeClassifier cascadeForTracking;
|
||||
|
||||
|
||||
void updateTrackedObjects(const std::vector<cv::Rect>& detectedObjects);
|
||||
cv::Rect calcTrackedObjectPositionToShow(int i) const;
|
||||
void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector<cv::Rect>& detectedObjectsInRegions);
|
||||
};
|
||||
|
||||
namespace cv
|
||||
{
|
||||
using ::DetectionBasedTracker;
|
||||
} //end of cv namespace
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,220 @@
|
||||
//*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_HYBRIDTRACKER_H_
|
||||
#define __OPENCV_HYBRIDTRACKER_H_
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/core/operations.hpp"
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
#include "opencv2/video/tracking.hpp"
|
||||
#include "opencv2/ml/ml.hpp"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
// Motion model for tracking algorithm. Currently supports objects that do not move much.
|
||||
// To add Kalman filter
|
||||
struct CV_EXPORTS CvMotionModel
|
||||
{
|
||||
enum {LOW_PASS_FILTER = 0, KALMAN_FILTER = 1, EM = 2};
|
||||
|
||||
CvMotionModel()
|
||||
{
|
||||
}
|
||||
|
||||
float low_pass_gain; // low pass gain
|
||||
};
|
||||
|
||||
// Mean Shift Tracker parameters for specifying use of HSV channel and CamShift parameters.
|
||||
struct CV_EXPORTS CvMeanShiftTrackerParams
|
||||
{
|
||||
enum { H = 0, HS = 1, HSV = 2 };
|
||||
CvMeanShiftTrackerParams(int tracking_type = CvMeanShiftTrackerParams::HS,
|
||||
CvTermCriteria term_crit = CvTermCriteria());
|
||||
|
||||
int tracking_type;
|
||||
vector<float> h_range;
|
||||
vector<float> s_range;
|
||||
vector<float> v_range;
|
||||
CvTermCriteria term_crit;
|
||||
};
|
||||
|
||||
// Feature tracking parameters
|
||||
struct CV_EXPORTS CvFeatureTrackerParams
|
||||
{
|
||||
enum { SIFT = 0, SURF = 1, OPTICAL_FLOW = 2 };
|
||||
CvFeatureTrackerParams(int featureType = 0, int windowSize = 0)
|
||||
{
|
||||
feature_type = featureType;
|
||||
window_size = windowSize;
|
||||
}
|
||||
|
||||
int feature_type; // Feature type to use
|
||||
int window_size; // Window size in pixels around which to search for new window
|
||||
};
|
||||
|
||||
// Hybrid Tracking parameters for specifying weights of individual trackers and motion model.
|
||||
struct CV_EXPORTS CvHybridTrackerParams
|
||||
{
|
||||
CvHybridTrackerParams(float ft_tracker_weight = 0.5, float ms_tracker_weight = 0.5,
|
||||
CvFeatureTrackerParams ft_params = CvFeatureTrackerParams(),
|
||||
CvMeanShiftTrackerParams ms_params = CvMeanShiftTrackerParams(),
|
||||
CvMotionModel model = CvMotionModel());
|
||||
|
||||
float ft_tracker_weight;
|
||||
float ms_tracker_weight;
|
||||
CvFeatureTrackerParams ft_params;
|
||||
CvMeanShiftTrackerParams ms_params;
|
||||
int motion_model;
|
||||
float low_pass_gain;
|
||||
};
|
||||
|
||||
// Performs Camshift using parameters from MeanShiftTrackerParams
|
||||
class CV_EXPORTS CvMeanShiftTracker
|
||||
{
|
||||
private:
|
||||
Mat hsv, hue;
|
||||
Mat backproj;
|
||||
Mat mask, maskroi;
|
||||
MatND hist;
|
||||
Rect prev_trackwindow;
|
||||
RotatedRect prev_trackbox;
|
||||
Point2f prev_center;
|
||||
|
||||
public:
|
||||
CvMeanShiftTrackerParams params;
|
||||
|
||||
CvMeanShiftTracker();
|
||||
explicit CvMeanShiftTracker(CvMeanShiftTrackerParams _params);
|
||||
~CvMeanShiftTracker();
|
||||
void newTrackingWindow(Mat image, Rect selection);
|
||||
RotatedRect updateTrackingWindow(Mat image);
|
||||
Mat getHistogramProjection(int type);
|
||||
void setTrackingWindow(Rect _window);
|
||||
Rect getTrackingWindow();
|
||||
RotatedRect getTrackingEllipse();
|
||||
Point2f getTrackingCenter();
|
||||
};
|
||||
|
||||
// Performs SIFT/SURF feature tracking using parameters from FeatureTrackerParams
|
||||
class CV_EXPORTS CvFeatureTracker
|
||||
{
|
||||
private:
|
||||
Ptr<Feature2D> dd;
|
||||
Ptr<DescriptorMatcher> matcher;
|
||||
vector<DMatch> matches;
|
||||
|
||||
Mat prev_image;
|
||||
Mat prev_image_bw;
|
||||
Rect prev_trackwindow;
|
||||
Point2d prev_center;
|
||||
|
||||
int ittr;
|
||||
vector<Point2f> features[2];
|
||||
|
||||
public:
|
||||
Mat disp_matches;
|
||||
CvFeatureTrackerParams params;
|
||||
|
||||
CvFeatureTracker();
|
||||
explicit CvFeatureTracker(CvFeatureTrackerParams params);
|
||||
~CvFeatureTracker();
|
||||
void newTrackingWindow(Mat image, Rect selection);
|
||||
Rect updateTrackingWindow(Mat image);
|
||||
Rect updateTrackingWindowWithSIFT(Mat image);
|
||||
Rect updateTrackingWindowWithFlow(Mat image);
|
||||
void setTrackingWindow(Rect _window);
|
||||
Rect getTrackingWindow();
|
||||
Point2f getTrackingCenter();
|
||||
};
|
||||
|
||||
// Performs Hybrid Tracking and combines individual trackers using EM or filters
|
||||
class CV_EXPORTS CvHybridTracker
|
||||
{
|
||||
private:
|
||||
CvMeanShiftTracker* mstracker;
|
||||
CvFeatureTracker* fttracker;
|
||||
|
||||
CvMat* samples;
|
||||
CvMat* labels;
|
||||
|
||||
Rect prev_window;
|
||||
Point2f prev_center;
|
||||
Mat prev_proj;
|
||||
RotatedRect trackbox;
|
||||
|
||||
int ittr;
|
||||
Point2f curr_center;
|
||||
|
||||
inline float getL2Norm(Point2f p1, Point2f p2);
|
||||
Mat getDistanceProjection(Mat image, Point2f center);
|
||||
Mat getGaussianProjection(Mat image, int ksize, double sigma, Point2f center);
|
||||
void updateTrackerWithEM(Mat image);
|
||||
void updateTrackerWithLowPassFilter(Mat image);
|
||||
|
||||
public:
|
||||
CvHybridTrackerParams params;
|
||||
CvHybridTracker();
|
||||
explicit CvHybridTracker(CvHybridTrackerParams params);
|
||||
~CvHybridTracker();
|
||||
|
||||
void newTracker(Mat image, Rect selection);
|
||||
void updateTracker(Mat image);
|
||||
Rect getTrackingWindow();
|
||||
};
|
||||
|
||||
typedef CvMotionModel MotionModel;
|
||||
typedef CvMeanShiftTrackerParams MeanShiftTrackerParams;
|
||||
typedef CvFeatureTrackerParams FeatureTrackerParams;
|
||||
typedef CvHybridTrackerParams HybridTrackerParams;
|
||||
typedef CvMeanShiftTracker MeanShiftTracker;
|
||||
typedef CvFeatureTracker FeatureTracker;
|
||||
typedef CvHybridTracker HybridTracker;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,405 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
// This file originates from the openFABMAP project:
|
||||
// [http://code.google.com/p/openfabmap/]
|
||||
//
|
||||
// For published work which uses all or part of OpenFABMAP, please cite:
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
|
||||
//
|
||||
// Original Algorithm by Mark Cummins and Paul Newman:
|
||||
// [http://ijr.sagepub.com/content/27/6/647.short]
|
||||
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
|
||||
// [http://ijr.sagepub.com/content/30/9/1100.abstract]
|
||||
//
|
||||
// License Agreement
|
||||
//
|
||||
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
|
||||
// Will Maddern [w.maddern@qut.edu.au], all rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OPENFABMAP_H_
|
||||
#define __OPENCV_OPENFABMAP_H_
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/features2d/features2d.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <valarray>
|
||||
|
||||
namespace cv {
|
||||
|
||||
namespace of2 {
|
||||
|
||||
using std::list;
|
||||
using std::map;
|
||||
using std::multiset;
|
||||
|
||||
/*
|
||||
Return data format of a FABMAP compare call
|
||||
*/
|
||||
struct CV_EXPORTS IMatch {
|
||||
|
||||
IMatch() :
|
||||
queryIdx(-1), imgIdx(-1), likelihood(-DBL_MAX), match(-DBL_MAX) {
|
||||
}
|
||||
IMatch(int _queryIdx, int _imgIdx, double _likelihood, double _match) :
|
||||
queryIdx(_queryIdx), imgIdx(_imgIdx), likelihood(_likelihood), match(
|
||||
_match) {
|
||||
}
|
||||
|
||||
int queryIdx; //query index
|
||||
int imgIdx; //test index
|
||||
|
||||
double likelihood; //raw loglikelihood
|
||||
double match; //normalised probability
|
||||
|
||||
bool operator<(const IMatch& m) const {
|
||||
return match < m.match;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
Base FabMap class. Each FabMap method inherits from this class.
|
||||
*/
|
||||
class CV_EXPORTS FabMap {
|
||||
public:
|
||||
|
||||
//FabMap options
|
||||
enum {
|
||||
MEAN_FIELD = 1,
|
||||
SAMPLED = 2,
|
||||
NAIVE_BAYES = 4,
|
||||
CHOW_LIU = 8,
|
||||
MOTION_MODEL = 16
|
||||
};
|
||||
|
||||
FabMap(const Mat& clTree, double PzGe, double PzGNe, int flags,
|
||||
int numSamples = 0);
|
||||
virtual ~FabMap();
|
||||
|
||||
//methods to add training data for sampling method
|
||||
virtual void addTraining(const Mat& queryImgDescriptor);
|
||||
virtual void addTraining(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
//methods to add to the test data
|
||||
virtual void add(const Mat& queryImgDescriptor);
|
||||
virtual void add(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
//accessors
|
||||
const vector<Mat>& getTrainingImgDescriptors() const;
|
||||
const vector<Mat>& getTestImgDescriptors() const;
|
||||
|
||||
//Main FabMap image comparison
|
||||
void compare(const Mat& queryImgDescriptor,
|
||||
vector<IMatch>& matches, bool addQuery = false,
|
||||
const Mat& mask = Mat());
|
||||
void compare(const Mat& queryImgDescriptor,
|
||||
const Mat& testImgDescriptors, vector<IMatch>& matches,
|
||||
const Mat& mask = Mat());
|
||||
void compare(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches, const Mat& mask = Mat());
|
||||
void compare(const vector<Mat>& queryImgDescriptors, vector<
|
||||
IMatch>& matches, bool addQuery = false, const Mat& mask =
|
||||
Mat());
|
||||
void compare(const vector<Mat>& queryImgDescriptors,
|
||||
const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches, const Mat& mask = Mat());
|
||||
|
||||
protected:
|
||||
|
||||
void compareImgDescriptor(const Mat& queryImgDescriptor,
|
||||
int queryIndex, const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches);
|
||||
|
||||
void addImgDescriptor(const Mat& queryImgDescriptor);
|
||||
|
||||
//the getLikelihoods method is overwritten for each different FabMap
|
||||
//method.
|
||||
virtual void getLikelihoods(const Mat& queryImgDescriptor,
|
||||
const vector<Mat>& testImgDescriptors,
|
||||
vector<IMatch>& matches);
|
||||
virtual double getNewPlaceLikelihood(const Mat& queryImgDescriptor);
|
||||
|
||||
//turn likelihoods into probabilities (also add in motion model if used)
|
||||
void normaliseDistribution(vector<IMatch>& matches);
|
||||
|
||||
//Chow-Liu Tree
|
||||
int pq(int q);
|
||||
double Pzq(int q, bool zq);
|
||||
double PzqGzpq(int q, bool zq, bool zpq);
|
||||
|
||||
//FAB-MAP Core
|
||||
double PzqGeq(bool zq, bool eq);
|
||||
double PeqGL(int q, bool Lzq, bool eq);
|
||||
double PzqGL(int q, bool zq, bool zpq, bool Lzq);
|
||||
double PzqGzpqL(int q, bool zq, bool zpq, bool Lzq);
|
||||
double (FabMap::*PzGL)(int q, bool zq, bool zpq, bool Lzq);
|
||||
|
||||
//data
|
||||
Mat clTree;
|
||||
vector<Mat> trainingImgDescriptors;
|
||||
vector<Mat> testImgDescriptors;
|
||||
vector<IMatch> priorMatches;
|
||||
|
||||
//parameters
|
||||
double PzGe;
|
||||
double PzGNe;
|
||||
double Pnew;
|
||||
|
||||
double mBias;
|
||||
double sFactor;
|
||||
|
||||
int flags;
|
||||
int numSamples;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
The original FAB-MAP algorithm, developed based on:
|
||||
http://ijr.sagepub.com/content/27/6/647.short
|
||||
*/
|
||||
class CV_EXPORTS FabMap1: public FabMap {
|
||||
public:
|
||||
FabMap1(const Mat& clTree, double PzGe, double PzGNe, int flags,
|
||||
int numSamples = 0);
|
||||
virtual ~FabMap1();
|
||||
protected:
|
||||
|
||||
//FabMap1 implementation of likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
};
|
||||
|
||||
/*
|
||||
A computationally faster version of the original FAB-MAP algorithm. A look-
|
||||
up-table is used to precompute many of the reoccuring calculations
|
||||
*/
|
||||
class CV_EXPORTS FabMapLUT: public FabMap {
|
||||
public:
|
||||
FabMapLUT(const Mat& clTree, double PzGe, double PzGNe,
|
||||
int flags, int numSamples = 0, int precision = 6);
|
||||
virtual ~FabMapLUT();
|
||||
protected:
|
||||
|
||||
//FabMap look-up-table implementation of the likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
|
||||
//precomputed data
|
||||
int (*table)[8];
|
||||
|
||||
//data precision
|
||||
int precision;
|
||||
};
|
||||
|
||||
/*
|
||||
The Accelerated FAB-MAP algorithm, developed based on:
|
||||
http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942
|
||||
*/
|
||||
class CV_EXPORTS FabMapFBO: public FabMap {
|
||||
public:
|
||||
FabMapFBO(const Mat& clTree, double PzGe, double PzGNe, int flags,
|
||||
int numSamples = 0, double rejectionThreshold = 1e-8, double PsGd =
|
||||
1e-8, int bisectionStart = 512, int bisectionIts = 9);
|
||||
virtual ~FabMapFBO();
|
||||
|
||||
protected:
|
||||
|
||||
//FabMap Fast Bail-out implementation of the likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
|
||||
//stucture used to determine word comparison order
|
||||
struct WordStats {
|
||||
WordStats() :
|
||||
q(0), info(0), V(0), M(0) {
|
||||
}
|
||||
|
||||
WordStats(int _q, double _info) :
|
||||
q(_q), info(_info), V(0), M(0) {
|
||||
}
|
||||
|
||||
int q;
|
||||
double info;
|
||||
mutable double V;
|
||||
mutable double M;
|
||||
|
||||
bool operator<(const WordStats& w) const {
|
||||
return info < w.info;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//private fast bail-out necessary functions
|
||||
void setWordStatistics(const Mat& queryImgDescriptor, multiset<WordStats>& wordData);
|
||||
double limitbisection(double v, double m);
|
||||
double bennettInequality(double v, double m, double delta);
|
||||
static bool compInfo(const WordStats& first, const WordStats& second);
|
||||
|
||||
//parameters
|
||||
double PsGd;
|
||||
double rejectionThreshold;
|
||||
int bisectionStart;
|
||||
int bisectionIts;
|
||||
};
|
||||
|
||||
/*
|
||||
The FAB-MAP2.0 algorithm, developed based on:
|
||||
http://ijr.sagepub.com/content/30/9/1100.abstract
|
||||
*/
|
||||
class CV_EXPORTS FabMap2: public FabMap {
|
||||
public:
|
||||
|
||||
FabMap2(const Mat& clTree, double PzGe, double PzGNe, int flags);
|
||||
virtual ~FabMap2();
|
||||
|
||||
//FabMap2 builds the inverted index and requires an additional training/test
|
||||
//add function
|
||||
void addTraining(const Mat& queryImgDescriptors) {
|
||||
FabMap::addTraining(queryImgDescriptors);
|
||||
}
|
||||
void addTraining(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
void add(const Mat& queryImgDescriptors) {
|
||||
FabMap::add(queryImgDescriptors);
|
||||
}
|
||||
void add(const vector<Mat>& queryImgDescriptors);
|
||||
|
||||
protected:
|
||||
|
||||
//FabMap2 implementation of the likelihood comparison
|
||||
void getLikelihoods(const Mat& queryImgDescriptor, const vector<
|
||||
Mat>& testImgDescriptors, vector<IMatch>& matches);
|
||||
double getNewPlaceLikelihood(const Mat& queryImgDescriptor);
|
||||
|
||||
//the likelihood function using the inverted index
|
||||
void getIndexLikelihoods(const Mat& queryImgDescriptor, vector<
|
||||
double>& defaults, map<int, vector<int> >& invertedMap,
|
||||
vector<IMatch>& matches);
|
||||
void addToIndex(const Mat& queryImgDescriptor,
|
||||
vector<double>& defaults,
|
||||
map<int, vector<int> >& invertedMap);
|
||||
|
||||
//data
|
||||
vector<double> d1, d2, d3, d4;
|
||||
vector<vector<int> > children;
|
||||
|
||||
// TODO: inverted map a vector?
|
||||
|
||||
vector<double> trainingDefaults;
|
||||
map<int, vector<int> > trainingInvertedMap;
|
||||
|
||||
vector<double> testDefaults;
|
||||
map<int, vector<int> > testInvertedMap;
|
||||
|
||||
};
|
||||
/*
|
||||
A Chow-Liu tree is required by FAB-MAP. The Chow-Liu tree provides an
|
||||
estimate of the full distribution of visual words using a minimum spanning
|
||||
tree. The tree is generated through training data.
|
||||
*/
|
||||
class CV_EXPORTS ChowLiuTree {
|
||||
public:
|
||||
ChowLiuTree();
|
||||
virtual ~ChowLiuTree();
|
||||
|
||||
//add data to the chow-liu tree before calling make
|
||||
void add(const Mat& imgDescriptor);
|
||||
void add(const vector<Mat>& imgDescriptors);
|
||||
|
||||
const vector<Mat>& getImgDescriptors() const;
|
||||
|
||||
Mat make(double infoThreshold = 0.0);
|
||||
|
||||
private:
|
||||
vector<Mat> imgDescriptors;
|
||||
Mat mergedImgDescriptors;
|
||||
|
||||
typedef struct info {
|
||||
float score;
|
||||
short word1;
|
||||
short word2;
|
||||
} info;
|
||||
|
||||
//probabilities extracted from mergedImgDescriptors
|
||||
double P(int a, bool za);
|
||||
double JP(int a, bool za, int b, bool zb); //a & b
|
||||
double CP(int a, bool za, int b, bool zb); // a | b
|
||||
|
||||
//calculating mutual information of all edges
|
||||
void createBaseEdges(list<info>& edges, double infoThreshold);
|
||||
double calcMutInfo(int word1, int word2);
|
||||
static bool sortInfoScores(const info& first, const info& second);
|
||||
|
||||
//selecting minimum spanning egdges with maximum information
|
||||
bool reduceEdgesToMinSpan(list<info>& edges);
|
||||
|
||||
//building the tree sctructure
|
||||
Mat buildTree(int root_word, list<info> &edges);
|
||||
void recAddToTree(Mat &cltree, int q, int pq,
|
||||
list<info> &remaining_edges);
|
||||
vector<int> extractChildren(list<info> &remaining_edges, int q);
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
A custom vocabulary training method based on:
|
||||
http://www.springerlink.com/content/d1h6j8x552532003/
|
||||
*/
|
||||
class CV_EXPORTS BOWMSCTrainer: public BOWTrainer {
|
||||
public:
|
||||
BOWMSCTrainer(double clusterSize = 0.4);
|
||||
virtual ~BOWMSCTrainer();
|
||||
|
||||
// Returns trained vocabulary (i.e. cluster centers).
|
||||
virtual Mat cluster() const;
|
||||
virtual Mat cluster(const Mat& descriptors) const;
|
||||
|
||||
protected:
|
||||
|
||||
double clusterSize;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENFABMAP_H_ */
|
||||
@@ -0,0 +1,355 @@
|
||||
/*#******************************************************************************
|
||||
** IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
**
|
||||
** By downloading, copying, installing or using the software you agree to this license.
|
||||
** If you do not agree to this license, do not download, install,
|
||||
** copy or use the software.
|
||||
**
|
||||
**
|
||||
** HVStools : interfaces allowing OpenCV users to integrate Human Vision System models. Presented models originate from Jeanny Herault's original research and have been reused and adapted by the author&collaborators for computed vision applications since his thesis with Alice Caplier at Gipsa-Lab.
|
||||
** Use: extract still images & image sequences features, from contours details to motion spatio-temporal features, etc. for high level visual scene analysis. Also contribute to image enhancement/compression such as tone mapping.
|
||||
**
|
||||
** Maintainers : Listic lab (code author current affiliation & applications) and Gipsa Lab (original research origins & applications)
|
||||
**
|
||||
** Creation - enhancement process 2007-2011
|
||||
** Author: Alexandre Benoit (benoit.alexandre.vision@gmail.com), LISTIC lab, Annecy le vieux, France
|
||||
**
|
||||
** Theses algorithm have been developped by Alexandre BENOIT since his thesis with Alice Caplier at Gipsa-Lab (www.gipsa-lab.inpg.fr) and the research he pursues at LISTIC Lab (www.listic.univ-savoie.fr).
|
||||
** Refer to the following research paper for more information:
|
||||
** Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011
|
||||
** This work have been carried out thanks to Jeanny Herault who's research and great discussions are the basis of all this work, please take a look at his book:
|
||||
** Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891.
|
||||
**
|
||||
** The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author :
|
||||
** _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper:
|
||||
** ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
|
||||
** _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions.
|
||||
** ====> more informations in the above cited Jeanny Heraults's book.
|
||||
**
|
||||
** License Agreement
|
||||
** For Open Source Computer Vision Library
|
||||
**
|
||||
** Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
** Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved.
|
||||
**
|
||||
** For Human Visual System tools (hvstools)
|
||||
** Copyright (C) 2007-2011, LISTIC Lab, Annecy le Vieux and GIPSA Lab, Grenoble, France, all rights reserved.
|
||||
**
|
||||
** Third party copyrights are property of their respective owners.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without modification,
|
||||
** are permitted provided that the following conditions are met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright notice,
|
||||
** this list of conditions and the following disclaimer.
|
||||
**
|
||||
** * Redistributions in binary form must reproduce the above copyright notice,
|
||||
** this list of conditions and the following disclaimer in the documentation
|
||||
** and/or other materials provided with the distribution.
|
||||
**
|
||||
** * The name of the copyright holders may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** This software is provided by the copyright holders and contributors "as is" and
|
||||
** any express or implied warranties, including, but not limited to, the implied
|
||||
** warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
** In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
** indirect, incidental, special, exemplary, or consequential damages
|
||||
** (including, but not limited to, procurement of substitute goods or services;
|
||||
** loss of use, data, or profits; or business interruption) however caused
|
||||
** and on any theory of liability, whether in contract, strict liability,
|
||||
** or tort (including negligence or otherwise) arising in any way out of
|
||||
** the use of this software, even if advised of the possibility of such damage.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OPENCV_CONTRIB_RETINA_HPP__
|
||||
#define __OPENCV_CONTRIB_RETINA_HPP__
|
||||
|
||||
/*
|
||||
* Retina.hpp
|
||||
*
|
||||
* Created on: Jul 19, 2011
|
||||
* Author: Alexandre Benoit
|
||||
*/
|
||||
|
||||
#include "opencv2/core/core.hpp" // for all OpenCV core functionalities access, including cv::Exception support
|
||||
#include <valarray>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
enum RETINA_COLORSAMPLINGMETHOD
|
||||
{
|
||||
RETINA_COLOR_RANDOM, //!< each pixel position is either R, G or B in a random choice
|
||||
RETINA_COLOR_DIAGONAL,//!< color sampling is RGBRGBRGB..., line 2 BRGBRGBRG..., line 3, GBRGBRGBR...
|
||||
RETINA_COLOR_BAYER//!< standard bayer sampling
|
||||
};
|
||||
|
||||
class RetinaFilter;
|
||||
|
||||
/**
|
||||
* @class Retina a wrapper class which allows the Gipsa/Listic Labs model to be used.
|
||||
* This retina model allows spatio-temporal image processing (applied on still images, video sequences).
|
||||
* As a summary, these are the retina model properties:
|
||||
* => It applies a spectral whithening (mid-frequency details enhancement)
|
||||
* => high frequency spatio-temporal noise reduction
|
||||
* => low frequency luminance to be reduced (luminance range compression)
|
||||
* => local logarithmic luminance compression allows details to be enhanced in low light conditions
|
||||
*
|
||||
* USE : this model can be used basically for spatio-temporal video effects but also for :
|
||||
* _using the getParvo method output matrix : texture analysiswith enhanced signal to noise ratio and enhanced details robust against input images luminance ranges
|
||||
* _using the getMagno method output matrix : motion analysis also with the previously cited properties
|
||||
*
|
||||
* for more information, reer to the following papers :
|
||||
* Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011
|
||||
* Vision: Images, Signals and Neural Networks: Models of Neural Processing in Visual Perception (Progress in Neural Processing),By: Jeanny Herault, ISBN: 9814273686. WAPI (Tower ID): 113266891.
|
||||
*
|
||||
* The retina filter includes the research contributions of phd/research collegues from which code has been redrawn by the author :
|
||||
* _take a look at the retinacolor.hpp module to discover Brice Chaix de Lavarene color mosaicing/demosaicing and the reference paper:
|
||||
* ====> B. Chaix de Lavarene, D. Alleysson, B. Durette, J. Herault (2007). "Efficient demosaicing through recursive filtering", IEEE International Conference on Image Processing ICIP 2007
|
||||
* _take a look at imagelogpolprojection.hpp to discover retina spatial log sampling which originates from Barthelemy Durette phd with Jeanny Herault. A Retina / V1 cortex projection is also proposed and originates from Jeanny's discussions.
|
||||
* ====> more informations in the above cited Jeanny Heraults's book.
|
||||
*/
|
||||
class CV_EXPORTS Retina {
|
||||
|
||||
public:
|
||||
|
||||
// parameters structure for better clarity, check explenations on the comments of methods : setupOPLandIPLParvoChannel and setupIPLMagnoChannel
|
||||
struct RetinaParameters{
|
||||
struct OPLandIplParvoParameters{ // Outer Plexiform Layer (OPL) and Inner Plexiform Layer Parvocellular (IplParvo) parameters
|
||||
OPLandIplParvoParameters():colorMode(true),
|
||||
normaliseOutput(true),
|
||||
photoreceptorsLocalAdaptationSensitivity(0.7f),
|
||||
photoreceptorsTemporalConstant(0.5f),
|
||||
photoreceptorsSpatialConstant(0.53f),
|
||||
horizontalCellsGain(0.0f),
|
||||
hcellsTemporalConstant(1.f),
|
||||
hcellsSpatialConstant(7.f),
|
||||
ganglionCellsSensitivity(0.7f){};// default setup
|
||||
bool colorMode, normaliseOutput;
|
||||
float photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, hcellsTemporalConstant, hcellsSpatialConstant, ganglionCellsSensitivity;
|
||||
};
|
||||
struct IplMagnoParameters{ // Inner Plexiform Layer Magnocellular channel (IplMagno)
|
||||
IplMagnoParameters():
|
||||
normaliseOutput(true),
|
||||
parasolCells_beta(0.f),
|
||||
parasolCells_tau(0.f),
|
||||
parasolCells_k(7.f),
|
||||
amacrinCellsTemporalCutFrequency(1.2f),
|
||||
V0CompressionParameter(0.95f),
|
||||
localAdaptintegration_tau(0.f),
|
||||
localAdaptintegration_k(7.f){};// default setup
|
||||
bool normaliseOutput;
|
||||
float parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k;
|
||||
};
|
||||
struct OPLandIplParvoParameters OPLandIplParvo;
|
||||
struct IplMagnoParameters IplMagno;
|
||||
};
|
||||
|
||||
/**
|
||||
* Main constructor with most commun use setup : create an instance of color ready retina model
|
||||
* @param inputSize : the input frame size
|
||||
*/
|
||||
Retina(Size inputSize);
|
||||
|
||||
/**
|
||||
* Complete Retina filter constructor which allows all basic structural parameters definition
|
||||
* @param inputSize : the input frame size
|
||||
* @param colorMode : the chosen processing mode : with or without color processing
|
||||
* @param colorSamplingMethod: specifies which kind of color sampling will be used
|
||||
* @param useRetinaLogSampling: activate retina log sampling, if true, the 2 following parameters can be used
|
||||
* @param reductionFactor: only usefull if param useRetinaLogSampling=true, specifies the reduction factor of the output frame (as the center (fovea) is high resolution and corners can be underscaled, then a reduction of the output is allowed without precision leak
|
||||
* @param samplingStrenght: only usefull if param useRetinaLogSampling=true, specifies the strenght of the log scale that is applied
|
||||
*/
|
||||
Retina(Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
|
||||
|
||||
virtual ~Retina();
|
||||
|
||||
/**
|
||||
* retreive retina input buffer size
|
||||
*/
|
||||
Size inputSize();
|
||||
|
||||
/**
|
||||
* retreive retina output buffer size
|
||||
*/
|
||||
Size outputSize();
|
||||
|
||||
/**
|
||||
* try to open an XML retina parameters file to adjust current retina instance setup
|
||||
* => if the xml file does not exist, then default setup is applied
|
||||
* => warning, Exceptions are thrown if read XML file is not valid
|
||||
* @param retinaParameterFile : the parameters filename
|
||||
* @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error
|
||||
*/
|
||||
void setup(std::string retinaParameterFile="", const bool applyDefaultSetupOnFailure=true);
|
||||
|
||||
|
||||
/**
|
||||
* try to open an XML retina parameters file to adjust current retina instance setup
|
||||
* => if the xml file does not exist, then default setup is applied
|
||||
* => warning, Exceptions are thrown if read XML file is not valid
|
||||
* @param fs : the open Filestorage which contains retina parameters
|
||||
* @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error
|
||||
*/
|
||||
void setup(cv::FileStorage &fs, const bool applyDefaultSetupOnFailure=true);
|
||||
|
||||
/**
|
||||
* try to open an XML retina parameters file to adjust current retina instance setup
|
||||
* => if the xml file does not exist, then default setup is applied
|
||||
* => warning, Exceptions are thrown if read XML file is not valid
|
||||
* @param newParameters : a parameters structures updated with the new target configuration
|
||||
* @param applyDefaultSetupOnFailure : set to true if an error must be thrown on error
|
||||
*/
|
||||
void setup(RetinaParameters newParameters);
|
||||
|
||||
/**
|
||||
* @return the current parameters setup
|
||||
*/
|
||||
Retina::RetinaParameters getParameters();
|
||||
|
||||
/**
|
||||
* parameters setup display method
|
||||
* @return a string which contains formatted parameters information
|
||||
*/
|
||||
const std::string printSetup();
|
||||
|
||||
/**
|
||||
* write xml/yml formated parameters information
|
||||
* @rparam fs : the filename of the xml file that will be open and writen with formatted parameters information
|
||||
*/
|
||||
virtual void write( std::string fs ) const;
|
||||
|
||||
|
||||
/**
|
||||
* write xml/yml formated parameters information
|
||||
* @param fs : a cv::Filestorage object ready to be filled
|
||||
*/
|
||||
virtual void write( FileStorage& fs ) const;
|
||||
|
||||
/**
|
||||
* setup the OPL and IPL parvo channels (see biologocal model)
|
||||
* OPL is referred as Outer Plexiform Layer of the retina, it allows the spatio-temporal filtering which withens the spectrum and reduces spatio-temporal noise while attenuating global luminance (low frequency energy)
|
||||
* IPL parvo is the OPL next processing stage, it refers to Inner Plexiform layer of the retina, it allows high contours sensitivity in foveal vision.
|
||||
* for more informations, please have a look at the paper Benoit A., Caplier A., Durette B., Herault, J., "USING HUMAN VISUAL SYSTEM MODELING FOR BIO-INSPIRED LOW LEVEL IMAGE PROCESSING", Elsevier, Computer Vision and Image Understanding 114 (2010), pp. 758-773, DOI: http://dx.doi.org/10.1016/j.cviu.2010.01.011
|
||||
* @param colorMode : specifies if (true) color is processed of not (false) to then processing gray level image
|
||||
* @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false)
|
||||
* @param photoreceptorsLocalAdaptationSensitivity: the photoreceptors sensitivity renage is 0-1 (more log compression effect when value increases)
|
||||
* @param photoreceptorsTemporalConstant: the time constant of the first order low pass filter of the photoreceptors, use it to cut high temporal frequencies (noise or fast motion), unit is frames, typical value is 1 frame
|
||||
* @param photoreceptorsSpatialConstant: the spatial constant of the first order low pass filter of the photoreceptors, use it to cut high spatial frequencies (noise or thick contours), unit is pixels, typical value is 1 pixel
|
||||
* @param horizontalCellsGain: gain of the horizontal cells network, if 0, then the mean value of the output is zero, if the parameter is near 1, then, the luminance is not filtered and is still reachable at the output, typicall value is 0
|
||||
* @param HcellsTemporalConstant: the time constant of the first order low pass filter of the horizontal cells, use it to cut low temporal frequencies (local luminance variations), unit is frames, typical value is 1 frame, as the photoreceptors
|
||||
* @param HcellsSpatialConstant: the spatial constant of the first order low pass filter of the horizontal cells, use it to cut low spatial frequencies (local luminance), unit is pixels, typical value is 5 pixel, this value is also used for local contrast computing when computing the local contrast adaptation at the ganglion cells level (Inner Plexiform Layer parvocellular channel model)
|
||||
* @param ganglionCellsSensitivity: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 230
|
||||
*/
|
||||
void setupOPLandIPLParvoChannel(const bool colorMode=true, const bool normaliseOutput = true, const float photoreceptorsLocalAdaptationSensitivity=0.7, const float photoreceptorsTemporalConstant=0.5, const float photoreceptorsSpatialConstant=0.53, const float horizontalCellsGain=0, const float HcellsTemporalConstant=1, const float HcellsSpatialConstant=7, const float ganglionCellsSensitivity=0.7);
|
||||
|
||||
/**
|
||||
* set parameters values for the Inner Plexiform Layer (IPL) magnocellular channel
|
||||
* this channel processes signals outpint from OPL processing stage in peripheral vision, it allows motion information enhancement. It is decorrelated from the details channel. See reference paper for more details.
|
||||
* @param normaliseOutput : specifies if (true) output is rescaled between 0 and 255 of not (false)
|
||||
* @param parasolCells_beta: the low pass filter gain used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), typical value is 0
|
||||
* @param parasolCells_tau: the low pass filter time constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is frame, typical value is 0 (immediate response)
|
||||
* @param parasolCells_k: the low pass filter spatial constant used for local contrast adaptation at the IPL level of the retina (for ganglion cells local adaptation), unit is pixels, typical value is 5
|
||||
* @param amacrinCellsTemporalCutFrequency: the time constant of the first order high pass fiter of the magnocellular way (motion information channel), unit is frames, tipicall value is 5
|
||||
* @param V0CompressionParameter: the compression strengh of the ganglion cells local adaptation output, set a value between 160 and 250 for best results, a high value increases more the low value sensitivity... and the output saturates faster, recommended value: 200
|
||||
* @param localAdaptintegration_tau: specifies the temporal constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
* @param localAdaptintegration_k: specifies the spatial constant of the low pas filter involved in the computation of the local "motion mean" for the local adaptation computation
|
||||
*/
|
||||
void setupIPLMagnoChannel(const bool normaliseOutput = true, const float parasolCells_beta=0, const float parasolCells_tau=0, const float parasolCells_k=7, const float amacrinCellsTemporalCutFrequency=1.2, const float V0CompressionParameter=0.95, const float localAdaptintegration_tau=0, const float localAdaptintegration_k=7);
|
||||
|
||||
/**
|
||||
* method which allows retina to be applied on an input image, after run, encapsulated retina module is ready to deliver its outputs using dedicated acccessors, see getParvo and getMagno methods
|
||||
* @param inputImage : the input cv::Mat image to be processed, can be gray level or BGR coded in any format (from 8bit to 16bits)
|
||||
*/
|
||||
void run(const Mat &inputImage);
|
||||
|
||||
/**
|
||||
* accessor of the details channel of the retina (models foveal vision)
|
||||
* @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV
|
||||
*/
|
||||
void getParvo(Mat &retinaOutput_parvo);
|
||||
|
||||
/**
|
||||
* accessor of the details channel of the retina (models foveal vision)
|
||||
* @param retinaOutput_parvo : the output buffer (reallocated if necessary), this output is the original retina filter model output, without any quantification or rescaling
|
||||
*/
|
||||
void getParvo(std::valarray<float> &retinaOutput_parvo);
|
||||
|
||||
/**
|
||||
* accessor of the motion channel of the retina (models peripheral vision)
|
||||
* @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is rescaled for standard 8bits image processing use in OpenCV
|
||||
*/
|
||||
void getMagno(Mat &retinaOutput_magno);
|
||||
|
||||
/**
|
||||
* accessor of the motion channel of the retina (models peripheral vision)
|
||||
* @param retinaOutput_magno : the output buffer (reallocated if necessary), this output is the original retina filter model output, without any quantification or rescaling
|
||||
*/
|
||||
void getMagno(std::valarray<float> &retinaOutput_magno);
|
||||
|
||||
// original API level data accessors : get buffers addresses...
|
||||
const std::valarray<float> & getMagno() const;
|
||||
const std::valarray<float> & getParvo() const;
|
||||
|
||||
/**
|
||||
* activate color saturation as the final step of the color demultiplexing process
|
||||
* -> this saturation is a sigmoide function applied to each channel of the demultiplexed image.
|
||||
* @param saturateColors: boolean that activates color saturation (if true) or desactivate (if false)
|
||||
* @param colorSaturationValue: the saturation factor
|
||||
*/
|
||||
void setColorSaturation(const bool saturateColors=true, const float colorSaturationValue=4.0);
|
||||
|
||||
/**
|
||||
* clear all retina buffers (equivalent to opening the eyes after a long period of eye close ;o)
|
||||
*/
|
||||
void clearBuffers();
|
||||
|
||||
/**
|
||||
* Activate/desactivate the Magnocellular pathway processing (motion information extraction), by default, it is activated
|
||||
* @param activate: true if Magnocellular output should be activated, false if not
|
||||
*/
|
||||
void activateMovingContoursProcessing(const bool activate);
|
||||
|
||||
/**
|
||||
* Activate/desactivate the Parvocellular pathway processing (contours information extraction), by default, it is activated
|
||||
* @param activate: true if Parvocellular (contours information extraction) output should be activated, false if not
|
||||
*/
|
||||
void activateContoursProcessing(const bool activate);
|
||||
|
||||
protected:
|
||||
// Parameteres setup members
|
||||
RetinaParameters _retinaParameters; // structure of parameters
|
||||
|
||||
// Retina model related modules
|
||||
std::valarray<float> _inputBuffer; //!< buffer used to convert input cv::Mat to internal retina buffers format (valarrays)
|
||||
|
||||
// pointer to retina model
|
||||
RetinaFilter* _retinaFilter; //!< the pointer to the retina module, allocated with instance construction
|
||||
|
||||
/**
|
||||
* exports a valarray buffer outing from HVStools objects to a cv::Mat in CV_8UC1 (gray level picture) or CV_8UC3 (color) format
|
||||
* @param grayMatrixToConvert the valarray to export to OpenCV
|
||||
* @param nbRows : the number of rows of the valarray flatten matrix
|
||||
* @param nbColumns : the number of rows of the valarray flatten matrix
|
||||
* @param colorMode : a flag which mentions if matrix is color (true) or graylevel (false)
|
||||
* @param outBuffer : the output matrix which is reallocated to satisfy Retina output buffer dimensions
|
||||
*/
|
||||
void _convertValarrayBuffer2cvMat(const std::valarray<float> &grayMatrixToConvert, const unsigned int nbRows, const unsigned int nbColumns, const bool colorMode, Mat &outBuffer);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param inputMatToConvert : the OpenCV cv::Mat that has to be converted to gray or RGB valarray buffer that will be processed by the retina model
|
||||
* @param outputValarrayMatrix : the output valarray
|
||||
* @return the input image color mode (color=true, gray levels=false)
|
||||
*/
|
||||
bool _convertCvMat2ValarrayBuffer(const cv::Mat inputMatToConvert, std::valarray<float> &outputValarrayMatrix);
|
||||
|
||||
//! private method called by constructors, gathers their parameters and use them in a unified way
|
||||
void _init(const Size inputSize, const bool colorMode, RETINA_COLORSAMPLINGMETHOD colorSamplingMethod=RETINA_COLOR_BAYER, const bool useRetinaLogSampling=false, const double reductionFactor=1.0, const double samplingStrenght=10.0);
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif /* __OPENCV_CONTRIB_RETINA_HPP__ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_CORE_DEVPTRS_HPP__
|
||||
#define __OPENCV_CORE_DEVPTRS_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef __CUDACC__
|
||||
#define __CV_GPU_HOST_DEVICE__ __host__ __device__ __forceinline__
|
||||
#else
|
||||
#define __CV_GPU_HOST_DEVICE__
|
||||
#endif
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace gpu
|
||||
{
|
||||
// Simple lightweight structures that encapsulates information about an image on device.
|
||||
// It is intended to pass to nvcc-compiled code. GpuMat depends on headers that nvcc can't compile
|
||||
|
||||
template <bool expr> struct StaticAssert;
|
||||
template <> struct StaticAssert<true> {static __CV_GPU_HOST_DEVICE__ void check(){}};
|
||||
|
||||
template<typename T> struct DevPtr
|
||||
{
|
||||
typedef T elem_type;
|
||||
typedef int index_type;
|
||||
|
||||
enum { elem_size = sizeof(elem_type) };
|
||||
|
||||
T* data;
|
||||
|
||||
__CV_GPU_HOST_DEVICE__ DevPtr() : data(0) {}
|
||||
__CV_GPU_HOST_DEVICE__ DevPtr(T* data_) : data(data_) {}
|
||||
|
||||
__CV_GPU_HOST_DEVICE__ size_t elemSize() const { return elem_size; }
|
||||
__CV_GPU_HOST_DEVICE__ operator T*() { return data; }
|
||||
__CV_GPU_HOST_DEVICE__ operator const T*() const { return data; }
|
||||
};
|
||||
|
||||
template<typename T> struct PtrSz : public DevPtr<T>
|
||||
{
|
||||
__CV_GPU_HOST_DEVICE__ PtrSz() : size(0) {}
|
||||
__CV_GPU_HOST_DEVICE__ PtrSz(T* data_, size_t size_) : DevPtr<T>(data_), size(size_) {}
|
||||
|
||||
size_t size;
|
||||
};
|
||||
|
||||
template<typename T> struct PtrStep : public DevPtr<T>
|
||||
{
|
||||
__CV_GPU_HOST_DEVICE__ PtrStep() : step(0) {}
|
||||
__CV_GPU_HOST_DEVICE__ PtrStep(T* data_, size_t step_) : DevPtr<T>(data_), step(step_) {}
|
||||
|
||||
/** \brief stride between two consecutive rows in bytes. Step is stored always and everywhere in bytes!!! */
|
||||
size_t step;
|
||||
|
||||
__CV_GPU_HOST_DEVICE__ T* ptr(int y = 0) { return ( T*)( ( char*)DevPtr<T>::data + y * step); }
|
||||
__CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const { return (const T*)( (const char*)DevPtr<T>::data + y * step); }
|
||||
|
||||
__CV_GPU_HOST_DEVICE__ T& operator ()(int y, int x) { return ptr(y)[x]; }
|
||||
__CV_GPU_HOST_DEVICE__ const T& operator ()(int y, int x) const { return ptr(y)[x]; }
|
||||
};
|
||||
|
||||
template <typename T> struct PtrStepSz : public PtrStep<T>
|
||||
{
|
||||
__CV_GPU_HOST_DEVICE__ PtrStepSz() : cols(0), rows(0) {}
|
||||
__CV_GPU_HOST_DEVICE__ PtrStepSz(int rows_, int cols_, T* data_, size_t step_)
|
||||
: PtrStep<T>(data_, step_), cols(cols_), rows(rows_) {}
|
||||
|
||||
template <typename U>
|
||||
explicit PtrStepSz(const PtrStepSz<U>& d) : PtrStep<T>((T*)d.data, d.step), cols(d.cols), rows(d.rows){}
|
||||
|
||||
int cols;
|
||||
int rows;
|
||||
};
|
||||
|
||||
typedef PtrStepSz<unsigned char> PtrStepSzb;
|
||||
typedef PtrStepSz<float> PtrStepSzf;
|
||||
typedef PtrStepSz<int> PtrStepSzi;
|
||||
|
||||
typedef PtrStep<unsigned char> PtrStepb;
|
||||
typedef PtrStep<float> PtrStepf;
|
||||
typedef PtrStep<int> PtrStepi;
|
||||
|
||||
|
||||
#if defined __GNUC__
|
||||
#define __CV_GPU_DEPR_BEFORE__
|
||||
#define __CV_GPU_DEPR_AFTER__ __attribute__ ((deprecated))
|
||||
#elif defined(__MSVC__) //|| defined(__CUDACC__)
|
||||
#pragma deprecated(DevMem2D_)
|
||||
#define __CV_GPU_DEPR_BEFORE__ __declspec(deprecated)
|
||||
#define __CV_GPU_DEPR_AFTER__
|
||||
#else
|
||||
#define __CV_GPU_DEPR_BEFORE__
|
||||
#define __CV_GPU_DEPR_AFTER__
|
||||
#endif
|
||||
|
||||
template <typename T> struct __CV_GPU_DEPR_BEFORE__ DevMem2D_ : public PtrStepSz<T>
|
||||
{
|
||||
DevMem2D_() {}
|
||||
DevMem2D_(int rows_, int cols_, T* data_, size_t step_) : PtrStepSz<T>(rows_, cols_, data_, step_) {}
|
||||
|
||||
template <typename U>
|
||||
explicit __CV_GPU_DEPR_BEFORE__ DevMem2D_(const DevMem2D_<U>& d) : PtrStepSz<T>(d.rows, d.cols, (T*)d.data, d.step) {}
|
||||
} __CV_GPU_DEPR_AFTER__ ;
|
||||
|
||||
typedef DevMem2D_<unsigned char> DevMem2Db;
|
||||
typedef DevMem2Db DevMem2D;
|
||||
typedef DevMem2D_<float> DevMem2Df;
|
||||
typedef DevMem2D_<int> DevMem2Di;
|
||||
|
||||
template<typename T> struct PtrElemStep_ : public PtrStep<T>
|
||||
{
|
||||
PtrElemStep_(const DevMem2D_<T>& mem) : PtrStep<T>(mem.data, mem.step)
|
||||
{
|
||||
StaticAssert<256 % sizeof(T) == 0>::check();
|
||||
|
||||
PtrStep<T>::step /= PtrStep<T>::elem_size;
|
||||
}
|
||||
__CV_GPU_HOST_DEVICE__ T* ptr(int y = 0) { return PtrStep<T>::data + y * PtrStep<T>::step; }
|
||||
__CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const { return PtrStep<T>::data + y * PtrStep<T>::step; }
|
||||
|
||||
__CV_GPU_HOST_DEVICE__ T& operator ()(int y, int x) { return ptr(y)[x]; }
|
||||
__CV_GPU_HOST_DEVICE__ const T& operator ()(int y, int x) const { return ptr(y)[x]; }
|
||||
};
|
||||
|
||||
template<typename T> struct PtrStep_ : public PtrStep<T>
|
||||
{
|
||||
PtrStep_() {}
|
||||
PtrStep_(const DevMem2D_<T>& mem) : PtrStep<T>(mem.data, mem.step) {}
|
||||
};
|
||||
|
||||
typedef PtrElemStep_<unsigned char> PtrElemStep;
|
||||
typedef PtrElemStep_<float> PtrElemStepf;
|
||||
typedef PtrElemStep_<int> PtrElemStepi;
|
||||
|
||||
//#undef __CV_GPU_DEPR_BEFORE__
|
||||
//#undef __CV_GPU_DEPR_AFTER__
|
||||
|
||||
namespace device
|
||||
{
|
||||
using cv::gpu::PtrSz;
|
||||
using cv::gpu::PtrStep;
|
||||
using cv::gpu::PtrStepSz;
|
||||
|
||||
using cv::gpu::PtrStepSzb;
|
||||
using cv::gpu::PtrStepSzf;
|
||||
using cv::gpu::PtrStepSzi;
|
||||
|
||||
using cv::gpu::PtrStepb;
|
||||
using cv::gpu::PtrStepf;
|
||||
using cv::gpu::PtrStepi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif /* __OPENCV_CORE_DEVPTRS_HPP__ */
|
||||
@@ -0,0 +1,43 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "opencv2/core/cuda_devptrs.hpp"
|
||||
@@ -0,0 +1,280 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_CORE_EIGEN_HPP__
|
||||
#define __OPENCV_CORE_EIGEN_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
#if defined _MSC_VER && _MSC_VER >= 1200
|
||||
#pragma warning( disable: 4714 ) //__forceinline is not inlined
|
||||
#pragma warning( disable: 4127 ) //conditional expression is constant
|
||||
#pragma warning( disable: 4244 ) //conversion from '__int64' to 'int', possible loss of data
|
||||
#endif
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
|
||||
void eigen2cv( const Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& src, Mat& dst )
|
||||
{
|
||||
if( !(src.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _src(src.cols(), src.rows(), DataType<_Tp>::type,
|
||||
(void*)src.data(), src.stride()*sizeof(_Tp));
|
||||
transpose(_src, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _src(src.rows(), src.cols(), DataType<_Tp>::type,
|
||||
(void*)src.data(), src.stride()*sizeof(_Tp));
|
||||
_src.copyTo(dst);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
|
||||
void cv2eigen( const Mat& src,
|
||||
Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
|
||||
{
|
||||
CV_DbgAssert(src.rows == _rows && src.cols == _cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
if( src.type() == _dst.type() )
|
||||
transpose(src, _dst);
|
||||
else if( src.cols == src.rows )
|
||||
{
|
||||
src.convertTo(_dst, _dst.type());
|
||||
transpose(_dst, _dst);
|
||||
}
|
||||
else
|
||||
Mat(src.t()).convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
src.convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows, int _cols, int _options, int _maxRows, int _maxCols>
|
||||
void cv2eigen( const Matx<_Tp, _rows, _cols>& src,
|
||||
Eigen::Matrix<_Tp, _rows, _cols, _options, _maxRows, _maxCols>& dst )
|
||||
{
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(_cols, _rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(_rows, _cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
Mat(src).copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
void cv2eigen( const Mat& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
|
||||
{
|
||||
dst.resize(src.rows, src.cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
if( src.type() == _dst.type() )
|
||||
transpose(src, _dst);
|
||||
else if( src.cols == src.rows )
|
||||
{
|
||||
src.convertTo(_dst, _dst.type());
|
||||
transpose(_dst, _dst);
|
||||
}
|
||||
else
|
||||
Mat(src.t()).convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
src.convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows, int _cols>
|
||||
void cv2eigen( const Matx<_Tp, _rows, _cols>& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, Eigen::Dynamic>& dst )
|
||||
{
|
||||
dst.resize(_rows, _cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(_cols, _rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(_rows, _cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
Mat(src).copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename _Tp>
|
||||
void cv2eigen( const Mat& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst )
|
||||
{
|
||||
CV_Assert(src.cols == 1);
|
||||
dst.resize(src.rows);
|
||||
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
if( src.type() == _dst.type() )
|
||||
transpose(src, _dst);
|
||||
else
|
||||
Mat(src.t()).convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
src.convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
// Matx case
|
||||
template<typename _Tp, int _rows>
|
||||
void cv2eigen( const Matx<_Tp, _rows, 1>& src,
|
||||
Eigen::Matrix<_Tp, Eigen::Dynamic, 1>& dst )
|
||||
{
|
||||
dst.resize(_rows);
|
||||
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(1, _rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(_rows, 1, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
src.copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename _Tp>
|
||||
void cv2eigen( const Mat& src,
|
||||
Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst )
|
||||
{
|
||||
CV_Assert(src.rows == 1);
|
||||
dst.resize(src.cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(src.cols, src.rows, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
if( src.type() == _dst.type() )
|
||||
transpose(src, _dst);
|
||||
else
|
||||
Mat(src.t()).convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(src.rows, src.cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
src.convertTo(_dst, _dst.type());
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
//Matx
|
||||
template<typename _Tp, int _cols>
|
||||
void cv2eigen( const Matx<_Tp, 1, _cols>& src,
|
||||
Eigen::Matrix<_Tp, 1, Eigen::Dynamic>& dst )
|
||||
{
|
||||
dst.resize(_cols);
|
||||
if( !(dst.Flags & Eigen::RowMajorBit) )
|
||||
{
|
||||
Mat _dst(_cols, 1, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
transpose(src, _dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat _dst(1, _cols, DataType<_Tp>::type,
|
||||
dst.data(), (size_t)(dst.stride()*sizeof(_Tp)));
|
||||
Mat(src).copyTo(_dst);
|
||||
CV_DbgAssert(_dst.data == (uchar*)dst.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,562 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPUMAT_HPP__
|
||||
#define __OPENCV_GPUMAT_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/core/cuda_devptrs.hpp"
|
||||
|
||||
namespace cv { namespace gpu
|
||||
{
|
||||
//////////////////////////////// Initialization & Info ////////////////////////
|
||||
|
||||
//! This is the only function that do not throw exceptions if the library is compiled without Cuda.
|
||||
CV_EXPORTS int getCudaEnabledDeviceCount();
|
||||
|
||||
//! Functions below throw cv::Expception if the library is compiled without Cuda.
|
||||
|
||||
CV_EXPORTS void setDevice(int device);
|
||||
CV_EXPORTS int getDevice();
|
||||
|
||||
//! Explicitly destroys and cleans up all resources associated with the current device in the current process.
|
||||
//! Any subsequent API call to this device will reinitialize the device.
|
||||
CV_EXPORTS void resetDevice();
|
||||
|
||||
enum FeatureSet
|
||||
{
|
||||
FEATURE_SET_COMPUTE_10 = 10,
|
||||
FEATURE_SET_COMPUTE_11 = 11,
|
||||
FEATURE_SET_COMPUTE_12 = 12,
|
||||
FEATURE_SET_COMPUTE_13 = 13,
|
||||
FEATURE_SET_COMPUTE_20 = 20,
|
||||
FEATURE_SET_COMPUTE_21 = 21,
|
||||
FEATURE_SET_COMPUTE_30 = 30,
|
||||
FEATURE_SET_COMPUTE_35 = 35,
|
||||
|
||||
GLOBAL_ATOMICS = FEATURE_SET_COMPUTE_11,
|
||||
SHARED_ATOMICS = FEATURE_SET_COMPUTE_12,
|
||||
NATIVE_DOUBLE = FEATURE_SET_COMPUTE_13,
|
||||
WARP_SHUFFLE_FUNCTIONS = FEATURE_SET_COMPUTE_30,
|
||||
DYNAMIC_PARALLELISM = FEATURE_SET_COMPUTE_35
|
||||
};
|
||||
|
||||
// Checks whether current device supports the given feature
|
||||
CV_EXPORTS bool deviceSupports(FeatureSet feature_set);
|
||||
|
||||
// Gives information about what GPU archs this OpenCV GPU module was
|
||||
// compiled for
|
||||
class CV_EXPORTS TargetArchs
|
||||
{
|
||||
public:
|
||||
static bool builtWith(FeatureSet feature_set);
|
||||
static bool has(int major, int minor);
|
||||
static bool hasPtx(int major, int minor);
|
||||
static bool hasBin(int major, int minor);
|
||||
static bool hasEqualOrLessPtx(int major, int minor);
|
||||
static bool hasEqualOrGreater(int major, int minor);
|
||||
static bool hasEqualOrGreaterPtx(int major, int minor);
|
||||
static bool hasEqualOrGreaterBin(int major, int minor);
|
||||
private:
|
||||
TargetArchs();
|
||||
};
|
||||
|
||||
// Gives information about the given GPU
|
||||
class CV_EXPORTS DeviceInfo
|
||||
{
|
||||
public:
|
||||
// Creates DeviceInfo object for the current GPU
|
||||
DeviceInfo() : device_id_(getDevice()) { query(); }
|
||||
|
||||
// Creates DeviceInfo object for the given GPU
|
||||
DeviceInfo(int device_id) : device_id_(device_id) { query(); }
|
||||
|
||||
std::string name() const { return name_; }
|
||||
|
||||
// Return compute capability versions
|
||||
int majorVersion() const { return majorVersion_; }
|
||||
int minorVersion() const { return minorVersion_; }
|
||||
|
||||
int multiProcessorCount() const { return multi_processor_count_; }
|
||||
|
||||
size_t sharedMemPerBlock() const;
|
||||
|
||||
void queryMemory(size_t& totalMemory, size_t& freeMemory) const;
|
||||
size_t freeMemory() const;
|
||||
size_t totalMemory() const;
|
||||
|
||||
// Checks whether device supports the given feature
|
||||
bool supports(FeatureSet feature_set) const;
|
||||
|
||||
// Checks whether the GPU module can be run on the given device
|
||||
bool isCompatible() const;
|
||||
|
||||
int deviceID() const { return device_id_; }
|
||||
|
||||
private:
|
||||
void query();
|
||||
|
||||
int device_id_;
|
||||
|
||||
std::string name_;
|
||||
int multi_processor_count_;
|
||||
int majorVersion_;
|
||||
int minorVersion_;
|
||||
};
|
||||
|
||||
CV_EXPORTS void printCudaDeviceInfo(int device);
|
||||
CV_EXPORTS void printShortCudaDeviceInfo(int device);
|
||||
|
||||
//////////////////////////////// GpuMat ///////////////////////////////
|
||||
|
||||
//! Smart pointer for GPU memory with reference counting. Its interface is mostly similar with cv::Mat.
|
||||
class CV_EXPORTS GpuMat
|
||||
{
|
||||
public:
|
||||
//! default constructor
|
||||
GpuMat();
|
||||
|
||||
//! constructs GpuMatrix of the specified size and type (_type is CV_8UC1, CV_64FC3, CV_32SC(12) etc.)
|
||||
GpuMat(int rows, int cols, int type);
|
||||
GpuMat(Size size, int type);
|
||||
|
||||
//! constucts GpuMatrix and fills it with the specified value _s.
|
||||
GpuMat(int rows, int cols, int type, Scalar s);
|
||||
GpuMat(Size size, int type, Scalar s);
|
||||
|
||||
//! copy constructor
|
||||
GpuMat(const GpuMat& m);
|
||||
|
||||
//! constructor for GpuMatrix headers pointing to user-allocated data
|
||||
GpuMat(int rows, int cols, int type, void* data, size_t step = Mat::AUTO_STEP);
|
||||
GpuMat(Size size, int type, void* data, size_t step = Mat::AUTO_STEP);
|
||||
|
||||
//! creates a matrix header for a part of the bigger matrix
|
||||
GpuMat(const GpuMat& m, Range rowRange, Range colRange);
|
||||
GpuMat(const GpuMat& m, Rect roi);
|
||||
|
||||
//! builds GpuMat from Mat. Perfom blocking upload to device.
|
||||
explicit GpuMat(const Mat& m);
|
||||
|
||||
//! destructor - calls release()
|
||||
~GpuMat();
|
||||
|
||||
//! assignment operators
|
||||
GpuMat& operator = (const GpuMat& m);
|
||||
|
||||
//! pefroms blocking upload data to GpuMat.
|
||||
void upload(const Mat& m);
|
||||
|
||||
//! downloads data from device to host memory. Blocking calls.
|
||||
void download(Mat& m) const;
|
||||
|
||||
//! returns a new GpuMatrix header for the specified row
|
||||
GpuMat row(int y) const;
|
||||
//! returns a new GpuMatrix header for the specified column
|
||||
GpuMat col(int x) const;
|
||||
//! ... for the specified row span
|
||||
GpuMat rowRange(int startrow, int endrow) const;
|
||||
GpuMat rowRange(Range r) const;
|
||||
//! ... for the specified column span
|
||||
GpuMat colRange(int startcol, int endcol) const;
|
||||
GpuMat colRange(Range r) const;
|
||||
|
||||
//! returns deep copy of the GpuMatrix, i.e. the data is copied
|
||||
GpuMat clone() const;
|
||||
//! copies the GpuMatrix content to "m".
|
||||
// It calls m.create(this->size(), this->type()).
|
||||
void copyTo(GpuMat& m) const;
|
||||
//! copies those GpuMatrix elements to "m" that are marked with non-zero mask elements.
|
||||
void copyTo(GpuMat& m, const GpuMat& mask) const;
|
||||
//! converts GpuMatrix to another datatype with optional scalng. See cvConvertScale.
|
||||
void convertTo(GpuMat& m, int rtype, double alpha = 1, double beta = 0) const;
|
||||
|
||||
void assignTo(GpuMat& m, int type=-1) const;
|
||||
|
||||
//! sets every GpuMatrix element to s
|
||||
GpuMat& operator = (Scalar s);
|
||||
//! sets some of the GpuMatrix elements to s, according to the mask
|
||||
GpuMat& setTo(Scalar s, const GpuMat& mask = GpuMat());
|
||||
//! creates alternative GpuMatrix header for the same data, with different
|
||||
// number of channels and/or different number of rows. see cvReshape.
|
||||
GpuMat reshape(int cn, int rows = 0) const;
|
||||
|
||||
//! allocates new GpuMatrix data unless the GpuMatrix already has specified size and type.
|
||||
// previous data is unreferenced if needed.
|
||||
void create(int rows, int cols, int type);
|
||||
void create(Size size, int type);
|
||||
//! decreases reference counter;
|
||||
// deallocate the data when reference counter reaches 0.
|
||||
void release();
|
||||
|
||||
//! swaps with other smart pointer
|
||||
void swap(GpuMat& mat);
|
||||
|
||||
//! locates GpuMatrix header within a parent GpuMatrix. See below
|
||||
void locateROI(Size& wholeSize, Point& ofs) const;
|
||||
//! moves/resizes the current GpuMatrix ROI inside the parent GpuMatrix.
|
||||
GpuMat& adjustROI(int dtop, int dbottom, int dleft, int dright);
|
||||
//! extracts a rectangular sub-GpuMatrix
|
||||
// (this is a generalized form of row, rowRange etc.)
|
||||
GpuMat operator()(Range rowRange, Range colRange) const;
|
||||
GpuMat operator()(Rect roi) const;
|
||||
|
||||
//! returns true iff the GpuMatrix data is continuous
|
||||
// (i.e. when there are no gaps between successive rows).
|
||||
// similar to CV_IS_GpuMat_CONT(cvGpuMat->type)
|
||||
bool isContinuous() const;
|
||||
//! returns element size in bytes,
|
||||
// similar to CV_ELEM_SIZE(cvMat->type)
|
||||
size_t elemSize() const;
|
||||
//! returns the size of element channel in bytes.
|
||||
size_t elemSize1() const;
|
||||
//! returns element type, similar to CV_MAT_TYPE(cvMat->type)
|
||||
int type() const;
|
||||
//! returns element type, similar to CV_MAT_DEPTH(cvMat->type)
|
||||
int depth() const;
|
||||
//! returns element type, similar to CV_MAT_CN(cvMat->type)
|
||||
int channels() const;
|
||||
//! returns step/elemSize1()
|
||||
size_t step1() const;
|
||||
//! returns GpuMatrix size:
|
||||
// width == number of columns, height == number of rows
|
||||
Size size() const;
|
||||
//! returns true if GpuMatrix data is NULL
|
||||
bool empty() const;
|
||||
|
||||
//! returns pointer to y-th row
|
||||
uchar* ptr(int y = 0);
|
||||
const uchar* ptr(int y = 0) const;
|
||||
|
||||
//! template version of the above method
|
||||
template<typename _Tp> _Tp* ptr(int y = 0);
|
||||
template<typename _Tp> const _Tp* ptr(int y = 0) const;
|
||||
|
||||
template <typename _Tp> operator PtrStepSz<_Tp>() const;
|
||||
template <typename _Tp> operator PtrStep<_Tp>() const;
|
||||
|
||||
// Deprecated function
|
||||
__CV_GPU_DEPR_BEFORE__ template <typename _Tp> operator DevMem2D_<_Tp>() const __CV_GPU_DEPR_AFTER__;
|
||||
__CV_GPU_DEPR_BEFORE__ template <typename _Tp> operator PtrStep_<_Tp>() const __CV_GPU_DEPR_AFTER__;
|
||||
#undef __CV_GPU_DEPR_BEFORE__
|
||||
#undef __CV_GPU_DEPR_AFTER__
|
||||
|
||||
/*! includes several bit-fields:
|
||||
- the magic signature
|
||||
- continuity flag
|
||||
- depth
|
||||
- number of channels
|
||||
*/
|
||||
int flags;
|
||||
|
||||
//! the number of rows and columns
|
||||
int rows, cols;
|
||||
|
||||
//! a distance between successive rows in bytes; includes the gap if any
|
||||
size_t step;
|
||||
|
||||
//! pointer to the data
|
||||
uchar* data;
|
||||
|
||||
//! pointer to the reference counter;
|
||||
// when GpuMatrix points to user-allocated data, the pointer is NULL
|
||||
int* refcount;
|
||||
|
||||
//! helper fields used in locateROI and adjustROI
|
||||
uchar* datastart;
|
||||
uchar* dataend;
|
||||
};
|
||||
|
||||
//! Creates continuous GPU matrix
|
||||
CV_EXPORTS void createContinuous(int rows, int cols, int type, GpuMat& m);
|
||||
CV_EXPORTS GpuMat createContinuous(int rows, int cols, int type);
|
||||
CV_EXPORTS void createContinuous(Size size, int type, GpuMat& m);
|
||||
CV_EXPORTS GpuMat createContinuous(Size size, int type);
|
||||
|
||||
//! Ensures that size of the given matrix is not less than (rows, cols) size
|
||||
//! and matrix type is match specified one too
|
||||
CV_EXPORTS void ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m);
|
||||
CV_EXPORTS void ensureSizeIsEnough(Size size, int type, GpuMat& m);
|
||||
|
||||
CV_EXPORTS GpuMat allocMatFromBuf(int rows, int cols, int type, GpuMat &mat);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Error handling
|
||||
|
||||
CV_EXPORTS void error(const char* error_string, const char* file, const int line, const char* func = "");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline GpuMat::GpuMat()
|
||||
: flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline GpuMat::GpuMat(int rows_, int cols_, int type_)
|
||||
: flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
|
||||
{
|
||||
if (rows_ > 0 && cols_ > 0)
|
||||
create(rows_, cols_, type_);
|
||||
}
|
||||
|
||||
inline GpuMat::GpuMat(Size size_, int type_)
|
||||
: flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
|
||||
{
|
||||
if (size_.height > 0 && size_.width > 0)
|
||||
create(size_.height, size_.width, type_);
|
||||
}
|
||||
|
||||
inline GpuMat::GpuMat(int rows_, int cols_, int type_, Scalar s_)
|
||||
: flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
|
||||
{
|
||||
if (rows_ > 0 && cols_ > 0)
|
||||
{
|
||||
create(rows_, cols_, type_);
|
||||
setTo(s_);
|
||||
}
|
||||
}
|
||||
|
||||
inline GpuMat::GpuMat(Size size_, int type_, Scalar s_)
|
||||
: flags(0), rows(0), cols(0), step(0), data(0), refcount(0), datastart(0), dataend(0)
|
||||
{
|
||||
if (size_.height > 0 && size_.width > 0)
|
||||
{
|
||||
create(size_.height, size_.width, type_);
|
||||
setTo(s_);
|
||||
}
|
||||
}
|
||||
|
||||
inline GpuMat::~GpuMat()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::clone() const
|
||||
{
|
||||
GpuMat m;
|
||||
copyTo(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
inline void GpuMat::assignTo(GpuMat& m, int _type) const
|
||||
{
|
||||
if (_type < 0)
|
||||
m = *this;
|
||||
else
|
||||
convertTo(m, _type);
|
||||
}
|
||||
|
||||
inline size_t GpuMat::step1() const
|
||||
{
|
||||
return step / elemSize1();
|
||||
}
|
||||
|
||||
inline bool GpuMat::empty() const
|
||||
{
|
||||
return data == 0;
|
||||
}
|
||||
|
||||
template<typename _Tp> inline _Tp* GpuMat::ptr(int y)
|
||||
{
|
||||
return (_Tp*)ptr(y);
|
||||
}
|
||||
|
||||
template<typename _Tp> inline const _Tp* GpuMat::ptr(int y) const
|
||||
{
|
||||
return (const _Tp*)ptr(y);
|
||||
}
|
||||
|
||||
inline void swap(GpuMat& a, GpuMat& b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::row(int y) const
|
||||
{
|
||||
return GpuMat(*this, Range(y, y+1), Range::all());
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::col(int x) const
|
||||
{
|
||||
return GpuMat(*this, Range::all(), Range(x, x+1));
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::rowRange(int startrow, int endrow) const
|
||||
{
|
||||
return GpuMat(*this, Range(startrow, endrow), Range::all());
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::rowRange(Range r) const
|
||||
{
|
||||
return GpuMat(*this, r, Range::all());
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::colRange(int startcol, int endcol) const
|
||||
{
|
||||
return GpuMat(*this, Range::all(), Range(startcol, endcol));
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::colRange(Range r) const
|
||||
{
|
||||
return GpuMat(*this, Range::all(), r);
|
||||
}
|
||||
|
||||
inline void GpuMat::create(Size size_, int type_)
|
||||
{
|
||||
create(size_.height, size_.width, type_);
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::operator()(Range _rowRange, Range _colRange) const
|
||||
{
|
||||
return GpuMat(*this, _rowRange, _colRange);
|
||||
}
|
||||
|
||||
inline GpuMat GpuMat::operator()(Rect roi) const
|
||||
{
|
||||
return GpuMat(*this, roi);
|
||||
}
|
||||
|
||||
inline bool GpuMat::isContinuous() const
|
||||
{
|
||||
return (flags & Mat::CONTINUOUS_FLAG) != 0;
|
||||
}
|
||||
|
||||
inline size_t GpuMat::elemSize() const
|
||||
{
|
||||
return CV_ELEM_SIZE(flags);
|
||||
}
|
||||
|
||||
inline size_t GpuMat::elemSize1() const
|
||||
{
|
||||
return CV_ELEM_SIZE1(flags);
|
||||
}
|
||||
|
||||
inline int GpuMat::type() const
|
||||
{
|
||||
return CV_MAT_TYPE(flags);
|
||||
}
|
||||
|
||||
inline int GpuMat::depth() const
|
||||
{
|
||||
return CV_MAT_DEPTH(flags);
|
||||
}
|
||||
|
||||
inline int GpuMat::channels() const
|
||||
{
|
||||
return CV_MAT_CN(flags);
|
||||
}
|
||||
|
||||
inline Size GpuMat::size() const
|
||||
{
|
||||
return Size(cols, rows);
|
||||
}
|
||||
|
||||
inline uchar* GpuMat::ptr(int y)
|
||||
{
|
||||
CV_DbgAssert((unsigned)y < (unsigned)rows);
|
||||
return data + step * y;
|
||||
}
|
||||
|
||||
inline const uchar* GpuMat::ptr(int y) const
|
||||
{
|
||||
CV_DbgAssert((unsigned)y < (unsigned)rows);
|
||||
return data + step * y;
|
||||
}
|
||||
|
||||
inline GpuMat& GpuMat::operator = (Scalar s)
|
||||
{
|
||||
setTo(s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T> inline GpuMat::operator PtrStepSz<T>() const
|
||||
{
|
||||
return PtrStepSz<T>(rows, cols, (T*)data, step);
|
||||
}
|
||||
|
||||
template <class T> inline GpuMat::operator PtrStep<T>() const
|
||||
{
|
||||
return PtrStep<T>((T*)data, step);
|
||||
}
|
||||
|
||||
template <class T> inline GpuMat::operator DevMem2D_<T>() const
|
||||
{
|
||||
return DevMem2D_<T>(rows, cols, (T*)data, step);
|
||||
}
|
||||
|
||||
template <class T> inline GpuMat::operator PtrStep_<T>() const
|
||||
{
|
||||
return PtrStep_<T>(static_cast< DevMem2D_<T> >(*this));
|
||||
}
|
||||
|
||||
inline GpuMat createContinuous(int rows, int cols, int type)
|
||||
{
|
||||
GpuMat m;
|
||||
createContinuous(rows, cols, type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
inline void createContinuous(Size size, int type, GpuMat& m)
|
||||
{
|
||||
createContinuous(size.height, size.width, type, m);
|
||||
}
|
||||
|
||||
inline GpuMat createContinuous(Size size, int type)
|
||||
{
|
||||
GpuMat m;
|
||||
createContinuous(size, type, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
inline void ensureSizeIsEnough(Size size, int type, GpuMat& m)
|
||||
{
|
||||
ensureSizeIsEnough(size.height, size.width, type, m);
|
||||
}
|
||||
}}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __OPENCV_GPUMAT_HPP__
|
||||
@@ -0,0 +1,781 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/* The header is for internal use and it is likely to change.
|
||||
It contains some macro definitions that are used in cxcore, cv, cvaux
|
||||
and, probably, other libraries. If you need some of this functionality,
|
||||
the safe way is to copy it into your code and rename the macros.
|
||||
*/
|
||||
#ifndef __OPENCV_CORE_INTERNAL_HPP__
|
||||
#define __OPENCV_CORE_INTERNAL_HPP__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/core/types_c.h"
|
||||
|
||||
#if defined WIN32 || defined _WIN32
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
# ifndef _WIN32
|
||||
# define _WIN32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined WIN32 && !defined WINCE
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
# ifndef _WIN32
|
||||
# define _WIN32
|
||||
# endif
|
||||
# define CV_DLL
|
||||
# undef _CV_ALWAYS_PROFILE_
|
||||
# define _CV_ALWAYS_NO_PROFILE_
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
# define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
#endif
|
||||
|
||||
#define __BEGIN__ __CV_BEGIN__
|
||||
#define __END__ __CV_END__
|
||||
#define EXIT __CV_EXIT__
|
||||
|
||||
#ifdef HAVE_IPP
|
||||
# include "ipp.h"
|
||||
|
||||
CV_INLINE IppiSize ippiSize(int width, int height)
|
||||
{
|
||||
IppiSize size = { width, height };
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef IPPI_CALL
|
||||
# define IPPI_CALL(func) CV_Assert((func) >= 0)
|
||||
#endif
|
||||
|
||||
#if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
|
||||
# include "emmintrin.h"
|
||||
# define CV_SSE 1
|
||||
# define CV_SSE2 1
|
||||
# if defined __SSE3__ || (defined _MSC_VER && _MSC_VER >= 1500)
|
||||
# include "pmmintrin.h"
|
||||
# define CV_SSE3 1
|
||||
# endif
|
||||
# if defined __SSSE3__ || (defined _MSC_VER && _MSC_VER >= 1500)
|
||||
# include "tmmintrin.h"
|
||||
# define CV_SSSE3 1
|
||||
# endif
|
||||
# if defined __SSE4_1__ || (defined _MSC_VER && _MSC_VER >= 1500)
|
||||
# include <smmintrin.h>
|
||||
# define CV_SSE4_1 1
|
||||
# endif
|
||||
# if defined __SSE4_2__ || (defined _MSC_VER && _MSC_VER >= 1500)
|
||||
# include <nmmintrin.h>
|
||||
# define CV_SSE4_2 1
|
||||
# endif
|
||||
# if defined __AVX__ || (defined _MSC_FULL_VER && _MSC_FULL_VER >= 160040219)
|
||||
// MS Visual Studio 2010 (2012?) has no macro pre-defined to identify the use of /arch:AVX
|
||||
// See: http://connect.microsoft.com/VisualStudio/feedback/details/605858/arch-avx-should-define-a-predefined-macro-in-x64-and-set-a-unique-value-for-m-ix86-fp-in-win32
|
||||
# include <immintrin.h>
|
||||
# define CV_AVX 1
|
||||
# if defined(_XCR_XFEATURE_ENABLED_MASK)
|
||||
# define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK)
|
||||
# else
|
||||
# define __xgetbv() 0
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if (defined WIN32 || defined _WIN32) && defined(_M_ARM)
|
||||
# include <Intrin.h>
|
||||
# include "arm_neon.h"
|
||||
# define CV_NEON 1
|
||||
# define CPU_HAS_NEON_FEATURE (true)
|
||||
#elif defined(__ARM_NEON__)
|
||||
# include <arm_neon.h>
|
||||
# define CV_NEON 1
|
||||
# define CPU_HAS_NEON_FEATURE (true)
|
||||
#endif
|
||||
|
||||
#ifndef CV_SSE
|
||||
# define CV_SSE 0
|
||||
#endif
|
||||
#ifndef CV_SSE2
|
||||
# define CV_SSE2 0
|
||||
#endif
|
||||
#ifndef CV_SSE3
|
||||
# define CV_SSE3 0
|
||||
#endif
|
||||
#ifndef CV_SSSE3
|
||||
# define CV_SSSE3 0
|
||||
#endif
|
||||
#ifndef CV_SSE4_1
|
||||
# define CV_SSE4_1 0
|
||||
#endif
|
||||
#ifndef CV_SSE4_2
|
||||
# define CV_SSE4_2 0
|
||||
#endif
|
||||
#ifndef CV_AVX
|
||||
# define CV_AVX 0
|
||||
#endif
|
||||
#ifndef CV_NEON
|
||||
# define CV_NEON 0
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
# include "tbb/tbb_stddef.h"
|
||||
# if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202
|
||||
# include "tbb/tbb.h"
|
||||
# include "tbb/task.h"
|
||||
# undef min
|
||||
# undef max
|
||||
# else
|
||||
# undef HAVE_TBB
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EIGEN
|
||||
# if defined __GNUC__ && defined __APPLE__
|
||||
# pragma GCC diagnostic ignored "-Wshadow"
|
||||
# endif
|
||||
# include <Eigen/Core>
|
||||
# include "opencv2/core/eigen.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace cv
|
||||
{
|
||||
#ifdef HAVE_TBB
|
||||
|
||||
typedef tbb::blocked_range<int> BlockedRange;
|
||||
|
||||
template<typename Body> static inline
|
||||
void parallel_for( const BlockedRange& range, const Body& body )
|
||||
{
|
||||
tbb::parallel_for(range, body);
|
||||
}
|
||||
|
||||
template<typename Iterator, typename Body> static inline
|
||||
void parallel_do( Iterator first, Iterator last, const Body& body )
|
||||
{
|
||||
tbb::parallel_do(first, last, body);
|
||||
}
|
||||
|
||||
typedef tbb::split Split;
|
||||
|
||||
template<typename Body> static inline
|
||||
void parallel_reduce( const BlockedRange& range, Body& body )
|
||||
{
|
||||
tbb::parallel_reduce(range, body);
|
||||
}
|
||||
|
||||
typedef tbb::concurrent_vector<Rect> ConcurrentRectVector;
|
||||
typedef tbb::concurrent_vector<double> ConcurrentDoubleVector;
|
||||
#else
|
||||
class BlockedRange
|
||||
{
|
||||
public:
|
||||
BlockedRange() : _begin(0), _end(0), _grainsize(0) {}
|
||||
BlockedRange(int b, int e, int g=1) : _begin(b), _end(e), _grainsize(g) {}
|
||||
int begin() const { return _begin; }
|
||||
int end() const { return _end; }
|
||||
int grainsize() const { return _grainsize; }
|
||||
|
||||
protected:
|
||||
int _begin, _end, _grainsize;
|
||||
};
|
||||
|
||||
template<typename Body> static inline
|
||||
void parallel_for( const BlockedRange& range, const Body& body )
|
||||
{
|
||||
body(range);
|
||||
}
|
||||
typedef std::vector<Rect> ConcurrentRectVector;
|
||||
typedef std::vector<double> ConcurrentDoubleVector;
|
||||
|
||||
template<typename Iterator, typename Body> static inline
|
||||
void parallel_do( Iterator first, Iterator last, const Body& body )
|
||||
{
|
||||
for( ; first != last; ++first )
|
||||
body(*first);
|
||||
}
|
||||
|
||||
class Split {};
|
||||
|
||||
template<typename Body> static inline
|
||||
void parallel_reduce( const BlockedRange& range, Body& body )
|
||||
{
|
||||
body(range);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns a static string if there is a parallel framework,
|
||||
// NULL otherwise.
|
||||
CV_EXPORTS const char* currentParallelFramework();
|
||||
} //namespace cv
|
||||
|
||||
#define CV_INIT_ALGORITHM(classname, algname, memberinit) \
|
||||
static ::cv::Algorithm* create##classname() \
|
||||
{ \
|
||||
return new classname; \
|
||||
} \
|
||||
\
|
||||
static ::cv::AlgorithmInfo& classname##_info() \
|
||||
{ \
|
||||
static ::cv::AlgorithmInfo classname##_info_var(algname, create##classname); \
|
||||
return classname##_info_var; \
|
||||
} \
|
||||
\
|
||||
static ::cv::AlgorithmInfo& classname##_info_auto = classname##_info(); \
|
||||
\
|
||||
::cv::AlgorithmInfo* classname::info() const \
|
||||
{ \
|
||||
static volatile bool initialized = false; \
|
||||
\
|
||||
if( !initialized ) \
|
||||
{ \
|
||||
initialized = true; \
|
||||
classname obj; \
|
||||
memberinit; \
|
||||
} \
|
||||
return &classname##_info(); \
|
||||
}
|
||||
|
||||
#endif //__cplusplus
|
||||
|
||||
/* maximal size of vector to run matrix operations on it inline (i.e. w/o ipp calls) */
|
||||
#define CV_MAX_INLINE_MAT_OP_SIZE 10
|
||||
|
||||
/* maximal linear size of matrix to allocate it on stack. */
|
||||
#define CV_MAX_LOCAL_MAT_SIZE 32
|
||||
|
||||
/* maximal size of local memory storage */
|
||||
#define CV_MAX_LOCAL_SIZE \
|
||||
(CV_MAX_LOCAL_MAT_SIZE*CV_MAX_LOCAL_MAT_SIZE*(int)sizeof(double))
|
||||
|
||||
/* default image row align (in bytes) */
|
||||
#define CV_DEFAULT_IMAGE_ROW_ALIGN 4
|
||||
|
||||
/* matrices are continuous by default */
|
||||
#define CV_DEFAULT_MAT_ROW_ALIGN 1
|
||||
|
||||
/* maximum size of dynamic memory buffer.
|
||||
cvAlloc reports an error if a larger block is requested. */
|
||||
#define CV_MAX_ALLOC_SIZE (((size_t)1 << (sizeof(size_t)*8-2)))
|
||||
|
||||
/* the alignment of all the allocated buffers */
|
||||
#define CV_MALLOC_ALIGN 16
|
||||
|
||||
/* default alignment for dynamic data strucutures, resided in storages. */
|
||||
#define CV_STRUCT_ALIGN ((int)sizeof(double))
|
||||
|
||||
/* default storage block size */
|
||||
#define CV_STORAGE_BLOCK_SIZE ((1<<16) - 128)
|
||||
|
||||
/* default memory block for sparse array elements */
|
||||
#define CV_SPARSE_MAT_BLOCK (1<<12)
|
||||
|
||||
/* initial hash table size */
|
||||
#define CV_SPARSE_HASH_SIZE0 (1<<10)
|
||||
|
||||
/* maximal average node_count/hash_size ratio beyond which hash table is resized */
|
||||
#define CV_SPARSE_HASH_RATIO 3
|
||||
|
||||
/* max length of strings */
|
||||
#define CV_MAX_STRLEN 1024
|
||||
|
||||
#if 0 /*def CV_CHECK_FOR_NANS*/
|
||||
# define CV_CHECK_NANS( arr ) cvCheckArray((arr))
|
||||
#else
|
||||
# define CV_CHECK_NANS( arr )
|
||||
#endif
|
||||
|
||||
/****************************************************************************************\
|
||||
* Common declarations *
|
||||
\****************************************************************************************/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define CV_DECL_ALIGNED(x) __attribute__ ((aligned (x)))
|
||||
#elif defined _MSC_VER
|
||||
# define CV_DECL_ALIGNED(x) __declspec(align(x))
|
||||
#else
|
||||
# define CV_DECL_ALIGNED(x)
|
||||
#endif
|
||||
|
||||
#ifndef CV_IMPL
|
||||
# define CV_IMPL CV_EXTERN_C
|
||||
#endif
|
||||
|
||||
#define CV_DBG_BREAK() { volatile int* crashMe = 0; *crashMe = 0; }
|
||||
|
||||
/* default step, set in case of continuous data
|
||||
to work around checks for valid step in some ipp functions */
|
||||
#define CV_STUB_STEP (1 << 30)
|
||||
|
||||
#define CV_SIZEOF_FLOAT ((int)sizeof(float))
|
||||
#define CV_SIZEOF_SHORT ((int)sizeof(short))
|
||||
|
||||
#define CV_ORIGIN_TL 0
|
||||
#define CV_ORIGIN_BL 1
|
||||
|
||||
/* IEEE754 constants and macros */
|
||||
#define CV_POS_INF 0x7f800000
|
||||
#define CV_NEG_INF 0x807fffff /* CV_TOGGLE_FLT(0xff800000) */
|
||||
#define CV_1F 0x3f800000
|
||||
#define CV_TOGGLE_FLT(x) ((x)^((int)(x) < 0 ? 0x7fffffff : 0))
|
||||
#define CV_TOGGLE_DBL(x) \
|
||||
((x)^((int64)(x) < 0 ? CV_BIG_INT(0x7fffffffffffffff) : 0))
|
||||
|
||||
#define CV_NOP(a) (a)
|
||||
#define CV_ADD(a, b) ((a) + (b))
|
||||
#define CV_SUB(a, b) ((a) - (b))
|
||||
#define CV_MUL(a, b) ((a) * (b))
|
||||
#define CV_AND(a, b) ((a) & (b))
|
||||
#define CV_OR(a, b) ((a) | (b))
|
||||
#define CV_XOR(a, b) ((a) ^ (b))
|
||||
#define CV_ANDN(a, b) (~(a) & (b))
|
||||
#define CV_ORN(a, b) (~(a) | (b))
|
||||
#define CV_SQR(a) ((a) * (a))
|
||||
|
||||
#define CV_LT(a, b) ((a) < (b))
|
||||
#define CV_LE(a, b) ((a) <= (b))
|
||||
#define CV_EQ(a, b) ((a) == (b))
|
||||
#define CV_NE(a, b) ((a) != (b))
|
||||
#define CV_GT(a, b) ((a) > (b))
|
||||
#define CV_GE(a, b) ((a) >= (b))
|
||||
|
||||
#define CV_NONZERO(a) ((a) != 0)
|
||||
#define CV_NONZERO_FLT(a) (((a)+(a)) != 0)
|
||||
|
||||
/* general-purpose saturation macros */
|
||||
#define CV_CAST_8U(t) (uchar)(!((t) & ~255) ? (t) : (t) > 0 ? 255 : 0)
|
||||
#define CV_CAST_8S(t) (schar)(!(((t)+128) & ~255) ? (t) : (t) > 0 ? 127 : -128)
|
||||
#define CV_CAST_16U(t) (ushort)(!((t) & ~65535) ? (t) : (t) > 0 ? 65535 : 0)
|
||||
#define CV_CAST_16S(t) (short)(!(((t)+32768) & ~65535) ? (t) : (t) > 0 ? 32767 : -32768)
|
||||
#define CV_CAST_32S(t) (int)(t)
|
||||
#define CV_CAST_64S(t) (int64)(t)
|
||||
#define CV_CAST_32F(t) (float)(t)
|
||||
#define CV_CAST_64F(t) (double)(t)
|
||||
|
||||
#define CV_PASTE2(a,b) a##b
|
||||
#define CV_PASTE(a,b) CV_PASTE2(a,b)
|
||||
|
||||
#define CV_EMPTY
|
||||
#define CV_MAKE_STR(a) #a
|
||||
|
||||
#define CV_ZERO_OBJ(x) memset((x), 0, sizeof(*(x)))
|
||||
|
||||
#define CV_DIM(static_array) ((int)(sizeof(static_array)/sizeof((static_array)[0])))
|
||||
|
||||
#define cvUnsupportedFormat "Unsupported format"
|
||||
|
||||
CV_INLINE void* cvAlignPtr( const void* ptr, int align CV_DEFAULT(32) )
|
||||
{
|
||||
assert( (align & (align-1)) == 0 );
|
||||
return (void*)( ((size_t)ptr + align - 1) & ~(size_t)(align-1) );
|
||||
}
|
||||
|
||||
CV_INLINE int cvAlign( int size, int align )
|
||||
{
|
||||
assert( (align & (align-1)) == 0 && size < INT_MAX );
|
||||
return (size + align - 1) & -align;
|
||||
}
|
||||
|
||||
CV_INLINE CvSize cvGetMatSize( const CvMat* mat )
|
||||
{
|
||||
CvSize size;
|
||||
size.width = mat->cols;
|
||||
size.height = mat->rows;
|
||||
return size;
|
||||
}
|
||||
|
||||
#define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))
|
||||
#define CV_FLT_TO_FIX(x,n) cvRound((x)*(1<<(n)))
|
||||
|
||||
/****************************************************************************************\
|
||||
|
||||
Generic implementation of QuickSort algorithm.
|
||||
----------------------------------------------
|
||||
Using this macro user can declare customized sort function that can be much faster
|
||||
than built-in qsort function because of lower overhead on elements
|
||||
comparison and exchange. The macro takes less_than (or LT) argument - a macro or function
|
||||
that takes 2 arguments returns non-zero if the first argument should be before the second
|
||||
one in the sorted sequence and zero otherwise.
|
||||
|
||||
Example:
|
||||
|
||||
Suppose that the task is to sort points by ascending of y coordinates and if
|
||||
y's are equal x's should ascend.
|
||||
|
||||
The code is:
|
||||
------------------------------------------------------------------------------
|
||||
#define cmp_pts( pt1, pt2 ) \
|
||||
((pt1).y < (pt2).y || ((pt1).y < (pt2).y && (pt1).x < (pt2).x))
|
||||
|
||||
[static] CV_IMPLEMENT_QSORT( icvSortPoints, CvPoint, cmp_pts )
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
After that the function "void icvSortPoints( CvPoint* array, size_t total, int aux );"
|
||||
is available to user.
|
||||
|
||||
aux is an additional parameter, which can be used when comparing elements.
|
||||
The current implementation was derived from *BSD system qsort():
|
||||
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
|
||||
\****************************************************************************************/
|
||||
|
||||
#define CV_IMPLEMENT_QSORT_EX( func_name, T, LT, user_data_type ) \
|
||||
void func_name( T *array, size_t total, user_data_type aux ) \
|
||||
{ \
|
||||
int isort_thresh = 7; \
|
||||
T t; \
|
||||
int sp = 0; \
|
||||
\
|
||||
struct \
|
||||
{ \
|
||||
T *lb; \
|
||||
T *ub; \
|
||||
} \
|
||||
stack[48]; \
|
||||
\
|
||||
aux = aux; \
|
||||
\
|
||||
if( total <= 1 ) \
|
||||
return; \
|
||||
\
|
||||
stack[0].lb = array; \
|
||||
stack[0].ub = array + (total - 1); \
|
||||
\
|
||||
while( sp >= 0 ) \
|
||||
{ \
|
||||
T* left = stack[sp].lb; \
|
||||
T* right = stack[sp--].ub; \
|
||||
\
|
||||
for(;;) \
|
||||
{ \
|
||||
int i, n = (int)(right - left) + 1, m; \
|
||||
T* ptr; \
|
||||
T* ptr2; \
|
||||
\
|
||||
if( n <= isort_thresh ) \
|
||||
{ \
|
||||
insert_sort: \
|
||||
for( ptr = left + 1; ptr <= right; ptr++ ) \
|
||||
{ \
|
||||
for( ptr2 = ptr; ptr2 > left && LT(ptr2[0],ptr2[-1]); ptr2--) \
|
||||
CV_SWAP( ptr2[0], ptr2[-1], t ); \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
T* left0; \
|
||||
T* left1; \
|
||||
T* right0; \
|
||||
T* right1; \
|
||||
T* pivot; \
|
||||
T* a; \
|
||||
T* b; \
|
||||
T* c; \
|
||||
int swap_cnt = 0; \
|
||||
\
|
||||
left0 = left; \
|
||||
right0 = right; \
|
||||
pivot = left + (n/2); \
|
||||
\
|
||||
if( n > 40 ) \
|
||||
{ \
|
||||
int d = n / 8; \
|
||||
a = left, b = left + d, c = left + 2*d; \
|
||||
left = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \
|
||||
: (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \
|
||||
\
|
||||
a = pivot - d, b = pivot, c = pivot + d; \
|
||||
pivot = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \
|
||||
: (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \
|
||||
\
|
||||
a = right - 2*d, b = right - d, c = right; \
|
||||
right = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \
|
||||
: (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \
|
||||
} \
|
||||
\
|
||||
a = left, b = pivot, c = right; \
|
||||
pivot = LT(*a, *b) ? (LT(*b, *c) ? b : (LT(*a, *c) ? c : a)) \
|
||||
: (LT(*c, *b) ? b : (LT(*a, *c) ? a : c)); \
|
||||
if( pivot != left0 ) \
|
||||
{ \
|
||||
CV_SWAP( *pivot, *left0, t ); \
|
||||
pivot = left0; \
|
||||
} \
|
||||
left = left1 = left0 + 1; \
|
||||
right = right1 = right0; \
|
||||
\
|
||||
for(;;) \
|
||||
{ \
|
||||
while( left <= right && !LT(*pivot, *left) ) \
|
||||
{ \
|
||||
if( !LT(*left, *pivot) ) \
|
||||
{ \
|
||||
if( left > left1 ) \
|
||||
CV_SWAP( *left1, *left, t ); \
|
||||
swap_cnt = 1; \
|
||||
left1++; \
|
||||
} \
|
||||
left++; \
|
||||
} \
|
||||
\
|
||||
while( left <= right && !LT(*right, *pivot) ) \
|
||||
{ \
|
||||
if( !LT(*pivot, *right) ) \
|
||||
{ \
|
||||
if( right < right1 ) \
|
||||
CV_SWAP( *right1, *right, t ); \
|
||||
swap_cnt = 1; \
|
||||
right1--; \
|
||||
} \
|
||||
right--; \
|
||||
} \
|
||||
\
|
||||
if( left > right ) \
|
||||
break; \
|
||||
CV_SWAP( *left, *right, t ); \
|
||||
swap_cnt = 1; \
|
||||
left++; \
|
||||
right--; \
|
||||
} \
|
||||
\
|
||||
if( swap_cnt == 0 ) \
|
||||
{ \
|
||||
left = left0, right = right0; \
|
||||
goto insert_sort; \
|
||||
} \
|
||||
\
|
||||
n = MIN( (int)(left1 - left0), (int)(left - left1) ); \
|
||||
for( i = 0; i < n; i++ ) \
|
||||
CV_SWAP( left0[i], left[i-n], t ); \
|
||||
\
|
||||
n = MIN( (int)(right0 - right1), (int)(right1 - right) ); \
|
||||
for( i = 0; i < n; i++ ) \
|
||||
CV_SWAP( left[i], right0[i-n+1], t ); \
|
||||
n = (int)(left - left1); \
|
||||
m = (int)(right1 - right); \
|
||||
if( n > 1 ) \
|
||||
{ \
|
||||
if( m > 1 ) \
|
||||
{ \
|
||||
if( n > m ) \
|
||||
{ \
|
||||
stack[++sp].lb = left0; \
|
||||
stack[sp].ub = left0 + n - 1; \
|
||||
left = right0 - m + 1, right = right0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
stack[++sp].lb = right0 - m + 1; \
|
||||
stack[sp].ub = right0; \
|
||||
left = left0, right = left0 + n - 1; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
left = left0, right = left0 + n - 1; \
|
||||
} \
|
||||
else if( m > 1 ) \
|
||||
left = right0 - m + 1, right = right0; \
|
||||
else \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CV_IMPLEMENT_QSORT( func_name, T, cmp ) \
|
||||
CV_IMPLEMENT_QSORT_EX( func_name, T, cmp, int )
|
||||
|
||||
/****************************************************************************************\
|
||||
* Structures and macros for integration with IPP *
|
||||
\****************************************************************************************/
|
||||
|
||||
/* IPP-compatible return codes */
|
||||
typedef enum CvStatus
|
||||
{
|
||||
CV_BADMEMBLOCK_ERR = -113,
|
||||
CV_INPLACE_NOT_SUPPORTED_ERR= -112,
|
||||
CV_UNMATCHED_ROI_ERR = -111,
|
||||
CV_NOTFOUND_ERR = -110,
|
||||
CV_BADCONVERGENCE_ERR = -109,
|
||||
|
||||
CV_BADDEPTH_ERR = -107,
|
||||
CV_BADROI_ERR = -106,
|
||||
CV_BADHEADER_ERR = -105,
|
||||
CV_UNMATCHED_FORMATS_ERR = -104,
|
||||
CV_UNSUPPORTED_COI_ERR = -103,
|
||||
CV_UNSUPPORTED_CHANNELS_ERR = -102,
|
||||
CV_UNSUPPORTED_DEPTH_ERR = -101,
|
||||
CV_UNSUPPORTED_FORMAT_ERR = -100,
|
||||
|
||||
CV_BADARG_ERR = -49, //ipp comp
|
||||
CV_NOTDEFINED_ERR = -48, //ipp comp
|
||||
|
||||
CV_BADCHANNELS_ERR = -47, //ipp comp
|
||||
CV_BADRANGE_ERR = -44, //ipp comp
|
||||
CV_BADSTEP_ERR = -29, //ipp comp
|
||||
|
||||
CV_BADFLAG_ERR = -12,
|
||||
CV_DIV_BY_ZERO_ERR = -11, //ipp comp
|
||||
CV_BADCOEF_ERR = -10,
|
||||
|
||||
CV_BADFACTOR_ERR = -7,
|
||||
CV_BADPOINT_ERR = -6,
|
||||
CV_BADSCALE_ERR = -4,
|
||||
CV_OUTOFMEM_ERR = -3,
|
||||
CV_NULLPTR_ERR = -2,
|
||||
CV_BADSIZE_ERR = -1,
|
||||
CV_NO_ERR = 0,
|
||||
CV_OK = CV_NO_ERR
|
||||
}
|
||||
CvStatus;
|
||||
|
||||
#define CV_NOTHROW throw()
|
||||
|
||||
typedef struct CvFuncTable
|
||||
{
|
||||
void* fn_2d[CV_DEPTH_MAX];
|
||||
}
|
||||
CvFuncTable;
|
||||
|
||||
typedef struct CvBigFuncTable
|
||||
{
|
||||
void* fn_2d[CV_DEPTH_MAX*4];
|
||||
} CvBigFuncTable;
|
||||
|
||||
#define CV_INIT_FUNC_TAB( tab, FUNCNAME, FLAG ) \
|
||||
(tab).fn_2d[CV_8U] = (void*)FUNCNAME##_8u##FLAG; \
|
||||
(tab).fn_2d[CV_8S] = 0; \
|
||||
(tab).fn_2d[CV_16U] = (void*)FUNCNAME##_16u##FLAG; \
|
||||
(tab).fn_2d[CV_16S] = (void*)FUNCNAME##_16s##FLAG; \
|
||||
(tab).fn_2d[CV_32S] = (void*)FUNCNAME##_32s##FLAG; \
|
||||
(tab).fn_2d[CV_32F] = (void*)FUNCNAME##_32f##FLAG; \
|
||||
(tab).fn_2d[CV_64F] = (void*)FUNCNAME##_64f##FLAG
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// < Deprecated
|
||||
|
||||
class CV_EXPORTS CvOpenGlFuncTab
|
||||
{
|
||||
public:
|
||||
virtual ~CvOpenGlFuncTab();
|
||||
|
||||
virtual void genBuffers(int n, unsigned int* buffers) const = 0;
|
||||
virtual void deleteBuffers(int n, const unsigned int* buffers) const = 0;
|
||||
|
||||
virtual void bufferData(unsigned int target, ptrdiff_t size, const void* data, unsigned int usage) const = 0;
|
||||
virtual void bufferSubData(unsigned int target, ptrdiff_t offset, ptrdiff_t size, const void* data) const = 0;
|
||||
|
||||
virtual void bindBuffer(unsigned int target, unsigned int buffer) const = 0;
|
||||
|
||||
virtual void* mapBuffer(unsigned int target, unsigned int access) const = 0;
|
||||
virtual void unmapBuffer(unsigned int target) const = 0;
|
||||
|
||||
virtual void generateBitmapFont(const std::string& family, int height, int weight, bool italic, bool underline, int start, int count, int base) const = 0;
|
||||
|
||||
virtual bool isGlContextInitialized() const = 0;
|
||||
};
|
||||
|
||||
CV_EXPORTS void icvSetOpenGlFuncTab(const CvOpenGlFuncTab* tab);
|
||||
|
||||
CV_EXPORTS bool icvCheckGlError(const char* file, const int line, const char* func = "");
|
||||
|
||||
// >
|
||||
|
||||
namespace cv { namespace ogl {
|
||||
CV_EXPORTS bool checkError(const char* file, const int line, const char* func = "");
|
||||
}}
|
||||
|
||||
#define CV_CheckGlError() CV_DbgAssert( (cv::ogl::checkError(__FILE__, __LINE__, CV_Func)) )
|
||||
|
||||
#endif //__cplusplus
|
||||
|
||||
#endif // __OPENCV_CORE_INTERNAL_HPP__
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,284 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OPENGL_INTEROP_HPP__
|
||||
#define __OPENCV_OPENGL_INTEROP_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/core/opengl_interop_deprecated.hpp"
|
||||
|
||||
namespace cv { namespace ogl {
|
||||
|
||||
/////////////////// OpenGL Objects ///////////////////
|
||||
|
||||
//! Smart pointer for OpenGL buffer memory with reference counting.
|
||||
class CV_EXPORTS Buffer
|
||||
{
|
||||
public:
|
||||
enum Target
|
||||
{
|
||||
ARRAY_BUFFER = 0x8892, //!< The buffer will be used as a source for vertex data
|
||||
ELEMENT_ARRAY_BUFFER = 0x8893, //!< The buffer will be used for indices (in glDrawElements, for example)
|
||||
PIXEL_PACK_BUFFER = 0x88EB, //!< The buffer will be used for reading from OpenGL textures
|
||||
PIXEL_UNPACK_BUFFER = 0x88EC //!< The buffer will be used for writing to OpenGL textures
|
||||
};
|
||||
|
||||
enum Access
|
||||
{
|
||||
READ_ONLY = 0x88B8,
|
||||
WRITE_ONLY = 0x88B9,
|
||||
READ_WRITE = 0x88BA
|
||||
};
|
||||
|
||||
//! create empty buffer
|
||||
Buffer();
|
||||
|
||||
//! create buffer from existed buffer id
|
||||
Buffer(int arows, int acols, int atype, unsigned int abufId, bool autoRelease = false);
|
||||
Buffer(Size asize, int atype, unsigned int abufId, bool autoRelease = false);
|
||||
|
||||
//! create buffer
|
||||
Buffer(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false);
|
||||
Buffer(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false);
|
||||
|
||||
//! copy from host/device memory
|
||||
explicit Buffer(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false);
|
||||
|
||||
//! create buffer
|
||||
void create(int arows, int acols, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false);
|
||||
void create(Size asize, int atype, Target target = ARRAY_BUFFER, bool autoRelease = false) { create(asize.height, asize.width, atype, target, autoRelease); }
|
||||
|
||||
//! release memory and delete buffer object
|
||||
void release();
|
||||
|
||||
//! set auto release mode (if true, release will be called in object's destructor)
|
||||
void setAutoRelease(bool flag);
|
||||
|
||||
//! copy from host/device memory
|
||||
void copyFrom(InputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false);
|
||||
|
||||
//! copy to host/device memory
|
||||
void copyTo(OutputArray arr, Target target = ARRAY_BUFFER, bool autoRelease = false) const;
|
||||
|
||||
//! create copy of current buffer
|
||||
Buffer clone(Target target = ARRAY_BUFFER, bool autoRelease = false) const;
|
||||
|
||||
//! bind buffer for specified target
|
||||
void bind(Target target) const;
|
||||
|
||||
//! unbind any buffers from specified target
|
||||
static void unbind(Target target);
|
||||
|
||||
//! map to host memory
|
||||
Mat mapHost(Access access);
|
||||
void unmapHost();
|
||||
|
||||
//! map to device memory
|
||||
gpu::GpuMat mapDevice();
|
||||
void unmapDevice();
|
||||
|
||||
int rows() const { return rows_; }
|
||||
int cols() const { return cols_; }
|
||||
Size size() const { return Size(cols_, rows_); }
|
||||
bool empty() const { return rows_ == 0 || cols_ == 0; }
|
||||
|
||||
int type() const { return type_; }
|
||||
int depth() const { return CV_MAT_DEPTH(type_); }
|
||||
int channels() const { return CV_MAT_CN(type_); }
|
||||
int elemSize() const { return CV_ELEM_SIZE(type_); }
|
||||
int elemSize1() const { return CV_ELEM_SIZE1(type_); }
|
||||
|
||||
unsigned int bufId() const;
|
||||
|
||||
class Impl;
|
||||
|
||||
private:
|
||||
Ptr<Impl> impl_;
|
||||
int rows_;
|
||||
int cols_;
|
||||
int type_;
|
||||
};
|
||||
|
||||
//! Smart pointer for OpenGL 2D texture memory with reference counting.
|
||||
class CV_EXPORTS Texture2D
|
||||
{
|
||||
public:
|
||||
enum Format
|
||||
{
|
||||
NONE = 0,
|
||||
DEPTH_COMPONENT = 0x1902, //!< Depth
|
||||
RGB = 0x1907, //!< Red, Green, Blue
|
||||
RGBA = 0x1908 //!< Red, Green, Blue, Alpha
|
||||
};
|
||||
|
||||
//! create empty texture
|
||||
Texture2D();
|
||||
|
||||
//! create texture from existed texture id
|
||||
Texture2D(int arows, int acols, Format aformat, unsigned int atexId, bool autoRelease = false);
|
||||
Texture2D(Size asize, Format aformat, unsigned int atexId, bool autoRelease = false);
|
||||
|
||||
//! create texture
|
||||
Texture2D(int arows, int acols, Format aformat, bool autoRelease = false);
|
||||
Texture2D(Size asize, Format aformat, bool autoRelease = false);
|
||||
|
||||
//! copy from host/device memory
|
||||
explicit Texture2D(InputArray arr, bool autoRelease = false);
|
||||
|
||||
//! create texture
|
||||
void create(int arows, int acols, Format aformat, bool autoRelease = false);
|
||||
void create(Size asize, Format aformat, bool autoRelease = false) { create(asize.height, asize.width, aformat, autoRelease); }
|
||||
|
||||
//! release memory and delete texture object
|
||||
void release();
|
||||
|
||||
//! set auto release mode (if true, release will be called in object's destructor)
|
||||
void setAutoRelease(bool flag);
|
||||
|
||||
//! copy from host/device memory
|
||||
void copyFrom(InputArray arr, bool autoRelease = false);
|
||||
|
||||
//! copy to host/device memory
|
||||
void copyTo(OutputArray arr, int ddepth = CV_32F, bool autoRelease = false) const;
|
||||
|
||||
//! bind texture to current active texture unit for GL_TEXTURE_2D target
|
||||
void bind() const;
|
||||
|
||||
int rows() const { return rows_; }
|
||||
int cols() const { return cols_; }
|
||||
Size size() const { return Size(cols_, rows_); }
|
||||
bool empty() const { return rows_ == 0 || cols_ == 0; }
|
||||
|
||||
Format format() const { return format_; }
|
||||
|
||||
unsigned int texId() const;
|
||||
|
||||
class Impl;
|
||||
|
||||
private:
|
||||
Ptr<Impl> impl_;
|
||||
int rows_;
|
||||
int cols_;
|
||||
Format format_;
|
||||
};
|
||||
|
||||
//! OpenGL Arrays
|
||||
class CV_EXPORTS Arrays
|
||||
{
|
||||
public:
|
||||
Arrays();
|
||||
|
||||
void setVertexArray(InputArray vertex);
|
||||
void resetVertexArray();
|
||||
|
||||
void setColorArray(InputArray color);
|
||||
void resetColorArray();
|
||||
|
||||
void setNormalArray(InputArray normal);
|
||||
void resetNormalArray();
|
||||
|
||||
void setTexCoordArray(InputArray texCoord);
|
||||
void resetTexCoordArray();
|
||||
|
||||
void release();
|
||||
|
||||
void setAutoRelease(bool flag);
|
||||
|
||||
void bind() const;
|
||||
|
||||
int size() const { return size_; }
|
||||
bool empty() const { return size_ == 0; }
|
||||
|
||||
private:
|
||||
int size_;
|
||||
Buffer vertex_;
|
||||
Buffer color_;
|
||||
Buffer normal_;
|
||||
Buffer texCoord_;
|
||||
};
|
||||
|
||||
/////////////////// Render Functions ///////////////////
|
||||
|
||||
//! render texture rectangle in window
|
||||
CV_EXPORTS void render(const Texture2D& tex,
|
||||
Rect_<double> wndRect = Rect_<double>(0.0, 0.0, 1.0, 1.0),
|
||||
Rect_<double> texRect = Rect_<double>(0.0, 0.0, 1.0, 1.0));
|
||||
|
||||
//! render mode
|
||||
enum {
|
||||
POINTS = 0x0000,
|
||||
LINES = 0x0001,
|
||||
LINE_LOOP = 0x0002,
|
||||
LINE_STRIP = 0x0003,
|
||||
TRIANGLES = 0x0004,
|
||||
TRIANGLE_STRIP = 0x0005,
|
||||
TRIANGLE_FAN = 0x0006,
|
||||
QUADS = 0x0007,
|
||||
QUAD_STRIP = 0x0008,
|
||||
POLYGON = 0x0009
|
||||
};
|
||||
|
||||
//! render OpenGL arrays
|
||||
CV_EXPORTS void render(const Arrays& arr, int mode = POINTS, Scalar color = Scalar::all(255));
|
||||
CV_EXPORTS void render(const Arrays& arr, InputArray indices, int mode = POINTS, Scalar color = Scalar::all(255));
|
||||
|
||||
}} // namespace cv::gl
|
||||
|
||||
namespace cv { namespace gpu {
|
||||
|
||||
//! set a CUDA device to use OpenGL interoperability
|
||||
CV_EXPORTS void setGlDevice(int device = 0);
|
||||
|
||||
}}
|
||||
|
||||
namespace cv {
|
||||
|
||||
template <> CV_EXPORTS void Ptr<cv::ogl::Buffer::Impl>::delete_obj();
|
||||
template <> CV_EXPORTS void Ptr<cv::ogl::Texture2D::Impl>::delete_obj();
|
||||
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __OPENCV_OPENGL_INTEROP_HPP__
|
||||
@@ -0,0 +1,330 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_OPENGL_INTEROP_DEPRECATED_HPP__
|
||||
#define __OPENCV_OPENGL_INTEROP_DEPRECATED_HPP__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
//! Smart pointer for OpenGL buffer memory with reference counting.
|
||||
class CV_EXPORTS GlBuffer
|
||||
{
|
||||
public:
|
||||
enum Usage
|
||||
{
|
||||
ARRAY_BUFFER = 0x8892, // buffer will use for OpenGL arrays (vertices, colors, normals, etc)
|
||||
TEXTURE_BUFFER = 0x88EC // buffer will ise for OpenGL textures
|
||||
};
|
||||
|
||||
//! create empty buffer
|
||||
explicit GlBuffer(Usage usage);
|
||||
|
||||
//! create buffer
|
||||
GlBuffer(int rows, int cols, int type, Usage usage);
|
||||
GlBuffer(Size size, int type, Usage usage);
|
||||
|
||||
//! copy from host/device memory
|
||||
GlBuffer(InputArray mat, Usage usage);
|
||||
|
||||
void create(int rows, int cols, int type, Usage usage);
|
||||
void create(Size size, int type, Usage usage);
|
||||
void create(int rows, int cols, int type);
|
||||
void create(Size size, int type);
|
||||
|
||||
void release();
|
||||
|
||||
//! copy from host/device memory
|
||||
void copyFrom(InputArray mat);
|
||||
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
|
||||
//! map to host memory
|
||||
Mat mapHost();
|
||||
void unmapHost();
|
||||
|
||||
//! map to device memory
|
||||
gpu::GpuMat mapDevice();
|
||||
void unmapDevice();
|
||||
|
||||
inline int rows() const { return rows_; }
|
||||
inline int cols() const { return cols_; }
|
||||
inline Size size() const { return Size(cols_, rows_); }
|
||||
inline bool empty() const { return rows_ == 0 || cols_ == 0; }
|
||||
|
||||
inline int type() const { return type_; }
|
||||
inline int depth() const { return CV_MAT_DEPTH(type_); }
|
||||
inline int channels() const { return CV_MAT_CN(type_); }
|
||||
inline int elemSize() const { return CV_ELEM_SIZE(type_); }
|
||||
inline int elemSize1() const { return CV_ELEM_SIZE1(type_); }
|
||||
|
||||
inline Usage usage() const { return usage_; }
|
||||
|
||||
class Impl;
|
||||
private:
|
||||
int rows_;
|
||||
int cols_;
|
||||
int type_;
|
||||
Usage usage_;
|
||||
|
||||
Ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
template <> CV_EXPORTS void Ptr<GlBuffer::Impl>::delete_obj();
|
||||
|
||||
//! Smart pointer for OpenGL 2d texture memory with reference counting.
|
||||
class CV_EXPORTS GlTexture
|
||||
{
|
||||
public:
|
||||
//! create empty texture
|
||||
GlTexture();
|
||||
|
||||
//! create texture
|
||||
GlTexture(int rows, int cols, int type);
|
||||
GlTexture(Size size, int type);
|
||||
|
||||
//! copy from host/device memory
|
||||
explicit GlTexture(InputArray mat, bool bgra = true);
|
||||
|
||||
void create(int rows, int cols, int type);
|
||||
void create(Size size, int type);
|
||||
void release();
|
||||
|
||||
//! copy from host/device memory
|
||||
void copyFrom(InputArray mat, bool bgra = true);
|
||||
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
|
||||
inline int rows() const { return rows_; }
|
||||
inline int cols() const { return cols_; }
|
||||
inline Size size() const { return Size(cols_, rows_); }
|
||||
inline bool empty() const { return rows_ == 0 || cols_ == 0; }
|
||||
|
||||
inline int type() const { return type_; }
|
||||
inline int depth() const { return CV_MAT_DEPTH(type_); }
|
||||
inline int channels() const { return CV_MAT_CN(type_); }
|
||||
inline int elemSize() const { return CV_ELEM_SIZE(type_); }
|
||||
inline int elemSize1() const { return CV_ELEM_SIZE1(type_); }
|
||||
|
||||
class Impl;
|
||||
private:
|
||||
int rows_;
|
||||
int cols_;
|
||||
int type_;
|
||||
|
||||
Ptr<Impl> impl_;
|
||||
GlBuffer buf_;
|
||||
};
|
||||
|
||||
template <> CV_EXPORTS void Ptr<GlTexture::Impl>::delete_obj();
|
||||
|
||||
//! OpenGL Arrays
|
||||
class CV_EXPORTS GlArrays
|
||||
{
|
||||
public:
|
||||
inline GlArrays()
|
||||
: vertex_(GlBuffer::ARRAY_BUFFER), color_(GlBuffer::ARRAY_BUFFER), bgra_(true), normal_(GlBuffer::ARRAY_BUFFER), texCoord_(GlBuffer::ARRAY_BUFFER)
|
||||
{
|
||||
}
|
||||
|
||||
void setVertexArray(InputArray vertex);
|
||||
inline void resetVertexArray() { vertex_.release(); }
|
||||
|
||||
void setColorArray(InputArray color, bool bgra = true);
|
||||
inline void resetColorArray() { color_.release(); }
|
||||
|
||||
void setNormalArray(InputArray normal);
|
||||
inline void resetNormalArray() { normal_.release(); }
|
||||
|
||||
void setTexCoordArray(InputArray texCoord);
|
||||
inline void resetTexCoordArray() { texCoord_.release(); }
|
||||
|
||||
void bind() const;
|
||||
void unbind() const;
|
||||
|
||||
inline int rows() const { return vertex_.rows(); }
|
||||
inline int cols() const { return vertex_.cols(); }
|
||||
inline Size size() const { return vertex_.size(); }
|
||||
inline bool empty() const { return vertex_.empty(); }
|
||||
|
||||
private:
|
||||
GlBuffer vertex_;
|
||||
GlBuffer color_;
|
||||
bool bgra_;
|
||||
GlBuffer normal_;
|
||||
GlBuffer texCoord_;
|
||||
};
|
||||
|
||||
//! OpenGL Font
|
||||
class CV_EXPORTS GlFont
|
||||
{
|
||||
public:
|
||||
enum Weight
|
||||
{
|
||||
WEIGHT_LIGHT = 300,
|
||||
WEIGHT_NORMAL = 400,
|
||||
WEIGHT_SEMIBOLD = 600,
|
||||
WEIGHT_BOLD = 700,
|
||||
WEIGHT_BLACK = 900
|
||||
};
|
||||
|
||||
enum Style
|
||||
{
|
||||
STYLE_NORMAL = 0,
|
||||
STYLE_ITALIC = 1,
|
||||
STYLE_UNDERLINE = 2
|
||||
};
|
||||
|
||||
static Ptr<GlFont> get(const std::string& family, int height = 12, Weight weight = WEIGHT_NORMAL, Style style = STYLE_NORMAL);
|
||||
|
||||
void draw(const char* str, int len) const;
|
||||
|
||||
inline const std::string& family() const { return family_; }
|
||||
inline int height() const { return height_; }
|
||||
inline Weight weight() const { return weight_; }
|
||||
inline Style style() const { return style_; }
|
||||
|
||||
private:
|
||||
GlFont(const std::string& family, int height, Weight weight, Style style);
|
||||
|
||||
std::string family_;
|
||||
int height_;
|
||||
Weight weight_;
|
||||
Style style_;
|
||||
|
||||
unsigned int base_;
|
||||
|
||||
GlFont(const GlFont&);
|
||||
GlFont& operator =(const GlFont&);
|
||||
};
|
||||
|
||||
//! render functions
|
||||
|
||||
//! render texture rectangle in window
|
||||
CV_EXPORTS void render(const GlTexture& tex,
|
||||
Rect_<double> wndRect = Rect_<double>(0.0, 0.0, 1.0, 1.0),
|
||||
Rect_<double> texRect = Rect_<double>(0.0, 0.0, 1.0, 1.0));
|
||||
|
||||
//! render mode
|
||||
namespace RenderMode {
|
||||
enum {
|
||||
POINTS = 0x0000,
|
||||
LINES = 0x0001,
|
||||
LINE_LOOP = 0x0002,
|
||||
LINE_STRIP = 0x0003,
|
||||
TRIANGLES = 0x0004,
|
||||
TRIANGLE_STRIP = 0x0005,
|
||||
TRIANGLE_FAN = 0x0006,
|
||||
QUADS = 0x0007,
|
||||
QUAD_STRIP = 0x0008,
|
||||
POLYGON = 0x0009
|
||||
};
|
||||
}
|
||||
|
||||
//! render OpenGL arrays
|
||||
CV_EXPORTS void render(const GlArrays& arr, int mode = RenderMode::POINTS, Scalar color = Scalar::all(255));
|
||||
|
||||
CV_EXPORTS void render(const std::string& str, const Ptr<GlFont>& font, Scalar color, Point2d pos);
|
||||
|
||||
//! OpenGL camera
|
||||
class CV_EXPORTS GlCamera
|
||||
{
|
||||
public:
|
||||
GlCamera();
|
||||
|
||||
void lookAt(Point3d eye, Point3d center, Point3d up);
|
||||
void setCameraPos(Point3d pos, double yaw, double pitch, double roll);
|
||||
|
||||
void setScale(Point3d scale);
|
||||
|
||||
void setProjectionMatrix(const Mat& projectionMatrix, bool transpose = true);
|
||||
void setPerspectiveProjection(double fov, double aspect, double zNear, double zFar);
|
||||
void setOrthoProjection(double left, double right, double bottom, double top, double zNear, double zFar);
|
||||
|
||||
void setupProjectionMatrix() const;
|
||||
void setupModelViewMatrix() const;
|
||||
|
||||
private:
|
||||
Point3d eye_;
|
||||
Point3d center_;
|
||||
Point3d up_;
|
||||
|
||||
Point3d pos_;
|
||||
double yaw_;
|
||||
double pitch_;
|
||||
double roll_;
|
||||
|
||||
bool useLookAtParams_;
|
||||
|
||||
Point3d scale_;
|
||||
|
||||
Mat projectionMatrix_;
|
||||
|
||||
double fov_;
|
||||
double aspect_;
|
||||
|
||||
double left_;
|
||||
double right_;
|
||||
double bottom_;
|
||||
double top_;
|
||||
|
||||
double zNear_;
|
||||
double zFar_;
|
||||
|
||||
bool perspectiveProjection_;
|
||||
};
|
||||
|
||||
inline void GlBuffer::create(Size _size, int _type, Usage _usage) { create(_size.height, _size.width, _type, _usage); }
|
||||
inline void GlBuffer::create(int _rows, int _cols, int _type) { create(_rows, _cols, _type, usage()); }
|
||||
inline void GlBuffer::create(Size _size, int _type) { create(_size.height, _size.width, _type, usage()); }
|
||||
inline void GlTexture::create(Size _size, int _type) { create(_size.height, _size.width, _type); }
|
||||
|
||||
} // namespace cv
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __OPENCV_OPENGL_INTEROP_DEPRECATED_HPP__
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// Intel License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright( C) 2000, Intel Corporation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
//(including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort(including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/*
|
||||
definition of the current version of OpenCV
|
||||
Usefull to test in user programs
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_VERSION_HPP__
|
||||
#define __OPENCV_VERSION_HPP__
|
||||
|
||||
#define CV_VERSION_EPOCH 2
|
||||
#define CV_VERSION_MAJOR 4
|
||||
#define CV_VERSION_MINOR 8
|
||||
#define CV_VERSION_REVISION 0
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
|
||||
|
||||
#define CVAUX_STRW_EXP(__A) L#__A
|
||||
#define CVAUX_STRW(__A) CVAUX_STRW_EXP(__A)
|
||||
|
||||
#if CV_VERSION_REVISION
|
||||
# define CV_VERSION CVAUX_STR(CV_VERSION_EPOCH) "." CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR) "." CVAUX_STR(CV_VERSION_REVISION)
|
||||
#else
|
||||
# define CV_VERSION CVAUX_STR(CV_VERSION_EPOCH) "." CVAUX_STR(CV_VERSION_MAJOR) "." CVAUX_STR(CV_VERSION_MINOR)
|
||||
#endif
|
||||
|
||||
/* old style version constants*/
|
||||
#define CV_MAJOR_VERSION CV_VERSION_EPOCH
|
||||
#define CV_MINOR_VERSION CV_VERSION_MAJOR
|
||||
#define CV_SUBMINOR_VERSION CV_VERSION_MINOR
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,621 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to
|
||||
// this license. If you do not agree to this license, do not download,
|
||||
// install, copy or use the software.
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2008, Google, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of Intel Corporation or contributors may not be used to endorse
|
||||
// or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is"
|
||||
// and any express or implied warranties, including, but not limited to, the
|
||||
// implied warranties of merchantability and fitness for a particular purpose
|
||||
// are disclaimed. In no event shall the Intel Corporation or contributors be
|
||||
// liable for any direct, indirect, incidental, special, exemplary, or
|
||||
// consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Image class which provides a thin layer around an IplImage. The goals
|
||||
// of the class design are:
|
||||
// 1. All the data has explicit ownership to avoid memory leaks
|
||||
// 2. No hidden allocations or copies for performance.
|
||||
// 3. Easy access to OpenCV methods (which will access IPP if available)
|
||||
// 4. Can easily treat external data as an image
|
||||
// 5. Easy to create images which are subsets of other images
|
||||
// 6. Fast pixel access which can take advantage of number of channels
|
||||
// if known at compile time.
|
||||
//
|
||||
// The WImage class is the image class which provides the data accessors.
|
||||
// The 'W' comes from the fact that it is also a wrapper around the popular
|
||||
// but inconvenient IplImage class. A WImage can be constructed either using a
|
||||
// WImageBuffer class which allocates and frees the data,
|
||||
// or using a WImageView class which constructs a subimage or a view into
|
||||
// external data. The view class does no memory management. Each class
|
||||
// actually has two versions, one when the number of channels is known at
|
||||
// compile time and one when it isn't. Using the one with the number of
|
||||
// channels specified can provide some compile time optimizations by using the
|
||||
// fact that the number of channels is a constant.
|
||||
//
|
||||
// We use the convention (c,r) to refer to column c and row r with (0,0) being
|
||||
// the upper left corner. This is similar to standard Euclidean coordinates
|
||||
// with the first coordinate varying in the horizontal direction and the second
|
||||
// coordinate varying in the vertical direction.
|
||||
// Thus (c,r) is usually in the domain [0, width) X [0, height)
|
||||
//
|
||||
// Example usage:
|
||||
// WImageBuffer3_b im(5,7); // Make a 5X7 3 channel image of type uchar
|
||||
// WImageView3_b sub_im(im, 2,2, 3,3); // 3X3 submatrix
|
||||
// vector<float> vec(10, 3.0f);
|
||||
// WImageView1_f user_im(&vec[0], 2, 5); // 2X5 image w/ supplied data
|
||||
//
|
||||
// im.SetZero(); // same as cvSetZero(im.Ipl())
|
||||
// *im(2, 3) = 15; // Modify the element at column 2, row 3
|
||||
// MySetRand(&sub_im);
|
||||
//
|
||||
// // Copy the second row into the first. This can be done with no memory
|
||||
// // allocation and will use SSE if IPP is available.
|
||||
// int w = im.Width();
|
||||
// im.View(0,0, w,1).CopyFrom(im.View(0,1, w,1));
|
||||
//
|
||||
// // Doesn't care about source of data since using WImage
|
||||
// void MySetRand(WImage_b* im) { // Works with any number of channels
|
||||
// for (int r = 0; r < im->Height(); ++r) {
|
||||
// float* row = im->Row(r);
|
||||
// for (int c = 0; c < im->Width(); ++c) {
|
||||
// for (int ch = 0; ch < im->Channels(); ++ch, ++row) {
|
||||
// *row = uchar(rand() & 255);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Functions that are not part of the basic image allocation, viewing, and
|
||||
// access should come from OpenCV, except some useful functions that are not
|
||||
// part of OpenCV can be found in wimage_util.h
|
||||
#ifndef __OPENCV_CORE_WIMAGE_HPP__
|
||||
#define __OPENCV_CORE_WIMAGE_HPP__
|
||||
|
||||
#include "opencv2/core/core_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace cv {
|
||||
|
||||
template <typename T> class WImage;
|
||||
template <typename T> class WImageBuffer;
|
||||
template <typename T> class WImageView;
|
||||
|
||||
template<typename T, int C> class WImageC;
|
||||
template<typename T, int C> class WImageBufferC;
|
||||
template<typename T, int C> class WImageViewC;
|
||||
|
||||
// Commonly used typedefs.
|
||||
typedef WImage<uchar> WImage_b;
|
||||
typedef WImageView<uchar> WImageView_b;
|
||||
typedef WImageBuffer<uchar> WImageBuffer_b;
|
||||
|
||||
typedef WImageC<uchar, 1> WImage1_b;
|
||||
typedef WImageViewC<uchar, 1> WImageView1_b;
|
||||
typedef WImageBufferC<uchar, 1> WImageBuffer1_b;
|
||||
|
||||
typedef WImageC<uchar, 3> WImage3_b;
|
||||
typedef WImageViewC<uchar, 3> WImageView3_b;
|
||||
typedef WImageBufferC<uchar, 3> WImageBuffer3_b;
|
||||
|
||||
typedef WImage<float> WImage_f;
|
||||
typedef WImageView<float> WImageView_f;
|
||||
typedef WImageBuffer<float> WImageBuffer_f;
|
||||
|
||||
typedef WImageC<float, 1> WImage1_f;
|
||||
typedef WImageViewC<float, 1> WImageView1_f;
|
||||
typedef WImageBufferC<float, 1> WImageBuffer1_f;
|
||||
|
||||
typedef WImageC<float, 3> WImage3_f;
|
||||
typedef WImageViewC<float, 3> WImageView3_f;
|
||||
typedef WImageBufferC<float, 3> WImageBuffer3_f;
|
||||
|
||||
// There isn't a standard for signed and unsigned short so be more
|
||||
// explicit in the typename for these cases.
|
||||
typedef WImage<short> WImage_16s;
|
||||
typedef WImageView<short> WImageView_16s;
|
||||
typedef WImageBuffer<short> WImageBuffer_16s;
|
||||
|
||||
typedef WImageC<short, 1> WImage1_16s;
|
||||
typedef WImageViewC<short, 1> WImageView1_16s;
|
||||
typedef WImageBufferC<short, 1> WImageBuffer1_16s;
|
||||
|
||||
typedef WImageC<short, 3> WImage3_16s;
|
||||
typedef WImageViewC<short, 3> WImageView3_16s;
|
||||
typedef WImageBufferC<short, 3> WImageBuffer3_16s;
|
||||
|
||||
typedef WImage<ushort> WImage_16u;
|
||||
typedef WImageView<ushort> WImageView_16u;
|
||||
typedef WImageBuffer<ushort> WImageBuffer_16u;
|
||||
|
||||
typedef WImageC<ushort, 1> WImage1_16u;
|
||||
typedef WImageViewC<ushort, 1> WImageView1_16u;
|
||||
typedef WImageBufferC<ushort, 1> WImageBuffer1_16u;
|
||||
|
||||
typedef WImageC<ushort, 3> WImage3_16u;
|
||||
typedef WImageViewC<ushort, 3> WImageView3_16u;
|
||||
typedef WImageBufferC<ushort, 3> WImageBuffer3_16u;
|
||||
|
||||
//
|
||||
// WImage definitions
|
||||
//
|
||||
// This WImage class gives access to the data it refers to. It can be
|
||||
// constructed either by allocating the data with a WImageBuffer class or
|
||||
// using the WImageView class to refer to a subimage or outside data.
|
||||
template<typename T>
|
||||
class WImage
|
||||
{
|
||||
public:
|
||||
typedef T BaseType;
|
||||
|
||||
// WImage is an abstract class with no other virtual methods so make the
|
||||
// destructor virtual.
|
||||
virtual ~WImage() = 0;
|
||||
|
||||
// Accessors
|
||||
IplImage* Ipl() {return image_; }
|
||||
const IplImage* Ipl() const {return image_; }
|
||||
T* ImageData() { return reinterpret_cast<T*>(image_->imageData); }
|
||||
const T* ImageData() const {
|
||||
return reinterpret_cast<const T*>(image_->imageData);
|
||||
}
|
||||
|
||||
int Width() const {return image_->width; }
|
||||
int Height() const {return image_->height; }
|
||||
|
||||
// WidthStep is the number of bytes to go to the pixel with the next y coord
|
||||
int WidthStep() const {return image_->widthStep; }
|
||||
|
||||
int Channels() const {return image_->nChannels; }
|
||||
int ChannelSize() const {return sizeof(T); } // number of bytes per channel
|
||||
|
||||
// Number of bytes per pixel
|
||||
int PixelSize() const {return Channels() * ChannelSize(); }
|
||||
|
||||
// Return depth type (e.g. IPL_DEPTH_8U, IPL_DEPTH_32F) which is the number
|
||||
// of bits per channel and with the signed bit set.
|
||||
// This is known at compile time using specializations.
|
||||
int Depth() const;
|
||||
|
||||
inline const T* Row(int r) const {
|
||||
return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep);
|
||||
}
|
||||
|
||||
inline T* Row(int r) {
|
||||
return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep);
|
||||
}
|
||||
|
||||
// Pixel accessors which returns a pointer to the start of the channel
|
||||
inline T* operator() (int c, int r) {
|
||||
return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) +
|
||||
c*Channels();
|
||||
}
|
||||
|
||||
inline const T* operator() (int c, int r) const {
|
||||
return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) +
|
||||
c*Channels();
|
||||
}
|
||||
|
||||
// Copy the contents from another image which is just a convenience to cvCopy
|
||||
void CopyFrom(const WImage<T>& src) { cvCopy(src.Ipl(), image_); }
|
||||
|
||||
// Set contents to zero which is just a convenient to cvSetZero
|
||||
void SetZero() { cvSetZero(image_); }
|
||||
|
||||
// Construct a view into a region of this image
|
||||
WImageView<T> View(int c, int r, int width, int height);
|
||||
|
||||
protected:
|
||||
// Disallow copy and assignment
|
||||
WImage(const WImage&);
|
||||
void operator=(const WImage&);
|
||||
|
||||
explicit WImage(IplImage* img) : image_(img) {
|
||||
assert(!img || img->depth == Depth());
|
||||
}
|
||||
|
||||
void SetIpl(IplImage* image) {
|
||||
assert(!image || image->depth == Depth());
|
||||
image_ = image;
|
||||
}
|
||||
|
||||
IplImage* image_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Image class when both the pixel type and number of channels
|
||||
// are known at compile time. This wrapper will speed up some of the operations
|
||||
// like accessing individual pixels using the () operator.
|
||||
template<typename T, int C>
|
||||
class WImageC : public WImage<T>
|
||||
{
|
||||
public:
|
||||
typedef typename WImage<T>::BaseType BaseType;
|
||||
enum { kChannels = C };
|
||||
|
||||
explicit WImageC(IplImage* img) : WImage<T>(img) {
|
||||
assert(!img || img->nChannels == Channels());
|
||||
}
|
||||
|
||||
// Construct a view into a region of this image
|
||||
WImageViewC<T, C> View(int c, int r, int width, int height);
|
||||
|
||||
// Copy the contents from another image which is just a convenience to cvCopy
|
||||
void CopyFrom(const WImageC<T, C>& src) {
|
||||
cvCopy(src.Ipl(), WImage<T>::image_);
|
||||
}
|
||||
|
||||
// WImageC is an abstract class with no other virtual methods so make the
|
||||
// destructor virtual.
|
||||
virtual ~WImageC() = 0;
|
||||
|
||||
int Channels() const {return C; }
|
||||
|
||||
protected:
|
||||
// Disallow copy and assignment
|
||||
WImageC(const WImageC&);
|
||||
void operator=(const WImageC&);
|
||||
|
||||
void SetIpl(IplImage* image) {
|
||||
assert(!image || image->depth == WImage<T>::Depth());
|
||||
WImage<T>::SetIpl(image);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// WImageBuffer definitions
|
||||
//
|
||||
// Image class which owns the data, so it can be allocated and is always
|
||||
// freed. It cannot be copied but can be explicity cloned.
|
||||
//
|
||||
template<typename T>
|
||||
class WImageBuffer : public WImage<T>
|
||||
{
|
||||
public:
|
||||
typedef typename WImage<T>::BaseType BaseType;
|
||||
|
||||
// Default constructor which creates an object that can be
|
||||
WImageBuffer() : WImage<T>(0) {}
|
||||
|
||||
WImageBuffer(int width, int height, int nchannels) : WImage<T>(0) {
|
||||
Allocate(width, height, nchannels);
|
||||
}
|
||||
|
||||
// Constructor which takes ownership of a given IplImage so releases
|
||||
// the image on destruction.
|
||||
explicit WImageBuffer(IplImage* img) : WImage<T>(img) {}
|
||||
|
||||
// Allocate an image. Does nothing if current size is the same as
|
||||
// the new size.
|
||||
void Allocate(int width, int height, int nchannels);
|
||||
|
||||
// Set the data to point to an image, releasing the old data
|
||||
void SetIpl(IplImage* img) {
|
||||
ReleaseImage();
|
||||
WImage<T>::SetIpl(img);
|
||||
}
|
||||
|
||||
// Clone an image which reallocates the image if of a different dimension.
|
||||
void CloneFrom(const WImage<T>& src) {
|
||||
Allocate(src.Width(), src.Height(), src.Channels());
|
||||
CopyFrom(src);
|
||||
}
|
||||
|
||||
~WImageBuffer() {
|
||||
ReleaseImage();
|
||||
}
|
||||
|
||||
// Release the image if it isn't null.
|
||||
void ReleaseImage() {
|
||||
if (WImage<T>::image_) {
|
||||
IplImage* image = WImage<T>::image_;
|
||||
cvReleaseImage(&image);
|
||||
WImage<T>::SetIpl(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsNull() const {return WImage<T>::image_ == NULL; }
|
||||
|
||||
private:
|
||||
// Disallow copy and assignment
|
||||
WImageBuffer(const WImageBuffer&);
|
||||
void operator=(const WImageBuffer&);
|
||||
};
|
||||
|
||||
// Like a WImageBuffer class but when the number of channels is known
|
||||
// at compile time.
|
||||
template<typename T, int C>
|
||||
class WImageBufferC : public WImageC<T, C>
|
||||
{
|
||||
public:
|
||||
typedef typename WImage<T>::BaseType BaseType;
|
||||
enum { kChannels = C };
|
||||
|
||||
// Default constructor which creates an object that can be
|
||||
WImageBufferC() : WImageC<T, C>(0) {}
|
||||
|
||||
WImageBufferC(int width, int height) : WImageC<T, C>(0) {
|
||||
Allocate(width, height);
|
||||
}
|
||||
|
||||
// Constructor which takes ownership of a given IplImage so releases
|
||||
// the image on destruction.
|
||||
explicit WImageBufferC(IplImage* img) : WImageC<T, C>(img) {}
|
||||
|
||||
// Allocate an image. Does nothing if current size is the same as
|
||||
// the new size.
|
||||
void Allocate(int width, int height);
|
||||
|
||||
// Set the data to point to an image, releasing the old data
|
||||
void SetIpl(IplImage* img) {
|
||||
ReleaseImage();
|
||||
WImageC<T, C>::SetIpl(img);
|
||||
}
|
||||
|
||||
// Clone an image which reallocates the image if of a different dimension.
|
||||
void CloneFrom(const WImageC<T, C>& src) {
|
||||
Allocate(src.Width(), src.Height());
|
||||
CopyFrom(src);
|
||||
}
|
||||
|
||||
~WImageBufferC() {
|
||||
ReleaseImage();
|
||||
}
|
||||
|
||||
// Release the image if it isn't null.
|
||||
void ReleaseImage() {
|
||||
if (WImage<T>::image_) {
|
||||
IplImage* image = WImage<T>::image_;
|
||||
cvReleaseImage(&image);
|
||||
WImageC<T, C>::SetIpl(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsNull() const {return WImage<T>::image_ == NULL; }
|
||||
|
||||
private:
|
||||
// Disallow copy and assignment
|
||||
WImageBufferC(const WImageBufferC&);
|
||||
void operator=(const WImageBufferC&);
|
||||
};
|
||||
|
||||
//
|
||||
// WImageView definitions
|
||||
//
|
||||
// View into an image class which allows treating a subimage as an image
|
||||
// or treating external data as an image
|
||||
//
|
||||
template<typename T>
|
||||
class WImageView : public WImage<T>
|
||||
{
|
||||
public:
|
||||
typedef typename WImage<T>::BaseType BaseType;
|
||||
|
||||
// Construct a subimage. No checks are done that the subimage lies
|
||||
// completely inside the original image.
|
||||
WImageView(WImage<T>* img, int c, int r, int width, int height);
|
||||
|
||||
// Refer to external data.
|
||||
// If not given width_step assumed to be same as width.
|
||||
WImageView(T* data, int width, int height, int channels, int width_step = -1);
|
||||
|
||||
// Refer to external data. This does NOT take ownership
|
||||
// of the supplied IplImage.
|
||||
WImageView(IplImage* img) : WImage<T>(img) {}
|
||||
|
||||
// Copy constructor
|
||||
WImageView(const WImage<T>& img) : WImage<T>(0) {
|
||||
header_ = *(img.Ipl());
|
||||
WImage<T>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
WImageView& operator=(const WImage<T>& img) {
|
||||
header_ = *(img.Ipl());
|
||||
WImage<T>::SetIpl(&header_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
IplImage header_;
|
||||
};
|
||||
|
||||
|
||||
template<typename T, int C>
|
||||
class WImageViewC : public WImageC<T, C>
|
||||
{
|
||||
public:
|
||||
typedef typename WImage<T>::BaseType BaseType;
|
||||
enum { kChannels = C };
|
||||
|
||||
// Default constructor needed for vectors of views.
|
||||
WImageViewC();
|
||||
|
||||
virtual ~WImageViewC() {}
|
||||
|
||||
// Construct a subimage. No checks are done that the subimage lies
|
||||
// completely inside the original image.
|
||||
WImageViewC(WImageC<T, C>* img,
|
||||
int c, int r, int width, int height);
|
||||
|
||||
// Refer to external data
|
||||
WImageViewC(T* data, int width, int height, int width_step = -1);
|
||||
|
||||
// Refer to external data. This does NOT take ownership
|
||||
// of the supplied IplImage.
|
||||
WImageViewC(IplImage* img) : WImageC<T, C>(img) {}
|
||||
|
||||
// Copy constructor which does a shallow copy to allow multiple views
|
||||
// of same data. gcc-4.1.1 gets confused if both versions of
|
||||
// the constructor and assignment operator are not provided.
|
||||
WImageViewC(const WImageC<T, C>& img) : WImageC<T, C>(0) {
|
||||
header_ = *(img.Ipl());
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
}
|
||||
WImageViewC(const WImageViewC<T, C>& img) : WImageC<T, C>(0) {
|
||||
header_ = *(img.Ipl());
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
WImageViewC& operator=(const WImageC<T, C>& img) {
|
||||
header_ = *(img.Ipl());
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
return *this;
|
||||
}
|
||||
WImageViewC& operator=(const WImageViewC<T, C>& img) {
|
||||
header_ = *(img.Ipl());
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
IplImage header_;
|
||||
};
|
||||
|
||||
|
||||
// Specializations for depth
|
||||
template<>
|
||||
inline int WImage<uchar>::Depth() const {return IPL_DEPTH_8U; }
|
||||
template<>
|
||||
inline int WImage<signed char>::Depth() const {return IPL_DEPTH_8S; }
|
||||
template<>
|
||||
inline int WImage<short>::Depth() const {return IPL_DEPTH_16S; }
|
||||
template<>
|
||||
inline int WImage<ushort>::Depth() const {return IPL_DEPTH_16U; }
|
||||
template<>
|
||||
inline int WImage<int>::Depth() const {return IPL_DEPTH_32S; }
|
||||
template<>
|
||||
inline int WImage<float>::Depth() const {return IPL_DEPTH_32F; }
|
||||
template<>
|
||||
inline int WImage<double>::Depth() const {return IPL_DEPTH_64F; }
|
||||
|
||||
//
|
||||
// Pure virtual destructors still need to be defined.
|
||||
//
|
||||
template<typename T> inline WImage<T>::~WImage() {}
|
||||
template<typename T, int C> inline WImageC<T, C>::~WImageC() {}
|
||||
|
||||
//
|
||||
// Allocate ImageData
|
||||
//
|
||||
template<typename T>
|
||||
inline void WImageBuffer<T>::Allocate(int width, int height, int nchannels)
|
||||
{
|
||||
if (IsNull() || WImage<T>::Width() != width ||
|
||||
WImage<T>::Height() != height || WImage<T>::Channels() != nchannels) {
|
||||
ReleaseImage();
|
||||
WImage<T>::image_ = cvCreateImage(cvSize(width, height),
|
||||
WImage<T>::Depth(), nchannels);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, int C>
|
||||
inline void WImageBufferC<T, C>::Allocate(int width, int height)
|
||||
{
|
||||
if (IsNull() || WImage<T>::Width() != width || WImage<T>::Height() != height) {
|
||||
ReleaseImage();
|
||||
WImageC<T, C>::SetIpl(cvCreateImage(cvSize(width, height),WImage<T>::Depth(), C));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ImageView methods
|
||||
//
|
||||
template<typename T>
|
||||
WImageView<T>::WImageView(WImage<T>* img, int c, int r, int width, int height)
|
||||
: WImage<T>(0)
|
||||
{
|
||||
header_ = *(img->Ipl());
|
||||
header_.imageData = reinterpret_cast<char*>((*img)(c, r));
|
||||
header_.width = width;
|
||||
header_.height = height;
|
||||
WImage<T>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
WImageView<T>::WImageView(T* data, int width, int height, int nchannels, int width_step)
|
||||
: WImage<T>(0)
|
||||
{
|
||||
cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), nchannels);
|
||||
header_.imageData = reinterpret_cast<char*>(data);
|
||||
if (width_step > 0) {
|
||||
header_.widthStep = width_step;
|
||||
}
|
||||
WImage<T>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
template<typename T, int C>
|
||||
WImageViewC<T, C>::WImageViewC(WImageC<T, C>* img, int c, int r, int width, int height)
|
||||
: WImageC<T, C>(0)
|
||||
{
|
||||
header_ = *(img->Ipl());
|
||||
header_.imageData = reinterpret_cast<char*>((*img)(c, r));
|
||||
header_.width = width;
|
||||
header_.height = height;
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
template<typename T, int C>
|
||||
WImageViewC<T, C>::WImageViewC() : WImageC<T, C>(0) {
|
||||
cvInitImageHeader(&header_, cvSize(0, 0), WImage<T>::Depth(), C);
|
||||
header_.imageData = reinterpret_cast<char*>(0);
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
template<typename T, int C>
|
||||
WImageViewC<T, C>::WImageViewC(T* data, int width, int height, int width_step)
|
||||
: WImageC<T, C>(0)
|
||||
{
|
||||
cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), C);
|
||||
header_.imageData = reinterpret_cast<char*>(data);
|
||||
if (width_step > 0) {
|
||||
header_.widthStep = width_step;
|
||||
}
|
||||
WImageC<T, C>::SetIpl(&header_);
|
||||
}
|
||||
|
||||
// Construct a view into a region of an image
|
||||
template<typename T>
|
||||
WImageView<T> WImage<T>::View(int c, int r, int width, int height) {
|
||||
return WImageView<T>(this, c, r, width, height);
|
||||
}
|
||||
|
||||
template<typename T, int C>
|
||||
WImageViewC<T, C> WImageC<T, C>::View(int c, int r, int width, int height) {
|
||||
return WImageViewC<T, C>(this, c, r, width, height);
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef OPENCV_FLANN_ALL_INDICES_H_
|
||||
#define OPENCV_FLANN_ALL_INDICES_H_
|
||||
|
||||
#include "general.h"
|
||||
|
||||
#include "nn_index.h"
|
||||
#include "kdtree_index.h"
|
||||
#include "kdtree_single_index.h"
|
||||
#include "kmeans_index.h"
|
||||
#include "composite_index.h"
|
||||
#include "linear_index.h"
|
||||
#include "hierarchical_clustering_index.h"
|
||||
#include "lsh_index.h"
|
||||
#include "autotuned_index.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
template<typename KDTreeCapability, typename VectorSpace, typename Distance>
|
||||
struct index_creator
|
||||
{
|
||||
static NNIndex<Distance>* create(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
|
||||
{
|
||||
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm");
|
||||
|
||||
NNIndex<Distance>* nnIndex;
|
||||
switch (index_type) {
|
||||
case FLANN_INDEX_LINEAR:
|
||||
nnIndex = new LinearIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_KDTREE_SINGLE:
|
||||
nnIndex = new KDTreeSingleIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_KDTREE:
|
||||
nnIndex = new KDTreeIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_KMEANS:
|
||||
nnIndex = new KMeansIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_COMPOSITE:
|
||||
nnIndex = new CompositeIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_AUTOTUNED:
|
||||
nnIndex = new AutotunedIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_HIERARCHICAL:
|
||||
nnIndex = new HierarchicalClusteringIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_LSH:
|
||||
nnIndex = new LshIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
default:
|
||||
throw FLANNException("Unknown index type");
|
||||
}
|
||||
|
||||
return nnIndex;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename VectorSpace, typename Distance>
|
||||
struct index_creator<False,VectorSpace,Distance>
|
||||
{
|
||||
static NNIndex<Distance>* create(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
|
||||
{
|
||||
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm");
|
||||
|
||||
NNIndex<Distance>* nnIndex;
|
||||
switch (index_type) {
|
||||
case FLANN_INDEX_LINEAR:
|
||||
nnIndex = new LinearIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_KMEANS:
|
||||
nnIndex = new KMeansIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_HIERARCHICAL:
|
||||
nnIndex = new HierarchicalClusteringIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_LSH:
|
||||
nnIndex = new LshIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
default:
|
||||
throw FLANNException("Unknown index type");
|
||||
}
|
||||
|
||||
return nnIndex;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Distance>
|
||||
struct index_creator<False,False,Distance>
|
||||
{
|
||||
static NNIndex<Distance>* create(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
|
||||
{
|
||||
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params, "algorithm");
|
||||
|
||||
NNIndex<Distance>* nnIndex;
|
||||
switch (index_type) {
|
||||
case FLANN_INDEX_LINEAR:
|
||||
nnIndex = new LinearIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_HIERARCHICAL:
|
||||
nnIndex = new HierarchicalClusteringIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
case FLANN_INDEX_LSH:
|
||||
nnIndex = new LshIndex<Distance>(dataset, params, distance);
|
||||
break;
|
||||
default:
|
||||
throw FLANNException("Unknown index type");
|
||||
}
|
||||
|
||||
return nnIndex;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Distance>
|
||||
NNIndex<Distance>* create_index_by_type(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance)
|
||||
{
|
||||
return index_creator<typename Distance::is_kdtree_distance,
|
||||
typename Distance::is_vector_space_distance,
|
||||
Distance>::create(dataset, params,distance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENCV_FLANN_ALL_INDICES_H_ */
|
||||
@@ -0,0 +1,188 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_ALLOCATOR_H_
|
||||
#define OPENCV_FLANN_ALLOCATOR_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Allocates (using C's malloc) a generic type T.
|
||||
*
|
||||
* Params:
|
||||
* count = number of instances to allocate.
|
||||
* Returns: pointer (of type T*) to memory buffer
|
||||
*/
|
||||
template <typename T>
|
||||
T* allocate(size_t count = 1)
|
||||
{
|
||||
T* mem = (T*) ::malloc(sizeof(T)*count);
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pooled storage allocator
|
||||
*
|
||||
* The following routines allow for the efficient allocation of storage in
|
||||
* small chunks from a specified pool. Rather than allowing each structure
|
||||
* to be freed individually, an entire pool of storage is freed at once.
|
||||
* This method has two advantages over just using malloc() and free(). First,
|
||||
* it is far more efficient for allocating small objects, as there is
|
||||
* no overhead for remembering all the information needed to free each
|
||||
* object or consolidating fragmented memory. Second, the decision about
|
||||
* how long to keep an object is made at the time of allocation, and there
|
||||
* is no need to track down all the objects to free them.
|
||||
*
|
||||
*/
|
||||
|
||||
const size_t WORDSIZE=16;
|
||||
const size_t BLOCKSIZE=8192;
|
||||
|
||||
class PooledAllocator
|
||||
{
|
||||
/* We maintain memory alignment to word boundaries by requiring that all
|
||||
allocations be in multiples of the machine wordsize. */
|
||||
/* Size of machine word in bytes. Must be power of 2. */
|
||||
/* Minimum number of bytes requested at a time from the system. Must be multiple of WORDSIZE. */
|
||||
|
||||
|
||||
int remaining; /* Number of bytes left in current block of storage. */
|
||||
void* base; /* Pointer to base of current block of storage. */
|
||||
void* loc; /* Current location in block to next allocate memory. */
|
||||
int blocksize;
|
||||
|
||||
|
||||
public:
|
||||
int usedMemory;
|
||||
int wastedMemory;
|
||||
|
||||
/**
|
||||
Default constructor. Initializes a new pool.
|
||||
*/
|
||||
PooledAllocator(int blockSize = BLOCKSIZE)
|
||||
{
|
||||
blocksize = blockSize;
|
||||
remaining = 0;
|
||||
base = NULL;
|
||||
|
||||
usedMemory = 0;
|
||||
wastedMemory = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor. Frees all the memory allocated in this pool.
|
||||
*/
|
||||
~PooledAllocator()
|
||||
{
|
||||
void* prev;
|
||||
|
||||
while (base != NULL) {
|
||||
prev = *((void**) base); /* Get pointer to prev block. */
|
||||
::free(base);
|
||||
base = prev;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to a piece of new memory of the given size in bytes
|
||||
* allocated from the pool.
|
||||
*/
|
||||
void* allocateMemory(int size)
|
||||
{
|
||||
int blockSize;
|
||||
|
||||
/* Round size up to a multiple of wordsize. The following expression
|
||||
only works for WORDSIZE that is a power of 2, by masking last bits of
|
||||
incremented size to zero.
|
||||
*/
|
||||
size = (size + (WORDSIZE - 1)) & ~(WORDSIZE - 1);
|
||||
|
||||
/* Check whether a new block must be allocated. Note that the first word
|
||||
of a block is reserved for a pointer to the previous block.
|
||||
*/
|
||||
if (size > remaining) {
|
||||
|
||||
wastedMemory += remaining;
|
||||
|
||||
/* Allocate new storage. */
|
||||
blockSize = (size + sizeof(void*) + (WORDSIZE-1) > BLOCKSIZE) ?
|
||||
size + sizeof(void*) + (WORDSIZE-1) : BLOCKSIZE;
|
||||
|
||||
// use the standard C malloc to allocate memory
|
||||
void* m = ::malloc(blockSize);
|
||||
if (!m) {
|
||||
fprintf(stderr,"Failed to allocate memory.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Fill first word of new block with pointer to previous block. */
|
||||
((void**) m)[0] = base;
|
||||
base = m;
|
||||
|
||||
int shift = 0;
|
||||
//int shift = (WORDSIZE - ( (((size_t)m) + sizeof(void*)) & (WORDSIZE-1))) & (WORDSIZE-1);
|
||||
|
||||
remaining = blockSize - sizeof(void*) - shift;
|
||||
loc = ((char*)m + sizeof(void*) + shift);
|
||||
}
|
||||
void* rloc = loc;
|
||||
loc = (char*)loc + size;
|
||||
remaining -= size;
|
||||
|
||||
usedMemory += size;
|
||||
|
||||
return rloc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates (using this pool) a generic type T.
|
||||
*
|
||||
* Params:
|
||||
* count = number of instances to allocate.
|
||||
* Returns: pointer (of type T*) to memory buffer
|
||||
*/
|
||||
template <typename T>
|
||||
T* allocate(size_t count = 1)
|
||||
{
|
||||
T* mem = (T*) this->allocateMemory((int)(sizeof(T)*count));
|
||||
return mem;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_ALLOCATOR_H_
|
||||
@@ -0,0 +1,304 @@
|
||||
#ifndef OPENCV_FLANN_ANY_H_
|
||||
#define OPENCV_FLANN_ANY_H_
|
||||
/*
|
||||
* (C) Copyright Christopher Diggins 2005-2011
|
||||
* (C) Copyright Pablo Aguilar 2005
|
||||
* (C) Copyright Kevlin Henney 2001
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0. (See
|
||||
* accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt
|
||||
*
|
||||
* Adapted for FLANN by Marius Muja
|
||||
*/
|
||||
|
||||
#include "defines.h"
|
||||
#include <stdexcept>
|
||||
#include <ostream>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
namespace anyimpl
|
||||
{
|
||||
|
||||
struct bad_any_cast
|
||||
{
|
||||
};
|
||||
|
||||
struct empty_any
|
||||
{
|
||||
};
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& out, const empty_any&)
|
||||
{
|
||||
out << "[empty_any]";
|
||||
return out;
|
||||
}
|
||||
|
||||
struct base_any_policy
|
||||
{
|
||||
virtual void static_delete(void** x) = 0;
|
||||
virtual void copy_from_value(void const* src, void** dest) = 0;
|
||||
virtual void clone(void* const* src, void** dest) = 0;
|
||||
virtual void move(void* const* src, void** dest) = 0;
|
||||
virtual void* get_value(void** src) = 0;
|
||||
virtual ::size_t get_size() = 0;
|
||||
virtual const std::type_info& type() = 0;
|
||||
virtual void print(std::ostream& out, void* const* src) = 0;
|
||||
|
||||
#ifdef OPENCV_CAN_BREAK_BINARY_COMPATIBILITY
|
||||
virtual ~base_any_policy() {}
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct typed_base_any_policy : base_any_policy
|
||||
{
|
||||
virtual ::size_t get_size() { return sizeof(T); }
|
||||
virtual const std::type_info& type() { return typeid(T); }
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct small_any_policy : typed_base_any_policy<T>
|
||||
{
|
||||
virtual void static_delete(void**) { }
|
||||
virtual void copy_from_value(void const* src, void** dest)
|
||||
{
|
||||
new (dest) T(* reinterpret_cast<T const*>(src));
|
||||
}
|
||||
virtual void clone(void* const* src, void** dest) { *dest = *src; }
|
||||
virtual void move(void* const* src, void** dest) { *dest = *src; }
|
||||
virtual void* get_value(void** src) { return reinterpret_cast<void*>(src); }
|
||||
virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(src); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct big_any_policy : typed_base_any_policy<T>
|
||||
{
|
||||
virtual void static_delete(void** x)
|
||||
{
|
||||
if (* x) delete (* reinterpret_cast<T**>(x)); *x = NULL;
|
||||
}
|
||||
virtual void copy_from_value(void const* src, void** dest)
|
||||
{
|
||||
*dest = new T(*reinterpret_cast<T const*>(src));
|
||||
}
|
||||
virtual void clone(void* const* src, void** dest)
|
||||
{
|
||||
*dest = new T(**reinterpret_cast<T* const*>(src));
|
||||
}
|
||||
virtual void move(void* const* src, void** dest)
|
||||
{
|
||||
(*reinterpret_cast<T**>(dest))->~T();
|
||||
**reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src);
|
||||
}
|
||||
virtual void* get_value(void** src) { return *src; }
|
||||
virtual void print(std::ostream& out, void* const* src) { out << *reinterpret_cast<T const*>(*src); }
|
||||
};
|
||||
|
||||
template<> inline void big_any_policy<flann_centers_init_t>::print(std::ostream& out, void* const* src)
|
||||
{
|
||||
out << int(*reinterpret_cast<flann_centers_init_t const*>(*src));
|
||||
}
|
||||
|
||||
template<> inline void big_any_policy<flann_algorithm_t>::print(std::ostream& out, void* const* src)
|
||||
{
|
||||
out << int(*reinterpret_cast<flann_algorithm_t const*>(*src));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct choose_policy
|
||||
{
|
||||
typedef big_any_policy<T> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct choose_policy<T*>
|
||||
{
|
||||
typedef small_any_policy<T*> type;
|
||||
};
|
||||
|
||||
struct any;
|
||||
|
||||
/// Choosing the policy for an any type is illegal, but should never happen.
|
||||
/// This is designed to throw a compiler error.
|
||||
template<>
|
||||
struct choose_policy<any>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
/// Specializations for small types.
|
||||
#define SMALL_POLICY(TYPE) \
|
||||
template<> \
|
||||
struct choose_policy<TYPE> { typedef small_any_policy<TYPE> type; \
|
||||
}
|
||||
|
||||
SMALL_POLICY(signed char);
|
||||
SMALL_POLICY(unsigned char);
|
||||
SMALL_POLICY(signed short);
|
||||
SMALL_POLICY(unsigned short);
|
||||
SMALL_POLICY(signed int);
|
||||
SMALL_POLICY(unsigned int);
|
||||
SMALL_POLICY(signed long);
|
||||
SMALL_POLICY(unsigned long);
|
||||
SMALL_POLICY(float);
|
||||
SMALL_POLICY(bool);
|
||||
|
||||
#undef SMALL_POLICY
|
||||
|
||||
/// This function will return a different policy for each type.
|
||||
template<typename T>
|
||||
base_any_policy* get_policy()
|
||||
{
|
||||
static typename choose_policy<T>::type policy;
|
||||
return &policy;
|
||||
}
|
||||
} // namespace anyimpl
|
||||
|
||||
struct any
|
||||
{
|
||||
private:
|
||||
// fields
|
||||
anyimpl::base_any_policy* policy;
|
||||
void* object;
|
||||
|
||||
public:
|
||||
/// Initializing constructor.
|
||||
template <typename T>
|
||||
any(const T& x)
|
||||
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
|
||||
{
|
||||
assign(x);
|
||||
}
|
||||
|
||||
/// Empty constructor.
|
||||
any()
|
||||
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
|
||||
{ }
|
||||
|
||||
/// Special initializing constructor for string literals.
|
||||
any(const char* x)
|
||||
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
|
||||
{
|
||||
assign(x);
|
||||
}
|
||||
|
||||
/// Copy constructor.
|
||||
any(const any& x)
|
||||
: policy(anyimpl::get_policy<anyimpl::empty_any>()), object(NULL)
|
||||
{
|
||||
assign(x);
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
~any()
|
||||
{
|
||||
policy->static_delete(&object);
|
||||
}
|
||||
|
||||
/// Assignment function from another any.
|
||||
any& assign(const any& x)
|
||||
{
|
||||
reset();
|
||||
policy = x.policy;
|
||||
policy->clone(&x.object, &object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assignment function.
|
||||
template <typename T>
|
||||
any& assign(const T& x)
|
||||
{
|
||||
reset();
|
||||
policy = anyimpl::get_policy<T>();
|
||||
policy->copy_from_value(&x, &object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assignment operator.
|
||||
template<typename T>
|
||||
any& operator=(const T& x)
|
||||
{
|
||||
return assign(x);
|
||||
}
|
||||
|
||||
/// Assignment operator, specialed for literal strings.
|
||||
/// They have types like const char [6] which don't work as expected.
|
||||
any& operator=(const char* x)
|
||||
{
|
||||
return assign(x);
|
||||
}
|
||||
|
||||
/// Utility functions
|
||||
any& swap(any& x)
|
||||
{
|
||||
std::swap(policy, x.policy);
|
||||
std::swap(object, x.object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Cast operator. You can only cast to the original type.
|
||||
template<typename T>
|
||||
T& cast()
|
||||
{
|
||||
if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
|
||||
T* r = reinterpret_cast<T*>(policy->get_value(&object));
|
||||
return *r;
|
||||
}
|
||||
|
||||
/// Cast operator. You can only cast to the original type.
|
||||
template<typename T>
|
||||
const T& cast() const
|
||||
{
|
||||
if (policy->type() != typeid(T)) throw anyimpl::bad_any_cast();
|
||||
T* r = reinterpret_cast<T*>(policy->get_value(const_cast<void **>(&object)));
|
||||
return *r;
|
||||
}
|
||||
|
||||
/// Returns true if the any contains no value.
|
||||
bool empty() const
|
||||
{
|
||||
return policy->type() == typeid(anyimpl::empty_any);
|
||||
}
|
||||
|
||||
/// Frees any allocated memory, and sets the value to NULL.
|
||||
void reset()
|
||||
{
|
||||
policy->static_delete(&object);
|
||||
policy = anyimpl::get_policy<anyimpl::empty_any>();
|
||||
}
|
||||
|
||||
/// Returns true if the two types are the same.
|
||||
bool compatible(const any& x) const
|
||||
{
|
||||
return policy->type() == x.policy->type();
|
||||
}
|
||||
|
||||
/// Returns if the type is compatible with the policy
|
||||
template<typename T>
|
||||
bool has_type()
|
||||
{
|
||||
return policy->type() == typeid(T);
|
||||
}
|
||||
|
||||
const std::type_info& type() const
|
||||
{
|
||||
return policy->type();
|
||||
}
|
||||
|
||||
friend std::ostream& operator <<(std::ostream& out, const any& any_val);
|
||||
};
|
||||
|
||||
inline std::ostream& operator <<(std::ostream& out, const any& any_val)
|
||||
{
|
||||
any_val.policy->print(out,&any_val.object);
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENCV_FLANN_ANY_H_
|
||||
@@ -0,0 +1,583 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
#ifndef OPENCV_FLANN_AUTOTUNED_INDEX_H_
|
||||
#define OPENCV_FLANN_AUTOTUNED_INDEX_H_
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
#include "ground_truth.h"
|
||||
#include "index_testing.h"
|
||||
#include "sampling.h"
|
||||
#include "kdtree_index.h"
|
||||
#include "kdtree_single_index.h"
|
||||
#include "kmeans_index.h"
|
||||
#include "composite_index.h"
|
||||
#include "linear_index.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
template<typename Distance>
|
||||
NNIndex<Distance>* create_index_by_type(const Matrix<typename Distance::ElementType>& dataset, const IndexParams& params, const Distance& distance);
|
||||
|
||||
|
||||
struct AutotunedIndexParams : public IndexParams
|
||||
{
|
||||
AutotunedIndexParams(float target_precision = 0.8, float build_weight = 0.01, float memory_weight = 0, float sample_fraction = 0.1)
|
||||
{
|
||||
(*this)["algorithm"] = FLANN_INDEX_AUTOTUNED;
|
||||
// precision desired (used for autotuning, -1 otherwise)
|
||||
(*this)["target_precision"] = target_precision;
|
||||
// build tree time weighting factor
|
||||
(*this)["build_weight"] = build_weight;
|
||||
// index memory weighting factor
|
||||
(*this)["memory_weight"] = memory_weight;
|
||||
// what fraction of the dataset to use for autotuning
|
||||
(*this)["sample_fraction"] = sample_fraction;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
class AutotunedIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
AutotunedIndex(const Matrix<ElementType>& inputData, const IndexParams& params = AutotunedIndexParams(), Distance d = Distance()) :
|
||||
dataset_(inputData), distance_(d)
|
||||
{
|
||||
target_precision_ = get_param(params, "target_precision",0.8f);
|
||||
build_weight_ = get_param(params,"build_weight", 0.01f);
|
||||
memory_weight_ = get_param(params, "memory_weight", 0.0f);
|
||||
sample_fraction_ = get_param(params,"sample_fraction", 0.1f);
|
||||
bestIndex_ = NULL;
|
||||
}
|
||||
|
||||
AutotunedIndex(const AutotunedIndex&);
|
||||
AutotunedIndex& operator=(const AutotunedIndex&);
|
||||
|
||||
virtual ~AutotunedIndex()
|
||||
{
|
||||
if (bestIndex_ != NULL) {
|
||||
delete bestIndex_;
|
||||
bestIndex_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method responsible with building the index.
|
||||
*/
|
||||
virtual void buildIndex()
|
||||
{
|
||||
bestParams_ = estimateBuildParams();
|
||||
Logger::info("----------------------------------------------------\n");
|
||||
Logger::info("Autotuned parameters:\n");
|
||||
print_params(bestParams_);
|
||||
Logger::info("----------------------------------------------------\n");
|
||||
|
||||
bestIndex_ = create_index_by_type(dataset_, bestParams_, distance_);
|
||||
bestIndex_->buildIndex();
|
||||
speedup_ = estimateSearchParams(bestSearchParams_);
|
||||
Logger::info("----------------------------------------------------\n");
|
||||
Logger::info("Search parameters:\n");
|
||||
print_params(bestSearchParams_);
|
||||
Logger::info("----------------------------------------------------\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the index to a stream
|
||||
*/
|
||||
virtual void saveIndex(FILE* stream)
|
||||
{
|
||||
save_value(stream, (int)bestIndex_->getType());
|
||||
bestIndex_->saveIndex(stream);
|
||||
save_value(stream, get_param<int>(bestSearchParams_, "checks"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the index from a stream
|
||||
*/
|
||||
virtual void loadIndex(FILE* stream)
|
||||
{
|
||||
int index_type;
|
||||
|
||||
load_value(stream, index_type);
|
||||
IndexParams params;
|
||||
params["algorithm"] = (flann_algorithm_t)index_type;
|
||||
bestIndex_ = create_index_by_type<Distance>(dataset_, params, distance_);
|
||||
bestIndex_->loadIndex(stream);
|
||||
int checks;
|
||||
load_value(stream, checks);
|
||||
bestSearchParams_["checks"] = checks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that searches for nearest-neighbors
|
||||
*/
|
||||
virtual void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
|
||||
{
|
||||
int checks = get_param<int>(searchParams,"checks",FLANN_CHECKS_AUTOTUNED);
|
||||
if (checks == FLANN_CHECKS_AUTOTUNED) {
|
||||
bestIndex_->findNeighbors(result, vec, bestSearchParams_);
|
||||
}
|
||||
else {
|
||||
bestIndex_->findNeighbors(result, vec, searchParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return bestIndex_->getParameters();
|
||||
}
|
||||
|
||||
SearchParams getSearchParameters() const
|
||||
{
|
||||
return bestSearchParams_;
|
||||
}
|
||||
|
||||
float getSpeedup() const
|
||||
{
|
||||
return speedup_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Number of features in this index.
|
||||
*/
|
||||
virtual size_t size() const
|
||||
{
|
||||
return bestIndex_->size();
|
||||
}
|
||||
|
||||
/**
|
||||
* The length of each vector in this index.
|
||||
*/
|
||||
virtual size_t veclen() const
|
||||
{
|
||||
return bestIndex_->veclen();
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of memory (in bytes) this index uses.
|
||||
*/
|
||||
virtual int usedMemory() const
|
||||
{
|
||||
return bestIndex_->usedMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm name
|
||||
*/
|
||||
virtual flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_AUTOTUNED;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct CostData
|
||||
{
|
||||
float searchTimeCost;
|
||||
float buildTimeCost;
|
||||
float memoryCost;
|
||||
float totalCost;
|
||||
IndexParams params;
|
||||
};
|
||||
|
||||
void evaluate_kmeans(CostData& cost)
|
||||
{
|
||||
StartStopTimer t;
|
||||
int checks;
|
||||
const int nn = 1;
|
||||
|
||||
Logger::info("KMeansTree using params: max_iterations=%d, branching=%d\n",
|
||||
get_param<int>(cost.params,"iterations"),
|
||||
get_param<int>(cost.params,"branching"));
|
||||
KMeansIndex<Distance> kmeans(sampledDataset_, cost.params, distance_);
|
||||
// measure index build time
|
||||
t.start();
|
||||
kmeans.buildIndex();
|
||||
t.stop();
|
||||
float buildTime = (float)t.value;
|
||||
|
||||
// measure search time
|
||||
float searchTime = test_index_precision(kmeans, sampledDataset_, testDataset_, gt_matches_, target_precision_, checks, distance_, nn);
|
||||
|
||||
float datasetMemory = float(sampledDataset_.rows * sampledDataset_.cols * sizeof(float));
|
||||
cost.memoryCost = (kmeans.usedMemory() + datasetMemory) / datasetMemory;
|
||||
cost.searchTimeCost = searchTime;
|
||||
cost.buildTimeCost = buildTime;
|
||||
Logger::info("KMeansTree buildTime=%g, searchTime=%g, build_weight=%g\n", buildTime, searchTime, build_weight_);
|
||||
}
|
||||
|
||||
|
||||
void evaluate_kdtree(CostData& cost)
|
||||
{
|
||||
StartStopTimer t;
|
||||
int checks;
|
||||
const int nn = 1;
|
||||
|
||||
Logger::info("KDTree using params: trees=%d\n", get_param<int>(cost.params,"trees"));
|
||||
KDTreeIndex<Distance> kdtree(sampledDataset_, cost.params, distance_);
|
||||
|
||||
t.start();
|
||||
kdtree.buildIndex();
|
||||
t.stop();
|
||||
float buildTime = (float)t.value;
|
||||
|
||||
//measure search time
|
||||
float searchTime = test_index_precision(kdtree, sampledDataset_, testDataset_, gt_matches_, target_precision_, checks, distance_, nn);
|
||||
|
||||
float datasetMemory = float(sampledDataset_.rows * sampledDataset_.cols * sizeof(float));
|
||||
cost.memoryCost = (kdtree.usedMemory() + datasetMemory) / datasetMemory;
|
||||
cost.searchTimeCost = searchTime;
|
||||
cost.buildTimeCost = buildTime;
|
||||
Logger::info("KDTree buildTime=%g, searchTime=%g\n", buildTime, searchTime);
|
||||
}
|
||||
|
||||
|
||||
// struct KMeansSimpleDownhillFunctor {
|
||||
//
|
||||
// Autotune& autotuner;
|
||||
// KMeansSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {};
|
||||
//
|
||||
// float operator()(int* params) {
|
||||
//
|
||||
// float maxFloat = numeric_limits<float>::max();
|
||||
//
|
||||
// if (params[0]<2) return maxFloat;
|
||||
// if (params[1]<0) return maxFloat;
|
||||
//
|
||||
// CostData c;
|
||||
// c.params["algorithm"] = KMEANS;
|
||||
// c.params["centers-init"] = CENTERS_RANDOM;
|
||||
// c.params["branching"] = params[0];
|
||||
// c.params["max-iterations"] = params[1];
|
||||
//
|
||||
// autotuner.evaluate_kmeans(c);
|
||||
//
|
||||
// return c.timeCost;
|
||||
//
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// struct KDTreeSimpleDownhillFunctor {
|
||||
//
|
||||
// Autotune& autotuner;
|
||||
// KDTreeSimpleDownhillFunctor(Autotune& autotuner_) : autotuner(autotuner_) {};
|
||||
//
|
||||
// float operator()(int* params) {
|
||||
// float maxFloat = numeric_limits<float>::max();
|
||||
//
|
||||
// if (params[0]<1) return maxFloat;
|
||||
//
|
||||
// CostData c;
|
||||
// c.params["algorithm"] = KDTREE;
|
||||
// c.params["trees"] = params[0];
|
||||
//
|
||||
// autotuner.evaluate_kdtree(c);
|
||||
//
|
||||
// return c.timeCost;
|
||||
//
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
void optimizeKMeans(std::vector<CostData>& costs)
|
||||
{
|
||||
Logger::info("KMEANS, Step 1: Exploring parameter space\n");
|
||||
|
||||
// explore kmeans parameters space using combinations of the parameters below
|
||||
int maxIterations[] = { 1, 5, 10, 15 };
|
||||
int branchingFactors[] = { 16, 32, 64, 128, 256 };
|
||||
|
||||
int kmeansParamSpaceSize = FLANN_ARRAY_LEN(maxIterations) * FLANN_ARRAY_LEN(branchingFactors);
|
||||
costs.reserve(costs.size() + kmeansParamSpaceSize);
|
||||
|
||||
// evaluate kmeans for all parameter combinations
|
||||
for (size_t i = 0; i < FLANN_ARRAY_LEN(maxIterations); ++i) {
|
||||
for (size_t j = 0; j < FLANN_ARRAY_LEN(branchingFactors); ++j) {
|
||||
CostData cost;
|
||||
cost.params["algorithm"] = FLANN_INDEX_KMEANS;
|
||||
cost.params["centers_init"] = FLANN_CENTERS_RANDOM;
|
||||
cost.params["iterations"] = maxIterations[i];
|
||||
cost.params["branching"] = branchingFactors[j];
|
||||
|
||||
evaluate_kmeans(cost);
|
||||
costs.push_back(cost);
|
||||
}
|
||||
}
|
||||
|
||||
// Logger::info("KMEANS, Step 2: simplex-downhill optimization\n");
|
||||
//
|
||||
// const int n = 2;
|
||||
// // choose initial simplex points as the best parameters so far
|
||||
// int kmeansNMPoints[n*(n+1)];
|
||||
// float kmeansVals[n+1];
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kmeansNMPoints[i*n] = (int)kmeansCosts[i].params["branching"];
|
||||
// kmeansNMPoints[i*n+1] = (int)kmeansCosts[i].params["max-iterations"];
|
||||
// kmeansVals[i] = kmeansCosts[i].timeCost;
|
||||
// }
|
||||
// KMeansSimpleDownhillFunctor kmeans_cost_func(*this);
|
||||
// // run optimization
|
||||
// optimizeSimplexDownhill(kmeansNMPoints,n,kmeans_cost_func,kmeansVals);
|
||||
// // store results
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kmeansCosts[i].params["branching"] = kmeansNMPoints[i*2];
|
||||
// kmeansCosts[i].params["max-iterations"] = kmeansNMPoints[i*2+1];
|
||||
// kmeansCosts[i].timeCost = kmeansVals[i];
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void optimizeKDTree(std::vector<CostData>& costs)
|
||||
{
|
||||
Logger::info("KD-TREE, Step 1: Exploring parameter space\n");
|
||||
|
||||
// explore kd-tree parameters space using the parameters below
|
||||
int testTrees[] = { 1, 4, 8, 16, 32 };
|
||||
|
||||
// evaluate kdtree for all parameter combinations
|
||||
for (size_t i = 0; i < FLANN_ARRAY_LEN(testTrees); ++i) {
|
||||
CostData cost;
|
||||
cost.params["trees"] = testTrees[i];
|
||||
|
||||
evaluate_kdtree(cost);
|
||||
costs.push_back(cost);
|
||||
}
|
||||
|
||||
// Logger::info("KD-TREE, Step 2: simplex-downhill optimization\n");
|
||||
//
|
||||
// const int n = 1;
|
||||
// // choose initial simplex points as the best parameters so far
|
||||
// int kdtreeNMPoints[n*(n+1)];
|
||||
// float kdtreeVals[n+1];
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kdtreeNMPoints[i] = (int)kdtreeCosts[i].params["trees"];
|
||||
// kdtreeVals[i] = kdtreeCosts[i].timeCost;
|
||||
// }
|
||||
// KDTreeSimpleDownhillFunctor kdtree_cost_func(*this);
|
||||
// // run optimization
|
||||
// optimizeSimplexDownhill(kdtreeNMPoints,n,kdtree_cost_func,kdtreeVals);
|
||||
// // store results
|
||||
// for (int i=0;i<n+1;++i) {
|
||||
// kdtreeCosts[i].params["trees"] = kdtreeNMPoints[i];
|
||||
// kdtreeCosts[i].timeCost = kdtreeVals[i];
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses the best nearest-neighbor algorithm and estimates the optimal
|
||||
* parameters to use when building the index (for a given precision).
|
||||
* Returns a dictionary with the optimal parameters.
|
||||
*/
|
||||
IndexParams estimateBuildParams()
|
||||
{
|
||||
std::vector<CostData> costs;
|
||||
|
||||
int sampleSize = int(sample_fraction_ * dataset_.rows);
|
||||
int testSampleSize = std::min(sampleSize / 10, 1000);
|
||||
|
||||
Logger::info("Entering autotuning, dataset size: %d, sampleSize: %d, testSampleSize: %d, target precision: %g\n", dataset_.rows, sampleSize, testSampleSize, target_precision_);
|
||||
|
||||
// For a very small dataset, it makes no sense to build any fancy index, just
|
||||
// use linear search
|
||||
if (testSampleSize < 10) {
|
||||
Logger::info("Choosing linear, dataset too small\n");
|
||||
return LinearIndexParams();
|
||||
}
|
||||
|
||||
// We use a fraction of the original dataset to speedup the autotune algorithm
|
||||
sampledDataset_ = random_sample(dataset_, sampleSize);
|
||||
// We use a cross-validation approach, first we sample a testset from the dataset
|
||||
testDataset_ = random_sample(sampledDataset_, testSampleSize, true);
|
||||
|
||||
// We compute the ground truth using linear search
|
||||
Logger::info("Computing ground truth... \n");
|
||||
gt_matches_ = Matrix<int>(new int[testDataset_.rows], testDataset_.rows, 1);
|
||||
StartStopTimer t;
|
||||
t.start();
|
||||
compute_ground_truth<Distance>(sampledDataset_, testDataset_, gt_matches_, 0, distance_);
|
||||
t.stop();
|
||||
|
||||
CostData linear_cost;
|
||||
linear_cost.searchTimeCost = (float)t.value;
|
||||
linear_cost.buildTimeCost = 0;
|
||||
linear_cost.memoryCost = 0;
|
||||
linear_cost.params["algorithm"] = FLANN_INDEX_LINEAR;
|
||||
|
||||
costs.push_back(linear_cost);
|
||||
|
||||
// Start parameter autotune process
|
||||
Logger::info("Autotuning parameters...\n");
|
||||
|
||||
optimizeKMeans(costs);
|
||||
optimizeKDTree(costs);
|
||||
|
||||
float bestTimeCost = costs[0].searchTimeCost;
|
||||
for (size_t i = 0; i < costs.size(); ++i) {
|
||||
float timeCost = costs[i].buildTimeCost * build_weight_ + costs[i].searchTimeCost;
|
||||
if (timeCost < bestTimeCost) {
|
||||
bestTimeCost = timeCost;
|
||||
}
|
||||
}
|
||||
|
||||
float bestCost = costs[0].searchTimeCost / bestTimeCost;
|
||||
IndexParams bestParams = costs[0].params;
|
||||
if (bestTimeCost > 0) {
|
||||
for (size_t i = 0; i < costs.size(); ++i) {
|
||||
float crtCost = (costs[i].buildTimeCost * build_weight_ + costs[i].searchTimeCost) / bestTimeCost +
|
||||
memory_weight_ * costs[i].memoryCost;
|
||||
if (crtCost < bestCost) {
|
||||
bestCost = crtCost;
|
||||
bestParams = costs[i].params;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] gt_matches_.data;
|
||||
delete[] testDataset_.data;
|
||||
delete[] sampledDataset_.data;
|
||||
|
||||
return bestParams;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Estimates the search time parameters needed to get the desired precision.
|
||||
* Precondition: the index is built
|
||||
* Postcondition: the searchParams will have the optimum params set, also the speedup obtained over linear search.
|
||||
*/
|
||||
float estimateSearchParams(SearchParams& searchParams)
|
||||
{
|
||||
const int nn = 1;
|
||||
const size_t SAMPLE_COUNT = 1000;
|
||||
|
||||
assert(bestIndex_ != NULL); // must have a valid index
|
||||
|
||||
float speedup = 0;
|
||||
|
||||
int samples = (int)std::min(dataset_.rows / 10, SAMPLE_COUNT);
|
||||
if (samples > 0) {
|
||||
Matrix<ElementType> testDataset = random_sample(dataset_, samples);
|
||||
|
||||
Logger::info("Computing ground truth\n");
|
||||
|
||||
// we need to compute the ground truth first
|
||||
Matrix<int> gt_matches(new int[testDataset.rows], testDataset.rows, 1);
|
||||
StartStopTimer t;
|
||||
t.start();
|
||||
compute_ground_truth<Distance>(dataset_, testDataset, gt_matches, 1, distance_);
|
||||
t.stop();
|
||||
float linear = (float)t.value;
|
||||
|
||||
int checks;
|
||||
Logger::info("Estimating number of checks\n");
|
||||
|
||||
float searchTime;
|
||||
float cb_index;
|
||||
if (bestIndex_->getType() == FLANN_INDEX_KMEANS) {
|
||||
Logger::info("KMeans algorithm, estimating cluster border factor\n");
|
||||
KMeansIndex<Distance>* kmeans = (KMeansIndex<Distance>*)bestIndex_;
|
||||
float bestSearchTime = -1;
|
||||
float best_cb_index = -1;
|
||||
int best_checks = -1;
|
||||
for (cb_index = 0; cb_index < 1.1f; cb_index += 0.2f) {
|
||||
kmeans->set_cb_index(cb_index);
|
||||
searchTime = test_index_precision(*kmeans, dataset_, testDataset, gt_matches, target_precision_, checks, distance_, nn, 1);
|
||||
if ((searchTime < bestSearchTime) || (bestSearchTime == -1)) {
|
||||
bestSearchTime = searchTime;
|
||||
best_cb_index = cb_index;
|
||||
best_checks = checks;
|
||||
}
|
||||
}
|
||||
searchTime = bestSearchTime;
|
||||
cb_index = best_cb_index;
|
||||
checks = best_checks;
|
||||
|
||||
kmeans->set_cb_index(best_cb_index);
|
||||
Logger::info("Optimum cb_index: %g\n", cb_index);
|
||||
bestParams_["cb_index"] = cb_index;
|
||||
}
|
||||
else {
|
||||
searchTime = test_index_precision(*bestIndex_, dataset_, testDataset, gt_matches, target_precision_, checks, distance_, nn, 1);
|
||||
}
|
||||
|
||||
Logger::info("Required number of checks: %d \n", checks);
|
||||
searchParams["checks"] = checks;
|
||||
|
||||
speedup = linear / searchTime;
|
||||
|
||||
delete[] gt_matches.data;
|
||||
delete[] testDataset.data;
|
||||
}
|
||||
|
||||
return speedup;
|
||||
}
|
||||
|
||||
private:
|
||||
NNIndex<Distance>* bestIndex_;
|
||||
|
||||
IndexParams bestParams_;
|
||||
SearchParams bestSearchParams_;
|
||||
|
||||
Matrix<ElementType> sampledDataset_;
|
||||
Matrix<ElementType> testDataset_;
|
||||
Matrix<int> gt_matches_;
|
||||
|
||||
float speedup_;
|
||||
|
||||
/**
|
||||
* The dataset used by this index
|
||||
*/
|
||||
const Matrix<ElementType> dataset_;
|
||||
|
||||
/**
|
||||
* Index parameters
|
||||
*/
|
||||
float target_precision_;
|
||||
float build_weight_;
|
||||
float memory_weight_;
|
||||
float sample_fraction_;
|
||||
|
||||
Distance distance_;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* OPENCV_FLANN_AUTOTUNED_INDEX_H_ */
|
||||
@@ -0,0 +1,194 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_COMPOSITE_INDEX_H_
|
||||
#define OPENCV_FLANN_COMPOSITE_INDEX_H_
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
#include "kdtree_index.h"
|
||||
#include "kmeans_index.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Index parameters for the CompositeIndex.
|
||||
*/
|
||||
struct CompositeIndexParams : public IndexParams
|
||||
{
|
||||
CompositeIndexParams(int trees = 4, int branching = 32, int iterations = 11,
|
||||
flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM, float cb_index = 0.2 )
|
||||
{
|
||||
(*this)["algorithm"] = FLANN_INDEX_KMEANS;
|
||||
// number of randomized trees to use (for kdtree)
|
||||
(*this)["trees"] = trees;
|
||||
// branching factor
|
||||
(*this)["branching"] = branching;
|
||||
// max iterations to perform in one kmeans clustering (kmeans tree)
|
||||
(*this)["iterations"] = iterations;
|
||||
// algorithm used for picking the initial cluster centers for kmeans tree
|
||||
(*this)["centers_init"] = centers_init;
|
||||
// cluster boundary index. Used when searching the kmeans tree
|
||||
(*this)["cb_index"] = cb_index;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This index builds a kd-tree index and a k-means index and performs nearest
|
||||
* neighbour search both indexes. This gives a slight boost in search performance
|
||||
* as some of the neighbours that are missed by one index are found by the other.
|
||||
*/
|
||||
template <typename Distance>
|
||||
class CompositeIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
/**
|
||||
* Index constructor
|
||||
* @param inputData dataset containing the points to index
|
||||
* @param params Index parameters
|
||||
* @param d Distance functor
|
||||
* @return
|
||||
*/
|
||||
CompositeIndex(const Matrix<ElementType>& inputData, const IndexParams& params = CompositeIndexParams(),
|
||||
Distance d = Distance()) : index_params_(params)
|
||||
{
|
||||
kdtree_index_ = new KDTreeIndex<Distance>(inputData, params, d);
|
||||
kmeans_index_ = new KMeansIndex<Distance>(inputData, params, d);
|
||||
|
||||
}
|
||||
|
||||
CompositeIndex(const CompositeIndex&);
|
||||
CompositeIndex& operator=(const CompositeIndex&);
|
||||
|
||||
virtual ~CompositeIndex()
|
||||
{
|
||||
delete kdtree_index_;
|
||||
delete kmeans_index_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The index type
|
||||
*/
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_COMPOSITE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Size of the index
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return kdtree_index_->size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns The dimensionality of the features in this index.
|
||||
*/
|
||||
size_t veclen() const
|
||||
{
|
||||
return kdtree_index_->veclen();
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns The amount of memory (in bytes) used by the index.
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
return kmeans_index_->usedMemory() + kdtree_index_->usedMemory();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
Logger::info("Building kmeans tree...\n");
|
||||
kmeans_index_->buildIndex();
|
||||
Logger::info("Building kdtree tree...\n");
|
||||
kdtree_index_->buildIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Saves the index to a stream
|
||||
* \param stream The stream to save the index to
|
||||
*/
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
kmeans_index_->saveIndex(stream);
|
||||
kdtree_index_->saveIndex(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Loads the index from a stream
|
||||
* \param stream The stream from which the index is loaded
|
||||
*/
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
kmeans_index_->loadIndex(stream);
|
||||
kdtree_index_->loadIndex(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns The index parameters
|
||||
*/
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return index_params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Method that searches for nearest-neighbours
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
|
||||
{
|
||||
kmeans_index_->findNeighbors(result, vec, searchParams);
|
||||
kdtree_index_->findNeighbors(result, vec, searchParams);
|
||||
}
|
||||
|
||||
private:
|
||||
/** The k-means index */
|
||||
KMeansIndex<Distance>* kmeans_index_;
|
||||
|
||||
/** The kd-tree index */
|
||||
KDTreeIndex<Distance>* kdtree_index_;
|
||||
|
||||
/** The index parameters */
|
||||
const IndexParams index_params_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_COMPOSITE_INDEX_H_
|
||||
@@ -0,0 +1,38 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef OPENCV_FLANN_CONFIG_H_
|
||||
#define OPENCV_FLANN_CONFIG_H_
|
||||
|
||||
#ifdef FLANN_VERSION_
|
||||
#undef FLANN_VERSION_
|
||||
#endif
|
||||
#define FLANN_VERSION_ "1.6.10"
|
||||
|
||||
#endif /* OPENCV_FLANN_CONFIG_H_ */
|
||||
@@ -0,0 +1,176 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef OPENCV_FLANN_DEFINES_H_
|
||||
#define OPENCV_FLANN_DEFINES_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef FLANN_EXPORT
|
||||
#undef FLANN_EXPORT
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
/* win32 dll export/import directives */
|
||||
#ifdef FLANN_EXPORTS
|
||||
#define FLANN_EXPORT __declspec(dllexport)
|
||||
#elif defined(FLANN_STATIC)
|
||||
#define FLANN_EXPORT
|
||||
#else
|
||||
#define FLANN_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
/* unix needs nothing */
|
||||
#define FLANN_EXPORT
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FLANN_DEPRECATED
|
||||
#undef FLANN_DEPRECATED
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
#define FLANN_DEPRECATED __attribute__ ((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define FLANN_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
#pragma message("WARNING: You need to implement FLANN_DEPRECATED for this compiler")
|
||||
#define FLANN_DEPRECATED
|
||||
#endif
|
||||
|
||||
|
||||
#undef FLANN_PLATFORM_32_BIT
|
||||
#undef FLANN_PLATFORM_64_BIT
|
||||
#if defined __amd64__ || defined __x86_64__ || defined _WIN64 || defined _M_X64
|
||||
#define FLANN_PLATFORM_64_BIT
|
||||
#else
|
||||
#define FLANN_PLATFORM_32_BIT
|
||||
#endif
|
||||
|
||||
|
||||
#undef FLANN_ARRAY_LEN
|
||||
#define FLANN_ARRAY_LEN(a) (sizeof(a)/sizeof(a[0]))
|
||||
|
||||
namespace cvflann {
|
||||
|
||||
/* Nearest neighbour index algorithms */
|
||||
enum flann_algorithm_t
|
||||
{
|
||||
FLANN_INDEX_LINEAR = 0,
|
||||
FLANN_INDEX_KDTREE = 1,
|
||||
FLANN_INDEX_KMEANS = 2,
|
||||
FLANN_INDEX_COMPOSITE = 3,
|
||||
FLANN_INDEX_KDTREE_SINGLE = 4,
|
||||
FLANN_INDEX_HIERARCHICAL = 5,
|
||||
FLANN_INDEX_LSH = 6,
|
||||
FLANN_INDEX_SAVED = 254,
|
||||
FLANN_INDEX_AUTOTUNED = 255,
|
||||
|
||||
// deprecated constants, should use the FLANN_INDEX_* ones instead
|
||||
LINEAR = 0,
|
||||
KDTREE = 1,
|
||||
KMEANS = 2,
|
||||
COMPOSITE = 3,
|
||||
KDTREE_SINGLE = 4,
|
||||
SAVED = 254,
|
||||
AUTOTUNED = 255
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum flann_centers_init_t
|
||||
{
|
||||
FLANN_CENTERS_RANDOM = 0,
|
||||
FLANN_CENTERS_GONZALES = 1,
|
||||
FLANN_CENTERS_KMEANSPP = 2,
|
||||
|
||||
// deprecated constants, should use the FLANN_CENTERS_* ones instead
|
||||
CENTERS_RANDOM = 0,
|
||||
CENTERS_GONZALES = 1,
|
||||
CENTERS_KMEANSPP = 2
|
||||
};
|
||||
|
||||
enum flann_log_level_t
|
||||
{
|
||||
FLANN_LOG_NONE = 0,
|
||||
FLANN_LOG_FATAL = 1,
|
||||
FLANN_LOG_ERROR = 2,
|
||||
FLANN_LOG_WARN = 3,
|
||||
FLANN_LOG_INFO = 4
|
||||
};
|
||||
|
||||
enum flann_distance_t
|
||||
{
|
||||
FLANN_DIST_EUCLIDEAN = 1,
|
||||
FLANN_DIST_L2 = 1,
|
||||
FLANN_DIST_MANHATTAN = 2,
|
||||
FLANN_DIST_L1 = 2,
|
||||
FLANN_DIST_MINKOWSKI = 3,
|
||||
FLANN_DIST_MAX = 4,
|
||||
FLANN_DIST_HIST_INTERSECT = 5,
|
||||
FLANN_DIST_HELLINGER = 6,
|
||||
FLANN_DIST_CHI_SQUARE = 7,
|
||||
FLANN_DIST_CS = 7,
|
||||
FLANN_DIST_KULLBACK_LEIBLER = 8,
|
||||
FLANN_DIST_KL = 8,
|
||||
FLANN_DIST_HAMMING = 9,
|
||||
|
||||
// deprecated constants, should use the FLANN_DIST_* ones instead
|
||||
EUCLIDEAN = 1,
|
||||
MANHATTAN = 2,
|
||||
MINKOWSKI = 3,
|
||||
MAX_DIST = 4,
|
||||
HIST_INTERSECT = 5,
|
||||
HELLINGER = 6,
|
||||
CS = 7,
|
||||
KL = 8,
|
||||
KULLBACK_LEIBLER = 8
|
||||
};
|
||||
|
||||
enum flann_datatype_t
|
||||
{
|
||||
FLANN_INT8 = 0,
|
||||
FLANN_INT16 = 1,
|
||||
FLANN_INT32 = 2,
|
||||
FLANN_INT64 = 3,
|
||||
FLANN_UINT8 = 4,
|
||||
FLANN_UINT16 = 5,
|
||||
FLANN_UINT32 = 6,
|
||||
FLANN_UINT64 = 7,
|
||||
FLANN_FLOAT32 = 8,
|
||||
FLANN_FLOAT64 = 9
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FLANN_CHECKS_UNLIMITED = -1,
|
||||
FLANN_CHECKS_AUTOTUNED = -2
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENCV_FLANN_DEFINES_H_ */
|
||||
@@ -0,0 +1,817 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_DIST_H_
|
||||
#define OPENCV_FLANN_DIST_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <string.h>
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
#if (defined WIN32 || defined _WIN32) && defined(_M_ARM)
|
||||
# include <Intrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef __ARM_NEON__
|
||||
# include "arm_neon.h"
|
||||
#endif
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
inline T abs(T x) { return (x<0) ? -x : x; }
|
||||
|
||||
template<>
|
||||
inline int abs<int>(int x) { return ::abs(x); }
|
||||
|
||||
template<>
|
||||
inline float abs<float>(float x) { return fabsf(x); }
|
||||
|
||||
template<>
|
||||
inline double abs<double>(double x) { return fabs(x); }
|
||||
|
||||
template<typename T>
|
||||
struct Accumulator { typedef T Type; };
|
||||
template<>
|
||||
struct Accumulator<unsigned char> { typedef float Type; };
|
||||
template<>
|
||||
struct Accumulator<unsigned short> { typedef float Type; };
|
||||
template<>
|
||||
struct Accumulator<unsigned int> { typedef float Type; };
|
||||
template<>
|
||||
struct Accumulator<char> { typedef float Type; };
|
||||
template<>
|
||||
struct Accumulator<short> { typedef float Type; };
|
||||
template<>
|
||||
struct Accumulator<int> { typedef float Type; };
|
||||
|
||||
#undef True
|
||||
#undef False
|
||||
|
||||
class True
|
||||
{
|
||||
};
|
||||
|
||||
class False
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Squared Euclidean distance functor.
|
||||
*
|
||||
* This is the simpler, unrolled version. This is preferable for
|
||||
* very low dimensionality data (eg 3D points)
|
||||
*/
|
||||
template<class T>
|
||||
struct L2_Simple
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType diff;
|
||||
for(size_t i = 0; i < size; ++i ) {
|
||||
diff = *a++ - *b++;
|
||||
result += diff*diff;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
return (a-b)*(a-b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Squared Euclidean distance functor, optimized version
|
||||
*/
|
||||
template<class T>
|
||||
struct L2
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the squared Euclidean distance between two vectors.
|
||||
*
|
||||
* This is highly optimised, with loop unrolling, as it is one
|
||||
* of the most expensive inner loops.
|
||||
*
|
||||
* The computation of squared root at the end is omitted for
|
||||
* efficiency.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType diff0, diff1, diff2, diff3;
|
||||
Iterator1 last = a + size;
|
||||
Iterator1 lastgroup = last - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (a < lastgroup) {
|
||||
diff0 = (ResultType)(a[0] - b[0]);
|
||||
diff1 = (ResultType)(a[1] - b[1]);
|
||||
diff2 = (ResultType)(a[2] - b[2]);
|
||||
diff3 = (ResultType)(a[3] - b[3]);
|
||||
result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
|
||||
a += 4;
|
||||
b += 4;
|
||||
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (a < last) {
|
||||
diff0 = (ResultType)(*a++ - *b++);
|
||||
result += diff0 * diff0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial euclidean distance, using just one dimension. This is used by the
|
||||
* kd-tree when computing partial distances while traversing the tree.
|
||||
*
|
||||
* Squared root is omitted for efficiency.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
return (a-b)*(a-b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Manhattan distance functor, optimized version
|
||||
*/
|
||||
template<class T>
|
||||
struct L1
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the Manhattan (L_1) distance between two vectors.
|
||||
*
|
||||
* This is highly optimised, with loop unrolling, as it is one
|
||||
* of the most expensive inner loops.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType diff0, diff1, diff2, diff3;
|
||||
Iterator1 last = a + size;
|
||||
Iterator1 lastgroup = last - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (a < lastgroup) {
|
||||
diff0 = (ResultType)abs(a[0] - b[0]);
|
||||
diff1 = (ResultType)abs(a[1] - b[1]);
|
||||
diff2 = (ResultType)abs(a[2] - b[2]);
|
||||
diff3 = (ResultType)abs(a[3] - b[3]);
|
||||
result += diff0 + diff1 + diff2 + diff3;
|
||||
a += 4;
|
||||
b += 4;
|
||||
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (a < last) {
|
||||
diff0 = (ResultType)abs(*a++ - *b++);
|
||||
result += diff0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial distance, used by the kd-tree.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
return abs(a-b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
struct MinkowskiDistance
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
int order;
|
||||
|
||||
MinkowskiDistance(int order_) : order(order_) {}
|
||||
|
||||
/**
|
||||
* Compute the Minkowsky (L_p) distance between two vectors.
|
||||
*
|
||||
* This is highly optimised, with loop unrolling, as it is one
|
||||
* of the most expensive inner loops.
|
||||
*
|
||||
* The computation of squared root at the end is omitted for
|
||||
* efficiency.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType diff0, diff1, diff2, diff3;
|
||||
Iterator1 last = a + size;
|
||||
Iterator1 lastgroup = last - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (a < lastgroup) {
|
||||
diff0 = (ResultType)abs(a[0] - b[0]);
|
||||
diff1 = (ResultType)abs(a[1] - b[1]);
|
||||
diff2 = (ResultType)abs(a[2] - b[2]);
|
||||
diff3 = (ResultType)abs(a[3] - b[3]);
|
||||
result += pow(diff0,order) + pow(diff1,order) + pow(diff2,order) + pow(diff3,order);
|
||||
a += 4;
|
||||
b += 4;
|
||||
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (a < last) {
|
||||
diff0 = (ResultType)abs(*a++ - *b++);
|
||||
result += pow(diff0,order);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial distance, used by the kd-tree.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
return pow(static_cast<ResultType>(abs(a-b)),order);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
struct MaxDistance
|
||||
{
|
||||
typedef False is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the max distance (L_infinity) between two vectors.
|
||||
*
|
||||
* This distance is not a valid kdtree distance, it's not dimensionwise additive.
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType diff0, diff1, diff2, diff3;
|
||||
Iterator1 last = a + size;
|
||||
Iterator1 lastgroup = last - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (a < lastgroup) {
|
||||
diff0 = abs(a[0] - b[0]);
|
||||
diff1 = abs(a[1] - b[1]);
|
||||
diff2 = abs(a[2] - b[2]);
|
||||
diff3 = abs(a[3] - b[3]);
|
||||
if (diff0>result) {result = diff0; }
|
||||
if (diff1>result) {result = diff1; }
|
||||
if (diff2>result) {result = diff2; }
|
||||
if (diff3>result) {result = diff3; }
|
||||
a += 4;
|
||||
b += 4;
|
||||
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (a < last) {
|
||||
diff0 = abs(*a++ - *b++);
|
||||
result = (diff0>result) ? diff0 : result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This distance functor is not dimension-wise additive, which
|
||||
* makes it an invalid kd-tree distance, not implementing the accum_dist method */
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
|
||||
* bit count of A exclusive XOR'ed with B
|
||||
*/
|
||||
struct HammingLUT
|
||||
{
|
||||
typedef False is_kdtree_distance;
|
||||
typedef False is_vector_space_distance;
|
||||
|
||||
typedef unsigned char ElementType;
|
||||
typedef int ResultType;
|
||||
|
||||
/** this will count the bits in a ^ b
|
||||
*/
|
||||
ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const
|
||||
{
|
||||
static const uchar popCountTable[] =
|
||||
{
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
||||
};
|
||||
ResultType result = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
result += popCountTable[a[i] ^ b[i]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
|
||||
* bit count of A exclusive XOR'ed with B
|
||||
*/
|
||||
struct HammingLUT2
|
||||
{
|
||||
typedef False is_kdtree_distance;
|
||||
typedef False is_vector_space_distance;
|
||||
|
||||
typedef unsigned char ElementType;
|
||||
typedef int ResultType;
|
||||
|
||||
/** this will count the bits in a ^ b
|
||||
*/
|
||||
ResultType operator()(const unsigned char* a, const unsigned char* b, size_t size) const
|
||||
{
|
||||
static const uchar popCountTable[] =
|
||||
{
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
||||
};
|
||||
ResultType result = 0;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
result += popCountTable[a[i] ^ b[i]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hamming distance functor (pop count between two binary vectors, i.e. xor them and count the number of bits set)
|
||||
* That code was taken from brief.cpp in OpenCV
|
||||
*/
|
||||
template<class T>
|
||||
struct Hamming
|
||||
{
|
||||
typedef False is_kdtree_distance;
|
||||
typedef False is_vector_space_distance;
|
||||
|
||||
|
||||
typedef T ElementType;
|
||||
typedef int ResultType;
|
||||
|
||||
template<typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
|
||||
{
|
||||
ResultType result = 0;
|
||||
#ifdef __ARM_NEON__
|
||||
{
|
||||
uint32x4_t bits = vmovq_n_u32(0);
|
||||
for (size_t i = 0; i < size; i += 16) {
|
||||
uint8x16_t A_vec = vld1q_u8 (a + i);
|
||||
uint8x16_t B_vec = vld1q_u8 (b + i);
|
||||
uint8x16_t AxorB = veorq_u8 (A_vec, B_vec);
|
||||
uint8x16_t bitsSet = vcntq_u8 (AxorB);
|
||||
uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet);
|
||||
uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8);
|
||||
bits = vaddq_u32(bits, bitSet4);
|
||||
}
|
||||
uint64x2_t bitSet2 = vpaddlq_u32 (bits);
|
||||
result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0);
|
||||
result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2);
|
||||
}
|
||||
#elif __GNUC__
|
||||
{
|
||||
//for portability just use unsigned long -- and use the __builtin_popcountll (see docs for __builtin_popcountll)
|
||||
typedef unsigned long long pop_t;
|
||||
const size_t modulo = size % sizeof(pop_t);
|
||||
const pop_t* a2 = reinterpret_cast<const pop_t*> (a);
|
||||
const pop_t* b2 = reinterpret_cast<const pop_t*> (b);
|
||||
const pop_t* a2_end = a2 + (size / sizeof(pop_t));
|
||||
|
||||
for (; a2 != a2_end; ++a2, ++b2) result += __builtin_popcountll((*a2) ^ (*b2));
|
||||
|
||||
if (modulo) {
|
||||
//in the case where size is not dividable by sizeof(size_t)
|
||||
//need to mask off the bits at the end
|
||||
pop_t a_final = 0, b_final = 0;
|
||||
memcpy(&a_final, a2, modulo);
|
||||
memcpy(&b_final, b2, modulo);
|
||||
result += __builtin_popcountll(a_final ^ b_final);
|
||||
}
|
||||
}
|
||||
#else // NO NEON and NOT GNUC
|
||||
typedef unsigned long long pop_t;
|
||||
HammingLUT lut;
|
||||
result = lut(reinterpret_cast<const unsigned char*> (a),
|
||||
reinterpret_cast<const unsigned char*> (b), size * sizeof(pop_t));
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Hamming2
|
||||
{
|
||||
typedef False is_kdtree_distance;
|
||||
typedef False is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef int ResultType;
|
||||
|
||||
/** This is popcount_3() from:
|
||||
* http://en.wikipedia.org/wiki/Hamming_weight */
|
||||
unsigned int popcnt32(uint32_t n) const
|
||||
{
|
||||
n -= ((n >> 1) & 0x55555555);
|
||||
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
|
||||
return (((n + (n >> 4))& 0xF0F0F0F)* 0x1010101) >> 24;
|
||||
}
|
||||
|
||||
#ifdef FLANN_PLATFORM_64_BIT
|
||||
unsigned int popcnt64(uint64_t n) const
|
||||
{
|
||||
n -= ((n >> 1) & 0x5555555555555555);
|
||||
n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333);
|
||||
return (((n + (n >> 4))& 0x0f0f0f0f0f0f0f0f)* 0x0101010101010101) >> 56;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
|
||||
{
|
||||
#ifdef FLANN_PLATFORM_64_BIT
|
||||
const uint64_t* pa = reinterpret_cast<const uint64_t*>(a);
|
||||
const uint64_t* pb = reinterpret_cast<const uint64_t*>(b);
|
||||
ResultType result = 0;
|
||||
size /= (sizeof(uint64_t)/sizeof(unsigned char));
|
||||
for(size_t i = 0; i < size; ++i ) {
|
||||
result += popcnt64(*pa ^ *pb);
|
||||
++pa;
|
||||
++pb;
|
||||
}
|
||||
#else
|
||||
const uint32_t* pa = reinterpret_cast<const uint32_t*>(a);
|
||||
const uint32_t* pb = reinterpret_cast<const uint32_t*>(b);
|
||||
ResultType result = 0;
|
||||
size /= (sizeof(uint32_t)/sizeof(unsigned char));
|
||||
for(size_t i = 0; i < size; ++i ) {
|
||||
result += popcnt32(*pa ^ *pb);
|
||||
++pa;
|
||||
++pb;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
struct HistIntersectionDistance
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the histogram intersection distance
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType min0, min1, min2, min3;
|
||||
Iterator1 last = a + size;
|
||||
Iterator1 lastgroup = last - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (a < lastgroup) {
|
||||
min0 = (ResultType)(a[0] < b[0] ? a[0] : b[0]);
|
||||
min1 = (ResultType)(a[1] < b[1] ? a[1] : b[1]);
|
||||
min2 = (ResultType)(a[2] < b[2] ? a[2] : b[2]);
|
||||
min3 = (ResultType)(a[3] < b[3] ? a[3] : b[3]);
|
||||
result += min0 + min1 + min2 + min3;
|
||||
a += 4;
|
||||
b += 4;
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
/* Process last 0-3 pixels. Not needed for standard vector lengths. */
|
||||
while (a < last) {
|
||||
min0 = (ResultType)(*a < *b ? *a : *b);
|
||||
result += min0;
|
||||
++a;
|
||||
++b;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial distance, used by the kd-tree.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<class T>
|
||||
struct HellingerDistance
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the histogram intersection distance
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType diff0, diff1, diff2, diff3;
|
||||
Iterator1 last = a + size;
|
||||
Iterator1 lastgroup = last - 3;
|
||||
|
||||
/* Process 4 items with each loop for efficiency. */
|
||||
while (a < lastgroup) {
|
||||
diff0 = sqrt(static_cast<ResultType>(a[0])) - sqrt(static_cast<ResultType>(b[0]));
|
||||
diff1 = sqrt(static_cast<ResultType>(a[1])) - sqrt(static_cast<ResultType>(b[1]));
|
||||
diff2 = sqrt(static_cast<ResultType>(a[2])) - sqrt(static_cast<ResultType>(b[2]));
|
||||
diff3 = sqrt(static_cast<ResultType>(a[3])) - sqrt(static_cast<ResultType>(b[3]));
|
||||
result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
|
||||
a += 4;
|
||||
b += 4;
|
||||
}
|
||||
while (a < last) {
|
||||
diff0 = sqrt(static_cast<ResultType>(*a++)) - sqrt(static_cast<ResultType>(*b++));
|
||||
result += diff0 * diff0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial distance, used by the kd-tree.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
return sqrt(static_cast<ResultType>(a)) - sqrt(static_cast<ResultType>(b));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
struct ChiSquareDistance
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the chi-square distance
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType sum, diff;
|
||||
Iterator1 last = a + size;
|
||||
|
||||
while (a < last) {
|
||||
sum = (ResultType)(*a + *b);
|
||||
if (sum>0) {
|
||||
diff = (ResultType)(*a - *b);
|
||||
result += diff*diff/sum;
|
||||
}
|
||||
++a;
|
||||
++b;
|
||||
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial distance, used by the kd-tree.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType sum, diff;
|
||||
|
||||
sum = (ResultType)(a+b);
|
||||
if (sum>0) {
|
||||
diff = (ResultType)(a-b);
|
||||
result = diff*diff/sum;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
struct KL_Divergence
|
||||
{
|
||||
typedef True is_kdtree_distance;
|
||||
typedef True is_vector_space_distance;
|
||||
|
||||
typedef T ElementType;
|
||||
typedef typename Accumulator<T>::Type ResultType;
|
||||
|
||||
/**
|
||||
* Compute the Kullback–Leibler divergence
|
||||
*/
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
Iterator1 last = a + size;
|
||||
|
||||
while (a < last) {
|
||||
if (* a != 0) {
|
||||
ResultType ratio = (ResultType)(*a / *b);
|
||||
if (ratio>0) {
|
||||
result += *a * log(ratio);
|
||||
}
|
||||
}
|
||||
++a;
|
||||
++b;
|
||||
|
||||
if ((worst_dist>0)&&(result>worst_dist)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial distance, used by the kd-tree.
|
||||
*/
|
||||
template <typename U, typename V>
|
||||
inline ResultType accum_dist(const U& a, const V& b, int) const
|
||||
{
|
||||
ResultType result = ResultType();
|
||||
ResultType ratio = (ResultType)(a / b);
|
||||
if (ratio>0) {
|
||||
result = a * log(ratio);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This is a "zero iterator". It basically behaves like a zero filled
|
||||
* array to all algorithms that use arrays as iterators (STL style).
|
||||
* It's useful when there's a need to compute the distance between feature
|
||||
* and origin it and allows for better compiler optimisation than using a
|
||||
* zero-filled array.
|
||||
*/
|
||||
template <typename T>
|
||||
struct ZeroIterator
|
||||
{
|
||||
|
||||
T operator*()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
T operator[](int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const ZeroIterator<T>& operator ++()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZeroIterator<T> operator ++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZeroIterator<T>& operator+=(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_DIST_H_
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
#ifndef OPENCV_FLANN_DUMMY_H_
|
||||
#define OPENCV_FLANN_DUMMY_H_
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
#if (defined WIN32 || defined _WIN32 || defined WINCE) && defined CVAPI_EXPORTS
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void dummyfunc();
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* OPENCV_FLANN_DUMMY_H_ */
|
||||
@@ -0,0 +1,159 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Author: Vincent Rabaud
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_DYNAMIC_BITSET_H_
|
||||
#define OPENCV_FLANN_DYNAMIC_BITSET_H_
|
||||
|
||||
#ifndef FLANN_USE_BOOST
|
||||
# define FLANN_USE_BOOST 0
|
||||
#endif
|
||||
//#define FLANN_USE_BOOST 1
|
||||
#if FLANN_USE_BOOST
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
typedef boost::dynamic_bitset<> DynamicBitset;
|
||||
#else
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "dist.h"
|
||||
|
||||
namespace cvflann {
|
||||
|
||||
/** Class re-implementing the boost version of it
|
||||
* This helps not depending on boost, it also does not do the bound checks
|
||||
* and has a way to reset a block for speed
|
||||
*/
|
||||
class DynamicBitset
|
||||
{
|
||||
public:
|
||||
/** @param default constructor
|
||||
*/
|
||||
DynamicBitset()
|
||||
{
|
||||
}
|
||||
|
||||
/** @param only constructor we use in our code
|
||||
* @param the size of the bitset (in bits)
|
||||
*/
|
||||
DynamicBitset(size_t sz)
|
||||
{
|
||||
resize(sz);
|
||||
reset();
|
||||
}
|
||||
|
||||
/** Sets all the bits to 0
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
std::fill(bitset_.begin(), bitset_.end(), 0);
|
||||
}
|
||||
|
||||
/** @brief checks if the bitset is empty
|
||||
* @return true if the bitset is empty
|
||||
*/
|
||||
bool empty() const
|
||||
{
|
||||
return bitset_.empty();
|
||||
}
|
||||
|
||||
/** @param set all the bits to 0
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
std::fill(bitset_.begin(), bitset_.end(), 0);
|
||||
}
|
||||
|
||||
/** @brief set one bit to 0
|
||||
* @param
|
||||
*/
|
||||
void reset(size_t index)
|
||||
{
|
||||
bitset_[index / cell_bit_size_] &= ~(size_t(1) << (index % cell_bit_size_));
|
||||
}
|
||||
|
||||
/** @brief sets a specific bit to 0, and more bits too
|
||||
* This function is useful when resetting a given set of bits so that the
|
||||
* whole bitset ends up being 0: if that's the case, we don't care about setting
|
||||
* other bits to 0
|
||||
* @param
|
||||
*/
|
||||
void reset_block(size_t index)
|
||||
{
|
||||
bitset_[index / cell_bit_size_] = 0;
|
||||
}
|
||||
|
||||
/** @param resize the bitset so that it contains at least size bits
|
||||
* @param size
|
||||
*/
|
||||
void resize(size_t sz)
|
||||
{
|
||||
size_ = sz;
|
||||
bitset_.resize(sz / cell_bit_size_ + 1);
|
||||
}
|
||||
|
||||
/** @param set a bit to true
|
||||
* @param index the index of the bit to set to 1
|
||||
*/
|
||||
void set(size_t index)
|
||||
{
|
||||
bitset_[index / cell_bit_size_] |= size_t(1) << (index % cell_bit_size_);
|
||||
}
|
||||
|
||||
/** @param gives the number of contained bits
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
/** @param check if a bit is set
|
||||
* @param index the index of the bit to check
|
||||
* @return true if the bit is set
|
||||
*/
|
||||
bool test(size_t index) const
|
||||
{
|
||||
return (bitset_[index / cell_bit_size_] & (size_t(1) << (index % cell_bit_size_))) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<size_t> bitset_;
|
||||
size_t size_;
|
||||
static const unsigned int cell_bit_size_ = CHAR_BIT * sizeof(size_t);
|
||||
};
|
||||
|
||||
} // namespace cvflann
|
||||
|
||||
#endif
|
||||
|
||||
#endif // OPENCV_FLANN_DYNAMIC_BITSET_H_
|
||||
@@ -0,0 +1,427 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef _OPENCV_FLANN_HPP_
|
||||
#define _OPENCV_FLANN_HPP_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "opencv2/core/types_c.h"
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/flann/flann_base.hpp"
|
||||
#include "opencv2/flann/miniflann.hpp"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
CV_EXPORTS flann_distance_t flann_distance_type();
|
||||
FLANN_DEPRECATED CV_EXPORTS void set_distance_type(flann_distance_t distance_type, int order);
|
||||
}
|
||||
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace flann
|
||||
{
|
||||
|
||||
template <typename T> struct CvType {};
|
||||
template <> struct CvType<unsigned char> { static int type() { return CV_8U; } };
|
||||
template <> struct CvType<char> { static int type() { return CV_8S; } };
|
||||
template <> struct CvType<unsigned short> { static int type() { return CV_16U; } };
|
||||
template <> struct CvType<short> { static int type() { return CV_16S; } };
|
||||
template <> struct CvType<int> { static int type() { return CV_32S; } };
|
||||
template <> struct CvType<float> { static int type() { return CV_32F; } };
|
||||
template <> struct CvType<double> { static int type() { return CV_64F; } };
|
||||
|
||||
|
||||
// bring the flann parameters into this namespace
|
||||
using ::cvflann::get_param;
|
||||
using ::cvflann::print_params;
|
||||
|
||||
// bring the flann distances into this namespace
|
||||
using ::cvflann::L2_Simple;
|
||||
using ::cvflann::L2;
|
||||
using ::cvflann::L1;
|
||||
using ::cvflann::MinkowskiDistance;
|
||||
using ::cvflann::MaxDistance;
|
||||
using ::cvflann::HammingLUT;
|
||||
using ::cvflann::Hamming;
|
||||
using ::cvflann::Hamming2;
|
||||
using ::cvflann::HistIntersectionDistance;
|
||||
using ::cvflann::HellingerDistance;
|
||||
using ::cvflann::ChiSquareDistance;
|
||||
using ::cvflann::KL_Divergence;
|
||||
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
class GenericIndex
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
GenericIndex(const Mat& features, const ::cvflann::IndexParams& params, Distance distance = Distance());
|
||||
|
||||
~GenericIndex();
|
||||
|
||||
void knnSearch(const vector<ElementType>& query, vector<int>& indices,
|
||||
vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& params);
|
||||
void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);
|
||||
|
||||
int radiusSearch(const vector<ElementType>& query, vector<int>& indices,
|
||||
vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& params);
|
||||
int radiusSearch(const Mat& query, Mat& indices, Mat& dists,
|
||||
DistanceType radius, const ::cvflann::SearchParams& params);
|
||||
|
||||
void save(std::string filename) { nnIndex->save(filename); }
|
||||
|
||||
int veclen() const { return nnIndex->veclen(); }
|
||||
|
||||
int size() const { return nnIndex->size(); }
|
||||
|
||||
::cvflann::IndexParams getParameters() { return nnIndex->getParameters(); }
|
||||
|
||||
FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters() { return nnIndex->getIndexParameters(); }
|
||||
|
||||
private:
|
||||
::cvflann::Index<Distance>* nnIndex;
|
||||
};
|
||||
|
||||
|
||||
#define FLANN_DISTANCE_CHECK \
|
||||
if ( ::cvflann::flann_distance_type() != cvflann::FLANN_DIST_L2) { \
|
||||
printf("[WARNING] You are using cv::flann::Index (or cv::flann::GenericIndex) and have also changed "\
|
||||
"the distance using cvflann::set_distance_type. This is no longer working as expected "\
|
||||
"(cv::flann::Index always uses L2). You should create the index templated on the distance, "\
|
||||
"for example for L1 distance use: GenericIndex< L1<float> > \n"); \
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
GenericIndex<Distance>::GenericIndex(const Mat& dataset, const ::cvflann::IndexParams& params, Distance distance)
|
||||
{
|
||||
CV_Assert(dataset.type() == CvType<ElementType>::type());
|
||||
CV_Assert(dataset.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_dataset((ElementType*)dataset.ptr<ElementType>(0), dataset.rows, dataset.cols);
|
||||
|
||||
nnIndex = new ::cvflann::Index<Distance>(m_dataset, params, distance);
|
||||
|
||||
FLANN_DISTANCE_CHECK
|
||||
|
||||
nnIndex->buildIndex();
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
GenericIndex<Distance>::~GenericIndex()
|
||||
{
|
||||
delete nnIndex;
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
void GenericIndex<Distance>::knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
|
||||
::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
|
||||
::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
|
||||
|
||||
FLANN_DISTANCE_CHECK
|
||||
|
||||
nnIndex->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
void GenericIndex<Distance>::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
CV_Assert(queries.type() == CvType<ElementType>::type());
|
||||
CV_Assert(queries.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_queries((ElementType*)queries.ptr<ElementType>(0), queries.rows, queries.cols);
|
||||
|
||||
CV_Assert(indices.type() == CV_32S);
|
||||
CV_Assert(indices.isContinuous());
|
||||
::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
|
||||
|
||||
CV_Assert(dists.type() == CvType<DistanceType>::type());
|
||||
CV_Assert(dists.isContinuous());
|
||||
::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
|
||||
|
||||
FLANN_DISTANCE_CHECK
|
||||
|
||||
nnIndex->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
int GenericIndex<Distance>::radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
|
||||
::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
|
||||
::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
|
||||
|
||||
FLANN_DISTANCE_CHECK
|
||||
|
||||
return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
int GenericIndex<Distance>::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
CV_Assert(query.type() == CvType<ElementType>::type());
|
||||
CV_Assert(query.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_query((ElementType*)query.ptr<ElementType>(0), query.rows, query.cols);
|
||||
|
||||
CV_Assert(indices.type() == CV_32S);
|
||||
CV_Assert(indices.isContinuous());
|
||||
::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
|
||||
|
||||
CV_Assert(dists.type() == CvType<DistanceType>::type());
|
||||
CV_Assert(dists.isContinuous());
|
||||
::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
|
||||
|
||||
FLANN_DISTANCE_CHECK
|
||||
|
||||
return nnIndex->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use GenericIndex class instead
|
||||
*/
|
||||
template <typename T>
|
||||
class
|
||||
#ifndef _MSC_VER
|
||||
FLANN_DEPRECATED
|
||||
#endif
|
||||
Index_ {
|
||||
public:
|
||||
typedef typename L2<T>::ElementType ElementType;
|
||||
typedef typename L2<T>::ResultType DistanceType;
|
||||
|
||||
Index_(const Mat& features, const ::cvflann::IndexParams& params);
|
||||
|
||||
~Index_();
|
||||
|
||||
void knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& params);
|
||||
void knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& params);
|
||||
|
||||
int radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& params);
|
||||
int radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& params);
|
||||
|
||||
void save(std::string filename)
|
||||
{
|
||||
if (nnIndex_L1) nnIndex_L1->save(filename);
|
||||
if (nnIndex_L2) nnIndex_L2->save(filename);
|
||||
}
|
||||
|
||||
int veclen() const
|
||||
{
|
||||
if (nnIndex_L1) return nnIndex_L1->veclen();
|
||||
if (nnIndex_L2) return nnIndex_L2->veclen();
|
||||
}
|
||||
|
||||
int size() const
|
||||
{
|
||||
if (nnIndex_L1) return nnIndex_L1->size();
|
||||
if (nnIndex_L2) return nnIndex_L2->size();
|
||||
}
|
||||
|
||||
::cvflann::IndexParams getParameters()
|
||||
{
|
||||
if (nnIndex_L1) return nnIndex_L1->getParameters();
|
||||
if (nnIndex_L2) return nnIndex_L2->getParameters();
|
||||
|
||||
}
|
||||
|
||||
FLANN_DEPRECATED const ::cvflann::IndexParams* getIndexParameters()
|
||||
{
|
||||
if (nnIndex_L1) return nnIndex_L1->getIndexParameters();
|
||||
if (nnIndex_L2) return nnIndex_L2->getIndexParameters();
|
||||
}
|
||||
|
||||
private:
|
||||
// providing backwards compatibility for L2 and L1 distances (most common)
|
||||
::cvflann::Index< L2<ElementType> >* nnIndex_L2;
|
||||
::cvflann::Index< L1<ElementType> >* nnIndex_L1;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
template <typename T>
|
||||
class FLANN_DEPRECATED Index_;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
Index_<T>::Index_(const Mat& dataset, const ::cvflann::IndexParams& params)
|
||||
{
|
||||
printf("[WARNING] The cv::flann::Index_<T> class is deperecated, use cv::flann::GenericIndex<Distance> instead\n");
|
||||
|
||||
CV_Assert(dataset.type() == CvType<ElementType>::type());
|
||||
CV_Assert(dataset.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_dataset((ElementType*)dataset.ptr<ElementType>(0), dataset.rows, dataset.cols);
|
||||
|
||||
if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) {
|
||||
nnIndex_L1 = NULL;
|
||||
nnIndex_L2 = new ::cvflann::Index< L2<ElementType> >(m_dataset, params);
|
||||
}
|
||||
else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) {
|
||||
nnIndex_L1 = new ::cvflann::Index< L1<ElementType> >(m_dataset, params);
|
||||
nnIndex_L2 = NULL;
|
||||
}
|
||||
else {
|
||||
printf("[ERROR] cv::flann::Index_<T> only provides backwards compatibility for the L1 and L2 distances. "
|
||||
"For other distance types you must use cv::flann::GenericIndex<Distance>\n");
|
||||
CV_Assert(0);
|
||||
}
|
||||
if (nnIndex_L1) nnIndex_L1->buildIndex();
|
||||
if (nnIndex_L2) nnIndex_L2->buildIndex();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Index_<T>::~Index_()
|
||||
{
|
||||
if (nnIndex_L1) delete nnIndex_L1;
|
||||
if (nnIndex_L2) delete nnIndex_L2;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Index_<T>::knnSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, int knn, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
|
||||
::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
|
||||
::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
|
||||
|
||||
if (nnIndex_L1) nnIndex_L1->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
|
||||
if (nnIndex_L2) nnIndex_L2->knnSearch(m_query,m_indices,m_dists,knn,searchParams);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void Index_<T>::knnSearch(const Mat& queries, Mat& indices, Mat& dists, int knn, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
CV_Assert(queries.type() == CvType<ElementType>::type());
|
||||
CV_Assert(queries.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_queries((ElementType*)queries.ptr<ElementType>(0), queries.rows, queries.cols);
|
||||
|
||||
CV_Assert(indices.type() == CV_32S);
|
||||
CV_Assert(indices.isContinuous());
|
||||
::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
|
||||
|
||||
CV_Assert(dists.type() == CvType<DistanceType>::type());
|
||||
CV_Assert(dists.isContinuous());
|
||||
::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
|
||||
|
||||
if (nnIndex_L1) nnIndex_L1->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
|
||||
if (nnIndex_L2) nnIndex_L2->knnSearch(m_queries,m_indices,m_dists,knn, searchParams);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int Index_<T>::radiusSearch(const vector<ElementType>& query, vector<int>& indices, vector<DistanceType>& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
::cvflann::Matrix<ElementType> m_query((ElementType*)&query[0], 1, query.size());
|
||||
::cvflann::Matrix<int> m_indices(&indices[0], 1, indices.size());
|
||||
::cvflann::Matrix<DistanceType> m_dists(&dists[0], 1, dists.size());
|
||||
|
||||
if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
|
||||
if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int Index_<T>::radiusSearch(const Mat& query, Mat& indices, Mat& dists, DistanceType radius, const ::cvflann::SearchParams& searchParams)
|
||||
{
|
||||
CV_Assert(query.type() == CvType<ElementType>::type());
|
||||
CV_Assert(query.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_query((ElementType*)query.ptr<ElementType>(0), query.rows, query.cols);
|
||||
|
||||
CV_Assert(indices.type() == CV_32S);
|
||||
CV_Assert(indices.isContinuous());
|
||||
::cvflann::Matrix<int> m_indices((int*)indices.ptr<int>(0), indices.rows, indices.cols);
|
||||
|
||||
CV_Assert(dists.type() == CvType<DistanceType>::type());
|
||||
CV_Assert(dists.isContinuous());
|
||||
::cvflann::Matrix<DistanceType> m_dists((DistanceType*)dists.ptr<DistanceType>(0), dists.rows, dists.cols);
|
||||
|
||||
if (nnIndex_L1) return nnIndex_L1->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
|
||||
if (nnIndex_L2) return nnIndex_L2->radiusSearch(m_query,m_indices,m_dists,radius,searchParams);
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params,
|
||||
Distance d = Distance())
|
||||
{
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
CV_Assert(features.type() == CvType<ElementType>::type());
|
||||
CV_Assert(features.isContinuous());
|
||||
::cvflann::Matrix<ElementType> m_features((ElementType*)features.ptr<ElementType>(0), features.rows, features.cols);
|
||||
|
||||
CV_Assert(centers.type() == CvType<DistanceType>::type());
|
||||
CV_Assert(centers.isContinuous());
|
||||
::cvflann::Matrix<DistanceType> m_centers((DistanceType*)centers.ptr<DistanceType>(0), centers.rows, centers.cols);
|
||||
|
||||
return ::cvflann::hierarchicalClustering<Distance>(m_features, m_centers, params, d);
|
||||
}
|
||||
|
||||
|
||||
template <typename ELEM_TYPE, typename DIST_TYPE>
|
||||
FLANN_DEPRECATED int hierarchicalClustering(const Mat& features, Mat& centers, const ::cvflann::KMeansIndexParams& params)
|
||||
{
|
||||
printf("[WARNING] cv::flann::hierarchicalClustering<ELEM_TYPE,DIST_TYPE> is deprecated, use "
|
||||
"cv::flann::hierarchicalClustering<Distance> instead\n");
|
||||
|
||||
if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L2 ) {
|
||||
return hierarchicalClustering< L2<ELEM_TYPE> >(features, centers, params);
|
||||
}
|
||||
else if ( ::cvflann::flann_distance_type() == cvflann::FLANN_DIST_L1 ) {
|
||||
return hierarchicalClustering< L1<ELEM_TYPE> >(features, centers, params);
|
||||
}
|
||||
else {
|
||||
printf("[ERROR] cv::flann::hierarchicalClustering<ELEM_TYPE,DIST_TYPE> only provides backwards "
|
||||
"compatibility for the L1 and L2 distances. "
|
||||
"For other distance types you must use cv::flann::hierarchicalClustering<Distance>\n");
|
||||
CV_Assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
} } // namespace cv::flann
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,291 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_BASE_HPP_
|
||||
#define OPENCV_FLANN_BASE_HPP_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include "general.h"
|
||||
#include "matrix.h"
|
||||
#include "params.h"
|
||||
#include "saving.h"
|
||||
|
||||
#include "all_indices.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets the log level used for all flann functions
|
||||
* @param level Verbosity level
|
||||
*/
|
||||
inline void log_verbosity(int level)
|
||||
{
|
||||
if (level >= 0) {
|
||||
Logger::setLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (Deprecated) Index parameters for creating a saved index.
|
||||
*/
|
||||
struct SavedIndexParams : public IndexParams
|
||||
{
|
||||
SavedIndexParams(std::string filename)
|
||||
{
|
||||
(* this)["algorithm"] = FLANN_INDEX_SAVED;
|
||||
(*this)["filename"] = filename;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Distance>
|
||||
NNIndex<Distance>* load_saved_index(const Matrix<typename Distance::ElementType>& dataset, const std::string& filename, Distance distance)
|
||||
{
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
|
||||
FILE* fin = fopen(filename.c_str(), "rb");
|
||||
if (fin == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
IndexHeader header = load_header(fin);
|
||||
if (header.data_type != Datatype<ElementType>::type()) {
|
||||
throw FLANNException("Datatype of saved index is different than of the one to be created.");
|
||||
}
|
||||
if ((size_t(header.rows) != dataset.rows)||(size_t(header.cols) != dataset.cols)) {
|
||||
throw FLANNException("The index saved belongs to a different dataset");
|
||||
}
|
||||
|
||||
IndexParams params;
|
||||
params["algorithm"] = header.index_type;
|
||||
NNIndex<Distance>* nnIndex = create_index_by_type<Distance>(dataset, params, distance);
|
||||
nnIndex->loadIndex(fin);
|
||||
fclose(fin);
|
||||
|
||||
return nnIndex;
|
||||
}
|
||||
|
||||
|
||||
template<typename Distance>
|
||||
class Index : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
Index(const Matrix<ElementType>& features, const IndexParams& params, Distance distance = Distance() )
|
||||
: index_params_(params)
|
||||
{
|
||||
flann_algorithm_t index_type = get_param<flann_algorithm_t>(params,"algorithm");
|
||||
loaded_ = false;
|
||||
|
||||
if (index_type == FLANN_INDEX_SAVED) {
|
||||
nnIndex_ = load_saved_index<Distance>(features, get_param<std::string>(params,"filename"), distance);
|
||||
loaded_ = true;
|
||||
}
|
||||
else {
|
||||
nnIndex_ = create_index_by_type<Distance>(features, params, distance);
|
||||
}
|
||||
}
|
||||
|
||||
~Index()
|
||||
{
|
||||
delete nnIndex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the index.
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
if (!loaded_) {
|
||||
nnIndex_->buildIndex();
|
||||
}
|
||||
}
|
||||
|
||||
void save(std::string filename)
|
||||
{
|
||||
FILE* fout = fopen(filename.c_str(), "wb");
|
||||
if (fout == NULL) {
|
||||
throw FLANNException("Cannot open file");
|
||||
}
|
||||
save_header(fout, *nnIndex_);
|
||||
saveIndex(fout);
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Saves the index to a stream
|
||||
* \param stream The stream to save the index to
|
||||
*/
|
||||
virtual void saveIndex(FILE* stream)
|
||||
{
|
||||
nnIndex_->saveIndex(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Loads the index from a stream
|
||||
* \param stream The stream from which the index is loaded
|
||||
*/
|
||||
virtual void loadIndex(FILE* stream)
|
||||
{
|
||||
nnIndex_->loadIndex(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns number of features in this index.
|
||||
*/
|
||||
size_t veclen() const
|
||||
{
|
||||
return nnIndex_->veclen();
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns The dimensionality of the features in this index.
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return nnIndex_->size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns The index type (kdtree, kmeans,...)
|
||||
*/
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return nnIndex_->getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns The amount of memory (in bytes) used by the index.
|
||||
*/
|
||||
virtual int usedMemory() const
|
||||
{
|
||||
return nnIndex_->usedMemory();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \returns The index parameters
|
||||
*/
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return nnIndex_->getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
void knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, int knn, const SearchParams& params)
|
||||
{
|
||||
nnIndex_->knnSearch(queries, indices, dists, knn, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform radius search
|
||||
* \param[in] query The query point
|
||||
* \param[out] indices The indinces of the neighbors found within the given radius
|
||||
* \param[out] dists The distances to the nearest neighbors found
|
||||
* \param[in] radius The radius used for search
|
||||
* \param[in] params Search parameters
|
||||
* \returns Number of neighbors found
|
||||
*/
|
||||
int radiusSearch(const Matrix<ElementType>& query, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params)
|
||||
{
|
||||
return nnIndex_->radiusSearch(query, indices, dists, radius, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Method that searches for nearest-neighbours
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
|
||||
{
|
||||
nnIndex_->findNeighbors(result, vec, searchParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns actual index
|
||||
*/
|
||||
FLANN_DEPRECATED NNIndex<Distance>* getIndex()
|
||||
{
|
||||
return nnIndex_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns index parameters.
|
||||
* \deprecated use getParameters() instead.
|
||||
*/
|
||||
FLANN_DEPRECATED const IndexParams* getIndexParameters()
|
||||
{
|
||||
return &index_params_;
|
||||
}
|
||||
|
||||
private:
|
||||
/** Pointer to actual index class */
|
||||
NNIndex<Distance>* nnIndex_;
|
||||
/** Indices if the index was loaded from a file */
|
||||
bool loaded_;
|
||||
/** Parameters passed to the index */
|
||||
IndexParams index_params_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a hierarchical clustering of the points passed as argument and then takes a cut in the
|
||||
* the clustering tree to return a flat clustering.
|
||||
* @param[in] points Points to be clustered
|
||||
* @param centers The computed cluster centres. Matrix should be preallocated and centers.rows is the
|
||||
* number of clusters requested.
|
||||
* @param params Clustering parameters (The same as for cvflann::KMeansIndex)
|
||||
* @param d Distance to be used for clustering (eg: cvflann::L2)
|
||||
* @return number of clusters computed (can be different than clusters.rows and is the highest number
|
||||
* of the form (branching-1)*K+1 smaller than clusters.rows).
|
||||
*/
|
||||
template <typename Distance>
|
||||
int hierarchicalClustering(const Matrix<typename Distance::ElementType>& points, Matrix<typename Distance::ResultType>& centers,
|
||||
const KMeansIndexParams& params, Distance d = Distance())
|
||||
{
|
||||
KMeansIndex<Distance> kmeans(points, params, d);
|
||||
kmeans.buildIndex();
|
||||
|
||||
int clusterNum = kmeans.getClusterCenters(centers);
|
||||
return clusterNum;
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* OPENCV_FLANN_BASE_HPP_ */
|
||||
@@ -0,0 +1,52 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_GENERAL_H_
|
||||
#define OPENCV_FLANN_GENERAL_H_
|
||||
|
||||
#include "defines.h"
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
class FLANNException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
FLANNException(const char* message) : std::runtime_error(message) { }
|
||||
|
||||
FLANNException(const std::string& message) : std::runtime_error(message) { }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* OPENCV_FLANN_GENERAL_H_ */
|
||||
@@ -0,0 +1,94 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_GROUND_TRUTH_H_
|
||||
#define OPENCV_FLANN_GROUND_TRUTH_H_
|
||||
|
||||
#include "dist.h"
|
||||
#include "matrix.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
template <typename Distance>
|
||||
void find_nearest(const Matrix<typename Distance::ElementType>& dataset, typename Distance::ElementType* query, int* matches, int nn,
|
||||
int skip = 0, Distance distance = Distance())
|
||||
{
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
int n = nn + skip;
|
||||
|
||||
std::vector<int> match(n);
|
||||
std::vector<DistanceType> dists(n);
|
||||
|
||||
dists[0] = distance(dataset[0], query, dataset.cols);
|
||||
match[0] = 0;
|
||||
int dcnt = 1;
|
||||
|
||||
for (size_t i=1; i<dataset.rows; ++i) {
|
||||
DistanceType tmp = distance(dataset[i], query, dataset.cols);
|
||||
|
||||
if (dcnt<n) {
|
||||
match[dcnt] = (int)i;
|
||||
dists[dcnt++] = tmp;
|
||||
}
|
||||
else if (tmp < dists[dcnt-1]) {
|
||||
dists[dcnt-1] = tmp;
|
||||
match[dcnt-1] = (int)i;
|
||||
}
|
||||
|
||||
int j = dcnt-1;
|
||||
// bubble up
|
||||
while (j>=1 && dists[j]<dists[j-1]) {
|
||||
std::swap(dists[j],dists[j-1]);
|
||||
std::swap(match[j],match[j-1]);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<nn; ++i) {
|
||||
matches[i] = match[i+skip];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
void compute_ground_truth(const Matrix<typename Distance::ElementType>& dataset, const Matrix<typename Distance::ElementType>& testset, Matrix<int>& matches,
|
||||
int skip=0, Distance d = Distance())
|
||||
{
|
||||
for (size_t i=0; i<testset.rows; ++i) {
|
||||
find_nearest<Distance>(dataset, testset[i], matches[i], (int)matches.cols, skip, d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_GROUND_TRUTH_H_
|
||||
@@ -0,0 +1,231 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef OPENCV_FLANN_HDF5_H_
|
||||
#define OPENCV_FLANN_HDF5_H_
|
||||
|
||||
#include <hdf5.h>
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
hid_t get_hdf5_type()
|
||||
{
|
||||
throw FLANNException("Unsupported type for IO operations");
|
||||
}
|
||||
|
||||
template<>
|
||||
hid_t get_hdf5_type<char>() { return H5T_NATIVE_CHAR; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned char>() { return H5T_NATIVE_UCHAR; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<short int>() { return H5T_NATIVE_SHORT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned short int>() { return H5T_NATIVE_USHORT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<int>() { return H5T_NATIVE_INT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned int>() { return H5T_NATIVE_UINT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<long>() { return H5T_NATIVE_LONG; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<unsigned long>() { return H5T_NATIVE_ULONG; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<float>() { return H5T_NATIVE_FLOAT; }
|
||||
template<>
|
||||
hid_t get_hdf5_type<double>() { return H5T_NATIVE_DOUBLE; }
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_ERROR(x,y) if ((x)<0) throw FLANNException((y));
|
||||
|
||||
template<typename T>
|
||||
void save_to_file(const cvflann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
|
||||
{
|
||||
|
||||
#if H5Eset_auto_vers == 2
|
||||
H5Eset_auto( H5E_DEFAULT, NULL, NULL );
|
||||
#else
|
||||
H5Eset_auto( NULL, NULL );
|
||||
#endif
|
||||
|
||||
herr_t status;
|
||||
hid_t file_id;
|
||||
file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
|
||||
if (file_id < 0) {
|
||||
file_id = H5Fcreate(filename.c_str(), H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
|
||||
}
|
||||
CHECK_ERROR(file_id,"Error creating hdf5 file.");
|
||||
|
||||
hsize_t dimsf[2]; // dataset dimensions
|
||||
dimsf[0] = dataset.rows;
|
||||
dimsf[1] = dataset.cols;
|
||||
|
||||
hid_t space_id = H5Screate_simple(2, dimsf, NULL);
|
||||
hid_t memspace_id = H5Screate_simple(2, dimsf, NULL);
|
||||
|
||||
hid_t dataset_id;
|
||||
#if H5Dcreate_vers == 2
|
||||
dataset_id = H5Dcreate2(file_id, name.c_str(), get_hdf5_type<T>(), space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dcreate(file_id, name.c_str(), get_hdf5_type<T>(), space_id, H5P_DEFAULT);
|
||||
#endif
|
||||
|
||||
if (dataset_id<0) {
|
||||
#if H5Dopen_vers == 2
|
||||
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dopen(file_id, name.c_str());
|
||||
#endif
|
||||
}
|
||||
CHECK_ERROR(dataset_id,"Error creating or opening dataset in file.");
|
||||
|
||||
status = H5Dwrite(dataset_id, get_hdf5_type<T>(), memspace_id, space_id, H5P_DEFAULT, dataset.data );
|
||||
CHECK_ERROR(status, "Error writing to dataset");
|
||||
|
||||
H5Sclose(memspace_id);
|
||||
H5Sclose(space_id);
|
||||
H5Dclose(dataset_id);
|
||||
H5Fclose(file_id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void load_from_file(cvflann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
|
||||
{
|
||||
herr_t status;
|
||||
hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
|
||||
CHECK_ERROR(file_id,"Error opening hdf5 file.");
|
||||
|
||||
hid_t dataset_id;
|
||||
#if H5Dopen_vers == 2
|
||||
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dopen(file_id, name.c_str());
|
||||
#endif
|
||||
CHECK_ERROR(dataset_id,"Error opening dataset in file.");
|
||||
|
||||
hid_t space_id = H5Dget_space(dataset_id);
|
||||
|
||||
hsize_t dims_out[2];
|
||||
H5Sget_simple_extent_dims(space_id, dims_out, NULL);
|
||||
|
||||
dataset = cvflann::Matrix<T>(new T[dims_out[0]*dims_out[1]], dims_out[0], dims_out[1]);
|
||||
|
||||
status = H5Dread(dataset_id, get_hdf5_type<T>(), H5S_ALL, H5S_ALL, H5P_DEFAULT, dataset[0]);
|
||||
CHECK_ERROR(status, "Error reading dataset");
|
||||
|
||||
H5Sclose(space_id);
|
||||
H5Dclose(dataset_id);
|
||||
H5Fclose(file_id);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_MPI
|
||||
|
||||
namespace mpi
|
||||
{
|
||||
/**
|
||||
* Loads a the hyperslice corresponding to this processor from a hdf5 file.
|
||||
* @param flann_dataset Dataset where the data is loaded
|
||||
* @param filename HDF5 file name
|
||||
* @param name Name of dataset inside file
|
||||
*/
|
||||
template<typename T>
|
||||
void load_from_file(cvflann::Matrix<T>& dataset, const std::string& filename, const std::string& name)
|
||||
{
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
MPI_Info info = MPI_INFO_NULL;
|
||||
|
||||
int mpi_size, mpi_rank;
|
||||
MPI_Comm_size(comm, &mpi_size);
|
||||
MPI_Comm_rank(comm, &mpi_rank);
|
||||
|
||||
herr_t status;
|
||||
|
||||
hid_t plist_id = H5Pcreate(H5P_FILE_ACCESS);
|
||||
H5Pset_fapl_mpio(plist_id, comm, info);
|
||||
hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, plist_id);
|
||||
CHECK_ERROR(file_id,"Error opening hdf5 file.");
|
||||
H5Pclose(plist_id);
|
||||
hid_t dataset_id;
|
||||
#if H5Dopen_vers == 2
|
||||
dataset_id = H5Dopen2(file_id, name.c_str(), H5P_DEFAULT);
|
||||
#else
|
||||
dataset_id = H5Dopen(file_id, name.c_str());
|
||||
#endif
|
||||
CHECK_ERROR(dataset_id,"Error opening dataset in file.");
|
||||
|
||||
hid_t space_id = H5Dget_space(dataset_id);
|
||||
hsize_t dims[2];
|
||||
H5Sget_simple_extent_dims(space_id, dims, NULL);
|
||||
|
||||
hsize_t count[2];
|
||||
hsize_t offset[2];
|
||||
|
||||
hsize_t item_cnt = dims[0]/mpi_size+(dims[0]%mpi_size==0 ? 0 : 1);
|
||||
hsize_t cnt = (mpi_rank<mpi_size-1 ? item_cnt : dims[0]-item_cnt*(mpi_size-1));
|
||||
|
||||
count[0] = cnt;
|
||||
count[1] = dims[1];
|
||||
offset[0] = mpi_rank*item_cnt;
|
||||
offset[1] = 0;
|
||||
|
||||
hid_t memspace_id = H5Screate_simple(2,count,NULL);
|
||||
|
||||
H5Sselect_hyperslab(space_id, H5S_SELECT_SET, offset, NULL, count, NULL);
|
||||
|
||||
dataset.rows = count[0];
|
||||
dataset.cols = count[1];
|
||||
dataset.data = new T[dataset.rows*dataset.cols];
|
||||
|
||||
plist_id = H5Pcreate(H5P_DATASET_XFER);
|
||||
H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
|
||||
status = H5Dread(dataset_id, get_hdf5_type<T>(), memspace_id, space_id, plist_id, dataset.data);
|
||||
CHECK_ERROR(status, "Error reading dataset");
|
||||
|
||||
H5Pclose(plist_id);
|
||||
H5Sclose(space_id);
|
||||
H5Sclose(memspace_id);
|
||||
H5Dclose(dataset_id);
|
||||
H5Fclose(file_id);
|
||||
}
|
||||
}
|
||||
#endif // HAVE_MPI
|
||||
} // namespace cvflann::mpi
|
||||
|
||||
#endif /* OPENCV_FLANN_HDF5_H_ */
|
||||
@@ -0,0 +1,165 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_HEAP_H_
|
||||
#define OPENCV_FLANN_HEAP_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Priority Queue Implementation
|
||||
*
|
||||
* The priority queue is implemented with a heap. A heap is a complete
|
||||
* (full) binary tree in which each parent is less than both of its
|
||||
* children, but the order of the children is unspecified.
|
||||
*/
|
||||
template <typename T>
|
||||
class Heap
|
||||
{
|
||||
|
||||
/**
|
||||
* Storage array for the heap.
|
||||
* Type T must be comparable.
|
||||
*/
|
||||
std::vector<T> heap;
|
||||
int length;
|
||||
|
||||
/**
|
||||
* Number of element in the heap
|
||||
*/
|
||||
int count;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Params:
|
||||
* sz = heap size
|
||||
*/
|
||||
|
||||
Heap(int sz)
|
||||
{
|
||||
length = sz;
|
||||
heap.reserve(length);
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns: heap size
|
||||
*/
|
||||
int size()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the heap is empty
|
||||
*
|
||||
* Returns: true is heap empty, false otherwise
|
||||
*/
|
||||
bool empty()
|
||||
{
|
||||
return size()==0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the heap.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
heap.clear();
|
||||
count = 0;
|
||||
}
|
||||
|
||||
struct CompareT
|
||||
{
|
||||
bool operator()(const T& t_1, const T& t_2) const
|
||||
{
|
||||
return t_2 < t_1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert a new element in the heap.
|
||||
*
|
||||
* We select the next empty leaf node, and then keep moving any larger
|
||||
* parents down until the right location is found to store this element.
|
||||
*
|
||||
* Params:
|
||||
* value = the new element to be inserted in the heap
|
||||
*/
|
||||
void insert(T value)
|
||||
{
|
||||
/* If heap is full, then return without adding this element. */
|
||||
if (count == length) {
|
||||
return;
|
||||
}
|
||||
|
||||
heap.push_back(value);
|
||||
static CompareT compareT;
|
||||
std::push_heap(heap.begin(), heap.end(), compareT);
|
||||
++count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the node of minimum value from the heap (top of the heap).
|
||||
*
|
||||
* Params:
|
||||
* value = out parameter used to return the min element
|
||||
* Returns: false if heap empty
|
||||
*/
|
||||
bool popMin(T& value)
|
||||
{
|
||||
if (count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = heap[0];
|
||||
static CompareT compareT;
|
||||
std::pop_heap(heap.begin(), heap.end(), compareT);
|
||||
heap.pop_back();
|
||||
--count;
|
||||
|
||||
return true; /* Return old last node. */
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_HEAP_H_
|
||||
@@ -0,0 +1,759 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
|
||||
#define OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
#include "dist.h"
|
||||
#include "matrix.h"
|
||||
#include "result_set.h"
|
||||
#include "heap.h"
|
||||
#include "allocator.h"
|
||||
#include "random.h"
|
||||
#include "saving.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
struct HierarchicalClusteringIndexParams : public IndexParams
|
||||
{
|
||||
HierarchicalClusteringIndexParams(int branching = 32,
|
||||
flann_centers_init_t centers_init = FLANN_CENTERS_RANDOM,
|
||||
int trees = 4, int leaf_size = 100)
|
||||
{
|
||||
(*this)["algorithm"] = FLANN_INDEX_HIERARCHICAL;
|
||||
// The branching factor used in the hierarchical clustering
|
||||
(*this)["branching"] = branching;
|
||||
// Algorithm used for picking the initial cluster centers
|
||||
(*this)["centers_init"] = centers_init;
|
||||
// number of parallel trees to build
|
||||
(*this)["trees"] = trees;
|
||||
// maximum leaf size
|
||||
(*this)["leaf_size"] = leaf_size;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hierarchical index
|
||||
*
|
||||
* Contains a tree constructed through a hierarchical clustering
|
||||
* and other information for indexing a set of points for nearest-neighbour matching.
|
||||
*/
|
||||
template <typename Distance>
|
||||
class HierarchicalClusteringIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
typedef void (HierarchicalClusteringIndex::* centersAlgFunction)(int, int*, int, int*, int&);
|
||||
|
||||
/**
|
||||
* The function used for choosing the cluster centers.
|
||||
*/
|
||||
centersAlgFunction chooseCenters;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Chooses the initial centers in the k-means clustering in a random manner.
|
||||
*
|
||||
* Params:
|
||||
* k = number of centers
|
||||
* vecs = the dataset of points
|
||||
* indices = indices in the dataset
|
||||
* indices_length = length of indices vector
|
||||
*
|
||||
*/
|
||||
void chooseCentersRandom(int k, int* dsindices, int indices_length, int* centers, int& centers_length)
|
||||
{
|
||||
UniqueRandom r(indices_length);
|
||||
|
||||
int index;
|
||||
for (index=0; index<k; ++index) {
|
||||
bool duplicate = true;
|
||||
int rnd;
|
||||
while (duplicate) {
|
||||
duplicate = false;
|
||||
rnd = r.next();
|
||||
if (rnd<0) {
|
||||
centers_length = index;
|
||||
return;
|
||||
}
|
||||
|
||||
centers[index] = dsindices[rnd];
|
||||
|
||||
for (int j=0; j<index; ++j) {
|
||||
DistanceType sq = distance(dataset[centers[index]], dataset[centers[j]], dataset.cols);
|
||||
if (sq<1e-16) {
|
||||
duplicate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
centers_length = index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chooses the initial centers in the k-means using Gonzales' algorithm
|
||||
* so that the centers are spaced apart from each other.
|
||||
*
|
||||
* Params:
|
||||
* k = number of centers
|
||||
* vecs = the dataset of points
|
||||
* indices = indices in the dataset
|
||||
* Returns:
|
||||
*/
|
||||
void chooseCentersGonzales(int k, int* dsindices, int indices_length, int* centers, int& centers_length)
|
||||
{
|
||||
int n = indices_length;
|
||||
|
||||
int rnd = rand_int(n);
|
||||
assert(rnd >=0 && rnd < n);
|
||||
|
||||
centers[0] = dsindices[rnd];
|
||||
|
||||
int index;
|
||||
for (index=1; index<k; ++index) {
|
||||
|
||||
int best_index = -1;
|
||||
DistanceType best_val = 0;
|
||||
for (int j=0; j<n; ++j) {
|
||||
DistanceType dist = distance(dataset[centers[0]],dataset[dsindices[j]],dataset.cols);
|
||||
for (int i=1; i<index; ++i) {
|
||||
DistanceType tmp_dist = distance(dataset[centers[i]],dataset[dsindices[j]],dataset.cols);
|
||||
if (tmp_dist<dist) {
|
||||
dist = tmp_dist;
|
||||
}
|
||||
}
|
||||
if (dist>best_val) {
|
||||
best_val = dist;
|
||||
best_index = j;
|
||||
}
|
||||
}
|
||||
if (best_index!=-1) {
|
||||
centers[index] = dsindices[best_index];
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
centers_length = index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chooses the initial centers in the k-means using the algorithm
|
||||
* proposed in the KMeans++ paper:
|
||||
* Arthur, David; Vassilvitskii, Sergei - k-means++: The Advantages of Careful Seeding
|
||||
*
|
||||
* Implementation of this function was converted from the one provided in Arthur's code.
|
||||
*
|
||||
* Params:
|
||||
* k = number of centers
|
||||
* vecs = the dataset of points
|
||||
* indices = indices in the dataset
|
||||
* Returns:
|
||||
*/
|
||||
void chooseCentersKMeanspp(int k, int* dsindices, int indices_length, int* centers, int& centers_length)
|
||||
{
|
||||
int n = indices_length;
|
||||
|
||||
double currentPot = 0;
|
||||
DistanceType* closestDistSq = new DistanceType[n];
|
||||
|
||||
// Choose one random center and set the closestDistSq values
|
||||
int index = rand_int(n);
|
||||
assert(index >=0 && index < n);
|
||||
centers[0] = dsindices[index];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
closestDistSq[i] = distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols);
|
||||
currentPot += closestDistSq[i];
|
||||
}
|
||||
|
||||
|
||||
const int numLocalTries = 1;
|
||||
|
||||
// Choose each center
|
||||
int centerCount;
|
||||
for (centerCount = 1; centerCount < k; centerCount++) {
|
||||
|
||||
// Repeat several trials
|
||||
double bestNewPot = -1;
|
||||
int bestNewIndex = 0;
|
||||
for (int localTrial = 0; localTrial < numLocalTries; localTrial++) {
|
||||
|
||||
// Choose our center - have to be slightly careful to return a valid answer even accounting
|
||||
// for possible rounding errors
|
||||
double randVal = rand_double(currentPot);
|
||||
for (index = 0; index < n-1; index++) {
|
||||
if (randVal <= closestDistSq[index]) break;
|
||||
else randVal -= closestDistSq[index];
|
||||
}
|
||||
|
||||
// Compute the new potential
|
||||
double newPot = 0;
|
||||
for (int i = 0; i < n; i++) newPot += std::min( distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols), closestDistSq[i] );
|
||||
|
||||
// Store the best result
|
||||
if ((bestNewPot < 0)||(newPot < bestNewPot)) {
|
||||
bestNewPot = newPot;
|
||||
bestNewIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the appropriate center
|
||||
centers[centerCount] = dsindices[bestNewIndex];
|
||||
currentPot = bestNewPot;
|
||||
for (int i = 0; i < n; i++) closestDistSq[i] = std::min( distance(dataset[dsindices[i]], dataset[dsindices[bestNewIndex]], dataset.cols), closestDistSq[i] );
|
||||
}
|
||||
|
||||
centers_length = centerCount;
|
||||
|
||||
delete[] closestDistSq;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
* Index constructor
|
||||
*
|
||||
* Params:
|
||||
* inputData = dataset with the input features
|
||||
* params = parameters passed to the hierarchical k-means algorithm
|
||||
*/
|
||||
HierarchicalClusteringIndex(const Matrix<ElementType>& inputData, const IndexParams& index_params = HierarchicalClusteringIndexParams(),
|
||||
Distance d = Distance())
|
||||
: dataset(inputData), params(index_params), root(NULL), indices(NULL), distance(d)
|
||||
{
|
||||
memoryCounter = 0;
|
||||
|
||||
size_ = dataset.rows;
|
||||
veclen_ = dataset.cols;
|
||||
|
||||
branching_ = get_param(params,"branching",32);
|
||||
centers_init_ = get_param(params,"centers_init", FLANN_CENTERS_RANDOM);
|
||||
trees_ = get_param(params,"trees",4);
|
||||
leaf_size_ = get_param(params,"leaf_size",100);
|
||||
|
||||
if (centers_init_==FLANN_CENTERS_RANDOM) {
|
||||
chooseCenters = &HierarchicalClusteringIndex::chooseCentersRandom;
|
||||
}
|
||||
else if (centers_init_==FLANN_CENTERS_GONZALES) {
|
||||
chooseCenters = &HierarchicalClusteringIndex::chooseCentersGonzales;
|
||||
}
|
||||
else if (centers_init_==FLANN_CENTERS_KMEANSPP) {
|
||||
chooseCenters = &HierarchicalClusteringIndex::chooseCentersKMeanspp;
|
||||
}
|
||||
else {
|
||||
throw FLANNException("Unknown algorithm for choosing initial centers.");
|
||||
}
|
||||
|
||||
trees_ = get_param(params,"trees",4);
|
||||
root = new NodePtr[trees_];
|
||||
indices = new int*[trees_];
|
||||
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
root[i] = NULL;
|
||||
indices[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
HierarchicalClusteringIndex(const HierarchicalClusteringIndex&);
|
||||
HierarchicalClusteringIndex& operator=(const HierarchicalClusteringIndex&);
|
||||
|
||||
/**
|
||||
* Index destructor.
|
||||
*
|
||||
* Release the memory used by the index.
|
||||
*/
|
||||
virtual ~HierarchicalClusteringIndex()
|
||||
{
|
||||
free_elements();
|
||||
|
||||
if (root!=NULL) {
|
||||
delete[] root;
|
||||
}
|
||||
|
||||
if (indices!=NULL) {
|
||||
delete[] indices;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Release the inner elements of indices[]
|
||||
*/
|
||||
void free_elements()
|
||||
{
|
||||
if (indices!=NULL) {
|
||||
for(int i=0; i<trees_; ++i) {
|
||||
if (indices[i]!=NULL) {
|
||||
delete[] indices[i];
|
||||
indices[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns size of index.
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of an index feature.
|
||||
*/
|
||||
size_t veclen() const
|
||||
{
|
||||
return veclen_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes the inde memory usage
|
||||
* Returns: memory used by the index
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
return pool.usedMemory+pool.wastedMemory+memoryCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
if (branching_<2) {
|
||||
throw FLANNException("Branching factor must be at least 2");
|
||||
}
|
||||
|
||||
free_elements();
|
||||
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
indices[i] = new int[size_];
|
||||
for (size_t j=0; j<size_; ++j) {
|
||||
indices[i][j] = (int)j;
|
||||
}
|
||||
root[i] = pool.allocate<Node>();
|
||||
computeClustering(root[i], indices[i], (int)size_, branching_,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_HIERARCHICAL;
|
||||
}
|
||||
|
||||
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
save_value(stream, branching_);
|
||||
save_value(stream, trees_);
|
||||
save_value(stream, centers_init_);
|
||||
save_value(stream, leaf_size_);
|
||||
save_value(stream, memoryCounter);
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
save_value(stream, *indices[i], size_);
|
||||
save_tree(stream, root[i], i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
load_value(stream, branching_);
|
||||
load_value(stream, trees_);
|
||||
load_value(stream, centers_init_);
|
||||
load_value(stream, leaf_size_);
|
||||
load_value(stream, memoryCounter);
|
||||
|
||||
free_elements();
|
||||
|
||||
if (root!=NULL) {
|
||||
delete[] root;
|
||||
}
|
||||
|
||||
if (indices!=NULL) {
|
||||
delete[] indices;
|
||||
}
|
||||
|
||||
indices = new int*[trees_];
|
||||
root = new NodePtr[trees_];
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
indices[i] = new int[size_];
|
||||
load_value(stream, *indices[i], size_);
|
||||
load_tree(stream, root[i], i);
|
||||
}
|
||||
|
||||
params["algorithm"] = getType();
|
||||
params["branching"] = branching_;
|
||||
params["trees"] = trees_;
|
||||
params["centers_init"] = centers_init_;
|
||||
params["leaf_size"] = leaf_size_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find set of nearest neighbors to vec. Their indices are stored inside
|
||||
* the result object.
|
||||
*
|
||||
* Params:
|
||||
* result = the result object in which the indices of the nearest-neighbors are stored
|
||||
* vec = the vector for which to search the nearest neighbors
|
||||
* searchParams = parameters that influence the search algorithm (checks)
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
|
||||
{
|
||||
|
||||
int maxChecks = get_param(searchParams,"checks",32);
|
||||
|
||||
// Priority queue storing intermediate branches in the best-bin-first search
|
||||
Heap<BranchSt>* heap = new Heap<BranchSt>((int)size_);
|
||||
|
||||
std::vector<bool> checked(size_,false);
|
||||
int checks = 0;
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
findNN(root[i], result, vec, checks, maxChecks, heap, checked);
|
||||
}
|
||||
|
||||
BranchSt branch;
|
||||
while (heap->popMin(branch) && (checks<maxChecks || !result.full())) {
|
||||
NodePtr node = branch.node;
|
||||
findNN(node, result, vec, checks, maxChecks, heap, checked);
|
||||
}
|
||||
assert(result.full());
|
||||
|
||||
delete heap;
|
||||
|
||||
}
|
||||
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Struture representing a node in the hierarchical k-means tree.
|
||||
*/
|
||||
struct Node
|
||||
{
|
||||
/**
|
||||
* The cluster center index
|
||||
*/
|
||||
int pivot;
|
||||
/**
|
||||
* The cluster size (number of points in the cluster)
|
||||
*/
|
||||
int size;
|
||||
/**
|
||||
* Child nodes (only for non-terminal nodes)
|
||||
*/
|
||||
Node** childs;
|
||||
/**
|
||||
* Node points (only for terminal nodes)
|
||||
*/
|
||||
int* indices;
|
||||
/**
|
||||
* Level
|
||||
*/
|
||||
int level;
|
||||
};
|
||||
typedef Node* NodePtr;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Alias definition for a nicer syntax.
|
||||
*/
|
||||
typedef BranchStruct<NodePtr, DistanceType> BranchSt;
|
||||
|
||||
|
||||
|
||||
void save_tree(FILE* stream, NodePtr node, int num)
|
||||
{
|
||||
save_value(stream, *node);
|
||||
if (node->childs==NULL) {
|
||||
int indices_offset = (int)(node->indices - indices[num]);
|
||||
save_value(stream, indices_offset);
|
||||
}
|
||||
else {
|
||||
for(int i=0; i<branching_; ++i) {
|
||||
save_tree(stream, node->childs[i], num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void load_tree(FILE* stream, NodePtr& node, int num)
|
||||
{
|
||||
node = pool.allocate<Node>();
|
||||
load_value(stream, *node);
|
||||
if (node->childs==NULL) {
|
||||
int indices_offset;
|
||||
load_value(stream, indices_offset);
|
||||
node->indices = indices[num] + indices_offset;
|
||||
}
|
||||
else {
|
||||
node->childs = pool.allocate<NodePtr>(branching_);
|
||||
for(int i=0; i<branching_; ++i) {
|
||||
load_tree(stream, node->childs[i], num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void computeLabels(int* dsindices, int indices_length, int* centers, int centers_length, int* labels, DistanceType& cost)
|
||||
{
|
||||
cost = 0;
|
||||
for (int i=0; i<indices_length; ++i) {
|
||||
ElementType* point = dataset[dsindices[i]];
|
||||
DistanceType dist = distance(point, dataset[centers[0]], veclen_);
|
||||
labels[i] = 0;
|
||||
for (int j=1; j<centers_length; ++j) {
|
||||
DistanceType new_dist = distance(point, dataset[centers[j]], veclen_);
|
||||
if (dist>new_dist) {
|
||||
labels[i] = j;
|
||||
dist = new_dist;
|
||||
}
|
||||
}
|
||||
cost += dist;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method responsible with actually doing the recursive hierarchical
|
||||
* clustering
|
||||
*
|
||||
* Params:
|
||||
* node = the node to cluster
|
||||
* indices = indices of the points belonging to the current node
|
||||
* branching = the branching factor to use in the clustering
|
||||
*
|
||||
* TODO: for 1-sized clusters don't store a cluster center (it's the same as the single cluster point)
|
||||
*/
|
||||
void computeClustering(NodePtr node, int* dsindices, int indices_length, int branching, int level)
|
||||
{
|
||||
node->size = indices_length;
|
||||
node->level = level;
|
||||
|
||||
if (indices_length < leaf_size_) { // leaf node
|
||||
node->indices = dsindices;
|
||||
std::sort(node->indices,node->indices+indices_length);
|
||||
node->childs = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> centers(branching);
|
||||
std::vector<int> labels(indices_length);
|
||||
|
||||
int centers_length;
|
||||
(this->*chooseCenters)(branching, dsindices, indices_length, ¢ers[0], centers_length);
|
||||
|
||||
if (centers_length<branching) {
|
||||
node->indices = dsindices;
|
||||
std::sort(node->indices,node->indices+indices_length);
|
||||
node->childs = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// assign points to clusters
|
||||
DistanceType cost;
|
||||
computeLabels(dsindices, indices_length, ¢ers[0], centers_length, &labels[0], cost);
|
||||
|
||||
node->childs = pool.allocate<NodePtr>(branching);
|
||||
int start = 0;
|
||||
int end = start;
|
||||
for (int i=0; i<branching; ++i) {
|
||||
for (int j=0; j<indices_length; ++j) {
|
||||
if (labels[j]==i) {
|
||||
std::swap(dsindices[j],dsindices[end]);
|
||||
std::swap(labels[j],labels[end]);
|
||||
end++;
|
||||
}
|
||||
}
|
||||
|
||||
node->childs[i] = pool.allocate<Node>();
|
||||
node->childs[i]->pivot = centers[i];
|
||||
node->childs[i]->indices = NULL;
|
||||
computeClustering(node->childs[i],dsindices+start, end-start, branching, level+1);
|
||||
start=end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Performs one descent in the hierarchical k-means tree. The branches not
|
||||
* visited are stored in a priority queue.
|
||||
*
|
||||
* Params:
|
||||
* node = node to explore
|
||||
* result = container for the k-nearest neighbors found
|
||||
* vec = query points
|
||||
* checks = how many points in the dataset have been checked so far
|
||||
* maxChecks = maximum dataset points to checks
|
||||
*/
|
||||
|
||||
|
||||
void findNN(NodePtr node, ResultSet<DistanceType>& result, const ElementType* vec, int& checks, int maxChecks,
|
||||
Heap<BranchSt>* heap, std::vector<bool>& checked)
|
||||
{
|
||||
if (node->childs==NULL) {
|
||||
if (checks>=maxChecks) {
|
||||
if (result.full()) return;
|
||||
}
|
||||
for (int i=0; i<node->size; ++i) {
|
||||
int index = node->indices[i];
|
||||
if (!checked[index]) {
|
||||
DistanceType dist = distance(dataset[index], vec, veclen_);
|
||||
result.addPoint(dist, index);
|
||||
checked[index] = true;
|
||||
++checks;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
DistanceType* domain_distances = new DistanceType[branching_];
|
||||
int best_index = 0;
|
||||
domain_distances[best_index] = distance(vec, dataset[node->childs[best_index]->pivot], veclen_);
|
||||
for (int i=1; i<branching_; ++i) {
|
||||
domain_distances[i] = distance(vec, dataset[node->childs[i]->pivot], veclen_);
|
||||
if (domain_distances[i]<domain_distances[best_index]) {
|
||||
best_index = i;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<branching_; ++i) {
|
||||
if (i!=best_index) {
|
||||
heap->insert(BranchSt(node->childs[i],domain_distances[i]));
|
||||
}
|
||||
}
|
||||
delete[] domain_distances;
|
||||
findNN(node->childs[best_index],result,vec, checks, maxChecks, heap, checked);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/**
|
||||
* The dataset used by this index
|
||||
*/
|
||||
const Matrix<ElementType> dataset;
|
||||
|
||||
/**
|
||||
* Parameters used by this index
|
||||
*/
|
||||
IndexParams params;
|
||||
|
||||
|
||||
/**
|
||||
* Number of features in the dataset.
|
||||
*/
|
||||
size_t size_;
|
||||
|
||||
/**
|
||||
* Length of each feature.
|
||||
*/
|
||||
size_t veclen_;
|
||||
|
||||
/**
|
||||
* The root node in the tree.
|
||||
*/
|
||||
NodePtr* root;
|
||||
|
||||
/**
|
||||
* Array of indices to vectors in the dataset.
|
||||
*/
|
||||
int** indices;
|
||||
|
||||
|
||||
/**
|
||||
* The distance
|
||||
*/
|
||||
Distance distance;
|
||||
|
||||
/**
|
||||
* Pooled memory allocator.
|
||||
*
|
||||
* Using a pooled memory allocator is more efficient
|
||||
* than allocating memory directly when there is a large
|
||||
* number small of memory allocations.
|
||||
*/
|
||||
PooledAllocator pool;
|
||||
|
||||
/**
|
||||
* Memory occupied by the index.
|
||||
*/
|
||||
int memoryCounter;
|
||||
|
||||
/** index parameters */
|
||||
int branching_;
|
||||
int trees_;
|
||||
flann_centers_init_t centers_init_;
|
||||
int leaf_size_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENCV_FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_ */
|
||||
@@ -0,0 +1,318 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_INDEX_TESTING_H_
|
||||
#define OPENCV_FLANN_INDEX_TESTING_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "matrix.h"
|
||||
#include "nn_index.h"
|
||||
#include "result_set.h"
|
||||
#include "logger.h"
|
||||
#include "timer.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
inline int countCorrectMatches(int* neighbors, int* groundTruth, int n)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i=0; i<n; ++i) {
|
||||
for (int k=0; k<n; ++k) {
|
||||
if (neighbors[i]==groundTruth[k]) {
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
typename Distance::ResultType computeDistanceRaport(const Matrix<typename Distance::ElementType>& inputData, typename Distance::ElementType* target,
|
||||
int* neighbors, int* groundTruth, int veclen, int n, const Distance& distance)
|
||||
{
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
DistanceType ret = 0;
|
||||
for (int i=0; i<n; ++i) {
|
||||
DistanceType den = distance(inputData[groundTruth[i]], target, veclen);
|
||||
DistanceType num = distance(inputData[neighbors[i]], target, veclen);
|
||||
|
||||
if ((den==0)&&(num==0)) {
|
||||
ret += 1;
|
||||
}
|
||||
else {
|
||||
ret += num/den;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
float search_with_ground_truth(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData,
|
||||
const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches, int nn, int checks,
|
||||
float& time, typename Distance::ResultType& dist, const Distance& distance, int skipMatches)
|
||||
{
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
if (matches.cols<size_t(nn)) {
|
||||
Logger::info("matches.cols=%d, nn=%d\n",matches.cols,nn);
|
||||
|
||||
throw FLANNException("Ground truth is not computed for as many neighbors as requested");
|
||||
}
|
||||
|
||||
KNNResultSet<DistanceType> resultSet(nn+skipMatches);
|
||||
SearchParams searchParams(checks);
|
||||
|
||||
std::vector<int> indices(nn+skipMatches);
|
||||
std::vector<DistanceType> dists(nn+skipMatches);
|
||||
int* neighbors = &indices[skipMatches];
|
||||
|
||||
int correct = 0;
|
||||
DistanceType distR = 0;
|
||||
StartStopTimer t;
|
||||
int repeats = 0;
|
||||
while (t.value<0.2) {
|
||||
repeats++;
|
||||
t.start();
|
||||
correct = 0;
|
||||
distR = 0;
|
||||
for (size_t i = 0; i < testData.rows; i++) {
|
||||
resultSet.init(&indices[0], &dists[0]);
|
||||
index.findNeighbors(resultSet, testData[i], searchParams);
|
||||
|
||||
correct += countCorrectMatches(neighbors,matches[i], nn);
|
||||
distR += computeDistanceRaport<Distance>(inputData, testData[i], neighbors, matches[i], (int)testData.cols, nn, distance);
|
||||
}
|
||||
t.stop();
|
||||
}
|
||||
time = float(t.value/repeats);
|
||||
|
||||
float precicion = (float)correct/(nn*testData.rows);
|
||||
|
||||
dist = distR/(testData.rows*nn);
|
||||
|
||||
Logger::info("%8d %10.4g %10.5g %10.5g %10.5g\n",
|
||||
checks, precicion, time, 1000.0 * time / testData.rows, dist);
|
||||
|
||||
return precicion;
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
float test_index_checks(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData,
|
||||
const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches,
|
||||
int checks, float& precision, const Distance& distance, int nn = 1, int skipMatches = 0)
|
||||
{
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n");
|
||||
Logger::info("---------------------------------------------------------\n");
|
||||
|
||||
float time = 0;
|
||||
DistanceType dist = 0;
|
||||
precision = search_with_ground_truth(index, inputData, testData, matches, nn, checks, time, dist, distance, skipMatches);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
template <typename Distance>
|
||||
float test_index_precision(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData,
|
||||
const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches,
|
||||
float precision, int& checks, const Distance& distance, int nn = 1, int skipMatches = 0)
|
||||
{
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
const float SEARCH_EPS = 0.001f;
|
||||
|
||||
Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n");
|
||||
Logger::info("---------------------------------------------------------\n");
|
||||
|
||||
int c2 = 1;
|
||||
float p2;
|
||||
int c1 = 1;
|
||||
//float p1;
|
||||
float time;
|
||||
DistanceType dist;
|
||||
|
||||
p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches);
|
||||
|
||||
if (p2>precision) {
|
||||
Logger::info("Got as close as I can\n");
|
||||
checks = c2;
|
||||
return time;
|
||||
}
|
||||
|
||||
while (p2<precision) {
|
||||
c1 = c2;
|
||||
//p1 = p2;
|
||||
c2 *=2;
|
||||
p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches);
|
||||
}
|
||||
|
||||
int cx;
|
||||
float realPrecision;
|
||||
if (fabs(p2-precision)>SEARCH_EPS) {
|
||||
Logger::info("Start linear estimation\n");
|
||||
// after we got to values in the vecinity of the desired precision
|
||||
// use linear approximation get a better estimation
|
||||
|
||||
cx = (c1+c2)/2;
|
||||
realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches);
|
||||
while (fabs(realPrecision-precision)>SEARCH_EPS) {
|
||||
|
||||
if (realPrecision<precision) {
|
||||
c1 = cx;
|
||||
}
|
||||
else {
|
||||
c2 = cx;
|
||||
}
|
||||
cx = (c1+c2)/2;
|
||||
if (cx==c1) {
|
||||
Logger::info("Got as close as I can\n");
|
||||
break;
|
||||
}
|
||||
realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches);
|
||||
}
|
||||
|
||||
c2 = cx;
|
||||
p2 = realPrecision;
|
||||
|
||||
}
|
||||
else {
|
||||
Logger::info("No need for linear estimation\n");
|
||||
cx = c2;
|
||||
realPrecision = p2;
|
||||
}
|
||||
|
||||
checks = cx;
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
template <typename Distance>
|
||||
void test_index_precisions(NNIndex<Distance>& index, const Matrix<typename Distance::ElementType>& inputData,
|
||||
const Matrix<typename Distance::ElementType>& testData, const Matrix<int>& matches,
|
||||
float* precisions, int precisions_length, const Distance& distance, int nn = 1, int skipMatches = 0, float maxTime = 0)
|
||||
{
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
const float SEARCH_EPS = 0.001;
|
||||
|
||||
// make sure precisions array is sorted
|
||||
std::sort(precisions, precisions+precisions_length);
|
||||
|
||||
int pindex = 0;
|
||||
float precision = precisions[pindex];
|
||||
|
||||
Logger::info(" Nodes Precision(%) Time(s) Time/vec(ms) Mean dist\n");
|
||||
Logger::info("---------------------------------------------------------\n");
|
||||
|
||||
int c2 = 1;
|
||||
float p2;
|
||||
|
||||
int c1 = 1;
|
||||
float p1;
|
||||
|
||||
float time;
|
||||
DistanceType dist;
|
||||
|
||||
p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches);
|
||||
|
||||
// if precision for 1 run down the tree is already
|
||||
// better then some of the requested precisions, then
|
||||
// skip those
|
||||
while (precisions[pindex]<p2 && pindex<precisions_length) {
|
||||
pindex++;
|
||||
}
|
||||
|
||||
if (pindex==precisions_length) {
|
||||
Logger::info("Got as close as I can\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i=pindex; i<precisions_length; ++i) {
|
||||
|
||||
precision = precisions[i];
|
||||
while (p2<precision) {
|
||||
c1 = c2;
|
||||
p1 = p2;
|
||||
c2 *=2;
|
||||
p2 = search_with_ground_truth(index, inputData, testData, matches, nn, c2, time, dist, distance, skipMatches);
|
||||
if ((maxTime> 0)&&(time > maxTime)&&(p2<precision)) return;
|
||||
}
|
||||
|
||||
int cx;
|
||||
float realPrecision;
|
||||
if (fabs(p2-precision)>SEARCH_EPS) {
|
||||
Logger::info("Start linear estimation\n");
|
||||
// after we got to values in the vecinity of the desired precision
|
||||
// use linear approximation get a better estimation
|
||||
|
||||
cx = (c1+c2)/2;
|
||||
realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches);
|
||||
while (fabs(realPrecision-precision)>SEARCH_EPS) {
|
||||
|
||||
if (realPrecision<precision) {
|
||||
c1 = cx;
|
||||
}
|
||||
else {
|
||||
c2 = cx;
|
||||
}
|
||||
cx = (c1+c2)/2;
|
||||
if (cx==c1) {
|
||||
Logger::info("Got as close as I can\n");
|
||||
break;
|
||||
}
|
||||
realPrecision = search_with_ground_truth(index, inputData, testData, matches, nn, cx, time, dist, distance, skipMatches);
|
||||
}
|
||||
|
||||
c2 = cx;
|
||||
p2 = realPrecision;
|
||||
|
||||
}
|
||||
else {
|
||||
Logger::info("No need for linear estimation\n");
|
||||
cx = c2;
|
||||
realPrecision = p2;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_INDEX_TESTING_H_
|
||||
@@ -0,0 +1,621 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_KDTREE_INDEX_H_
|
||||
#define OPENCV_FLANN_KDTREE_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
#include "dynamic_bitset.h"
|
||||
#include "matrix.h"
|
||||
#include "result_set.h"
|
||||
#include "heap.h"
|
||||
#include "allocator.h"
|
||||
#include "random.h"
|
||||
#include "saving.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
struct KDTreeIndexParams : public IndexParams
|
||||
{
|
||||
KDTreeIndexParams(int trees = 4)
|
||||
{
|
||||
(*this)["algorithm"] = FLANN_INDEX_KDTREE;
|
||||
(*this)["trees"] = trees;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Randomized kd-tree index
|
||||
*
|
||||
* Contains the k-d trees and other information for indexing a set of points
|
||||
* for nearest-neighbor matching.
|
||||
*/
|
||||
template <typename Distance>
|
||||
class KDTreeIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
|
||||
/**
|
||||
* KDTree constructor
|
||||
*
|
||||
* Params:
|
||||
* inputData = dataset with the input features
|
||||
* params = parameters passed to the kdtree algorithm
|
||||
*/
|
||||
KDTreeIndex(const Matrix<ElementType>& inputData, const IndexParams& params = KDTreeIndexParams(),
|
||||
Distance d = Distance() ) :
|
||||
dataset_(inputData), index_params_(params), distance_(d)
|
||||
{
|
||||
size_ = dataset_.rows;
|
||||
veclen_ = dataset_.cols;
|
||||
|
||||
trees_ = get_param(index_params_,"trees",4);
|
||||
tree_roots_ = new NodePtr[trees_];
|
||||
|
||||
// Create a permutable array of indices to the input vectors.
|
||||
vind_.resize(size_);
|
||||
for (size_t i = 0; i < size_; ++i) {
|
||||
vind_[i] = int(i);
|
||||
}
|
||||
|
||||
mean_ = new DistanceType[veclen_];
|
||||
var_ = new DistanceType[veclen_];
|
||||
}
|
||||
|
||||
|
||||
KDTreeIndex(const KDTreeIndex&);
|
||||
KDTreeIndex& operator=(const KDTreeIndex&);
|
||||
|
||||
/**
|
||||
* Standard destructor
|
||||
*/
|
||||
~KDTreeIndex()
|
||||
{
|
||||
if (tree_roots_!=NULL) {
|
||||
delete[] tree_roots_;
|
||||
}
|
||||
delete[] mean_;
|
||||
delete[] var_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
/* Construct the randomized trees. */
|
||||
for (int i = 0; i < trees_; i++) {
|
||||
/* Randomize the order of vectors to allow for unbiased sampling. */
|
||||
std::random_shuffle(vind_.begin(), vind_.end());
|
||||
tree_roots_[i] = divideTree(&vind_[0], int(size_) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_KDTREE;
|
||||
}
|
||||
|
||||
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
save_value(stream, trees_);
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
save_tree(stream, tree_roots_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
load_value(stream, trees_);
|
||||
if (tree_roots_!=NULL) {
|
||||
delete[] tree_roots_;
|
||||
}
|
||||
tree_roots_ = new NodePtr[trees_];
|
||||
for (int i=0; i<trees_; ++i) {
|
||||
load_tree(stream,tree_roots_[i]);
|
||||
}
|
||||
|
||||
index_params_["algorithm"] = getType();
|
||||
index_params_["trees"] = tree_roots_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size of index.
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of an index feature.
|
||||
*/
|
||||
size_t veclen() const
|
||||
{
|
||||
return veclen_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the inde memory usage
|
||||
* Returns: memory used by the index
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
return int(pool_.usedMemory+pool_.wastedMemory+dataset_.rows*sizeof(int)); // pool memory and vind array memory
|
||||
}
|
||||
|
||||
/**
|
||||
* Find set of nearest neighbors to vec. Their indices are stored inside
|
||||
* the result object.
|
||||
*
|
||||
* Params:
|
||||
* result = the result object in which the indices of the nearest-neighbors are stored
|
||||
* vec = the vector for which to search the nearest neighbors
|
||||
* maxCheck = the maximum number of restarts (in a best-bin-first manner)
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
|
||||
{
|
||||
int maxChecks = get_param(searchParams,"checks", 32);
|
||||
float epsError = 1+get_param(searchParams,"eps",0.0f);
|
||||
|
||||
if (maxChecks==FLANN_CHECKS_UNLIMITED) {
|
||||
getExactNeighbors(result, vec, epsError);
|
||||
}
|
||||
else {
|
||||
getNeighbors(result, vec, maxChecks, epsError);
|
||||
}
|
||||
}
|
||||
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return index_params_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/*--------------------- Internal Data Structures --------------------------*/
|
||||
struct Node
|
||||
{
|
||||
/**
|
||||
* Dimension used for subdivision.
|
||||
*/
|
||||
int divfeat;
|
||||
/**
|
||||
* The values used for subdivision.
|
||||
*/
|
||||
DistanceType divval;
|
||||
/**
|
||||
* The child nodes.
|
||||
*/
|
||||
Node* child1, * child2;
|
||||
};
|
||||
typedef Node* NodePtr;
|
||||
typedef BranchStruct<NodePtr, DistanceType> BranchSt;
|
||||
typedef BranchSt* Branch;
|
||||
|
||||
|
||||
|
||||
void save_tree(FILE* stream, NodePtr tree)
|
||||
{
|
||||
save_value(stream, *tree);
|
||||
if (tree->child1!=NULL) {
|
||||
save_tree(stream, tree->child1);
|
||||
}
|
||||
if (tree->child2!=NULL) {
|
||||
save_tree(stream, tree->child2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void load_tree(FILE* stream, NodePtr& tree)
|
||||
{
|
||||
tree = pool_.allocate<Node>();
|
||||
load_value(stream, *tree);
|
||||
if (tree->child1!=NULL) {
|
||||
load_tree(stream, tree->child1);
|
||||
}
|
||||
if (tree->child2!=NULL) {
|
||||
load_tree(stream, tree->child2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a tree node that subdivides the list of vecs from vind[first]
|
||||
* to vind[last]. The routine is called recursively on each sublist.
|
||||
* Place a pointer to this new tree node in the location pTree.
|
||||
*
|
||||
* Params: pTree = the new node to create
|
||||
* first = index of the first vector
|
||||
* last = index of the last vector
|
||||
*/
|
||||
NodePtr divideTree(int* ind, int count)
|
||||
{
|
||||
NodePtr node = pool_.allocate<Node>(); // allocate memory
|
||||
|
||||
/* If too few exemplars remain, then make this a leaf node. */
|
||||
if ( count == 1) {
|
||||
node->child1 = node->child2 = NULL; /* Mark as leaf node. */
|
||||
node->divfeat = *ind; /* Store index of this vec. */
|
||||
}
|
||||
else {
|
||||
int idx;
|
||||
int cutfeat;
|
||||
DistanceType cutval;
|
||||
meanSplit(ind, count, idx, cutfeat, cutval);
|
||||
|
||||
node->divfeat = cutfeat;
|
||||
node->divval = cutval;
|
||||
node->child1 = divideTree(ind, idx);
|
||||
node->child2 = divideTree(ind+idx, count-idx);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Choose which feature to use in order to subdivide this set of vectors.
|
||||
* Make a random choice among those with the highest variance, and use
|
||||
* its variance as the threshold value.
|
||||
*/
|
||||
void meanSplit(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval)
|
||||
{
|
||||
memset(mean_,0,veclen_*sizeof(DistanceType));
|
||||
memset(var_,0,veclen_*sizeof(DistanceType));
|
||||
|
||||
/* Compute mean values. Only the first SAMPLE_MEAN values need to be
|
||||
sampled to get a good estimate.
|
||||
*/
|
||||
int cnt = std::min((int)SAMPLE_MEAN+1, count);
|
||||
for (int j = 0; j < cnt; ++j) {
|
||||
ElementType* v = dataset_[ind[j]];
|
||||
for (size_t k=0; k<veclen_; ++k) {
|
||||
mean_[k] += v[k];
|
||||
}
|
||||
}
|
||||
for (size_t k=0; k<veclen_; ++k) {
|
||||
mean_[k] /= cnt;
|
||||
}
|
||||
|
||||
/* Compute variances (no need to divide by count). */
|
||||
for (int j = 0; j < cnt; ++j) {
|
||||
ElementType* v = dataset_[ind[j]];
|
||||
for (size_t k=0; k<veclen_; ++k) {
|
||||
DistanceType dist = v[k] - mean_[k];
|
||||
var_[k] += dist * dist;
|
||||
}
|
||||
}
|
||||
/* Select one of the highest variance indices at random. */
|
||||
cutfeat = selectDivision(var_);
|
||||
cutval = mean_[cutfeat];
|
||||
|
||||
int lim1, lim2;
|
||||
planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
|
||||
|
||||
if (lim1>count/2) index = lim1;
|
||||
else if (lim2<count/2) index = lim2;
|
||||
else index = count/2;
|
||||
|
||||
/* If either list is empty, it means that all remaining features
|
||||
* are identical. Split in the middle to maintain a balanced tree.
|
||||
*/
|
||||
if ((lim1==count)||(lim2==0)) index = count/2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Select the top RAND_DIM largest values from v and return the index of
|
||||
* one of these selected at random.
|
||||
*/
|
||||
int selectDivision(DistanceType* v)
|
||||
{
|
||||
int num = 0;
|
||||
size_t topind[RAND_DIM];
|
||||
|
||||
/* Create a list of the indices of the top RAND_DIM values. */
|
||||
for (size_t i = 0; i < veclen_; ++i) {
|
||||
if ((num < RAND_DIM)||(v[i] > v[topind[num-1]])) {
|
||||
/* Put this element at end of topind. */
|
||||
if (num < RAND_DIM) {
|
||||
topind[num++] = i; /* Add to list. */
|
||||
}
|
||||
else {
|
||||
topind[num-1] = i; /* Replace last element. */
|
||||
}
|
||||
/* Bubble end value down to right location by repeated swapping. */
|
||||
int j = num - 1;
|
||||
while (j > 0 && v[topind[j]] > v[topind[j-1]]) {
|
||||
std::swap(topind[j], topind[j-1]);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Select a random integer in range [0,num-1], and return that index. */
|
||||
int rnd = rand_int(num);
|
||||
return (int)topind[rnd];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subdivide the list of points by a plane perpendicular on axe corresponding
|
||||
* to the 'cutfeat' dimension at 'cutval' position.
|
||||
*
|
||||
* On return:
|
||||
* dataset[ind[0..lim1-1]][cutfeat]<cutval
|
||||
* dataset[ind[lim1..lim2-1]][cutfeat]==cutval
|
||||
* dataset[ind[lim2..count]][cutfeat]>cutval
|
||||
*/
|
||||
void planeSplit(int* ind, int count, int cutfeat, DistanceType cutval, int& lim1, int& lim2)
|
||||
{
|
||||
/* Move vector indices for left subtree to front of list. */
|
||||
int left = 0;
|
||||
int right = count-1;
|
||||
for (;; ) {
|
||||
while (left<=right && dataset_[ind[left]][cutfeat]<cutval) ++left;
|
||||
while (left<=right && dataset_[ind[right]][cutfeat]>=cutval) --right;
|
||||
if (left>right) break;
|
||||
std::swap(ind[left], ind[right]); ++left; --right;
|
||||
}
|
||||
lim1 = left;
|
||||
right = count-1;
|
||||
for (;; ) {
|
||||
while (left<=right && dataset_[ind[left]][cutfeat]<=cutval) ++left;
|
||||
while (left<=right && dataset_[ind[right]][cutfeat]>cutval) --right;
|
||||
if (left>right) break;
|
||||
std::swap(ind[left], ind[right]); ++left; --right;
|
||||
}
|
||||
lim2 = left;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an exact nearest neighbor search. The exact search performs a full
|
||||
* traversal of the tree.
|
||||
*/
|
||||
void getExactNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, float epsError)
|
||||
{
|
||||
// checkID -= 1; /* Set a different unique ID for each search. */
|
||||
|
||||
if (trees_ > 1) {
|
||||
fprintf(stderr,"It doesn't make any sense to use more than one tree for exact search");
|
||||
}
|
||||
if (trees_>0) {
|
||||
searchLevelExact(result, vec, tree_roots_[0], 0.0, epsError);
|
||||
}
|
||||
assert(result.full());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the approximate nearest-neighbor search. The search is approximate
|
||||
* because the tree traversal is abandoned after a given number of descends in
|
||||
* the tree.
|
||||
*/
|
||||
void getNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, int maxCheck, float epsError)
|
||||
{
|
||||
int i;
|
||||
BranchSt branch;
|
||||
|
||||
int checkCount = 0;
|
||||
Heap<BranchSt>* heap = new Heap<BranchSt>((int)size_);
|
||||
DynamicBitset checked(size_);
|
||||
|
||||
/* Search once through each tree down to root. */
|
||||
for (i = 0; i < trees_; ++i) {
|
||||
searchLevel(result, vec, tree_roots_[i], 0, checkCount, maxCheck, epsError, heap, checked);
|
||||
}
|
||||
|
||||
/* Keep searching other branches from heap until finished. */
|
||||
while ( heap->popMin(branch) && (checkCount < maxCheck || !result.full() )) {
|
||||
searchLevel(result, vec, branch.node, branch.mindist, checkCount, maxCheck, epsError, heap, checked);
|
||||
}
|
||||
|
||||
delete heap;
|
||||
|
||||
assert(result.full());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search starting from a given node of the tree. Based on any mismatches at
|
||||
* higher levels, all exemplars below this level must have a distance of
|
||||
* at least "mindistsq".
|
||||
*/
|
||||
void searchLevel(ResultSet<DistanceType>& result_set, const ElementType* vec, NodePtr node, DistanceType mindist, int& checkCount, int maxCheck,
|
||||
float epsError, Heap<BranchSt>* heap, DynamicBitset& checked)
|
||||
{
|
||||
if (result_set.worstDist()<mindist) {
|
||||
// printf("Ignoring branch, too far\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if ((node->child1 == NULL)&&(node->child2 == NULL)) {
|
||||
/* Do not check same node more than once when searching multiple trees.
|
||||
Once a vector is checked, we set its location in vind to the
|
||||
current checkID.
|
||||
*/
|
||||
int index = node->divfeat;
|
||||
if ( checked.test(index) || ((checkCount>=maxCheck)&& result_set.full()) ) return;
|
||||
checked.set(index);
|
||||
checkCount++;
|
||||
|
||||
DistanceType dist = distance_(dataset_[index], vec, veclen_);
|
||||
result_set.addPoint(dist,index);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Which child branch should be taken first? */
|
||||
ElementType val = vec[node->divfeat];
|
||||
DistanceType diff = val - node->divval;
|
||||
NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
|
||||
NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
|
||||
|
||||
/* Create a branch record for the branch not taken. Add distance
|
||||
of this feature boundary (we don't attempt to correct for any
|
||||
use of this feature in a parent node, which is unlikely to
|
||||
happen and would have only a small effect). Don't bother
|
||||
adding more branches to heap after halfway point, as cost of
|
||||
adding exceeds their value.
|
||||
*/
|
||||
|
||||
DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat);
|
||||
// if (2 * checkCount < maxCheck || !result.full()) {
|
||||
if ((new_distsq*epsError < result_set.worstDist())|| !result_set.full()) {
|
||||
heap->insert( BranchSt(otherChild, new_distsq) );
|
||||
}
|
||||
|
||||
/* Call recursively to search next level down. */
|
||||
searchLevel(result_set, vec, bestChild, mindist, checkCount, maxCheck, epsError, heap, checked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an exact search in the tree starting from a node.
|
||||
*/
|
||||
void searchLevelExact(ResultSet<DistanceType>& result_set, const ElementType* vec, const NodePtr node, DistanceType mindist, const float epsError)
|
||||
{
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if ((node->child1 == NULL)&&(node->child2 == NULL)) {
|
||||
int index = node->divfeat;
|
||||
DistanceType dist = distance_(dataset_[index], vec, veclen_);
|
||||
result_set.addPoint(dist,index);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Which child branch should be taken first? */
|
||||
ElementType val = vec[node->divfeat];
|
||||
DistanceType diff = val - node->divval;
|
||||
NodePtr bestChild = (diff < 0) ? node->child1 : node->child2;
|
||||
NodePtr otherChild = (diff < 0) ? node->child2 : node->child1;
|
||||
|
||||
/* Create a branch record for the branch not taken. Add distance
|
||||
of this feature boundary (we don't attempt to correct for any
|
||||
use of this feature in a parent node, which is unlikely to
|
||||
happen and would have only a small effect). Don't bother
|
||||
adding more branches to heap after halfway point, as cost of
|
||||
adding exceeds their value.
|
||||
*/
|
||||
|
||||
DistanceType new_distsq = mindist + distance_.accum_dist(val, node->divval, node->divfeat);
|
||||
|
||||
/* Call recursively to search next level down. */
|
||||
searchLevelExact(result_set, vec, bestChild, mindist, epsError);
|
||||
|
||||
if (new_distsq*epsError<=result_set.worstDist()) {
|
||||
searchLevelExact(result_set, vec, otherChild, new_distsq, epsError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
/**
|
||||
* To improve efficiency, only SAMPLE_MEAN random values are used to
|
||||
* compute the mean and variance at each level when building a tree.
|
||||
* A value of 100 seems to perform as well as using all values.
|
||||
*/
|
||||
SAMPLE_MEAN = 100,
|
||||
/**
|
||||
* Top random dimensions to consider
|
||||
*
|
||||
* When creating random trees, the dimension on which to subdivide is
|
||||
* selected at random from among the top RAND_DIM dimensions with the
|
||||
* highest variance. A value of 5 works well.
|
||||
*/
|
||||
RAND_DIM=5
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Number of randomized trees that are used
|
||||
*/
|
||||
int trees_;
|
||||
|
||||
/**
|
||||
* Array of indices to vectors in the dataset.
|
||||
*/
|
||||
std::vector<int> vind_;
|
||||
|
||||
/**
|
||||
* The dataset used by this index
|
||||
*/
|
||||
const Matrix<ElementType> dataset_;
|
||||
|
||||
IndexParams index_params_;
|
||||
|
||||
size_t size_;
|
||||
size_t veclen_;
|
||||
|
||||
|
||||
DistanceType* mean_;
|
||||
DistanceType* var_;
|
||||
|
||||
|
||||
/**
|
||||
* Array of k-d trees used to find neighbours.
|
||||
*/
|
||||
NodePtr* tree_roots_;
|
||||
|
||||
/**
|
||||
* Pooled memory allocator.
|
||||
*
|
||||
* Using a pooled memory allocator is more efficient
|
||||
* than allocating memory directly when there is a large
|
||||
* number small of memory allocations.
|
||||
*/
|
||||
PooledAllocator pool_;
|
||||
|
||||
Distance distance_;
|
||||
|
||||
|
||||
}; // class KDTreeForest
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_KDTREE_INDEX_H_
|
||||
@@ -0,0 +1,634 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
#define OPENCV_FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
#include "matrix.h"
|
||||
#include "result_set.h"
|
||||
#include "heap.h"
|
||||
#include "allocator.h"
|
||||
#include "random.h"
|
||||
#include "saving.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
struct KDTreeSingleIndexParams : public IndexParams
|
||||
{
|
||||
KDTreeSingleIndexParams(int leaf_max_size = 10, bool reorder = true, int dim = -1)
|
||||
{
|
||||
(*this)["algorithm"] = FLANN_INDEX_KDTREE_SINGLE;
|
||||
(*this)["leaf_max_size"] = leaf_max_size;
|
||||
(*this)["reorder"] = reorder;
|
||||
(*this)["dim"] = dim;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Randomized kd-tree index
|
||||
*
|
||||
* Contains the k-d trees and other information for indexing a set of points
|
||||
* for nearest-neighbor matching.
|
||||
*/
|
||||
template <typename Distance>
|
||||
class KDTreeSingleIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
|
||||
/**
|
||||
* KDTree constructor
|
||||
*
|
||||
* Params:
|
||||
* inputData = dataset with the input features
|
||||
* params = parameters passed to the kdtree algorithm
|
||||
*/
|
||||
KDTreeSingleIndex(const Matrix<ElementType>& inputData, const IndexParams& params = KDTreeSingleIndexParams(),
|
||||
Distance d = Distance() ) :
|
||||
dataset_(inputData), index_params_(params), distance_(d)
|
||||
{
|
||||
size_ = dataset_.rows;
|
||||
dim_ = dataset_.cols;
|
||||
int dim_param = get_param(params,"dim",-1);
|
||||
if (dim_param>0) dim_ = dim_param;
|
||||
leaf_max_size_ = get_param(params,"leaf_max_size",10);
|
||||
reorder_ = get_param(params,"reorder",true);
|
||||
|
||||
// Create a permutable array of indices to the input vectors.
|
||||
vind_.resize(size_);
|
||||
for (size_t i = 0; i < size_; i++) {
|
||||
vind_[i] = (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
KDTreeSingleIndex(const KDTreeSingleIndex&);
|
||||
KDTreeSingleIndex& operator=(const KDTreeSingleIndex&);
|
||||
|
||||
/**
|
||||
* Standard destructor
|
||||
*/
|
||||
~KDTreeSingleIndex()
|
||||
{
|
||||
if (reorder_) delete[] data_.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
computeBoundingBox(root_bbox_);
|
||||
root_node_ = divideTree(0, (int)size_, root_bbox_ ); // construct the tree
|
||||
|
||||
if (reorder_) {
|
||||
delete[] data_.data;
|
||||
data_ = cvflann::Matrix<ElementType>(new ElementType[size_*dim_], size_, dim_);
|
||||
for (size_t i=0; i<size_; ++i) {
|
||||
for (size_t j=0; j<dim_; ++j) {
|
||||
data_[i][j] = dataset_[vind_[i]][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
data_ = dataset_;
|
||||
}
|
||||
}
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_KDTREE_SINGLE;
|
||||
}
|
||||
|
||||
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
save_value(stream, size_);
|
||||
save_value(stream, dim_);
|
||||
save_value(stream, root_bbox_);
|
||||
save_value(stream, reorder_);
|
||||
save_value(stream, leaf_max_size_);
|
||||
save_value(stream, vind_);
|
||||
if (reorder_) {
|
||||
save_value(stream, data_);
|
||||
}
|
||||
save_tree(stream, root_node_);
|
||||
}
|
||||
|
||||
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
load_value(stream, size_);
|
||||
load_value(stream, dim_);
|
||||
load_value(stream, root_bbox_);
|
||||
load_value(stream, reorder_);
|
||||
load_value(stream, leaf_max_size_);
|
||||
load_value(stream, vind_);
|
||||
if (reorder_) {
|
||||
load_value(stream, data_);
|
||||
}
|
||||
else {
|
||||
data_ = dataset_;
|
||||
}
|
||||
load_tree(stream, root_node_);
|
||||
|
||||
|
||||
index_params_["algorithm"] = getType();
|
||||
index_params_["leaf_max_size"] = leaf_max_size_;
|
||||
index_params_["reorder"] = reorder_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size of index.
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of an index feature.
|
||||
*/
|
||||
size_t veclen() const
|
||||
{
|
||||
return dim_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the inde memory usage
|
||||
* Returns: memory used by the index
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
return (int)(pool_.usedMemory+pool_.wastedMemory+dataset_.rows*sizeof(int)); // pool memory and vind array memory
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
void knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, int knn, const SearchParams& params)
|
||||
{
|
||||
assert(queries.cols == veclen());
|
||||
assert(indices.rows >= queries.rows);
|
||||
assert(dists.rows >= queries.rows);
|
||||
assert(int(indices.cols) >= knn);
|
||||
assert(int(dists.cols) >= knn);
|
||||
|
||||
KNNSimpleResultSet<DistanceType> resultSet(knn);
|
||||
for (size_t i = 0; i < queries.rows; i++) {
|
||||
resultSet.init(indices[i], dists[i]);
|
||||
findNeighbors(resultSet, queries[i], params);
|
||||
}
|
||||
}
|
||||
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return index_params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find set of nearest neighbors to vec. Their indices are stored inside
|
||||
* the result object.
|
||||
*
|
||||
* Params:
|
||||
* result = the result object in which the indices of the nearest-neighbors are stored
|
||||
* vec = the vector for which to search the nearest neighbors
|
||||
* maxCheck = the maximum number of restarts (in a best-bin-first manner)
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams)
|
||||
{
|
||||
float epsError = 1+get_param(searchParams,"eps",0.0f);
|
||||
|
||||
std::vector<DistanceType> dists(dim_,0);
|
||||
DistanceType distsq = computeInitialDistances(vec, dists);
|
||||
searchLevel(result, vec, root_node_, distsq, dists, epsError);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
||||
/*--------------------- Internal Data Structures --------------------------*/
|
||||
struct Node
|
||||
{
|
||||
/**
|
||||
* Indices of points in leaf node
|
||||
*/
|
||||
int left, right;
|
||||
/**
|
||||
* Dimension used for subdivision.
|
||||
*/
|
||||
int divfeat;
|
||||
/**
|
||||
* The values used for subdivision.
|
||||
*/
|
||||
DistanceType divlow, divhigh;
|
||||
/**
|
||||
* The child nodes.
|
||||
*/
|
||||
Node* child1, * child2;
|
||||
};
|
||||
typedef Node* NodePtr;
|
||||
|
||||
|
||||
struct Interval
|
||||
{
|
||||
DistanceType low, high;
|
||||
};
|
||||
|
||||
typedef std::vector<Interval> BoundingBox;
|
||||
|
||||
typedef BranchStruct<NodePtr, DistanceType> BranchSt;
|
||||
typedef BranchSt* Branch;
|
||||
|
||||
|
||||
|
||||
|
||||
void save_tree(FILE* stream, NodePtr tree)
|
||||
{
|
||||
save_value(stream, *tree);
|
||||
if (tree->child1!=NULL) {
|
||||
save_tree(stream, tree->child1);
|
||||
}
|
||||
if (tree->child2!=NULL) {
|
||||
save_tree(stream, tree->child2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void load_tree(FILE* stream, NodePtr& tree)
|
||||
{
|
||||
tree = pool_.allocate<Node>();
|
||||
load_value(stream, *tree);
|
||||
if (tree->child1!=NULL) {
|
||||
load_tree(stream, tree->child1);
|
||||
}
|
||||
if (tree->child2!=NULL) {
|
||||
load_tree(stream, tree->child2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void computeBoundingBox(BoundingBox& bbox)
|
||||
{
|
||||
bbox.resize(dim_);
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
bbox[i].low = (DistanceType)dataset_[0][i];
|
||||
bbox[i].high = (DistanceType)dataset_[0][i];
|
||||
}
|
||||
for (size_t k=1; k<dataset_.rows; ++k) {
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
if (dataset_[k][i]<bbox[i].low) bbox[i].low = (DistanceType)dataset_[k][i];
|
||||
if (dataset_[k][i]>bbox[i].high) bbox[i].high = (DistanceType)dataset_[k][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a tree node that subdivides the list of vecs from vind[first]
|
||||
* to vind[last]. The routine is called recursively on each sublist.
|
||||
* Place a pointer to this new tree node in the location pTree.
|
||||
*
|
||||
* Params: pTree = the new node to create
|
||||
* first = index of the first vector
|
||||
* last = index of the last vector
|
||||
*/
|
||||
NodePtr divideTree(int left, int right, BoundingBox& bbox)
|
||||
{
|
||||
NodePtr node = pool_.allocate<Node>(); // allocate memory
|
||||
|
||||
/* If too few exemplars remain, then make this a leaf node. */
|
||||
if ( (right-left) <= leaf_max_size_) {
|
||||
node->child1 = node->child2 = NULL; /* Mark as leaf node. */
|
||||
node->left = left;
|
||||
node->right = right;
|
||||
|
||||
// compute bounding-box of leaf points
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
bbox[i].low = (DistanceType)dataset_[vind_[left]][i];
|
||||
bbox[i].high = (DistanceType)dataset_[vind_[left]][i];
|
||||
}
|
||||
for (int k=left+1; k<right; ++k) {
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
if (bbox[i].low>dataset_[vind_[k]][i]) bbox[i].low=(DistanceType)dataset_[vind_[k]][i];
|
||||
if (bbox[i].high<dataset_[vind_[k]][i]) bbox[i].high=(DistanceType)dataset_[vind_[k]][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int idx;
|
||||
int cutfeat;
|
||||
DistanceType cutval;
|
||||
middleSplit_(&vind_[0]+left, right-left, idx, cutfeat, cutval, bbox);
|
||||
|
||||
node->divfeat = cutfeat;
|
||||
|
||||
BoundingBox left_bbox(bbox);
|
||||
left_bbox[cutfeat].high = cutval;
|
||||
node->child1 = divideTree(left, left+idx, left_bbox);
|
||||
|
||||
BoundingBox right_bbox(bbox);
|
||||
right_bbox[cutfeat].low = cutval;
|
||||
node->child2 = divideTree(left+idx, right, right_bbox);
|
||||
|
||||
node->divlow = left_bbox[cutfeat].high;
|
||||
node->divhigh = right_bbox[cutfeat].low;
|
||||
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low);
|
||||
bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void computeMinMax(int* ind, int count, int dim, ElementType& min_elem, ElementType& max_elem)
|
||||
{
|
||||
min_elem = dataset_[ind[0]][dim];
|
||||
max_elem = dataset_[ind[0]][dim];
|
||||
for (int i=1; i<count; ++i) {
|
||||
ElementType val = dataset_[ind[i]][dim];
|
||||
if (val<min_elem) min_elem = val;
|
||||
if (val>max_elem) max_elem = val;
|
||||
}
|
||||
}
|
||||
|
||||
void middleSplit(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
|
||||
{
|
||||
// find the largest span from the approximate bounding box
|
||||
ElementType max_span = bbox[0].high-bbox[0].low;
|
||||
cutfeat = 0;
|
||||
cutval = (bbox[0].high+bbox[0].low)/2;
|
||||
for (size_t i=1; i<dim_; ++i) {
|
||||
ElementType span = bbox[i].high-bbox[i].low;
|
||||
if (span>max_span) {
|
||||
max_span = span;
|
||||
cutfeat = i;
|
||||
cutval = (bbox[i].high+bbox[i].low)/2;
|
||||
}
|
||||
}
|
||||
|
||||
// compute exact span on the found dimension
|
||||
ElementType min_elem, max_elem;
|
||||
computeMinMax(ind, count, cutfeat, min_elem, max_elem);
|
||||
cutval = (min_elem+max_elem)/2;
|
||||
max_span = max_elem - min_elem;
|
||||
|
||||
// check if a dimension of a largest span exists
|
||||
size_t k = cutfeat;
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
if (i==k) continue;
|
||||
ElementType span = bbox[i].high-bbox[i].low;
|
||||
if (span>max_span) {
|
||||
computeMinMax(ind, count, i, min_elem, max_elem);
|
||||
span = max_elem - min_elem;
|
||||
if (span>max_span) {
|
||||
max_span = span;
|
||||
cutfeat = i;
|
||||
cutval = (min_elem+max_elem)/2;
|
||||
}
|
||||
}
|
||||
}
|
||||
int lim1, lim2;
|
||||
planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
|
||||
|
||||
if (lim1>count/2) index = lim1;
|
||||
else if (lim2<count/2) index = lim2;
|
||||
else index = count/2;
|
||||
}
|
||||
|
||||
|
||||
void middleSplit_(int* ind, int count, int& index, int& cutfeat, DistanceType& cutval, const BoundingBox& bbox)
|
||||
{
|
||||
const float EPS=0.00001f;
|
||||
DistanceType max_span = bbox[0].high-bbox[0].low;
|
||||
for (size_t i=1; i<dim_; ++i) {
|
||||
DistanceType span = bbox[i].high-bbox[i].low;
|
||||
if (span>max_span) {
|
||||
max_span = span;
|
||||
}
|
||||
}
|
||||
DistanceType max_spread = -1;
|
||||
cutfeat = 0;
|
||||
for (size_t i=0; i<dim_; ++i) {
|
||||
DistanceType span = bbox[i].high-bbox[i].low;
|
||||
if (span>(DistanceType)((1-EPS)*max_span)) {
|
||||
ElementType min_elem, max_elem;
|
||||
computeMinMax(ind, count, cutfeat, min_elem, max_elem);
|
||||
DistanceType spread = (DistanceType)(max_elem-min_elem);
|
||||
if (spread>max_spread) {
|
||||
cutfeat = (int)i;
|
||||
max_spread = spread;
|
||||
}
|
||||
}
|
||||
}
|
||||
// split in the middle
|
||||
DistanceType split_val = (bbox[cutfeat].low+bbox[cutfeat].high)/2;
|
||||
ElementType min_elem, max_elem;
|
||||
computeMinMax(ind, count, cutfeat, min_elem, max_elem);
|
||||
|
||||
if (split_val<min_elem) cutval = (DistanceType)min_elem;
|
||||
else if (split_val>max_elem) cutval = (DistanceType)max_elem;
|
||||
else cutval = split_val;
|
||||
|
||||
int lim1, lim2;
|
||||
planeSplit(ind, count, cutfeat, cutval, lim1, lim2);
|
||||
|
||||
if (lim1>count/2) index = lim1;
|
||||
else if (lim2<count/2) index = lim2;
|
||||
else index = count/2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subdivide the list of points by a plane perpendicular on axe corresponding
|
||||
* to the 'cutfeat' dimension at 'cutval' position.
|
||||
*
|
||||
* On return:
|
||||
* dataset[ind[0..lim1-1]][cutfeat]<cutval
|
||||
* dataset[ind[lim1..lim2-1]][cutfeat]==cutval
|
||||
* dataset[ind[lim2..count]][cutfeat]>cutval
|
||||
*/
|
||||
void planeSplit(int* ind, int count, int cutfeat, DistanceType cutval, int& lim1, int& lim2)
|
||||
{
|
||||
/* Move vector indices for left subtree to front of list. */
|
||||
int left = 0;
|
||||
int right = count-1;
|
||||
for (;; ) {
|
||||
while (left<=right && dataset_[ind[left]][cutfeat]<cutval) ++left;
|
||||
while (left<=right && dataset_[ind[right]][cutfeat]>=cutval) --right;
|
||||
if (left>right) break;
|
||||
std::swap(ind[left], ind[right]); ++left; --right;
|
||||
}
|
||||
/* If either list is empty, it means that all remaining features
|
||||
* are identical. Split in the middle to maintain a balanced tree.
|
||||
*/
|
||||
lim1 = left;
|
||||
right = count-1;
|
||||
for (;; ) {
|
||||
while (left<=right && dataset_[ind[left]][cutfeat]<=cutval) ++left;
|
||||
while (left<=right && dataset_[ind[right]][cutfeat]>cutval) --right;
|
||||
if (left>right) break;
|
||||
std::swap(ind[left], ind[right]); ++left; --right;
|
||||
}
|
||||
lim2 = left;
|
||||
}
|
||||
|
||||
DistanceType computeInitialDistances(const ElementType* vec, std::vector<DistanceType>& dists)
|
||||
{
|
||||
DistanceType distsq = 0.0;
|
||||
|
||||
for (size_t i = 0; i < dim_; ++i) {
|
||||
if (vec[i] < root_bbox_[i].low) {
|
||||
dists[i] = distance_.accum_dist(vec[i], root_bbox_[i].low, (int)i);
|
||||
distsq += dists[i];
|
||||
}
|
||||
if (vec[i] > root_bbox_[i].high) {
|
||||
dists[i] = distance_.accum_dist(vec[i], root_bbox_[i].high, (int)i);
|
||||
distsq += dists[i];
|
||||
}
|
||||
}
|
||||
|
||||
return distsq;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an exact search in the tree starting from a node.
|
||||
*/
|
||||
void searchLevel(ResultSet<DistanceType>& result_set, const ElementType* vec, const NodePtr node, DistanceType mindistsq,
|
||||
std::vector<DistanceType>& dists, const float epsError)
|
||||
{
|
||||
/* If this is a leaf node, then do check and return. */
|
||||
if ((node->child1 == NULL)&&(node->child2 == NULL)) {
|
||||
DistanceType worst_dist = result_set.worstDist();
|
||||
for (int i=node->left; i<node->right; ++i) {
|
||||
int index = reorder_ ? i : vind_[i];
|
||||
DistanceType dist = distance_(vec, data_[index], dim_, worst_dist);
|
||||
if (dist<worst_dist) {
|
||||
result_set.addPoint(dist,vind_[i]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Which child branch should be taken first? */
|
||||
int idx = node->divfeat;
|
||||
ElementType val = vec[idx];
|
||||
DistanceType diff1 = val - node->divlow;
|
||||
DistanceType diff2 = val - node->divhigh;
|
||||
|
||||
NodePtr bestChild;
|
||||
NodePtr otherChild;
|
||||
DistanceType cut_dist;
|
||||
if ((diff1+diff2)<0) {
|
||||
bestChild = node->child1;
|
||||
otherChild = node->child2;
|
||||
cut_dist = distance_.accum_dist(val, node->divhigh, idx);
|
||||
}
|
||||
else {
|
||||
bestChild = node->child2;
|
||||
otherChild = node->child1;
|
||||
cut_dist = distance_.accum_dist( val, node->divlow, idx);
|
||||
}
|
||||
|
||||
/* Call recursively to search next level down. */
|
||||
searchLevel(result_set, vec, bestChild, mindistsq, dists, epsError);
|
||||
|
||||
DistanceType dst = dists[idx];
|
||||
mindistsq = mindistsq + cut_dist - dst;
|
||||
dists[idx] = cut_dist;
|
||||
if (mindistsq*epsError<=result_set.worstDist()) {
|
||||
searchLevel(result_set, vec, otherChild, mindistsq, dists, epsError);
|
||||
}
|
||||
dists[idx] = dst;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The dataset used by this index
|
||||
*/
|
||||
const Matrix<ElementType> dataset_;
|
||||
|
||||
IndexParams index_params_;
|
||||
|
||||
int leaf_max_size_;
|
||||
bool reorder_;
|
||||
|
||||
|
||||
/**
|
||||
* Array of indices to vectors in the dataset.
|
||||
*/
|
||||
std::vector<int> vind_;
|
||||
|
||||
Matrix<ElementType> data_;
|
||||
|
||||
size_t size_;
|
||||
size_t dim_;
|
||||
|
||||
/**
|
||||
* Array of k-d trees used to find neighbours.
|
||||
*/
|
||||
NodePtr root_node_;
|
||||
|
||||
BoundingBox root_bbox_;
|
||||
|
||||
/**
|
||||
* Pooled memory allocator.
|
||||
*
|
||||
* Using a pooled memory allocator is more efficient
|
||||
* than allocating memory directly when there is a large
|
||||
* number small of memory allocations.
|
||||
*/
|
||||
PooledAllocator pool_;
|
||||
|
||||
Distance distance_;
|
||||
}; // class KDTree
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_KDTREE_SINGLE_INDEX_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,132 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_LINEAR_INDEX_H_
|
||||
#define OPENCV_FLANN_LINEAR_INDEX_H_
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
struct LinearIndexParams : public IndexParams
|
||||
{
|
||||
LinearIndexParams()
|
||||
{
|
||||
(* this)["algorithm"] = FLANN_INDEX_LINEAR;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Distance>
|
||||
class LinearIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
|
||||
LinearIndex(const Matrix<ElementType>& inputData, const IndexParams& params = LinearIndexParams(),
|
||||
Distance d = Distance()) :
|
||||
dataset_(inputData), index_params_(params), distance_(d)
|
||||
{
|
||||
}
|
||||
|
||||
LinearIndex(const LinearIndex&);
|
||||
LinearIndex& operator=(const LinearIndex&);
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_LINEAR;
|
||||
}
|
||||
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return dataset_.rows;
|
||||
}
|
||||
|
||||
size_t veclen() const
|
||||
{
|
||||
return dataset_.cols;
|
||||
}
|
||||
|
||||
|
||||
int usedMemory() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void buildIndex()
|
||||
{
|
||||
/* nothing to do here for linear search */
|
||||
}
|
||||
|
||||
void saveIndex(FILE*)
|
||||
{
|
||||
/* nothing to do here for linear search */
|
||||
}
|
||||
|
||||
|
||||
void loadIndex(FILE*)
|
||||
{
|
||||
/* nothing to do here for linear search */
|
||||
|
||||
index_params_["algorithm"] = getType();
|
||||
}
|
||||
|
||||
void findNeighbors(ResultSet<DistanceType>& resultSet, const ElementType* vec, const SearchParams& /*searchParams*/)
|
||||
{
|
||||
ElementType* data = dataset_.data;
|
||||
for (size_t i = 0; i < dataset_.rows; ++i, data += dataset_.cols) {
|
||||
DistanceType dist = distance_(data, vec, dataset_.cols);
|
||||
resultSet.addPoint(dist, (int)i);
|
||||
}
|
||||
}
|
||||
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return index_params_;
|
||||
}
|
||||
|
||||
private:
|
||||
/** The dataset */
|
||||
const Matrix<ElementType> dataset_;
|
||||
/** Index parameters */
|
||||
IndexParams index_params_;
|
||||
/** Index distance */
|
||||
Distance distance_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENCV_FLANN_LINEAR_INDEX_H_
|
||||
@@ -0,0 +1,130 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_LOGGER_H
|
||||
#define OPENCV_FLANN_LOGGER_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "defines.h"
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
class Logger
|
||||
{
|
||||
Logger() : stream(stdout), logLevel(FLANN_LOG_WARN) {}
|
||||
|
||||
~Logger()
|
||||
{
|
||||
if ((stream!=NULL)&&(stream!=stdout)) {
|
||||
fclose(stream);
|
||||
}
|
||||
}
|
||||
|
||||
static Logger& instance()
|
||||
{
|
||||
static Logger logger;
|
||||
return logger;
|
||||
}
|
||||
|
||||
void _setDestination(const char* name)
|
||||
{
|
||||
if (name==NULL) {
|
||||
stream = stdout;
|
||||
}
|
||||
else {
|
||||
stream = fopen(name,"w");
|
||||
if (stream == NULL) {
|
||||
stream = stdout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int _log(int level, const char* fmt, va_list arglist)
|
||||
{
|
||||
if (level > logLevel ) return -1;
|
||||
int ret = vfprintf(stream, fmt, arglist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Sets the logging level. All messages with lower priority will be ignored.
|
||||
* @param level Logging level
|
||||
*/
|
||||
static void setLevel(int level) { instance().logLevel = level; }
|
||||
|
||||
/**
|
||||
* Sets the logging destination
|
||||
* @param name Filename or NULL for console
|
||||
*/
|
||||
static void setDestination(const char* name) { instance()._setDestination(name); }
|
||||
|
||||
/**
|
||||
* Print log message
|
||||
* @param level Log level
|
||||
* @param fmt Message format
|
||||
* @return
|
||||
*/
|
||||
static int log(int level, const char* fmt, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start(arglist, fmt);
|
||||
int ret = instance()._log(level,fmt,arglist);
|
||||
va_end(arglist);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LOG_METHOD(NAME,LEVEL) \
|
||||
static int NAME(const char* fmt, ...) \
|
||||
{ \
|
||||
va_list ap; \
|
||||
va_start(ap, fmt); \
|
||||
int ret = instance()._log(LEVEL, fmt, ap); \
|
||||
va_end(ap); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
LOG_METHOD(fatal, FLANN_LOG_FATAL)
|
||||
LOG_METHOD(error, FLANN_LOG_ERROR)
|
||||
LOG_METHOD(warn, FLANN_LOG_WARN)
|
||||
LOG_METHOD(info, FLANN_LOG_INFO)
|
||||
|
||||
private:
|
||||
FILE* stream;
|
||||
int logLevel;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_LOGGER_H
|
||||
@@ -0,0 +1,392 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Author: Vincent Rabaud
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_LSH_INDEX_H_
|
||||
#define OPENCV_FLANN_LSH_INDEX_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
#include "matrix.h"
|
||||
#include "result_set.h"
|
||||
#include "heap.h"
|
||||
#include "lsh_table.h"
|
||||
#include "allocator.h"
|
||||
#include "random.h"
|
||||
#include "saving.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
struct LshIndexParams : public IndexParams
|
||||
{
|
||||
LshIndexParams(unsigned int table_number = 12, unsigned int key_size = 20, unsigned int multi_probe_level = 2)
|
||||
{
|
||||
(* this)["algorithm"] = FLANN_INDEX_LSH;
|
||||
// The number of hash tables to use
|
||||
(*this)["table_number"] = table_number;
|
||||
// The length of the key in the hash tables
|
||||
(*this)["key_size"] = key_size;
|
||||
// Number of levels to use in multi-probe (0 for standard LSH)
|
||||
(*this)["multi_probe_level"] = multi_probe_level;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Randomized kd-tree index
|
||||
*
|
||||
* Contains the k-d trees and other information for indexing a set of points
|
||||
* for nearest-neighbor matching.
|
||||
*/
|
||||
template<typename Distance>
|
||||
class LshIndex : public NNIndex<Distance>
|
||||
{
|
||||
public:
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
/** Constructor
|
||||
* @param input_data dataset with the input features
|
||||
* @param params parameters passed to the LSH algorithm
|
||||
* @param d the distance used
|
||||
*/
|
||||
LshIndex(const Matrix<ElementType>& input_data, const IndexParams& params = LshIndexParams(),
|
||||
Distance d = Distance()) :
|
||||
dataset_(input_data), index_params_(params), distance_(d)
|
||||
{
|
||||
// cv::flann::IndexParams sets integer params as 'int', so it is used with get_param
|
||||
// in place of 'unsigned int'
|
||||
table_number_ = (unsigned int)get_param<int>(index_params_,"table_number",12);
|
||||
key_size_ = (unsigned int)get_param<int>(index_params_,"key_size",20);
|
||||
multi_probe_level_ = (unsigned int)get_param<int>(index_params_,"multi_probe_level",2);
|
||||
|
||||
feature_size_ = (unsigned)dataset_.cols;
|
||||
fill_xor_mask(0, key_size_, multi_probe_level_, xor_masks_);
|
||||
}
|
||||
|
||||
|
||||
LshIndex(const LshIndex&);
|
||||
LshIndex& operator=(const LshIndex&);
|
||||
|
||||
/**
|
||||
* Builds the index
|
||||
*/
|
||||
void buildIndex()
|
||||
{
|
||||
tables_.resize(table_number_);
|
||||
for (unsigned int i = 0; i < table_number_; ++i) {
|
||||
lsh::LshTable<ElementType>& table = tables_[i];
|
||||
table = lsh::LshTable<ElementType>(feature_size_, key_size_);
|
||||
|
||||
// Add the features to the table
|
||||
table.add(dataset_);
|
||||
}
|
||||
}
|
||||
|
||||
flann_algorithm_t getType() const
|
||||
{
|
||||
return FLANN_INDEX_LSH;
|
||||
}
|
||||
|
||||
|
||||
void saveIndex(FILE* stream)
|
||||
{
|
||||
save_value(stream,table_number_);
|
||||
save_value(stream,key_size_);
|
||||
save_value(stream,multi_probe_level_);
|
||||
save_value(stream, dataset_);
|
||||
}
|
||||
|
||||
void loadIndex(FILE* stream)
|
||||
{
|
||||
load_value(stream, table_number_);
|
||||
load_value(stream, key_size_);
|
||||
load_value(stream, multi_probe_level_);
|
||||
load_value(stream, dataset_);
|
||||
// Building the index is so fast we can afford not storing it
|
||||
buildIndex();
|
||||
|
||||
index_params_["algorithm"] = getType();
|
||||
index_params_["table_number"] = table_number_;
|
||||
index_params_["key_size"] = key_size_;
|
||||
index_params_["multi_probe_level"] = multi_probe_level_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns size of index.
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return dataset_.rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of an index feature.
|
||||
*/
|
||||
size_t veclen() const
|
||||
{
|
||||
return feature_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the index memory usage
|
||||
* Returns: memory used by the index
|
||||
*/
|
||||
int usedMemory() const
|
||||
{
|
||||
return (int)(dataset_.rows * sizeof(int));
|
||||
}
|
||||
|
||||
|
||||
IndexParams getParameters() const
|
||||
{
|
||||
return index_params_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
virtual void knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, int knn, const SearchParams& params)
|
||||
{
|
||||
assert(queries.cols == veclen());
|
||||
assert(indices.rows >= queries.rows);
|
||||
assert(dists.rows >= queries.rows);
|
||||
assert(int(indices.cols) >= knn);
|
||||
assert(int(dists.cols) >= knn);
|
||||
|
||||
|
||||
KNNUniqueResultSet<DistanceType> resultSet(knn);
|
||||
for (size_t i = 0; i < queries.rows; i++) {
|
||||
resultSet.clear();
|
||||
std::fill_n(indices[i], knn, -1);
|
||||
std::fill_n(dists[i], knn, std::numeric_limits<DistanceType>::max());
|
||||
findNeighbors(resultSet, queries[i], params);
|
||||
if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices[i], dists[i], knn);
|
||||
else resultSet.copy(indices[i], dists[i], knn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find set of nearest neighbors to vec. Their indices are stored inside
|
||||
* the result object.
|
||||
*
|
||||
* Params:
|
||||
* result = the result object in which the indices of the nearest-neighbors are stored
|
||||
* vec = the vector for which to search the nearest neighbors
|
||||
* maxCheck = the maximum number of restarts (in a best-bin-first manner)
|
||||
*/
|
||||
void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& /*searchParams*/)
|
||||
{
|
||||
getNeighbors(vec, result);
|
||||
}
|
||||
|
||||
private:
|
||||
/** Defines the comparator on score and index
|
||||
*/
|
||||
typedef std::pair<float, unsigned int> ScoreIndexPair;
|
||||
struct SortScoreIndexPairOnSecond
|
||||
{
|
||||
bool operator()(const ScoreIndexPair& left, const ScoreIndexPair& right) const
|
||||
{
|
||||
return left.second < right.second;
|
||||
}
|
||||
};
|
||||
|
||||
/** Fills the different xor masks to use when getting the neighbors in multi-probe LSH
|
||||
* @param key the key we build neighbors from
|
||||
* @param lowest_index the lowest index of the bit set
|
||||
* @param level the multi-probe level we are at
|
||||
* @param xor_masks all the xor mask
|
||||
*/
|
||||
void fill_xor_mask(lsh::BucketKey key, int lowest_index, unsigned int level,
|
||||
std::vector<lsh::BucketKey>& xor_masks)
|
||||
{
|
||||
xor_masks.push_back(key);
|
||||
if (level == 0) return;
|
||||
for (int index = lowest_index - 1; index >= 0; --index) {
|
||||
// Create a new key
|
||||
lsh::BucketKey new_key = key | (1 << index);
|
||||
fill_xor_mask(new_key, index, level - 1, xor_masks);
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs the approximate nearest-neighbor search.
|
||||
* @param vec the feature to analyze
|
||||
* @param do_radius flag indicating if we check the radius too
|
||||
* @param radius the radius if it is a radius search
|
||||
* @param do_k flag indicating if we limit the number of nn
|
||||
* @param k_nn the number of nearest neighbors
|
||||
* @param checked_average used for debugging
|
||||
*/
|
||||
void getNeighbors(const ElementType* vec, bool /*do_radius*/, float radius, bool do_k, unsigned int k_nn,
|
||||
float& /*checked_average*/)
|
||||
{
|
||||
static std::vector<ScoreIndexPair> score_index_heap;
|
||||
|
||||
if (do_k) {
|
||||
unsigned int worst_score = std::numeric_limits<unsigned int>::max();
|
||||
typename std::vector<lsh::LshTable<ElementType> >::const_iterator table = tables_.begin();
|
||||
typename std::vector<lsh::LshTable<ElementType> >::const_iterator table_end = tables_.end();
|
||||
for (; table != table_end; ++table) {
|
||||
size_t key = table->getKey(vec);
|
||||
std::vector<lsh::BucketKey>::const_iterator xor_mask = xor_masks_.begin();
|
||||
std::vector<lsh::BucketKey>::const_iterator xor_mask_end = xor_masks_.end();
|
||||
for (; xor_mask != xor_mask_end; ++xor_mask) {
|
||||
size_t sub_key = key ^ (*xor_mask);
|
||||
const lsh::Bucket* bucket = table->getBucketFromKey(sub_key);
|
||||
if (bucket == 0) continue;
|
||||
|
||||
// Go over each descriptor index
|
||||
std::vector<lsh::FeatureIndex>::const_iterator training_index = bucket->begin();
|
||||
std::vector<lsh::FeatureIndex>::const_iterator last_training_index = bucket->end();
|
||||
DistanceType hamming_distance;
|
||||
|
||||
// Process the rest of the candidates
|
||||
for (; training_index < last_training_index; ++training_index) {
|
||||
hamming_distance = distance_(vec, dataset_[*training_index], dataset_.cols);
|
||||
|
||||
if (hamming_distance < worst_score) {
|
||||
// Insert the new element
|
||||
score_index_heap.push_back(ScoreIndexPair(hamming_distance, training_index));
|
||||
std::push_heap(score_index_heap.begin(), score_index_heap.end());
|
||||
|
||||
if (score_index_heap.size() > (unsigned int)k_nn) {
|
||||
// Remove the highest distance value as we have too many elements
|
||||
std::pop_heap(score_index_heap.begin(), score_index_heap.end());
|
||||
score_index_heap.pop_back();
|
||||
// Keep track of the worst score
|
||||
worst_score = score_index_heap.front().first;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
typename std::vector<lsh::LshTable<ElementType> >::const_iterator table = tables_.begin();
|
||||
typename std::vector<lsh::LshTable<ElementType> >::const_iterator table_end = tables_.end();
|
||||
for (; table != table_end; ++table) {
|
||||
size_t key = table->getKey(vec);
|
||||
std::vector<lsh::BucketKey>::const_iterator xor_mask = xor_masks_.begin();
|
||||
std::vector<lsh::BucketKey>::const_iterator xor_mask_end = xor_masks_.end();
|
||||
for (; xor_mask != xor_mask_end; ++xor_mask) {
|
||||
size_t sub_key = key ^ (*xor_mask);
|
||||
const lsh::Bucket* bucket = table->getBucketFromKey(sub_key);
|
||||
if (bucket == 0) continue;
|
||||
|
||||
// Go over each descriptor index
|
||||
std::vector<lsh::FeatureIndex>::const_iterator training_index = bucket->begin();
|
||||
std::vector<lsh::FeatureIndex>::const_iterator last_training_index = bucket->end();
|
||||
DistanceType hamming_distance;
|
||||
|
||||
// Process the rest of the candidates
|
||||
for (; training_index < last_training_index; ++training_index) {
|
||||
// Compute the Hamming distance
|
||||
hamming_distance = distance_(vec, dataset_[*training_index], dataset_.cols);
|
||||
if (hamming_distance < radius) score_index_heap.push_back(ScoreIndexPair(hamming_distance, training_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs the approximate nearest-neighbor search.
|
||||
* This is a slower version than the above as it uses the ResultSet
|
||||
* @param vec the feature to analyze
|
||||
*/
|
||||
void getNeighbors(const ElementType* vec, ResultSet<DistanceType>& result)
|
||||
{
|
||||
typename std::vector<lsh::LshTable<ElementType> >::const_iterator table = tables_.begin();
|
||||
typename std::vector<lsh::LshTable<ElementType> >::const_iterator table_end = tables_.end();
|
||||
for (; table != table_end; ++table) {
|
||||
size_t key = table->getKey(vec);
|
||||
std::vector<lsh::BucketKey>::const_iterator xor_mask = xor_masks_.begin();
|
||||
std::vector<lsh::BucketKey>::const_iterator xor_mask_end = xor_masks_.end();
|
||||
for (; xor_mask != xor_mask_end; ++xor_mask) {
|
||||
size_t sub_key = key ^ (*xor_mask);
|
||||
const lsh::Bucket* bucket = table->getBucketFromKey((lsh::BucketKey)sub_key);
|
||||
if (bucket == 0) continue;
|
||||
|
||||
// Go over each descriptor index
|
||||
std::vector<lsh::FeatureIndex>::const_iterator training_index = bucket->begin();
|
||||
std::vector<lsh::FeatureIndex>::const_iterator last_training_index = bucket->end();
|
||||
DistanceType hamming_distance;
|
||||
|
||||
// Process the rest of the candidates
|
||||
for (; training_index < last_training_index; ++training_index) {
|
||||
// Compute the Hamming distance
|
||||
hamming_distance = distance_(vec, dataset_[*training_index], (int)dataset_.cols);
|
||||
result.addPoint(hamming_distance, *training_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The different hash tables */
|
||||
std::vector<lsh::LshTable<ElementType> > tables_;
|
||||
|
||||
/** The data the LSH tables where built from */
|
||||
Matrix<ElementType> dataset_;
|
||||
|
||||
/** The size of the features (as ElementType[]) */
|
||||
unsigned int feature_size_;
|
||||
|
||||
IndexParams index_params_;
|
||||
|
||||
/** table number */
|
||||
unsigned int table_number_;
|
||||
/** key size */
|
||||
unsigned int key_size_;
|
||||
/** How far should we look for neighbors in multi-probe LSH */
|
||||
unsigned int multi_probe_level_;
|
||||
|
||||
/** The XOR masks to apply to a key to get the neighboring buckets */
|
||||
std::vector<lsh::BucketKey> xor_masks_;
|
||||
|
||||
Distance distance_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_LSH_INDEX_H_
|
||||
@@ -0,0 +1,492 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Author: Vincent Rabaud
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_LSH_TABLE_H_
|
||||
#define OPENCV_FLANN_LSH_TABLE_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <limits.h>
|
||||
// TODO as soon as we use C++0x, use the code in USE_UNORDERED_MAP
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
# define USE_UNORDERED_MAP 1
|
||||
#else
|
||||
# define USE_UNORDERED_MAP 0
|
||||
#endif
|
||||
#if USE_UNORDERED_MAP
|
||||
#include <unordered_map>
|
||||
#else
|
||||
#include <map>
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dynamic_bitset.h"
|
||||
#include "matrix.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
namespace lsh
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** What is stored in an LSH bucket
|
||||
*/
|
||||
typedef uint32_t FeatureIndex;
|
||||
/** The id from which we can get a bucket back in an LSH table
|
||||
*/
|
||||
typedef unsigned int BucketKey;
|
||||
|
||||
/** A bucket in an LSH table
|
||||
*/
|
||||
typedef std::vector<FeatureIndex> Bucket;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** POD for stats about an LSH table
|
||||
*/
|
||||
struct LshStats
|
||||
{
|
||||
std::vector<unsigned int> bucket_sizes_;
|
||||
size_t n_buckets_;
|
||||
size_t bucket_size_mean_;
|
||||
size_t bucket_size_median_;
|
||||
size_t bucket_size_min_;
|
||||
size_t bucket_size_max_;
|
||||
size_t bucket_size_std_dev;
|
||||
/** Each contained vector contains three value: beginning/end for interval, number of elements in the bin
|
||||
*/
|
||||
std::vector<std::vector<unsigned int> > size_histogram_;
|
||||
};
|
||||
|
||||
/** Overload the << operator for LshStats
|
||||
* @param out the streams
|
||||
* @param stats the stats to display
|
||||
* @return the streams
|
||||
*/
|
||||
inline std::ostream& operator <<(std::ostream& out, const LshStats& stats)
|
||||
{
|
||||
int w = 20;
|
||||
out << "Lsh Table Stats:\n" << std::setw(w) << std::setiosflags(std::ios::right) << "N buckets : "
|
||||
<< stats.n_buckets_ << "\n" << std::setw(w) << std::setiosflags(std::ios::right) << "mean size : "
|
||||
<< std::setiosflags(std::ios::left) << stats.bucket_size_mean_ << "\n" << std::setw(w)
|
||||
<< std::setiosflags(std::ios::right) << "median size : " << stats.bucket_size_median_ << "\n" << std::setw(w)
|
||||
<< std::setiosflags(std::ios::right) << "min size : " << std::setiosflags(std::ios::left)
|
||||
<< stats.bucket_size_min_ << "\n" << std::setw(w) << std::setiosflags(std::ios::right) << "max size : "
|
||||
<< std::setiosflags(std::ios::left) << stats.bucket_size_max_;
|
||||
|
||||
// Display the histogram
|
||||
out << std::endl << std::setw(w) << std::setiosflags(std::ios::right) << "histogram : "
|
||||
<< std::setiosflags(std::ios::left);
|
||||
for (std::vector<std::vector<unsigned int> >::const_iterator iterator = stats.size_histogram_.begin(), end =
|
||||
stats.size_histogram_.end(); iterator != end; ++iterator) out << (*iterator)[0] << "-" << (*iterator)[1] << ": " << (*iterator)[2] << ", ";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Lsh hash table. As its key is a sub-feature, and as usually
|
||||
* the size of it is pretty small, we keep it as a continuous memory array.
|
||||
* The value is an index in the corpus of features (we keep it as an unsigned
|
||||
* int for pure memory reasons, it could be a size_t)
|
||||
*/
|
||||
template<typename ElementType>
|
||||
class LshTable
|
||||
{
|
||||
public:
|
||||
/** A container of all the feature indices. Optimized for space
|
||||
*/
|
||||
#if USE_UNORDERED_MAP
|
||||
typedef std::unordered_map<BucketKey, Bucket> BucketsSpace;
|
||||
#else
|
||||
typedef std::map<BucketKey, Bucket> BucketsSpace;
|
||||
#endif
|
||||
|
||||
/** A container of all the feature indices. Optimized for speed
|
||||
*/
|
||||
typedef std::vector<Bucket> BucketsSpeed;
|
||||
|
||||
/** Default constructor
|
||||
*/
|
||||
LshTable()
|
||||
{
|
||||
}
|
||||
|
||||
/** Default constructor
|
||||
* Create the mask and allocate the memory
|
||||
* @param feature_size is the size of the feature (considered as a ElementType[])
|
||||
* @param key_size is the number of bits that are turned on in the feature
|
||||
*/
|
||||
LshTable(unsigned int /*feature_size*/, unsigned int /*key_size*/)
|
||||
{
|
||||
std::cerr << "LSH is not implemented for that type" << std::endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/** Add a feature to the table
|
||||
* @param value the value to store for that feature
|
||||
* @param feature the feature itself
|
||||
*/
|
||||
void add(unsigned int value, const ElementType* feature)
|
||||
{
|
||||
// Add the value to the corresponding bucket
|
||||
BucketKey key = (lsh::BucketKey)getKey(feature);
|
||||
|
||||
switch (speed_level_) {
|
||||
case kArray:
|
||||
// That means we get the buckets from an array
|
||||
buckets_speed_[key].push_back(value);
|
||||
break;
|
||||
case kBitsetHash:
|
||||
// That means we can check the bitset for the presence of a key
|
||||
key_bitset_.set(key);
|
||||
buckets_space_[key].push_back(value);
|
||||
break;
|
||||
case kHash:
|
||||
{
|
||||
// That means we have to check for the hash table for the presence of a key
|
||||
buckets_space_[key].push_back(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a set of features to the table
|
||||
* @param dataset the values to store
|
||||
*/
|
||||
void add(Matrix<ElementType> dataset)
|
||||
{
|
||||
#if USE_UNORDERED_MAP
|
||||
buckets_space_.rehash((buckets_space_.size() + dataset.rows) * 1.2);
|
||||
#endif
|
||||
// Add the features to the table
|
||||
for (unsigned int i = 0; i < dataset.rows; ++i) add(i, dataset[i]);
|
||||
// Now that the table is full, optimize it for speed/space
|
||||
optimize();
|
||||
}
|
||||
|
||||
/** Get a bucket given the key
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
inline const Bucket* getBucketFromKey(BucketKey key) const
|
||||
{
|
||||
// Generate other buckets
|
||||
switch (speed_level_) {
|
||||
case kArray:
|
||||
// That means we get the buckets from an array
|
||||
return &buckets_speed_[key];
|
||||
break;
|
||||
case kBitsetHash:
|
||||
// That means we can check the bitset for the presence of a key
|
||||
if (key_bitset_.test(key)) return &buckets_space_.find(key)->second;
|
||||
else return 0;
|
||||
break;
|
||||
case kHash:
|
||||
{
|
||||
// That means we have to check for the hash table for the presence of a key
|
||||
BucketsSpace::const_iterator bucket_it, bucket_end = buckets_space_.end();
|
||||
bucket_it = buckets_space_.find(key);
|
||||
// Stop here if that bucket does not exist
|
||||
if (bucket_it == bucket_end) return 0;
|
||||
else return &bucket_it->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Compute the sub-signature of a feature
|
||||
*/
|
||||
size_t getKey(const ElementType* /*feature*/) const
|
||||
{
|
||||
std::cerr << "LSH is not implemented for that type" << std::endl;
|
||||
assert(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Get statistics about the table
|
||||
* @return
|
||||
*/
|
||||
LshStats getStats() const;
|
||||
|
||||
private:
|
||||
/** defines the speed fo the implementation
|
||||
* kArray uses a vector for storing data
|
||||
* kBitsetHash uses a hash map but checks for the validity of a key with a bitset
|
||||
* kHash uses a hash map only
|
||||
*/
|
||||
enum SpeedLevel
|
||||
{
|
||||
kArray, kBitsetHash, kHash
|
||||
};
|
||||
|
||||
/** Initialize some variables
|
||||
*/
|
||||
void initialize(size_t key_size)
|
||||
{
|
||||
const size_t key_size_lower_bound = 1;
|
||||
//a value (size_t(1) << key_size) must fit the size_t type so key_size has to be strictly less than size of size_t
|
||||
const size_t key_size_upper_bound = std::min(sizeof(BucketKey) * CHAR_BIT + 1, sizeof(size_t) * CHAR_BIT);
|
||||
if (key_size < key_size_lower_bound || key_size >= key_size_upper_bound)
|
||||
{
|
||||
std::stringstream errorMessage;
|
||||
errorMessage << "Invalid key_size (=" << key_size << "). Valid values for your system are " << key_size_lower_bound << " <= key_size < " << key_size_upper_bound << ".";
|
||||
CV_Error(CV_StsBadArg, errorMessage.str());
|
||||
}
|
||||
|
||||
speed_level_ = kHash;
|
||||
key_size_ = (unsigned)key_size;
|
||||
}
|
||||
|
||||
/** Optimize the table for speed/space
|
||||
*/
|
||||
void optimize()
|
||||
{
|
||||
// If we are already using the fast storage, no need to do anything
|
||||
if (speed_level_ == kArray) return;
|
||||
|
||||
// Use an array if it will be more than half full
|
||||
if (buckets_space_.size() > ((size_t(1) << key_size_) / 2)) {
|
||||
speed_level_ = kArray;
|
||||
// Fill the array version of it
|
||||
buckets_speed_.resize(size_t(1) << key_size_);
|
||||
for (BucketsSpace::const_iterator key_bucket = buckets_space_.begin(); key_bucket != buckets_space_.end(); ++key_bucket) buckets_speed_[key_bucket->first] = key_bucket->second;
|
||||
|
||||
// Empty the hash table
|
||||
buckets_space_.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the bitset is going to use less than 10% of the RAM of the hash map (at least 1 size_t for the key and two
|
||||
// for the vector) or less than 512MB (key_size_ <= 30)
|
||||
if (((std::max(buckets_space_.size(), buckets_speed_.size()) * CHAR_BIT * 3 * sizeof(BucketKey)) / 10
|
||||
>= (size_t(1) << key_size_)) || (key_size_ <= 32)) {
|
||||
speed_level_ = kBitsetHash;
|
||||
key_bitset_.resize(size_t(1) << key_size_);
|
||||
key_bitset_.reset();
|
||||
// Try with the BucketsSpace
|
||||
for (BucketsSpace::const_iterator key_bucket = buckets_space_.begin(); key_bucket != buckets_space_.end(); ++key_bucket) key_bitset_.set(key_bucket->first);
|
||||
}
|
||||
else {
|
||||
speed_level_ = kHash;
|
||||
key_bitset_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** The vector of all the buckets if they are held for speed
|
||||
*/
|
||||
BucketsSpeed buckets_speed_;
|
||||
|
||||
/** The hash table of all the buckets in case we cannot use the speed version
|
||||
*/
|
||||
BucketsSpace buckets_space_;
|
||||
|
||||
/** What is used to store the data */
|
||||
SpeedLevel speed_level_;
|
||||
|
||||
/** If the subkey is small enough, it will keep track of which subkeys are set through that bitset
|
||||
* That is just a speedup so that we don't look in the hash table (which can be mush slower that checking a bitset)
|
||||
*/
|
||||
DynamicBitset key_bitset_;
|
||||
|
||||
/** The size of the sub-signature in bits
|
||||
*/
|
||||
unsigned int key_size_;
|
||||
|
||||
// Members only used for the unsigned char specialization
|
||||
/** The mask to apply to a feature to get the hash key
|
||||
* Only used in the unsigned char case
|
||||
*/
|
||||
std::vector<size_t> mask_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Specialization for unsigned char
|
||||
|
||||
template<>
|
||||
inline LshTable<unsigned char>::LshTable(unsigned int feature_size, unsigned int subsignature_size)
|
||||
{
|
||||
initialize(subsignature_size);
|
||||
// Allocate the mask
|
||||
mask_ = std::vector<size_t>((size_t)ceil((float)(feature_size * sizeof(char)) / (float)sizeof(size_t)), 0);
|
||||
|
||||
// A bit brutal but fast to code
|
||||
std::vector<size_t> indices(feature_size * CHAR_BIT);
|
||||
for (size_t i = 0; i < feature_size * CHAR_BIT; ++i) indices[i] = i;
|
||||
std::random_shuffle(indices.begin(), indices.end());
|
||||
|
||||
// Generate a random set of order of subsignature_size_ bits
|
||||
for (unsigned int i = 0; i < key_size_; ++i) {
|
||||
size_t index = indices[i];
|
||||
|
||||
// Set that bit in the mask
|
||||
size_t divisor = CHAR_BIT * sizeof(size_t);
|
||||
size_t idx = index / divisor; //pick the right size_t index
|
||||
mask_[idx] |= size_t(1) << (index % divisor); //use modulo to find the bit offset
|
||||
}
|
||||
|
||||
// Set to 1 if you want to display the mask for debug
|
||||
#if 0
|
||||
{
|
||||
size_t bcount = 0;
|
||||
BOOST_FOREACH(size_t mask_block, mask_){
|
||||
out << std::setw(sizeof(size_t) * CHAR_BIT / 4) << std::setfill('0') << std::hex << mask_block
|
||||
<< std::endl;
|
||||
bcount += __builtin_popcountll(mask_block);
|
||||
}
|
||||
out << "bit count : " << std::dec << bcount << std::endl;
|
||||
out << "mask size : " << mask_.size() << std::endl;
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Return the Subsignature of a feature
|
||||
* @param feature the feature to analyze
|
||||
*/
|
||||
template<>
|
||||
inline size_t LshTable<unsigned char>::getKey(const unsigned char* feature) const
|
||||
{
|
||||
// no need to check if T is dividable by sizeof(size_t) like in the Hamming
|
||||
// distance computation as we have a mask
|
||||
const size_t* feature_block_ptr = reinterpret_cast<const size_t*> ((const void*)feature);
|
||||
|
||||
// Figure out the subsignature of the feature
|
||||
// Given the feature ABCDEF, and the mask 001011, the output will be
|
||||
// 000CEF
|
||||
size_t subsignature = 0;
|
||||
size_t bit_index = 1;
|
||||
|
||||
for (std::vector<size_t>::const_iterator pmask_block = mask_.begin(); pmask_block != mask_.end(); ++pmask_block) {
|
||||
// get the mask and signature blocks
|
||||
size_t feature_block = *feature_block_ptr;
|
||||
size_t mask_block = *pmask_block;
|
||||
while (mask_block) {
|
||||
// Get the lowest set bit in the mask block
|
||||
size_t lowest_bit = mask_block & (-(ptrdiff_t)mask_block);
|
||||
// Add it to the current subsignature if necessary
|
||||
subsignature += (feature_block & lowest_bit) ? bit_index : 0;
|
||||
// Reset the bit in the mask block
|
||||
mask_block ^= lowest_bit;
|
||||
// increment the bit index for the subsignature
|
||||
bit_index <<= 1;
|
||||
}
|
||||
// Check the next feature block
|
||||
++feature_block_ptr;
|
||||
}
|
||||
return subsignature;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline LshStats LshTable<unsigned char>::getStats() const
|
||||
{
|
||||
LshStats stats;
|
||||
stats.bucket_size_mean_ = 0;
|
||||
if ((buckets_speed_.empty()) && (buckets_space_.empty())) {
|
||||
stats.n_buckets_ = 0;
|
||||
stats.bucket_size_median_ = 0;
|
||||
stats.bucket_size_min_ = 0;
|
||||
stats.bucket_size_max_ = 0;
|
||||
return stats;
|
||||
}
|
||||
|
||||
if (!buckets_speed_.empty()) {
|
||||
for (BucketsSpeed::const_iterator pbucket = buckets_speed_.begin(); pbucket != buckets_speed_.end(); ++pbucket) {
|
||||
stats.bucket_sizes_.push_back((lsh::FeatureIndex)pbucket->size());
|
||||
stats.bucket_size_mean_ += pbucket->size();
|
||||
}
|
||||
stats.bucket_size_mean_ /= buckets_speed_.size();
|
||||
stats.n_buckets_ = buckets_speed_.size();
|
||||
}
|
||||
else {
|
||||
for (BucketsSpace::const_iterator x = buckets_space_.begin(); x != buckets_space_.end(); ++x) {
|
||||
stats.bucket_sizes_.push_back((lsh::FeatureIndex)x->second.size());
|
||||
stats.bucket_size_mean_ += x->second.size();
|
||||
}
|
||||
stats.bucket_size_mean_ /= buckets_space_.size();
|
||||
stats.n_buckets_ = buckets_space_.size();
|
||||
}
|
||||
|
||||
std::sort(stats.bucket_sizes_.begin(), stats.bucket_sizes_.end());
|
||||
|
||||
// BOOST_FOREACH(int size, stats.bucket_sizes_)
|
||||
// std::cout << size << " ";
|
||||
// std::cout << std::endl;
|
||||
stats.bucket_size_median_ = stats.bucket_sizes_[stats.bucket_sizes_.size() / 2];
|
||||
stats.bucket_size_min_ = stats.bucket_sizes_.front();
|
||||
stats.bucket_size_max_ = stats.bucket_sizes_.back();
|
||||
|
||||
// TODO compute mean and std
|
||||
/*float mean, stddev;
|
||||
stats.bucket_size_mean_ = mean;
|
||||
stats.bucket_size_std_dev = stddev;*/
|
||||
|
||||
// Include a histogram of the buckets
|
||||
unsigned int bin_start = 0;
|
||||
unsigned int bin_end = 20;
|
||||
bool is_new_bin = true;
|
||||
for (std::vector<unsigned int>::iterator iterator = stats.bucket_sizes_.begin(), end = stats.bucket_sizes_.end(); iterator
|
||||
!= end; )
|
||||
if (*iterator < bin_end) {
|
||||
if (is_new_bin) {
|
||||
stats.size_histogram_.push_back(std::vector<unsigned int>(3, 0));
|
||||
stats.size_histogram_.back()[0] = bin_start;
|
||||
stats.size_histogram_.back()[1] = bin_end - 1;
|
||||
is_new_bin = false;
|
||||
}
|
||||
++stats.size_histogram_.back()[2];
|
||||
++iterator;
|
||||
}
|
||||
else {
|
||||
bin_start += 20;
|
||||
bin_end += 20;
|
||||
is_new_bin = true;
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
// End the two namespaces
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif /* OPENCV_FLANN_LSH_TABLE_H_ */
|
||||
@@ -0,0 +1,116 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_DATASET_H_
|
||||
#define OPENCV_FLANN_DATASET_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "general.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Class that implements a simple rectangular matrix stored in a memory buffer and
|
||||
* provides convenient matrix-like access using the [] operators.
|
||||
*/
|
||||
template <typename T>
|
||||
class Matrix
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
size_t rows;
|
||||
size_t cols;
|
||||
size_t stride;
|
||||
T* data;
|
||||
|
||||
Matrix() : rows(0), cols(0), stride(0), data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Matrix(T* data_, size_t rows_, size_t cols_, size_t stride_ = 0) :
|
||||
rows(rows_), cols(cols_), stride(stride_), data(data_)
|
||||
{
|
||||
if (stride==0) stride = cols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for deallocating the storage data.
|
||||
*/
|
||||
FLANN_DEPRECATED void free()
|
||||
{
|
||||
fprintf(stderr, "The cvflann::Matrix<T>::free() method is deprecated "
|
||||
"and it does not do any memory deallocation any more. You are"
|
||||
"responsible for deallocating the matrix memory (by doing"
|
||||
"'delete[] matrix.data' for example)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Operator that return a (pointer to a) row of the data.
|
||||
*/
|
||||
T* operator[](size_t index) const
|
||||
{
|
||||
return data+index*stride;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class UntypedMatrix
|
||||
{
|
||||
public:
|
||||
size_t rows;
|
||||
size_t cols;
|
||||
void* data;
|
||||
flann_datatype_t type;
|
||||
|
||||
UntypedMatrix(void* data_, long rows_, long cols_) :
|
||||
rows(rows_), cols(cols_), data(data_)
|
||||
{
|
||||
}
|
||||
|
||||
~UntypedMatrix()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
Matrix<T> as()
|
||||
{
|
||||
return Matrix<T>((T*)data, rows, cols);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_DATASET_H_
|
||||
@@ -0,0 +1,162 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef _OPENCV_MINIFLANN_HPP_
|
||||
#define _OPENCV_MINIFLANN_HPP_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "opencv2/flann/defines.h"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
namespace flann
|
||||
{
|
||||
|
||||
struct CV_EXPORTS IndexParams
|
||||
{
|
||||
IndexParams();
|
||||
~IndexParams();
|
||||
|
||||
std::string getString(const std::string& key, const std::string& defaultVal=std::string()) const;
|
||||
int getInt(const std::string& key, int defaultVal=-1) const;
|
||||
double getDouble(const std::string& key, double defaultVal=-1) const;
|
||||
|
||||
void setString(const std::string& key, const std::string& value);
|
||||
void setInt(const std::string& key, int value);
|
||||
void setDouble(const std::string& key, double value);
|
||||
void setFloat(const std::string& key, float value);
|
||||
void setBool(const std::string& key, bool value);
|
||||
void setAlgorithm(int value);
|
||||
|
||||
void getAll(std::vector<std::string>& names,
|
||||
std::vector<int>& types,
|
||||
std::vector<std::string>& strValues,
|
||||
std::vector<double>& numValues) const;
|
||||
|
||||
void* params;
|
||||
};
|
||||
|
||||
struct CV_EXPORTS KDTreeIndexParams : public IndexParams
|
||||
{
|
||||
KDTreeIndexParams(int trees=4);
|
||||
};
|
||||
|
||||
struct CV_EXPORTS LinearIndexParams : public IndexParams
|
||||
{
|
||||
LinearIndexParams();
|
||||
};
|
||||
|
||||
struct CV_EXPORTS CompositeIndexParams : public IndexParams
|
||||
{
|
||||
CompositeIndexParams(int trees = 4, int branching = 32, int iterations = 11,
|
||||
cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM, float cb_index = 0.2 );
|
||||
};
|
||||
|
||||
struct CV_EXPORTS AutotunedIndexParams : public IndexParams
|
||||
{
|
||||
AutotunedIndexParams(float target_precision = 0.8, float build_weight = 0.01,
|
||||
float memory_weight = 0, float sample_fraction = 0.1);
|
||||
};
|
||||
|
||||
struct CV_EXPORTS HierarchicalClusteringIndexParams : public IndexParams
|
||||
{
|
||||
HierarchicalClusteringIndexParams(int branching = 32,
|
||||
cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM, int trees = 4, int leaf_size = 100 );
|
||||
};
|
||||
|
||||
struct CV_EXPORTS KMeansIndexParams : public IndexParams
|
||||
{
|
||||
KMeansIndexParams(int branching = 32, int iterations = 11,
|
||||
cvflann::flann_centers_init_t centers_init = cvflann::FLANN_CENTERS_RANDOM, float cb_index = 0.2 );
|
||||
};
|
||||
|
||||
struct CV_EXPORTS LshIndexParams : public IndexParams
|
||||
{
|
||||
LshIndexParams(int table_number, int key_size, int multi_probe_level);
|
||||
};
|
||||
|
||||
struct CV_EXPORTS SavedIndexParams : public IndexParams
|
||||
{
|
||||
SavedIndexParams(const std::string& filename);
|
||||
};
|
||||
|
||||
struct CV_EXPORTS SearchParams : public IndexParams
|
||||
{
|
||||
SearchParams( int checks = 32, float eps = 0, bool sorted = true );
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W Index
|
||||
{
|
||||
public:
|
||||
CV_WRAP Index();
|
||||
CV_WRAP Index(InputArray features, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2);
|
||||
virtual ~Index();
|
||||
|
||||
CV_WRAP virtual void build(InputArray features, const IndexParams& params, cvflann::flann_distance_t distType=cvflann::FLANN_DIST_L2);
|
||||
CV_WRAP virtual void knnSearch(InputArray query, OutputArray indices,
|
||||
OutputArray dists, int knn, const SearchParams& params=SearchParams());
|
||||
|
||||
CV_WRAP virtual int radiusSearch(InputArray query, OutputArray indices,
|
||||
OutputArray dists, double radius, int maxResults,
|
||||
const SearchParams& params=SearchParams());
|
||||
|
||||
CV_WRAP virtual void save(const std::string& filename) const;
|
||||
CV_WRAP virtual bool load(InputArray features, const std::string& filename);
|
||||
CV_WRAP virtual void release();
|
||||
CV_WRAP cvflann::flann_distance_t getDistance() const;
|
||||
CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const;
|
||||
|
||||
protected:
|
||||
cvflann::flann_distance_t distType;
|
||||
cvflann::flann_algorithm_t algo;
|
||||
int featureType;
|
||||
void* index;
|
||||
};
|
||||
|
||||
} } // namespace cv::flann
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,179 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_NNINDEX_H
|
||||
#define OPENCV_FLANN_NNINDEX_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "general.h"
|
||||
#include "matrix.h"
|
||||
#include "result_set.h"
|
||||
#include "params.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Nearest-neighbour index base class
|
||||
*/
|
||||
template <typename Distance>
|
||||
class NNIndex
|
||||
{
|
||||
typedef typename Distance::ElementType ElementType;
|
||||
typedef typename Distance::ResultType DistanceType;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~NNIndex() {}
|
||||
|
||||
/**
|
||||
* \brief Builds the index
|
||||
*/
|
||||
virtual void buildIndex() = 0;
|
||||
|
||||
/**
|
||||
* \brief Perform k-nearest neighbor search
|
||||
* \param[in] queries The query points for which to find the nearest neighbors
|
||||
* \param[out] indices The indices of the nearest neighbors found
|
||||
* \param[out] dists Distances to the nearest neighbors found
|
||||
* \param[in] knn Number of nearest neighbors to return
|
||||
* \param[in] params Search parameters
|
||||
*/
|
||||
virtual void knnSearch(const Matrix<ElementType>& queries, Matrix<int>& indices, Matrix<DistanceType>& dists, int knn, const SearchParams& params)
|
||||
{
|
||||
assert(queries.cols == veclen());
|
||||
assert(indices.rows >= queries.rows);
|
||||
assert(dists.rows >= queries.rows);
|
||||
assert(int(indices.cols) >= knn);
|
||||
assert(int(dists.cols) >= knn);
|
||||
|
||||
#if 0
|
||||
KNNResultSet<DistanceType> resultSet(knn);
|
||||
for (size_t i = 0; i < queries.rows; i++) {
|
||||
resultSet.init(indices[i], dists[i]);
|
||||
findNeighbors(resultSet, queries[i], params);
|
||||
}
|
||||
#else
|
||||
KNNUniqueResultSet<DistanceType> resultSet(knn);
|
||||
for (size_t i = 0; i < queries.rows; i++) {
|
||||
resultSet.clear();
|
||||
findNeighbors(resultSet, queries[i], params);
|
||||
if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices[i], dists[i], knn);
|
||||
else resultSet.copy(indices[i], dists[i], knn);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform radius search
|
||||
* \param[in] query The query point
|
||||
* \param[out] indices The indinces of the neighbors found within the given radius
|
||||
* \param[out] dists The distances to the nearest neighbors found
|
||||
* \param[in] radius The radius used for search
|
||||
* \param[in] params Search parameters
|
||||
* \returns Number of neighbors found
|
||||
*/
|
||||
virtual int radiusSearch(const Matrix<ElementType>& query, Matrix<int>& indices, Matrix<DistanceType>& dists, float radius, const SearchParams& params)
|
||||
{
|
||||
if (query.rows != 1) {
|
||||
fprintf(stderr, "I can only search one feature at a time for range search\n");
|
||||
return -1;
|
||||
}
|
||||
assert(query.cols == veclen());
|
||||
assert(indices.cols == dists.cols);
|
||||
|
||||
int n = 0;
|
||||
int* indices_ptr = NULL;
|
||||
DistanceType* dists_ptr = NULL;
|
||||
if (indices.cols > 0) {
|
||||
n = (int)indices.cols;
|
||||
indices_ptr = indices[0];
|
||||
dists_ptr = dists[0];
|
||||
}
|
||||
|
||||
RadiusUniqueResultSet<DistanceType> resultSet((DistanceType)radius);
|
||||
resultSet.clear();
|
||||
findNeighbors(resultSet, query[0], params);
|
||||
if (n>0) {
|
||||
if (get_param(params,"sorted",true)) resultSet.sortAndCopy(indices_ptr, dists_ptr, n);
|
||||
else resultSet.copy(indices_ptr, dists_ptr, n);
|
||||
}
|
||||
|
||||
return (int)resultSet.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Saves the index to a stream
|
||||
* \param stream The stream to save the index to
|
||||
*/
|
||||
virtual void saveIndex(FILE* stream) = 0;
|
||||
|
||||
/**
|
||||
* \brief Loads the index from a stream
|
||||
* \param stream The stream from which the index is loaded
|
||||
*/
|
||||
virtual void loadIndex(FILE* stream) = 0;
|
||||
|
||||
/**
|
||||
* \returns number of features in this index.
|
||||
*/
|
||||
virtual size_t size() const = 0;
|
||||
|
||||
/**
|
||||
* \returns The dimensionality of the features in this index.
|
||||
*/
|
||||
virtual size_t veclen() const = 0;
|
||||
|
||||
/**
|
||||
* \returns The amount of memory (in bytes) used by the index.
|
||||
*/
|
||||
virtual int usedMemory() const = 0;
|
||||
|
||||
/**
|
||||
* \returns The index type (kdtree, kmeans,...)
|
||||
*/
|
||||
virtual flann_algorithm_t getType() const = 0;
|
||||
|
||||
/**
|
||||
* \returns The index parameters
|
||||
*/
|
||||
virtual IndexParams getParameters() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Method that searches for nearest-neighbours
|
||||
*/
|
||||
virtual void findNeighbors(ResultSet<DistanceType>& result, const ElementType* vec, const SearchParams& searchParams) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_NNINDEX_H
|
||||
@@ -0,0 +1,91 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_OBJECT_FACTORY_H_
|
||||
#define OPENCV_FLANN_OBJECT_FACTORY_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
class CreatorNotFound
|
||||
{
|
||||
};
|
||||
|
||||
template<typename BaseClass,
|
||||
typename UniqueIdType,
|
||||
typename ObjectCreator = BaseClass* (*)()>
|
||||
class ObjectFactory
|
||||
{
|
||||
typedef ObjectFactory<BaseClass,UniqueIdType,ObjectCreator> ThisClass;
|
||||
typedef std::map<UniqueIdType, ObjectCreator> ObjectRegistry;
|
||||
|
||||
// singleton class, private constructor
|
||||
ObjectFactory() {}
|
||||
|
||||
public:
|
||||
|
||||
bool subscribe(UniqueIdType id, ObjectCreator creator)
|
||||
{
|
||||
if (object_registry.find(id) != object_registry.end()) return false;
|
||||
|
||||
object_registry[id] = creator;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool unregister(UniqueIdType id)
|
||||
{
|
||||
return object_registry.erase(id) == 1;
|
||||
}
|
||||
|
||||
ObjectCreator create(UniqueIdType id)
|
||||
{
|
||||
typename ObjectRegistry::const_iterator iter = object_registry.find(id);
|
||||
|
||||
if (iter == object_registry.end()) {
|
||||
throw CreatorNotFound();
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
static ThisClass& instance()
|
||||
{
|
||||
static ThisClass the_factory;
|
||||
return the_factory;
|
||||
}
|
||||
private:
|
||||
ObjectRegistry object_registry;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENCV_FLANN_OBJECT_FACTORY_H_ */
|
||||
@@ -0,0 +1,96 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2011 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2011 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef OPENCV_FLANN_PARAMS_H_
|
||||
#define OPENCV_FLANN_PARAMS_H_
|
||||
|
||||
#include "any.h"
|
||||
#include "general.h"
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
typedef std::map<std::string, any> IndexParams;
|
||||
|
||||
struct SearchParams : public IndexParams
|
||||
{
|
||||
SearchParams(int checks = 32, float eps = 0, bool sorted = true )
|
||||
{
|
||||
// how many leafs to visit when searching for neighbours (-1 for unlimited)
|
||||
(*this)["checks"] = checks;
|
||||
// search for eps-approximate neighbours (default: 0)
|
||||
(*this)["eps"] = eps;
|
||||
// only for radius search, require neighbours sorted by distance (default: true)
|
||||
(*this)["sorted"] = sorted;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
T get_param(const IndexParams& params, std::string name, const T& default_value)
|
||||
{
|
||||
IndexParams::const_iterator it = params.find(name);
|
||||
if (it != params.end()) {
|
||||
return it->second.cast<T>();
|
||||
}
|
||||
else {
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get_param(const IndexParams& params, std::string name)
|
||||
{
|
||||
IndexParams::const_iterator it = params.find(name);
|
||||
if (it != params.end()) {
|
||||
return it->second.cast<T>();
|
||||
}
|
||||
else {
|
||||
throw FLANNException(std::string("Missing parameter '")+name+std::string("' in the parameters given"));
|
||||
}
|
||||
}
|
||||
|
||||
inline void print_params(const IndexParams& params)
|
||||
{
|
||||
IndexParams::const_iterator it;
|
||||
|
||||
for(it=params.begin(); it!=params.end(); ++it) {
|
||||
std::cout << it->first << " : " << it->second << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* OPENCV_FLANN_PARAMS_H_ */
|
||||
@@ -0,0 +1,133 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_RANDOM_H
|
||||
#define OPENCV_FLANN_RANDOM_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
#include "general.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* Seeds the random number generator
|
||||
* @param seed Random seed
|
||||
*/
|
||||
inline void seed_random(unsigned int seed)
|
||||
{
|
||||
srand(seed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a random double value.
|
||||
*/
|
||||
/**
|
||||
* Generates a random double value.
|
||||
* @param high Upper limit
|
||||
* @param low Lower limit
|
||||
* @return Random double value
|
||||
*/
|
||||
inline double rand_double(double high = 1.0, double low = 0)
|
||||
{
|
||||
return low + ((high-low) * (std::rand() / (RAND_MAX + 1.0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random integer value.
|
||||
* @param high Upper limit
|
||||
* @param low Lower limit
|
||||
* @return Random integer value
|
||||
*/
|
||||
inline int rand_int(int high = RAND_MAX, int low = 0)
|
||||
{
|
||||
return low + (int) ( double(high-low) * (std::rand() / (RAND_MAX + 1.0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Random number generator that returns a distinct number from
|
||||
* the [0,n) interval each time.
|
||||
*/
|
||||
class UniqueRandom
|
||||
{
|
||||
std::vector<int> vals_;
|
||||
int size_;
|
||||
int counter_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param n Size of the interval from which to generate
|
||||
* @return
|
||||
*/
|
||||
UniqueRandom(int n)
|
||||
{
|
||||
init(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the number generator.
|
||||
* @param n the size of the interval from which to generate random numbers.
|
||||
*/
|
||||
void init(int n)
|
||||
{
|
||||
// create and initialize an array of size n
|
||||
vals_.resize(n);
|
||||
size_ = n;
|
||||
for (int i = 0; i < size_; ++i) vals_[i] = i;
|
||||
|
||||
// shuffle the elements in the array
|
||||
std::random_shuffle(vals_.begin(), vals_.end());
|
||||
|
||||
counter_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a distinct random integer in greater or equal to 0 and less
|
||||
* than 'n' on each call. It should be called maximum 'n' times.
|
||||
* Returns: a random integer
|
||||
*/
|
||||
int next()
|
||||
{
|
||||
if (counter_ == size_) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return vals_[counter_++];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_RANDOM_H
|
||||
@@ -0,0 +1,542 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_RESULTSET_H
|
||||
#define OPENCV_FLANN_RESULTSET_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/* This record represents a branch point when finding neighbors in
|
||||
the tree. It contains a record of the minimum distance to the query
|
||||
point, as well as the node at which the search resumes.
|
||||
*/
|
||||
|
||||
template <typename T, typename DistanceType>
|
||||
struct BranchStruct
|
||||
{
|
||||
T node; /* Tree node at which search resumes */
|
||||
DistanceType mindist; /* Minimum distance to query for all nodes below. */
|
||||
|
||||
BranchStruct() {}
|
||||
BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {}
|
||||
|
||||
bool operator<(const BranchStruct<T, DistanceType>& rhs) const
|
||||
{
|
||||
return mindist<rhs.mindist;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename DistanceType>
|
||||
class ResultSet
|
||||
{
|
||||
public:
|
||||
virtual ~ResultSet() {}
|
||||
|
||||
virtual bool full() const = 0;
|
||||
|
||||
virtual void addPoint(DistanceType dist, int index) = 0;
|
||||
|
||||
virtual DistanceType worstDist() const = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* KNNSimpleResultSet does not ensure that the element it holds are unique.
|
||||
* Is used in those cases where the nearest neighbour algorithm used does not
|
||||
* attempt to insert the same element multiple times.
|
||||
*/
|
||||
template <typename DistanceType>
|
||||
class KNNSimpleResultSet : public ResultSet<DistanceType>
|
||||
{
|
||||
int* indices;
|
||||
DistanceType* dists;
|
||||
int capacity;
|
||||
int count;
|
||||
DistanceType worst_distance_;
|
||||
|
||||
public:
|
||||
KNNSimpleResultSet(int capacity_) : capacity(capacity_), count(0)
|
||||
{
|
||||
}
|
||||
|
||||
void init(int* indices_, DistanceType* dists_)
|
||||
{
|
||||
indices = indices_;
|
||||
dists = dists_;
|
||||
count = 0;
|
||||
worst_distance_ = (std::numeric_limits<DistanceType>::max)();
|
||||
dists[capacity-1] = worst_distance_;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return count == capacity;
|
||||
}
|
||||
|
||||
|
||||
void addPoint(DistanceType dist, int index)
|
||||
{
|
||||
if (dist >= worst_distance_) return;
|
||||
int i;
|
||||
for (i=count; i>0; --i) {
|
||||
#ifdef FLANN_FIRST_MATCH
|
||||
if ( (dists[i-1]>dist) || ((dist==dists[i-1])&&(indices[i-1]>index)) )
|
||||
#else
|
||||
if (dists[i-1]>dist)
|
||||
#endif
|
||||
{
|
||||
if (i<capacity) {
|
||||
dists[i] = dists[i-1];
|
||||
indices[i] = indices[i-1];
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
if (count < capacity) ++count;
|
||||
dists[i] = dist;
|
||||
indices[i] = index;
|
||||
worst_distance_ = dists[capacity-1];
|
||||
}
|
||||
|
||||
DistanceType worstDist() const
|
||||
{
|
||||
return worst_distance_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* K-Nearest neighbour result set. Ensures that the elements inserted are unique
|
||||
*/
|
||||
template <typename DistanceType>
|
||||
class KNNResultSet : public ResultSet<DistanceType>
|
||||
{
|
||||
int* indices;
|
||||
DistanceType* dists;
|
||||
int capacity;
|
||||
int count;
|
||||
DistanceType worst_distance_;
|
||||
|
||||
public:
|
||||
KNNResultSet(int capacity_) : capacity(capacity_), count(0)
|
||||
{
|
||||
}
|
||||
|
||||
void init(int* indices_, DistanceType* dists_)
|
||||
{
|
||||
indices = indices_;
|
||||
dists = dists_;
|
||||
count = 0;
|
||||
worst_distance_ = (std::numeric_limits<DistanceType>::max)();
|
||||
dists[capacity-1] = worst_distance_;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return count == capacity;
|
||||
}
|
||||
|
||||
|
||||
void addPoint(DistanceType dist, int index)
|
||||
{
|
||||
if (dist >= worst_distance_) return;
|
||||
int i;
|
||||
for (i = count; i > 0; --i) {
|
||||
#ifdef FLANN_FIRST_MATCH
|
||||
if ( (dists[i-1]<=dist) && ((dist!=dists[i-1])||(indices[i-1]<=index)) )
|
||||
#else
|
||||
if (dists[i-1]<=dist)
|
||||
#endif
|
||||
{
|
||||
// Check for duplicate indices
|
||||
int j = i - 1;
|
||||
while ((j >= 0) && (dists[j] == dist)) {
|
||||
if (indices[j] == index) {
|
||||
return;
|
||||
}
|
||||
--j;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (count < capacity) ++count;
|
||||
for (int j = count-1; j > i; --j) {
|
||||
dists[j] = dists[j-1];
|
||||
indices[j] = indices[j-1];
|
||||
}
|
||||
dists[i] = dist;
|
||||
indices[i] = index;
|
||||
worst_distance_ = dists[capacity-1];
|
||||
}
|
||||
|
||||
DistanceType worstDist() const
|
||||
{
|
||||
return worst_distance_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A result-set class used when performing a radius based search.
|
||||
*/
|
||||
template <typename DistanceType>
|
||||
class RadiusResultSet : public ResultSet<DistanceType>
|
||||
{
|
||||
DistanceType radius;
|
||||
int* indices;
|
||||
DistanceType* dists;
|
||||
size_t capacity;
|
||||
size_t count;
|
||||
|
||||
public:
|
||||
RadiusResultSet(DistanceType radius_, int* indices_, DistanceType* dists_, int capacity_) :
|
||||
radius(radius_), indices(indices_), dists(dists_), capacity(capacity_)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
~RadiusResultSet()
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
bool full() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void addPoint(DistanceType dist, int index)
|
||||
{
|
||||
if (dist<radius) {
|
||||
if ((capacity>0)&&(count < capacity)) {
|
||||
dists[count] = dist;
|
||||
indices[count] = index;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
DistanceType worstDist() const
|
||||
{
|
||||
return radius;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Class that holds the k NN neighbors
|
||||
* Faster than KNNResultSet as it uses a binary heap and does not maintain two arrays
|
||||
*/
|
||||
template<typename DistanceType>
|
||||
class UniqueResultSet : public ResultSet<DistanceType>
|
||||
{
|
||||
public:
|
||||
struct DistIndex
|
||||
{
|
||||
DistIndex(DistanceType dist, unsigned int index) :
|
||||
dist_(dist), index_(index)
|
||||
{
|
||||
}
|
||||
bool operator<(const DistIndex dist_index) const
|
||||
{
|
||||
return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_);
|
||||
}
|
||||
DistanceType dist_;
|
||||
unsigned int index_;
|
||||
};
|
||||
|
||||
/** Default cosntructor */
|
||||
UniqueResultSet() :
|
||||
worst_distance_(std::numeric_limits<DistanceType>::max())
|
||||
{
|
||||
}
|
||||
|
||||
/** Check the status of the set
|
||||
* @return true if we have k NN
|
||||
*/
|
||||
inline bool full() const
|
||||
{
|
||||
return is_full_;
|
||||
}
|
||||
|
||||
/** Remove all elements in the set
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/** Copy the set to two C arrays
|
||||
* @param indices pointer to a C array of indices
|
||||
* @param dist pointer to a C array of distances
|
||||
* @param n_neighbors the number of neighbors to copy
|
||||
*/
|
||||
virtual void copy(int* indices, DistanceType* dist, int n_neighbors = -1) const
|
||||
{
|
||||
if (n_neighbors < 0) {
|
||||
for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
|
||||
dist_indices_.end(); dist_index != dist_index_end; ++dist_index, ++indices, ++dist) {
|
||||
*indices = dist_index->index_;
|
||||
*dist = dist_index->dist_;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i = 0;
|
||||
for (typename std::set<DistIndex>::const_iterator dist_index = dist_indices_.begin(), dist_index_end =
|
||||
dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) {
|
||||
*indices = dist_index->index_;
|
||||
*dist = dist_index->dist_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy the set to two C arrays but sort it according to the distance first
|
||||
* @param indices pointer to a C array of indices
|
||||
* @param dist pointer to a C array of distances
|
||||
* @param n_neighbors the number of neighbors to copy
|
||||
*/
|
||||
virtual void sortAndCopy(int* indices, DistanceType* dist, int n_neighbors = -1) const
|
||||
{
|
||||
copy(indices, dist, n_neighbors);
|
||||
}
|
||||
|
||||
/** The number of neighbors in the set
|
||||
* @return
|
||||
*/
|
||||
size_t size() const
|
||||
{
|
||||
return dist_indices_.size();
|
||||
}
|
||||
|
||||
/** The distance of the furthest neighbor
|
||||
* If we don't have enough neighbors, it returns the max possible value
|
||||
* @return
|
||||
*/
|
||||
inline DistanceType worstDist() const
|
||||
{
|
||||
return worst_distance_;
|
||||
}
|
||||
protected:
|
||||
/** Flag to say if the set is full */
|
||||
bool is_full_;
|
||||
|
||||
/** The worst distance found so far */
|
||||
DistanceType worst_distance_;
|
||||
|
||||
/** The best candidates so far */
|
||||
std::set<DistIndex> dist_indices_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Class that holds the k NN neighbors
|
||||
* Faster than KNNResultSet as it uses a binary heap and does not maintain two arrays
|
||||
*/
|
||||
template<typename DistanceType>
|
||||
class KNNUniqueResultSet : public UniqueResultSet<DistanceType>
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
* @param capacity the number of neighbors to store at max
|
||||
*/
|
||||
KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity)
|
||||
{
|
||||
this->is_full_ = false;
|
||||
this->clear();
|
||||
}
|
||||
|
||||
/** Add a possible candidate to the best neighbors
|
||||
* @param dist distance for that neighbor
|
||||
* @param index index of that neighbor
|
||||
*/
|
||||
inline void addPoint(DistanceType dist, int index)
|
||||
{
|
||||
// Don't do anything if we are worse than the worst
|
||||
if (dist >= worst_distance_) return;
|
||||
dist_indices_.insert(DistIndex(dist, index));
|
||||
|
||||
if (is_full_) {
|
||||
if (dist_indices_.size() > capacity_) {
|
||||
dist_indices_.erase(*dist_indices_.rbegin());
|
||||
worst_distance_ = dist_indices_.rbegin()->dist_;
|
||||
}
|
||||
}
|
||||
else if (dist_indices_.size() == capacity_) {
|
||||
is_full_ = true;
|
||||
worst_distance_ = dist_indices_.rbegin()->dist_;
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove all elements in the set
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
dist_indices_.clear();
|
||||
worst_distance_ = std::numeric_limits<DistanceType>::max();
|
||||
is_full_ = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
|
||||
using UniqueResultSet<DistanceType>::is_full_;
|
||||
using UniqueResultSet<DistanceType>::worst_distance_;
|
||||
using UniqueResultSet<DistanceType>::dist_indices_;
|
||||
|
||||
/** The number of neighbors to keep */
|
||||
unsigned int capacity_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Class that holds the radius nearest neighbors
|
||||
* It is more accurate than RadiusResult as it is not limited in the number of neighbors
|
||||
*/
|
||||
template<typename DistanceType>
|
||||
class RadiusUniqueResultSet : public UniqueResultSet<DistanceType>
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
* @param capacity the number of neighbors to store at max
|
||||
*/
|
||||
RadiusUniqueResultSet(DistanceType radius) :
|
||||
radius_(radius)
|
||||
{
|
||||
is_full_ = true;
|
||||
}
|
||||
|
||||
/** Add a possible candidate to the best neighbors
|
||||
* @param dist distance for that neighbor
|
||||
* @param index index of that neighbor
|
||||
*/
|
||||
void addPoint(DistanceType dist, int index)
|
||||
{
|
||||
if (dist <= radius_) dist_indices_.insert(DistIndex(dist, index));
|
||||
}
|
||||
|
||||
/** Remove all elements in the set
|
||||
*/
|
||||
inline void clear()
|
||||
{
|
||||
dist_indices_.clear();
|
||||
}
|
||||
|
||||
|
||||
/** Check the status of the set
|
||||
* @return alwys false
|
||||
*/
|
||||
inline bool full() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** The distance of the furthest neighbor
|
||||
* If we don't have enough neighbors, it returns the max possible value
|
||||
* @return
|
||||
*/
|
||||
inline DistanceType worstDist() const
|
||||
{
|
||||
return radius_;
|
||||
}
|
||||
private:
|
||||
typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex;
|
||||
using UniqueResultSet<DistanceType>::dist_indices_;
|
||||
using UniqueResultSet<DistanceType>::is_full_;
|
||||
|
||||
/** The furthest distance a neighbor can be */
|
||||
DistanceType radius_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Class that holds the k NN neighbors within a radius distance
|
||||
*/
|
||||
template<typename DistanceType>
|
||||
class KNNRadiusUniqueResultSet : public KNNUniqueResultSet<DistanceType>
|
||||
{
|
||||
public:
|
||||
/** Constructor
|
||||
* @param capacity the number of neighbors to store at max
|
||||
*/
|
||||
KNNRadiusUniqueResultSet(unsigned int capacity, DistanceType radius)
|
||||
{
|
||||
this->capacity_ = capacity;
|
||||
this->radius_ = radius;
|
||||
this->dist_indices_.reserve(capacity_);
|
||||
this->clear();
|
||||
}
|
||||
|
||||
/** Remove all elements in the set
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
dist_indices_.clear();
|
||||
worst_distance_ = radius_;
|
||||
is_full_ = false;
|
||||
}
|
||||
private:
|
||||
using KNNUniqueResultSet<DistanceType>::dist_indices_;
|
||||
using KNNUniqueResultSet<DistanceType>::is_full_;
|
||||
using KNNUniqueResultSet<DistanceType>::worst_distance_;
|
||||
|
||||
/** The maximum number of neighbors to consider */
|
||||
unsigned int capacity_;
|
||||
|
||||
/** The maximum distance of a neighbor */
|
||||
DistanceType radius_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_RESULTSET_H
|
||||
@@ -0,0 +1,81 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
#ifndef OPENCV_FLANN_SAMPLING_H_
|
||||
#define OPENCV_FLANN_SAMPLING_H_
|
||||
|
||||
#include "matrix.h"
|
||||
#include "random.h"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
Matrix<T> random_sample(Matrix<T>& srcMatrix, long size, bool remove = false)
|
||||
{
|
||||
Matrix<T> newSet(new T[size * srcMatrix.cols], size,srcMatrix.cols);
|
||||
|
||||
T* src,* dest;
|
||||
for (long i=0; i<size; ++i) {
|
||||
long r = rand_int((int)(srcMatrix.rows-i));
|
||||
dest = newSet[i];
|
||||
src = srcMatrix[r];
|
||||
std::copy(src, src+srcMatrix.cols, dest);
|
||||
if (remove) {
|
||||
src = srcMatrix[srcMatrix.rows-i-1];
|
||||
dest = srcMatrix[r];
|
||||
std::copy(src, src+srcMatrix.cols, dest);
|
||||
}
|
||||
}
|
||||
if (remove) {
|
||||
srcMatrix.rows -= size;
|
||||
}
|
||||
return newSet;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Matrix<T> random_sample(const Matrix<T>& srcMatrix, size_t size)
|
||||
{
|
||||
UniqueRandom rand((int)srcMatrix.rows);
|
||||
Matrix<T> newSet(new T[size * srcMatrix.cols], size,srcMatrix.cols);
|
||||
|
||||
T* src,* dest;
|
||||
for (size_t i=0; i<size; ++i) {
|
||||
long r = rand.next();
|
||||
dest = newSet[i];
|
||||
src = srcMatrix[r];
|
||||
std::copy(src, src+srcMatrix.cols, dest);
|
||||
}
|
||||
return newSet;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif /* OPENCV_FLANN_SAMPLING_H_ */
|
||||
@@ -0,0 +1,187 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE NNIndexGOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_SAVING_H_
|
||||
#define OPENCV_FLANN_SAVING_H_
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "general.h"
|
||||
#include "nn_index.h"
|
||||
|
||||
#ifdef FLANN_SIGNATURE_
|
||||
#undef FLANN_SIGNATURE_
|
||||
#endif
|
||||
#define FLANN_SIGNATURE_ "FLANN_INDEX"
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct Datatype {};
|
||||
template<>
|
||||
struct Datatype<char> { static flann_datatype_t type() { return FLANN_INT8; } };
|
||||
template<>
|
||||
struct Datatype<short> { static flann_datatype_t type() { return FLANN_INT16; } };
|
||||
template<>
|
||||
struct Datatype<int> { static flann_datatype_t type() { return FLANN_INT32; } };
|
||||
template<>
|
||||
struct Datatype<unsigned char> { static flann_datatype_t type() { return FLANN_UINT8; } };
|
||||
template<>
|
||||
struct Datatype<unsigned short> { static flann_datatype_t type() { return FLANN_UINT16; } };
|
||||
template<>
|
||||
struct Datatype<unsigned int> { static flann_datatype_t type() { return FLANN_UINT32; } };
|
||||
template<>
|
||||
struct Datatype<float> { static flann_datatype_t type() { return FLANN_FLOAT32; } };
|
||||
template<>
|
||||
struct Datatype<double> { static flann_datatype_t type() { return FLANN_FLOAT64; } };
|
||||
|
||||
|
||||
/**
|
||||
* Structure representing the index header.
|
||||
*/
|
||||
struct IndexHeader
|
||||
{
|
||||
char signature[16];
|
||||
char version[16];
|
||||
flann_datatype_t data_type;
|
||||
flann_algorithm_t index_type;
|
||||
size_t rows;
|
||||
size_t cols;
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves index header to stream
|
||||
*
|
||||
* @param stream - Stream to save to
|
||||
* @param index - The index to save
|
||||
*/
|
||||
template<typename Distance>
|
||||
void save_header(FILE* stream, const NNIndex<Distance>& index)
|
||||
{
|
||||
IndexHeader header;
|
||||
memset(header.signature, 0, sizeof(header.signature));
|
||||
strcpy(header.signature, FLANN_SIGNATURE_);
|
||||
memset(header.version, 0, sizeof(header.version));
|
||||
strcpy(header.version, FLANN_VERSION_);
|
||||
header.data_type = Datatype<typename Distance::ElementType>::type();
|
||||
header.index_type = index.getType();
|
||||
header.rows = index.size();
|
||||
header.cols = index.veclen();
|
||||
|
||||
std::fwrite(&header, sizeof(header),1,stream);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param stream - Stream to load from
|
||||
* @return Index header
|
||||
*/
|
||||
inline IndexHeader load_header(FILE* stream)
|
||||
{
|
||||
IndexHeader header;
|
||||
size_t read_size = fread(&header,sizeof(header),1,stream);
|
||||
|
||||
if (read_size!=(size_t)1) {
|
||||
throw FLANNException("Invalid index file, cannot read");
|
||||
}
|
||||
|
||||
if (strcmp(header.signature,FLANN_SIGNATURE_)!=0) {
|
||||
throw FLANNException("Invalid index file, wrong signature");
|
||||
}
|
||||
|
||||
return header;
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void save_value(FILE* stream, const T& value, size_t count = 1)
|
||||
{
|
||||
fwrite(&value, sizeof(value),count, stream);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void save_value(FILE* stream, const cvflann::Matrix<T>& value)
|
||||
{
|
||||
fwrite(&value, sizeof(value),1, stream);
|
||||
fwrite(value.data, sizeof(T),value.rows*value.cols, stream);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void save_value(FILE* stream, const std::vector<T>& value)
|
||||
{
|
||||
size_t size = value.size();
|
||||
fwrite(&size, sizeof(size_t), 1, stream);
|
||||
fwrite(&value[0], sizeof(T), size, stream);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void load_value(FILE* stream, T& value, size_t count = 1)
|
||||
{
|
||||
size_t read_cnt = fread(&value, sizeof(value), count, stream);
|
||||
if (read_cnt != count) {
|
||||
throw FLANNException("Cannot read from file");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void load_value(FILE* stream, cvflann::Matrix<T>& value)
|
||||
{
|
||||
size_t read_cnt = fread(&value, sizeof(value), 1, stream);
|
||||
if (read_cnt != 1) {
|
||||
throw FLANNException("Cannot read from file");
|
||||
}
|
||||
value.data = new T[value.rows*value.cols];
|
||||
read_cnt = fread(value.data, sizeof(T), value.rows*value.cols, stream);
|
||||
if (read_cnt != (size_t)(value.rows*value.cols)) {
|
||||
throw FLANNException("Cannot read from file");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void load_value(FILE* stream, std::vector<T>& value)
|
||||
{
|
||||
size_t size;
|
||||
size_t read_cnt = fread(&size, sizeof(size_t), 1, stream);
|
||||
if (read_cnt!=1) {
|
||||
throw FLANNException("Cannot read from file");
|
||||
}
|
||||
value.resize(size);
|
||||
read_cnt = fread(&value[0], sizeof(T), size, stream);
|
||||
if (read_cnt != size) {
|
||||
throw FLANNException("Cannot read from file");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* OPENCV_FLANN_SAVING_H_ */
|
||||
@@ -0,0 +1,186 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_SIMPLEX_DOWNHILL_H_
|
||||
#define OPENCV_FLANN_SIMPLEX_DOWNHILL_H_
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
Adds val to array vals (and point to array points) and keeping the arrays sorted by vals.
|
||||
*/
|
||||
template <typename T>
|
||||
void addValue(int pos, float val, float* vals, T* point, T* points, int n)
|
||||
{
|
||||
vals[pos] = val;
|
||||
for (int i=0; i<n; ++i) {
|
||||
points[pos*n+i] = point[i];
|
||||
}
|
||||
|
||||
// bubble down
|
||||
int j=pos;
|
||||
while (j>0 && vals[j]<vals[j-1]) {
|
||||
swap(vals[j],vals[j-1]);
|
||||
for (int i=0; i<n; ++i) {
|
||||
swap(points[j*n+i],points[(j-1)*n+i]);
|
||||
}
|
||||
--j;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Simplex downhill optimization function.
|
||||
Preconditions: points is a 2D mattrix of size (n+1) x n
|
||||
func is the cost function taking n an array of n params and returning float
|
||||
vals is the cost function in the n+1 simplex points, if NULL it will be computed
|
||||
|
||||
Postcondition: returns optimum value and points[0..n] are the optimum parameters
|
||||
*/
|
||||
template <typename T, typename F>
|
||||
float optimizeSimplexDownhill(T* points, int n, F func, float* vals = NULL )
|
||||
{
|
||||
const int MAX_ITERATIONS = 10;
|
||||
|
||||
assert(n>0);
|
||||
|
||||
T* p_o = new T[n];
|
||||
T* p_r = new T[n];
|
||||
T* p_e = new T[n];
|
||||
|
||||
int alpha = 1;
|
||||
|
||||
int iterations = 0;
|
||||
|
||||
bool ownVals = false;
|
||||
if (vals == NULL) {
|
||||
ownVals = true;
|
||||
vals = new float[n+1];
|
||||
for (int i=0; i<n+1; ++i) {
|
||||
float val = func(points+i*n);
|
||||
addValue(i, val, vals, points+i*n, points, n);
|
||||
}
|
||||
}
|
||||
int nn = n*n;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (iterations++ > MAX_ITERATIONS) break;
|
||||
|
||||
// compute average of simplex points (except the highest point)
|
||||
for (int j=0; j<n; ++j) {
|
||||
p_o[j] = 0;
|
||||
for (int i=0; i<n; ++i) {
|
||||
p_o[i] += points[j*n+i];
|
||||
}
|
||||
}
|
||||
for (int i=0; i<n; ++i) {
|
||||
p_o[i] /= n;
|
||||
}
|
||||
|
||||
bool converged = true;
|
||||
for (int i=0; i<n; ++i) {
|
||||
if (p_o[i] != points[nn+i]) {
|
||||
converged = false;
|
||||
}
|
||||
}
|
||||
if (converged) break;
|
||||
|
||||
// trying a reflection
|
||||
for (int i=0; i<n; ++i) {
|
||||
p_r[i] = p_o[i] + alpha*(p_o[i]-points[nn+i]);
|
||||
}
|
||||
float val_r = func(p_r);
|
||||
|
||||
if ((val_r>=vals[0])&&(val_r<vals[n])) {
|
||||
// reflection between second highest and lowest
|
||||
// add it to the simplex
|
||||
Logger::info("Choosing reflection\n");
|
||||
addValue(n, val_r,vals, p_r, points, n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val_r<vals[0]) {
|
||||
// value is smaller than smalest in simplex
|
||||
|
||||
// expand some more to see if it drops further
|
||||
for (int i=0; i<n; ++i) {
|
||||
p_e[i] = 2*p_r[i]-p_o[i];
|
||||
}
|
||||
float val_e = func(p_e);
|
||||
|
||||
if (val_e<val_r) {
|
||||
Logger::info("Choosing reflection and expansion\n");
|
||||
addValue(n, val_e,vals,p_e,points,n);
|
||||
}
|
||||
else {
|
||||
Logger::info("Choosing reflection\n");
|
||||
addValue(n, val_r,vals,p_r,points,n);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (val_r>=vals[n]) {
|
||||
for (int i=0; i<n; ++i) {
|
||||
p_e[i] = (p_o[i]+points[nn+i])/2;
|
||||
}
|
||||
float val_e = func(p_e);
|
||||
|
||||
if (val_e<vals[n]) {
|
||||
Logger::info("Choosing contraction\n");
|
||||
addValue(n,val_e,vals,p_e,points,n);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
{
|
||||
Logger::info("Full contraction\n");
|
||||
for (int j=1; j<=n; ++j) {
|
||||
for (int i=0; i<n; ++i) {
|
||||
points[j*n+i] = (points[j*n+i]+points[i])/2;
|
||||
}
|
||||
float val = func(points+j*n);
|
||||
addValue(j,val,vals,points+j*n,points,n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float bestVal = vals[0];
|
||||
|
||||
delete[] p_r;
|
||||
delete[] p_o;
|
||||
delete[] p_e;
|
||||
if (ownVals) delete[] vals;
|
||||
|
||||
return bestVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif //OPENCV_FLANN_SIMPLEX_DOWNHILL_H_
|
||||
@@ -0,0 +1,93 @@
|
||||
/***********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
|
||||
* Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
|
||||
*
|
||||
* THE BSD LICENSE
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*************************************************************************/
|
||||
|
||||
#ifndef OPENCV_FLANN_TIMER_H
|
||||
#define OPENCV_FLANN_TIMER_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
/**
|
||||
* A start-stop timer class.
|
||||
*
|
||||
* Can be used to time portions of code.
|
||||
*/
|
||||
class StartStopTimer
|
||||
{
|
||||
clock_t startTime;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Value of the timer.
|
||||
*/
|
||||
double value;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
StartStopTimer()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the timer.
|
||||
*/
|
||||
void start()
|
||||
{
|
||||
startTime = clock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the timer and updates timer value.
|
||||
*/
|
||||
void stop()
|
||||
{
|
||||
clock_t stopTime = clock();
|
||||
value += ( (double)stopTime - startTime) / CLOCKS_PER_SEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the timer value to 0.
|
||||
*/
|
||||
void reset()
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FLANN_TIMER_H
|
||||
@@ -0,0 +1,203 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_DEVICE_BLOCK_HPP__
|
||||
#define __OPENCV_GPU_DEVICE_BLOCK_HPP__
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
struct Block
|
||||
{
|
||||
static __device__ __forceinline__ unsigned int id()
|
||||
{
|
||||
return blockIdx.x;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int stride()
|
||||
{
|
||||
return blockDim.x * blockDim.y * blockDim.z;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ void sync()
|
||||
{
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ int flattenedThreadId()
|
||||
{
|
||||
return threadIdx.z * blockDim.x * blockDim.y + threadIdx.y * blockDim.x + threadIdx.x;
|
||||
}
|
||||
|
||||
template<typename It, typename T>
|
||||
static __device__ __forceinline__ void fill(It beg, It end, const T& value)
|
||||
{
|
||||
int STRIDE = stride();
|
||||
It t = beg + flattenedThreadId();
|
||||
|
||||
for(; t < end; t += STRIDE)
|
||||
*t = value;
|
||||
}
|
||||
|
||||
template<typename OutIt, typename T>
|
||||
static __device__ __forceinline__ void yota(OutIt beg, OutIt end, T value)
|
||||
{
|
||||
int STRIDE = stride();
|
||||
int tid = flattenedThreadId();
|
||||
value += tid;
|
||||
|
||||
for(OutIt t = beg + tid; t < end; t += STRIDE, value += STRIDE)
|
||||
*t = value;
|
||||
}
|
||||
|
||||
template<typename InIt, typename OutIt>
|
||||
static __device__ __forceinline__ void copy(InIt beg, InIt end, OutIt out)
|
||||
{
|
||||
int STRIDE = stride();
|
||||
InIt t = beg + flattenedThreadId();
|
||||
OutIt o = out + (t - beg);
|
||||
|
||||
for(; t < end; t += STRIDE, o += STRIDE)
|
||||
*o = *t;
|
||||
}
|
||||
|
||||
template<typename InIt, typename OutIt, class UnOp>
|
||||
static __device__ __forceinline__ void transfrom(InIt beg, InIt end, OutIt out, UnOp op)
|
||||
{
|
||||
int STRIDE = stride();
|
||||
InIt t = beg + flattenedThreadId();
|
||||
OutIt o = out + (t - beg);
|
||||
|
||||
for(; t < end; t += STRIDE, o += STRIDE)
|
||||
*o = op(*t);
|
||||
}
|
||||
|
||||
template<typename InIt1, typename InIt2, typename OutIt, class BinOp>
|
||||
static __device__ __forceinline__ void transfrom(InIt1 beg1, InIt1 end1, InIt2 beg2, OutIt out, BinOp op)
|
||||
{
|
||||
int STRIDE = stride();
|
||||
InIt1 t1 = beg1 + flattenedThreadId();
|
||||
InIt2 t2 = beg2 + flattenedThreadId();
|
||||
OutIt o = out + (t1 - beg1);
|
||||
|
||||
for(; t1 < end1; t1 += STRIDE, t2 += STRIDE, o += STRIDE)
|
||||
*o = op(*t1, *t2);
|
||||
}
|
||||
|
||||
template<int CTA_SIZE, typename T, class BinOp>
|
||||
static __device__ __forceinline__ void reduce(volatile T* buffer, BinOp op)
|
||||
{
|
||||
int tid = flattenedThreadId();
|
||||
T val = buffer[tid];
|
||||
|
||||
if (CTA_SIZE >= 1024) { if (tid < 512) buffer[tid] = val = op(val, buffer[tid + 512]); __syncthreads(); }
|
||||
if (CTA_SIZE >= 512) { if (tid < 256) buffer[tid] = val = op(val, buffer[tid + 256]); __syncthreads(); }
|
||||
if (CTA_SIZE >= 256) { if (tid < 128) buffer[tid] = val = op(val, buffer[tid + 128]); __syncthreads(); }
|
||||
if (CTA_SIZE >= 128) { if (tid < 64) buffer[tid] = val = op(val, buffer[tid + 64]); __syncthreads(); }
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
if (CTA_SIZE >= 64) { buffer[tid] = val = op(val, buffer[tid + 32]); }
|
||||
if (CTA_SIZE >= 32) { buffer[tid] = val = op(val, buffer[tid + 16]); }
|
||||
if (CTA_SIZE >= 16) { buffer[tid] = val = op(val, buffer[tid + 8]); }
|
||||
if (CTA_SIZE >= 8) { buffer[tid] = val = op(val, buffer[tid + 4]); }
|
||||
if (CTA_SIZE >= 4) { buffer[tid] = val = op(val, buffer[tid + 2]); }
|
||||
if (CTA_SIZE >= 2) { buffer[tid] = val = op(val, buffer[tid + 1]); }
|
||||
}
|
||||
}
|
||||
|
||||
template<int CTA_SIZE, typename T, class BinOp>
|
||||
static __device__ __forceinline__ T reduce(volatile T* buffer, T init, BinOp op)
|
||||
{
|
||||
int tid = flattenedThreadId();
|
||||
T val = buffer[tid] = init;
|
||||
__syncthreads();
|
||||
|
||||
if (CTA_SIZE >= 1024) { if (tid < 512) buffer[tid] = val = op(val, buffer[tid + 512]); __syncthreads(); }
|
||||
if (CTA_SIZE >= 512) { if (tid < 256) buffer[tid] = val = op(val, buffer[tid + 256]); __syncthreads(); }
|
||||
if (CTA_SIZE >= 256) { if (tid < 128) buffer[tid] = val = op(val, buffer[tid + 128]); __syncthreads(); }
|
||||
if (CTA_SIZE >= 128) { if (tid < 64) buffer[tid] = val = op(val, buffer[tid + 64]); __syncthreads(); }
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
if (CTA_SIZE >= 64) { buffer[tid] = val = op(val, buffer[tid + 32]); }
|
||||
if (CTA_SIZE >= 32) { buffer[tid] = val = op(val, buffer[tid + 16]); }
|
||||
if (CTA_SIZE >= 16) { buffer[tid] = val = op(val, buffer[tid + 8]); }
|
||||
if (CTA_SIZE >= 8) { buffer[tid] = val = op(val, buffer[tid + 4]); }
|
||||
if (CTA_SIZE >= 4) { buffer[tid] = val = op(val, buffer[tid + 2]); }
|
||||
if (CTA_SIZE >= 2) { buffer[tid] = val = op(val, buffer[tid + 1]); }
|
||||
}
|
||||
__syncthreads();
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
template <typename T, class BinOp>
|
||||
static __device__ __forceinline__ void reduce_n(T* data, unsigned int n, BinOp op)
|
||||
{
|
||||
int ftid = flattenedThreadId();
|
||||
int sft = stride();
|
||||
|
||||
if (sft < n)
|
||||
{
|
||||
for (unsigned int i = sft + ftid; i < n; i += sft)
|
||||
data[ftid] = op(data[ftid], data[i]);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
n = sft;
|
||||
}
|
||||
|
||||
while (n > 1)
|
||||
{
|
||||
unsigned int half = n/2;
|
||||
|
||||
if (ftid < half)
|
||||
data[ftid] = op(data[ftid], data[n - ftid - 1]);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
n = n - half;
|
||||
}
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif /* __OPENCV_GPU_DEVICE_BLOCK_HPP__ */
|
||||
@@ -0,0 +1,714 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_BORDER_INTERPOLATE_HPP__
|
||||
#define __OPENCV_GPU_BORDER_INTERPOLATE_HPP__
|
||||
|
||||
#include "saturate_cast.hpp"
|
||||
#include "vec_traits.hpp"
|
||||
#include "vec_math.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
//////////////////////////////////////////////////////////////
|
||||
// BrdConstant
|
||||
|
||||
template <typename D> struct BrdRowConstant
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdRowConstant(int width_, const D& val_ = VecTraits<D>::all(0)) : width(width_), val(val_) {}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int x, const T* data) const
|
||||
{
|
||||
return x >= 0 ? saturate_cast<D>(data[x]) : val;
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int x, const T* data) const
|
||||
{
|
||||
return x < width ? saturate_cast<D>(data[x]) : val;
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int x, const T* data) const
|
||||
{
|
||||
return (x >= 0 && x < width) ? saturate_cast<D>(data[x]) : val;
|
||||
}
|
||||
|
||||
const int width;
|
||||
const D val;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdColConstant
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdColConstant(int height_, const D& val_ = VecTraits<D>::all(0)) : height(height_), val(val_) {}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const
|
||||
{
|
||||
return y >= 0 ? saturate_cast<D>(*(const T*)((const char*)data + y * step)) : val;
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const
|
||||
{
|
||||
return y < height ? saturate_cast<D>(*(const T*)((const char*)data + y * step)) : val;
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, const T* data, size_t step) const
|
||||
{
|
||||
return (y >= 0 && y < height) ? saturate_cast<D>(*(const T*)((const char*)data + y * step)) : val;
|
||||
}
|
||||
|
||||
const int height;
|
||||
const D val;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdConstant
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BrdConstant(int height_, int width_, const D& val_ = VecTraits<D>::all(0)) : height(height_), width(width_), val(val_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const
|
||||
{
|
||||
return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast<D>(((const T*)((const uchar*)data + y * step))[x]) : val;
|
||||
}
|
||||
|
||||
template <typename Ptr2D> __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const
|
||||
{
|
||||
return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast<D>(src(y, x)) : val;
|
||||
}
|
||||
|
||||
const int height;
|
||||
const int width;
|
||||
const D val;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// BrdReplicate
|
||||
|
||||
template <typename D> struct BrdRowReplicate
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdRowReplicate(int width) : last_col(width - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdRowReplicate(int width, U) : last_col(width - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return ::max(x, 0);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return ::min(x, last_col);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_low(idx_col_high(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_low(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_high(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col(x)]);
|
||||
}
|
||||
|
||||
const int last_col;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdColReplicate
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdColReplicate(int height) : last_row(height - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdColReplicate(int height, U) : last_row(height - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return ::max(y, 0);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return ::min(y, last_row);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_low(idx_row_high(y));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const T*)((const char*)data + idx_row_low(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const T*)((const char*)data + idx_row_high(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const T*)((const char*)data + idx_row(y) * step));
|
||||
}
|
||||
|
||||
const int last_row;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdReplicate
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BrdReplicate(int height, int width) : last_row(height - 1), last_col(width - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdReplicate(int height, int width, U) : last_row(height - 1), last_col(width - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return ::max(y, 0);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return ::min(y, last_row);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_low(idx_row_high(y));
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return ::max(x, 0);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return ::min(x, last_col);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_low(idx_col_high(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]);
|
||||
}
|
||||
|
||||
template <typename Ptr2D> __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const
|
||||
{
|
||||
return saturate_cast<D>(src(idx_row(y), idx_col(x)));
|
||||
}
|
||||
|
||||
const int last_row;
|
||||
const int last_col;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// BrdReflect101
|
||||
|
||||
template <typename D> struct BrdRowReflect101
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdRowReflect101(int width) : last_col(width - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdRowReflect101(int width, U) : last_col(width - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return ::abs(x) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return ::abs(last_col - ::abs(last_col - x)) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_low(idx_col_high(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_low(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_high(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col(x)]);
|
||||
}
|
||||
|
||||
const int last_col;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdColReflect101
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdColReflect101(int height) : last_row(height - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdColReflect101(int height, U) : last_row(height - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return ::abs(y) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return ::abs(last_row - ::abs(last_row - y)) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_low(idx_row_high(y));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row_low(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row_high(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row(y) * step));
|
||||
}
|
||||
|
||||
const int last_row;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdReflect101
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BrdReflect101(int height, int width) : last_row(height - 1), last_col(width - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdReflect101(int height, int width, U) : last_row(height - 1), last_col(width - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return ::abs(y) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return ::abs(last_row - ::abs(last_row - y)) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_low(idx_row_high(y));
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return ::abs(x) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return ::abs(last_col - ::abs(last_col - x)) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_low(idx_col_high(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]);
|
||||
}
|
||||
|
||||
template <typename Ptr2D> __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const
|
||||
{
|
||||
return saturate_cast<D>(src(idx_row(y), idx_col(x)));
|
||||
}
|
||||
|
||||
const int last_row;
|
||||
const int last_col;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// BrdReflect
|
||||
|
||||
template <typename D> struct BrdRowReflect
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdRowReflect(int width) : last_col(width - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdRowReflect(int width, U) : last_col(width - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return (::abs(x) - (x < 0)) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return ::abs(last_col - ::abs(last_col - x) + (x > last_col)) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_high(::abs(x) - (x < 0));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_low(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_high(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col(x)]);
|
||||
}
|
||||
|
||||
const int last_col;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdColReflect
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdColReflect(int height) : last_row(height - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdColReflect(int height, U) : last_row(height - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return (::abs(y) - (y < 0)) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return ::abs(last_row - ::abs(last_row - y) + (y > last_row)) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_high(::abs(y) - (y < 0));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row_low(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row_high(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row(y) * step));
|
||||
}
|
||||
|
||||
const int last_row;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdReflect
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BrdReflect(int height, int width) : last_row(height - 1), last_col(width - 1) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdReflect(int height, int width, U) : last_row(height - 1), last_col(width - 1) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return (::abs(y) - (y < 0)) % (last_row + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return /*::abs*/(last_row - ::abs(last_row - y) + (y > last_row)) /*% (last_row + 1)*/;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_low(idx_row_high(y));
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return (::abs(x) - (x < 0)) % (last_col + 1);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return (last_col - ::abs(last_col - x) + (x > last_col));
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_low(idx_col_high(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]);
|
||||
}
|
||||
|
||||
template <typename Ptr2D> __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const
|
||||
{
|
||||
return saturate_cast<D>(src(idx_row(y), idx_col(x)));
|
||||
}
|
||||
|
||||
const int last_row;
|
||||
const int last_col;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// BrdWrap
|
||||
|
||||
template <typename D> struct BrdRowWrap
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdRowWrap(int width_) : width(width_) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdRowWrap(int width_, U) : width(width_) {}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return (x >= 0) * x + (x < 0) * (x - ((x - width + 1) / width) * width);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return (x < width) * x + (x >= width) * (x % width);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_high(idx_col_low(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_low(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col_high(x)]);
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int x, const T* data) const
|
||||
{
|
||||
return saturate_cast<D>(data[idx_col(x)]);
|
||||
}
|
||||
|
||||
const int width;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdColWrap
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ BrdColWrap(int height_) : height(height_) {}
|
||||
template <typename U> __host__ __device__ __forceinline__ BrdColWrap(int height_, U) : height(height_) {}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return (y >= 0) * y + (y < 0) * (y - ((y - height + 1) / height) * height);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return (y < height) * y + (y >= height) * (y % height);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_high(idx_row_low(y));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_low(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row_low(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at_high(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row_high(y) * step));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(*(const D*)((const char*)data + idx_row(y) * step));
|
||||
}
|
||||
|
||||
const int height;
|
||||
};
|
||||
|
||||
template <typename D> struct BrdWrap
|
||||
{
|
||||
typedef D result_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BrdWrap(int height_, int width_) :
|
||||
height(height_), width(width_)
|
||||
{
|
||||
}
|
||||
template <typename U>
|
||||
__host__ __device__ __forceinline__ BrdWrap(int height_, int width_, U) :
|
||||
height(height_), width(width_)
|
||||
{
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_low(int y) const
|
||||
{
|
||||
return (y >= 0) * y + (y < 0) * (y - ((y - height + 1) / height) * height);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row_high(int y) const
|
||||
{
|
||||
return (y < height) * y + (y >= height) * (y % height);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_row(int y) const
|
||||
{
|
||||
return idx_row_high(idx_row_low(y));
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_low(int x) const
|
||||
{
|
||||
return (x >= 0) * x + (x < 0) * (x - ((x - width + 1) / width) * width);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col_high(int x) const
|
||||
{
|
||||
return (x < width) * x + (x >= width) * (x % width);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ int idx_col(int x) const
|
||||
{
|
||||
return idx_col_high(idx_col_low(x));
|
||||
}
|
||||
|
||||
template <typename T> __device__ __forceinline__ D at(int y, int x, const T* data, size_t step) const
|
||||
{
|
||||
return saturate_cast<D>(((const T*)((const char*)data + idx_row(y) * step))[idx_col(x)]);
|
||||
}
|
||||
|
||||
template <typename Ptr2D> __device__ __forceinline__ D at(typename Ptr2D::index_type y, typename Ptr2D::index_type x, const Ptr2D& src) const
|
||||
{
|
||||
return saturate_cast<D>(src(idx_row(y), idx_col(x)));
|
||||
}
|
||||
|
||||
const int height;
|
||||
const int width;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// BorderReader
|
||||
|
||||
template <typename Ptr2D, typename B> struct BorderReader
|
||||
{
|
||||
typedef typename B::result_type elem_type;
|
||||
typedef typename Ptr2D::index_type index_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BorderReader(const Ptr2D& ptr_, const B& b_) : ptr(ptr_), b(b_) {}
|
||||
|
||||
__device__ __forceinline__ elem_type operator ()(index_type y, index_type x) const
|
||||
{
|
||||
return b.at(y, x, ptr);
|
||||
}
|
||||
|
||||
const Ptr2D ptr;
|
||||
const B b;
|
||||
};
|
||||
|
||||
// under win32 there is some bug with templated types that passed as kernel parameters
|
||||
// with this specialization all works fine
|
||||
template <typename Ptr2D, typename D> struct BorderReader< Ptr2D, BrdConstant<D> >
|
||||
{
|
||||
typedef typename BrdConstant<D>::result_type elem_type;
|
||||
typedef typename Ptr2D::index_type index_type;
|
||||
|
||||
__host__ __device__ __forceinline__ BorderReader(const Ptr2D& src_, const BrdConstant<D>& b) :
|
||||
src(src_), height(b.height), width(b.width), val(b.val)
|
||||
{
|
||||
}
|
||||
|
||||
__device__ __forceinline__ D operator ()(index_type y, index_type x) const
|
||||
{
|
||||
return (x >= 0 && x < width && y >= 0 && y < height) ? saturate_cast<D>(src(y, x)) : val;
|
||||
}
|
||||
|
||||
const Ptr2D src;
|
||||
const int height;
|
||||
const int width;
|
||||
const D val;
|
||||
};
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_BORDER_INTERPOLATE_HPP__
|
||||
@@ -0,0 +1,301 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_COLOR_HPP__
|
||||
#define __OPENCV_GPU_COLOR_HPP__
|
||||
|
||||
#include "detail/color_detail.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
// All OPENCV_GPU_IMPLEMENT_*_TRAITS(ColorSpace1_to_ColorSpace2, ...) macros implements
|
||||
// template <typename T> class ColorSpace1_to_ColorSpace2_traits
|
||||
// {
|
||||
// typedef ... functor_type;
|
||||
// static __host__ __device__ functor_type create_functor();
|
||||
// };
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(bgr_to_rgb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(bgr_to_bgra, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(bgr_to_rgba, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(bgra_to_bgr, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(bgra_to_rgb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(bgra_to_rgba, 4, 4, 2)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(bgr_to_bgr555, 3, 0, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(bgr_to_bgr565, 3, 0, 6)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(rgb_to_bgr555, 3, 2, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(rgb_to_bgr565, 3, 2, 6)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(bgra_to_bgr555, 4, 0, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(bgra_to_bgr565, 4, 0, 6)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(rgba_to_bgr555, 4, 2, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(rgba_to_bgr565, 4, 2, 6)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_rgb, 3, 2, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_rgb, 3, 2, 6)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_bgr, 3, 0, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_bgr, 3, 0, 6)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_rgba, 4, 2, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_rgba, 4, 2, 6)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr555_to_bgra, 4, 0, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(bgr565_to_bgra, 4, 0, 6)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_GRAY2RGB_TRAITS(gray_to_bgr, 3)
|
||||
OPENCV_GPU_IMPLEMENT_GRAY2RGB_TRAITS(gray_to_bgra, 4)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_GRAY2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_GRAY2RGB5x5_TRAITS(gray_to_bgr555, 5)
|
||||
OPENCV_GPU_IMPLEMENT_GRAY2RGB5x5_TRAITS(gray_to_bgr565, 6)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_GRAY2RGB5x5_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52GRAY_TRAITS(bgr555_to_gray, 5)
|
||||
OPENCV_GPU_IMPLEMENT_RGB5x52GRAY_TRAITS(bgr565_to_gray, 6)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB5x52GRAY_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(rgb_to_gray, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(bgr_to_gray, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(rgba_to_gray, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(bgra_to_gray, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgb_to_yuv4, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(rgba_to_yuv4, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgr_to_yuv4, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(bgra_to_yuv4, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_rgba, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_rgba, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgr, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv_to_bgra, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgr, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(yuv4_to_bgra, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(rgb_to_YCrCb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(rgba_to_YCrCb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(rgb_to_YCrCb4, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(rgba_to_YCrCb4, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(bgr_to_YCrCb, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(bgra_to_YCrCb, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(bgr_to_YCrCb4, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(bgra_to_YCrCb4, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_rgb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_rgba, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_rgb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_rgba, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_bgr, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb_to_bgra, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_bgr, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(YCrCb4_to_bgra, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(rgb_to_xyz, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(rgba_to_xyz, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(rgb_to_xyz4, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(rgba_to_xyz4, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(bgr_to_xyz, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(bgra_to_xyz, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(bgr_to_xyz4, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(bgra_to_xyz4, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_rgb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_rgb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_rgba, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_rgba, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_bgr, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_bgr, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz_to_bgra, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(xyz4_to_bgra, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(rgb_to_hsv, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(rgba_to_hsv, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(rgb_to_hsv4, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(rgba_to_hsv4, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(bgr_to_hsv, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(bgra_to_hsv, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(bgr_to_hsv4, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(bgra_to_hsv4, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_rgb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_rgba, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_rgb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_rgba, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_bgr, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv_to_bgra, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_bgr, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(hsv4_to_bgra, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(rgb_to_hls, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(rgba_to_hls, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(rgb_to_hls4, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(rgba_to_hls4, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(bgr_to_hls, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(bgra_to_hls, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(bgr_to_hls4, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(bgra_to_hls4, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls_to_rgb, 3, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls_to_rgba, 3, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_rgb, 4, 3, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_rgba, 4, 4, 2)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls_to_bgr, 3, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls_to_bgra, 3, 4, 0)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_bgr, 4, 3, 0)
|
||||
OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(hls4_to_bgra, 4, 4, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(rgb_to_lab, 3, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(rgba_to_lab, 4, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(rgb_to_lab4, 3, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(rgba_to_lab4, 4, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(bgr_to_lab, 3, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(bgra_to_lab, 4, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(bgr_to_lab4, 3, 4, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(bgra_to_lab4, 4, 4, true, 0)
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lrgb_to_lab, 3, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lrgba_to_lab, 4, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lrgb_to_lab4, 3, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lrgba_to_lab4, 4, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lbgr_to_lab, 3, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lbgra_to_lab, 4, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lbgr_to_lab4, 3, 4, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS(lbgra_to_lab4, 4, 4, false, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2Lab_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_rgb, 3, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_rgb, 4, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_rgba, 3, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_rgba, 4, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_bgr, 3, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_bgr, 4, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_bgra, 3, 4, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_bgra, 4, 4, true, 0)
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lrgb, 3, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lrgb, 4, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lrgba, 3, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lrgba, 4, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lbgr, 3, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lbgr, 4, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab_to_lbgra, 3, 4, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS(lab4_to_lbgra, 4, 4, false, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_Lab2RGB_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(rgb_to_luv, 3, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(rgba_to_luv, 4, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(rgb_to_luv4, 3, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(rgba_to_luv4, 4, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(bgr_to_luv, 3, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(bgra_to_luv, 4, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(bgr_to_luv4, 3, 4, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(bgra_to_luv4, 4, 4, true, 0)
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lrgb_to_luv, 3, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lrgba_to_luv, 4, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lrgb_to_luv4, 3, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lrgba_to_luv4, 4, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lbgr_to_luv, 3, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lbgra_to_luv, 4, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lbgr_to_luv4, 3, 4, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS(lbgra_to_luv4, 4, 4, false, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_RGB2Luv_TRAITS
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_rgb, 3, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_rgb, 4, 3, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_rgba, 3, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_rgba, 4, 4, true, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_bgr, 3, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_bgr, 4, 3, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_bgra, 3, 4, true, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_bgra, 4, 4, true, 0)
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lrgb, 3, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lrgb, 4, 3, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lrgba, 3, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lrgba, 4, 4, false, 2)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lbgr, 3, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lbgr, 4, 3, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv_to_lbgra, 3, 4, false, 0)
|
||||
OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS(luv4_to_lbgra, 4, 4, false, 0)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_Luv2RGB_TRAITS
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_BORDER_INTERPOLATE_HPP__
|
||||
@@ -0,0 +1,118 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_COMMON_HPP__
|
||||
#define __OPENCV_GPU_COMMON_HPP__
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include "opencv2/core/cuda_devptrs.hpp"
|
||||
|
||||
#ifndef CV_PI
|
||||
#define CV_PI 3.1415926535897932384626433832795
|
||||
#endif
|
||||
|
||||
#ifndef CV_PI_F
|
||||
#ifndef CV_PI
|
||||
#define CV_PI_F 3.14159265f
|
||||
#else
|
||||
#define CV_PI_F ((float)CV_PI)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__, __func__)
|
||||
#else /* defined(__CUDACC__) || defined(__MSVC__) */
|
||||
#define cudaSafeCall(expr) ___cudaSafeCall(expr, __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
namespace cv { namespace gpu
|
||||
{
|
||||
void error(const char *error_string, const char *file, const int line, const char *func);
|
||||
|
||||
template <typename T> static inline bool isAligned(const T* ptr, size_t size)
|
||||
{
|
||||
return reinterpret_cast<size_t>(ptr) % size == 0;
|
||||
}
|
||||
|
||||
static inline bool isAligned(size_t step, size_t size)
|
||||
{
|
||||
return step % size == 0;
|
||||
}
|
||||
}}
|
||||
|
||||
static inline void ___cudaSafeCall(cudaError_t err, const char *file, const int line, const char *func = "")
|
||||
{
|
||||
if (cudaSuccess != err)
|
||||
cv::gpu::error(cudaGetErrorString(err), file, line, func);
|
||||
}
|
||||
|
||||
namespace cv { namespace gpu
|
||||
{
|
||||
__host__ __device__ __forceinline__ int divUp(int total, int grain)
|
||||
{
|
||||
return (total + grain - 1) / grain;
|
||||
}
|
||||
|
||||
namespace device
|
||||
{
|
||||
using cv::gpu::divUp;
|
||||
|
||||
#ifdef __CUDACC__
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef signed char schar;
|
||||
#if defined (_WIN32) || defined (__APPLE__)
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
|
||||
template<class T> inline void bindTexture(const textureReference* tex, const PtrStepSz<T>& img)
|
||||
{
|
||||
cudaChannelFormatDesc desc = cudaCreateChannelDesc<T>();
|
||||
cudaSafeCall( cudaBindTexture2D(0, tex, img.ptr(), &desc, img.cols, img.rows, img.step) );
|
||||
}
|
||||
#endif // __CUDACC__
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
|
||||
#endif // __OPENCV_GPU_COMMON_HPP__
|
||||
@@ -0,0 +1,105 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_DATAMOV_UTILS_HPP__
|
||||
#define __OPENCV_GPU_DATAMOV_UTILS_HPP__
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 200
|
||||
|
||||
// for Fermi memory space is detected automatically
|
||||
template <typename T> struct ForceGlob
|
||||
{
|
||||
__device__ __forceinline__ static void Load(const T* ptr, int offset, T& val) { val = ptr[offset]; }
|
||||
};
|
||||
|
||||
#else // __CUDA_ARCH__ >= 200
|
||||
|
||||
#if defined(_WIN64) || defined(__LP64__)
|
||||
// 64-bit register modifier for inlined asm
|
||||
#define OPENCV_GPU_ASM_PTR "l"
|
||||
#else
|
||||
// 32-bit register modifier for inlined asm
|
||||
#define OPENCV_GPU_ASM_PTR "r"
|
||||
#endif
|
||||
|
||||
template<class T> struct ForceGlob;
|
||||
|
||||
#define OPENCV_GPU_DEFINE_FORCE_GLOB(base_type, ptx_type, reg_mod) \
|
||||
template <> struct ForceGlob<base_type> \
|
||||
{ \
|
||||
__device__ __forceinline__ static void Load(const base_type* ptr, int offset, base_type& val) \
|
||||
{ \
|
||||
asm("ld.global."#ptx_type" %0, [%1];" : "="#reg_mod(val) : OPENCV_GPU_ASM_PTR(ptr + offset)); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define OPENCV_GPU_DEFINE_FORCE_GLOB_B(base_type, ptx_type) \
|
||||
template <> struct ForceGlob<base_type> \
|
||||
{ \
|
||||
__device__ __forceinline__ static void Load(const base_type* ptr, int offset, base_type& val) \
|
||||
{ \
|
||||
asm("ld.global."#ptx_type" %0, [%1];" : "=r"(*reinterpret_cast<uint*>(&val)) : OPENCV_GPU_ASM_PTR(ptr + offset)); \
|
||||
} \
|
||||
};
|
||||
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB_B(uchar, u8)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB_B(schar, s8)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB_B(char, b8)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB (ushort, u16, h)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB (short, s16, h)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB (uint, u32, r)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB (int, s32, r)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB (float, f32, f)
|
||||
OPENCV_GPU_DEFINE_FORCE_GLOB (double, f64, d)
|
||||
|
||||
#undef OPENCV_GPU_DEFINE_FORCE_GLOB
|
||||
#undef OPENCV_GPU_DEFINE_FORCE_GLOB_B
|
||||
#undef OPENCV_GPU_ASM_PTR
|
||||
|
||||
#endif // __CUDA_ARCH__ >= 200
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_DATAMOV_UTILS_HPP__
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,361 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_REDUCE_DETAIL_HPP__
|
||||
#define __OPENCV_GPU_REDUCE_DETAIL_HPP__
|
||||
|
||||
#include <thrust/tuple.h>
|
||||
#include "../warp.hpp"
|
||||
#include "../warp_shuffle.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace reduce_detail
|
||||
{
|
||||
template <typename T> struct GetType;
|
||||
template <typename T> struct GetType<T*>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
template <typename T> struct GetType<volatile T*>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
template <typename T> struct GetType<T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <unsigned int I, unsigned int N>
|
||||
struct For
|
||||
{
|
||||
template <class PointerTuple, class ValTuple>
|
||||
static __device__ void loadToSmem(const PointerTuple& smem, const ValTuple& val, unsigned int tid)
|
||||
{
|
||||
thrust::get<I>(smem)[tid] = thrust::get<I>(val);
|
||||
|
||||
For<I + 1, N>::loadToSmem(smem, val, tid);
|
||||
}
|
||||
template <class PointerTuple, class ValTuple>
|
||||
static __device__ void loadFromSmem(const PointerTuple& smem, const ValTuple& val, unsigned int tid)
|
||||
{
|
||||
thrust::get<I>(val) = thrust::get<I>(smem)[tid];
|
||||
|
||||
For<I + 1, N>::loadFromSmem(smem, val, tid);
|
||||
}
|
||||
|
||||
template <class PointerTuple, class ValTuple, class OpTuple>
|
||||
static __device__ void merge(const PointerTuple& smem, const ValTuple& val, unsigned int tid, unsigned int delta, const OpTuple& op)
|
||||
{
|
||||
typename GetType<typename thrust::tuple_element<I, PointerTuple>::type>::type reg = thrust::get<I>(smem)[tid + delta];
|
||||
thrust::get<I>(smem)[tid] = thrust::get<I>(val) = thrust::get<I>(op)(thrust::get<I>(val), reg);
|
||||
|
||||
For<I + 1, N>::merge(smem, val, tid, delta, op);
|
||||
}
|
||||
template <class ValTuple, class OpTuple>
|
||||
static __device__ void mergeShfl(const ValTuple& val, unsigned int delta, unsigned int width, const OpTuple& op)
|
||||
{
|
||||
typename GetType<typename thrust::tuple_element<I, ValTuple>::type>::type reg = shfl_down(thrust::get<I>(val), delta, width);
|
||||
thrust::get<I>(val) = thrust::get<I>(op)(thrust::get<I>(val), reg);
|
||||
|
||||
For<I + 1, N>::mergeShfl(val, delta, width, op);
|
||||
}
|
||||
};
|
||||
template <unsigned int N>
|
||||
struct For<N, N>
|
||||
{
|
||||
template <class PointerTuple, class ValTuple>
|
||||
static __device__ void loadToSmem(const PointerTuple&, const ValTuple&, unsigned int)
|
||||
{
|
||||
}
|
||||
template <class PointerTuple, class ValTuple>
|
||||
static __device__ void loadFromSmem(const PointerTuple&, const ValTuple&, unsigned int)
|
||||
{
|
||||
}
|
||||
|
||||
template <class PointerTuple, class ValTuple, class OpTuple>
|
||||
static __device__ void merge(const PointerTuple&, const ValTuple&, unsigned int, unsigned int, const OpTuple&)
|
||||
{
|
||||
}
|
||||
template <class ValTuple, class OpTuple>
|
||||
static __device__ void mergeShfl(const ValTuple&, unsigned int, unsigned int, const OpTuple&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
__device__ __forceinline__ void loadToSmem(volatile T* smem, T& val, unsigned int tid)
|
||||
{
|
||||
smem[tid] = val;
|
||||
}
|
||||
template <typename T>
|
||||
__device__ __forceinline__ void loadFromSmem(volatile T* smem, T& val, unsigned int tid)
|
||||
{
|
||||
val = smem[tid];
|
||||
}
|
||||
template <typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9,
|
||||
typename R0, typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7, typename R8, typename R9>
|
||||
__device__ __forceinline__ void loadToSmem(const thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9>& smem,
|
||||
const thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9>& val,
|
||||
unsigned int tid)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9> >::value>::loadToSmem(smem, val, tid);
|
||||
}
|
||||
template <typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9,
|
||||
typename R0, typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7, typename R8, typename R9>
|
||||
__device__ __forceinline__ void loadFromSmem(const thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9>& smem,
|
||||
const thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9>& val,
|
||||
unsigned int tid)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9> >::value>::loadFromSmem(smem, val, tid);
|
||||
}
|
||||
|
||||
template <typename T, class Op>
|
||||
__device__ __forceinline__ void merge(volatile T* smem, T& val, unsigned int tid, unsigned int delta, const Op& op)
|
||||
{
|
||||
T reg = smem[tid + delta];
|
||||
smem[tid] = val = op(val, reg);
|
||||
}
|
||||
template <typename T, class Op>
|
||||
__device__ __forceinline__ void mergeShfl(T& val, unsigned int delta, unsigned int width, const Op& op)
|
||||
{
|
||||
T reg = shfl_down(val, delta, width);
|
||||
val = op(val, reg);
|
||||
}
|
||||
template <typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9,
|
||||
typename R0, typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7, typename R8, typename R9,
|
||||
class Op0, class Op1, class Op2, class Op3, class Op4, class Op5, class Op6, class Op7, class Op8, class Op9>
|
||||
__device__ __forceinline__ void merge(const thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9>& smem,
|
||||
const thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9>& val,
|
||||
unsigned int tid,
|
||||
unsigned int delta,
|
||||
const thrust::tuple<Op0, Op1, Op2, Op3, Op4, Op5, Op6, Op7, Op8, Op9>& op)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9> >::value>::merge(smem, val, tid, delta, op);
|
||||
}
|
||||
template <typename R0, typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7, typename R8, typename R9,
|
||||
class Op0, class Op1, class Op2, class Op3, class Op4, class Op5, class Op6, class Op7, class Op8, class Op9>
|
||||
__device__ __forceinline__ void mergeShfl(const thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9>& val,
|
||||
unsigned int delta,
|
||||
unsigned int width,
|
||||
const thrust::tuple<Op0, Op1, Op2, Op3, Op4, Op5, Op6, Op7, Op8, Op9>& op)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9> >::value>::mergeShfl(val, delta, width, op);
|
||||
}
|
||||
|
||||
template <unsigned int N> struct Generic
|
||||
{
|
||||
template <typename Pointer, typename Reference, class Op>
|
||||
static __device__ void reduce(Pointer smem, Reference val, unsigned int tid, Op op)
|
||||
{
|
||||
loadToSmem(smem, val, tid);
|
||||
if (N >= 32)
|
||||
__syncthreads();
|
||||
|
||||
if (N >= 2048)
|
||||
{
|
||||
if (tid < 1024)
|
||||
merge(smem, val, tid, 1024, op);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 1024)
|
||||
{
|
||||
if (tid < 512)
|
||||
merge(smem, val, tid, 512, op);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 512)
|
||||
{
|
||||
if (tid < 256)
|
||||
merge(smem, val, tid, 256, op);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 256)
|
||||
{
|
||||
if (tid < 128)
|
||||
merge(smem, val, tid, 128, op);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 128)
|
||||
{
|
||||
if (tid < 64)
|
||||
merge(smem, val, tid, 64, op);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 64)
|
||||
{
|
||||
if (tid < 32)
|
||||
merge(smem, val, tid, 32, op);
|
||||
}
|
||||
|
||||
if (tid < 16)
|
||||
{
|
||||
merge(smem, val, tid, 16, op);
|
||||
merge(smem, val, tid, 8, op);
|
||||
merge(smem, val, tid, 4, op);
|
||||
merge(smem, val, tid, 2, op);
|
||||
merge(smem, val, tid, 1, op);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int I, typename Pointer, typename Reference, class Op>
|
||||
struct Unroll
|
||||
{
|
||||
static __device__ void loopShfl(Reference val, Op op, unsigned int N)
|
||||
{
|
||||
mergeShfl(val, I, N, op);
|
||||
Unroll<I / 2, Pointer, Reference, Op>::loopShfl(val, op, N);
|
||||
}
|
||||
static __device__ void loop(Pointer smem, Reference val, unsigned int tid, Op op)
|
||||
{
|
||||
merge(smem, val, tid, I, op);
|
||||
Unroll<I / 2, Pointer, Reference, Op>::loop(smem, val, tid, op);
|
||||
}
|
||||
};
|
||||
template <typename Pointer, typename Reference, class Op>
|
||||
struct Unroll<0, Pointer, Reference, Op>
|
||||
{
|
||||
static __device__ void loopShfl(Reference, Op, unsigned int)
|
||||
{
|
||||
}
|
||||
static __device__ void loop(Pointer, Reference, unsigned int, Op)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int N> struct WarpOptimized
|
||||
{
|
||||
template <typename Pointer, typename Reference, class Op>
|
||||
static __device__ void reduce(Pointer smem, Reference val, unsigned int tid, Op op)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
(void) smem;
|
||||
(void) tid;
|
||||
|
||||
Unroll<N / 2, Pointer, Reference, Op>::loopShfl(val, op, N);
|
||||
#else
|
||||
loadToSmem(smem, val, tid);
|
||||
|
||||
if (tid < N / 2)
|
||||
Unroll<N / 2, Pointer, Reference, Op>::loop(smem, val, tid, op);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int N> struct GenericOptimized32
|
||||
{
|
||||
enum { M = N / 32 };
|
||||
|
||||
template <typename Pointer, typename Reference, class Op>
|
||||
static __device__ void reduce(Pointer smem, Reference val, unsigned int tid, Op op)
|
||||
{
|
||||
const unsigned int laneId = Warp::laneId();
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
Unroll<16, Pointer, Reference, Op>::loopShfl(val, op, warpSize);
|
||||
|
||||
if (laneId == 0)
|
||||
loadToSmem(smem, val, tid / 32);
|
||||
#else
|
||||
loadToSmem(smem, val, tid);
|
||||
|
||||
if (laneId < 16)
|
||||
Unroll<16, Pointer, Reference, Op>::loop(smem, val, tid, op);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (laneId == 0)
|
||||
loadToSmem(smem, val, tid / 32);
|
||||
#endif
|
||||
|
||||
__syncthreads();
|
||||
|
||||
loadFromSmem(smem, val, tid);
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
Unroll<M / 2, Pointer, Reference, Op>::loopShfl(val, op, M);
|
||||
#else
|
||||
Unroll<M / 2, Pointer, Reference, Op>::loop(smem, val, tid, op);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <bool val, class T1, class T2> struct StaticIf;
|
||||
template <class T1, class T2> struct StaticIf<true, T1, T2>
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
template <class T1, class T2> struct StaticIf<false, T1, T2>
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
|
||||
template <unsigned int N> struct IsPowerOf2
|
||||
{
|
||||
enum { value = ((N != 0) && !(N & (N - 1))) };
|
||||
};
|
||||
|
||||
template <unsigned int N> struct Dispatcher
|
||||
{
|
||||
typedef typename StaticIf<
|
||||
(N <= 32) && IsPowerOf2<N>::value,
|
||||
WarpOptimized<N>,
|
||||
typename StaticIf<
|
||||
(N <= 1024) && IsPowerOf2<N>::value,
|
||||
GenericOptimized32<N>,
|
||||
Generic<N>
|
||||
>::type
|
||||
>::type reductor;
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif // __OPENCV_GPU_REDUCE_DETAIL_HPP__
|
||||
@@ -0,0 +1,498 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_PRED_VAL_REDUCE_DETAIL_HPP__
|
||||
#define __OPENCV_GPU_PRED_VAL_REDUCE_DETAIL_HPP__
|
||||
|
||||
#include <thrust/tuple.h>
|
||||
#include "../warp.hpp"
|
||||
#include "../warp_shuffle.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace reduce_key_val_detail
|
||||
{
|
||||
template <typename T> struct GetType;
|
||||
template <typename T> struct GetType<T*>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
template <typename T> struct GetType<volatile T*>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
template <typename T> struct GetType<T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <unsigned int I, unsigned int N>
|
||||
struct For
|
||||
{
|
||||
template <class PointerTuple, class ReferenceTuple>
|
||||
static __device__ void loadToSmem(const PointerTuple& smem, const ReferenceTuple& data, unsigned int tid)
|
||||
{
|
||||
thrust::get<I>(smem)[tid] = thrust::get<I>(data);
|
||||
|
||||
For<I + 1, N>::loadToSmem(smem, data, tid);
|
||||
}
|
||||
template <class PointerTuple, class ReferenceTuple>
|
||||
static __device__ void loadFromSmem(const PointerTuple& smem, const ReferenceTuple& data, unsigned int tid)
|
||||
{
|
||||
thrust::get<I>(data) = thrust::get<I>(smem)[tid];
|
||||
|
||||
For<I + 1, N>::loadFromSmem(smem, data, tid);
|
||||
}
|
||||
|
||||
template <class ReferenceTuple>
|
||||
static __device__ void copyShfl(const ReferenceTuple& val, unsigned int delta, int width)
|
||||
{
|
||||
thrust::get<I>(val) = shfl_down(thrust::get<I>(val), delta, width);
|
||||
|
||||
For<I + 1, N>::copyShfl(val, delta, width);
|
||||
}
|
||||
template <class PointerTuple, class ReferenceTuple>
|
||||
static __device__ void copy(const PointerTuple& svals, const ReferenceTuple& val, unsigned int tid, unsigned int delta)
|
||||
{
|
||||
thrust::get<I>(svals)[tid] = thrust::get<I>(val) = thrust::get<I>(svals)[tid + delta];
|
||||
|
||||
For<I + 1, N>::copy(svals, val, tid, delta);
|
||||
}
|
||||
|
||||
template <class KeyReferenceTuple, class ValReferenceTuple, class CmpTuple>
|
||||
static __device__ void mergeShfl(const KeyReferenceTuple& key, const ValReferenceTuple& val, const CmpTuple& cmp, unsigned int delta, int width)
|
||||
{
|
||||
typename GetType<typename thrust::tuple_element<I, KeyReferenceTuple>::type>::type reg = shfl_down(thrust::get<I>(key), delta, width);
|
||||
|
||||
if (thrust::get<I>(cmp)(reg, thrust::get<I>(key)))
|
||||
{
|
||||
thrust::get<I>(key) = reg;
|
||||
thrust::get<I>(val) = shfl_down(thrust::get<I>(val), delta, width);
|
||||
}
|
||||
|
||||
For<I + 1, N>::mergeShfl(key, val, cmp, delta, width);
|
||||
}
|
||||
template <class KeyPointerTuple, class KeyReferenceTuple, class ValPointerTuple, class ValReferenceTuple, class CmpTuple>
|
||||
static __device__ void merge(const KeyPointerTuple& skeys, const KeyReferenceTuple& key,
|
||||
const ValPointerTuple& svals, const ValReferenceTuple& val,
|
||||
const CmpTuple& cmp,
|
||||
unsigned int tid, unsigned int delta)
|
||||
{
|
||||
typename GetType<typename thrust::tuple_element<I, KeyPointerTuple>::type>::type reg = thrust::get<I>(skeys)[tid + delta];
|
||||
|
||||
if (thrust::get<I>(cmp)(reg, thrust::get<I>(key)))
|
||||
{
|
||||
thrust::get<I>(skeys)[tid] = thrust::get<I>(key) = reg;
|
||||
thrust::get<I>(svals)[tid] = thrust::get<I>(val) = thrust::get<I>(svals)[tid + delta];
|
||||
}
|
||||
|
||||
For<I + 1, N>::merge(skeys, key, svals, val, cmp, tid, delta);
|
||||
}
|
||||
};
|
||||
template <unsigned int N>
|
||||
struct For<N, N>
|
||||
{
|
||||
template <class PointerTuple, class ReferenceTuple>
|
||||
static __device__ void loadToSmem(const PointerTuple&, const ReferenceTuple&, unsigned int)
|
||||
{
|
||||
}
|
||||
template <class PointerTuple, class ReferenceTuple>
|
||||
static __device__ void loadFromSmem(const PointerTuple&, const ReferenceTuple&, unsigned int)
|
||||
{
|
||||
}
|
||||
|
||||
template <class ReferenceTuple>
|
||||
static __device__ void copyShfl(const ReferenceTuple&, unsigned int, int)
|
||||
{
|
||||
}
|
||||
template <class PointerTuple, class ReferenceTuple>
|
||||
static __device__ void copy(const PointerTuple&, const ReferenceTuple&, unsigned int, unsigned int)
|
||||
{
|
||||
}
|
||||
|
||||
template <class KeyReferenceTuple, class ValReferenceTuple, class CmpTuple>
|
||||
static __device__ void mergeShfl(const KeyReferenceTuple&, const ValReferenceTuple&, const CmpTuple&, unsigned int, int)
|
||||
{
|
||||
}
|
||||
template <class KeyPointerTuple, class KeyReferenceTuple, class ValPointerTuple, class ValReferenceTuple, class CmpTuple>
|
||||
static __device__ void merge(const KeyPointerTuple&, const KeyReferenceTuple&,
|
||||
const ValPointerTuple&, const ValReferenceTuple&,
|
||||
const CmpTuple&,
|
||||
unsigned int, unsigned int)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// loadToSmem
|
||||
|
||||
template <typename T>
|
||||
__device__ __forceinline__ void loadToSmem(volatile T* smem, T& data, unsigned int tid)
|
||||
{
|
||||
smem[tid] = data;
|
||||
}
|
||||
template <typename T>
|
||||
__device__ __forceinline__ void loadFromSmem(volatile T* smem, T& data, unsigned int tid)
|
||||
{
|
||||
data = smem[tid];
|
||||
}
|
||||
template <typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9>
|
||||
__device__ __forceinline__ void loadToSmem(const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& smem,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& data,
|
||||
unsigned int tid)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9> >::value>::loadToSmem(smem, data, tid);
|
||||
}
|
||||
template <typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9>
|
||||
__device__ __forceinline__ void loadFromSmem(const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& smem,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& data,
|
||||
unsigned int tid)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9> >::value>::loadFromSmem(smem, data, tid);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// copyVals
|
||||
|
||||
template <typename V>
|
||||
__device__ __forceinline__ void copyValsShfl(V& val, unsigned int delta, int width)
|
||||
{
|
||||
val = shfl_down(val, delta, width);
|
||||
}
|
||||
template <typename V>
|
||||
__device__ __forceinline__ void copyVals(volatile V* svals, V& val, unsigned int tid, unsigned int delta)
|
||||
{
|
||||
svals[tid] = val = svals[tid + delta];
|
||||
}
|
||||
template <typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9>
|
||||
__device__ __forceinline__ void copyValsShfl(const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
unsigned int delta,
|
||||
int width)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9> >::value>::copyShfl(val, delta, width);
|
||||
}
|
||||
template <typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9>
|
||||
__device__ __forceinline__ void copyVals(const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& svals,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
unsigned int tid, unsigned int delta)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9> >::value>::copy(svals, val, tid, delta);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// merge
|
||||
|
||||
template <typename K, typename V, class Cmp>
|
||||
__device__ __forceinline__ void mergeShfl(K& key, V& val, const Cmp& cmp, unsigned int delta, int width)
|
||||
{
|
||||
K reg = shfl_down(key, delta, width);
|
||||
|
||||
if (cmp(reg, key))
|
||||
{
|
||||
key = reg;
|
||||
copyValsShfl(val, delta, width);
|
||||
}
|
||||
}
|
||||
template <typename K, typename V, class Cmp>
|
||||
__device__ __forceinline__ void merge(volatile K* skeys, K& key, volatile V* svals, V& val, const Cmp& cmp, unsigned int tid, unsigned int delta)
|
||||
{
|
||||
K reg = skeys[tid + delta];
|
||||
|
||||
if (cmp(reg, key))
|
||||
{
|
||||
skeys[tid] = key = reg;
|
||||
copyVals(svals, val, tid, delta);
|
||||
}
|
||||
}
|
||||
template <typename K,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9,
|
||||
class Cmp>
|
||||
__device__ __forceinline__ void mergeShfl(K& key,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
const Cmp& cmp,
|
||||
unsigned int delta, int width)
|
||||
{
|
||||
K reg = shfl_down(key, delta, width);
|
||||
|
||||
if (cmp(reg, key))
|
||||
{
|
||||
key = reg;
|
||||
copyValsShfl(val, delta, width);
|
||||
}
|
||||
}
|
||||
template <typename K,
|
||||
typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9,
|
||||
class Cmp>
|
||||
__device__ __forceinline__ void merge(volatile K* skeys, K& key,
|
||||
const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& svals,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
const Cmp& cmp, unsigned int tid, unsigned int delta)
|
||||
{
|
||||
K reg = skeys[tid + delta];
|
||||
|
||||
if (cmp(reg, key))
|
||||
{
|
||||
skeys[tid] = key = reg;
|
||||
copyVals(svals, val, tid, delta);
|
||||
}
|
||||
}
|
||||
template <typename KR0, typename KR1, typename KR2, typename KR3, typename KR4, typename KR5, typename KR6, typename KR7, typename KR8, typename KR9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9,
|
||||
class Cmp0, class Cmp1, class Cmp2, class Cmp3, class Cmp4, class Cmp5, class Cmp6, class Cmp7, class Cmp8, class Cmp9>
|
||||
__device__ __forceinline__ void mergeShfl(const thrust::tuple<KR0, KR1, KR2, KR3, KR4, KR5, KR6, KR7, KR8, KR9>& key,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
const thrust::tuple<Cmp0, Cmp1, Cmp2, Cmp3, Cmp4, Cmp5, Cmp6, Cmp7, Cmp8, Cmp9>& cmp,
|
||||
unsigned int delta, int width)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<KR0, KR1, KR2, KR3, KR4, KR5, KR6, KR7, KR8, KR9> >::value>::mergeShfl(key, val, cmp, delta, width);
|
||||
}
|
||||
template <typename KP0, typename KP1, typename KP2, typename KP3, typename KP4, typename KP5, typename KP6, typename KP7, typename KP8, typename KP9,
|
||||
typename KR0, typename KR1, typename KR2, typename KR3, typename KR4, typename KR5, typename KR6, typename KR7, typename KR8, typename KR9,
|
||||
typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9,
|
||||
class Cmp0, class Cmp1, class Cmp2, class Cmp3, class Cmp4, class Cmp5, class Cmp6, class Cmp7, class Cmp8, class Cmp9>
|
||||
__device__ __forceinline__ void merge(const thrust::tuple<KP0, KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9>& skeys,
|
||||
const thrust::tuple<KR0, KR1, KR2, KR3, KR4, KR5, KR6, KR7, KR8, KR9>& key,
|
||||
const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& svals,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
const thrust::tuple<Cmp0, Cmp1, Cmp2, Cmp3, Cmp4, Cmp5, Cmp6, Cmp7, Cmp8, Cmp9>& cmp,
|
||||
unsigned int tid, unsigned int delta)
|
||||
{
|
||||
For<0, thrust::tuple_size<thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9> >::value>::merge(skeys, key, svals, val, cmp, tid, delta);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Generic
|
||||
|
||||
template <unsigned int N> struct Generic
|
||||
{
|
||||
template <class KP, class KR, class VP, class VR, class Cmp>
|
||||
static __device__ void reduce(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp)
|
||||
{
|
||||
loadToSmem(skeys, key, tid);
|
||||
loadValsToSmem(svals, val, tid);
|
||||
if (N >= 32)
|
||||
__syncthreads();
|
||||
|
||||
if (N >= 2048)
|
||||
{
|
||||
if (tid < 1024)
|
||||
merge(skeys, key, svals, val, cmp, tid, 1024);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 1024)
|
||||
{
|
||||
if (tid < 512)
|
||||
merge(skeys, key, svals, val, cmp, tid, 512);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 512)
|
||||
{
|
||||
if (tid < 256)
|
||||
merge(skeys, key, svals, val, cmp, tid, 256);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 256)
|
||||
{
|
||||
if (tid < 128)
|
||||
merge(skeys, key, svals, val, cmp, tid, 128);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 128)
|
||||
{
|
||||
if (tid < 64)
|
||||
merge(skeys, key, svals, val, cmp, tid, 64);
|
||||
|
||||
__syncthreads();
|
||||
}
|
||||
if (N >= 64)
|
||||
{
|
||||
if (tid < 32)
|
||||
merge(skeys, key, svals, val, cmp, tid, 32);
|
||||
}
|
||||
|
||||
if (tid < 16)
|
||||
{
|
||||
merge(skeys, key, svals, val, cmp, tid, 16);
|
||||
merge(skeys, key, svals, val, cmp, tid, 8);
|
||||
merge(skeys, key, svals, val, cmp, tid, 4);
|
||||
merge(skeys, key, svals, val, cmp, tid, 2);
|
||||
merge(skeys, key, svals, val, cmp, tid, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int I, class KP, class KR, class VP, class VR, class Cmp>
|
||||
struct Unroll
|
||||
{
|
||||
static __device__ void loopShfl(KR key, VR val, Cmp cmp, unsigned int N)
|
||||
{
|
||||
mergeShfl(key, val, cmp, I, N);
|
||||
Unroll<I / 2, KP, KR, VP, VR, Cmp>::loopShfl(key, val, cmp, N);
|
||||
}
|
||||
static __device__ void loop(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp)
|
||||
{
|
||||
merge(skeys, key, svals, val, cmp, tid, I);
|
||||
Unroll<I / 2, KP, KR, VP, VR, Cmp>::loop(skeys, key, svals, val, tid, cmp);
|
||||
}
|
||||
};
|
||||
template <class KP, class KR, class VP, class VR, class Cmp>
|
||||
struct Unroll<0, KP, KR, VP, VR, Cmp>
|
||||
{
|
||||
static __device__ void loopShfl(KR, VR, Cmp, unsigned int)
|
||||
{
|
||||
}
|
||||
static __device__ void loop(KP, KR, VP, VR, unsigned int, Cmp)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int N> struct WarpOptimized
|
||||
{
|
||||
template <class KP, class KR, class VP, class VR, class Cmp>
|
||||
static __device__ void reduce(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp)
|
||||
{
|
||||
#if 0 // __CUDA_ARCH__ >= 300
|
||||
(void) skeys;
|
||||
(void) svals;
|
||||
(void) tid;
|
||||
|
||||
Unroll<N / 2, KP, KR, VP, VR, Cmp>::loopShfl(key, val, cmp, N);
|
||||
#else
|
||||
loadToSmem(skeys, key, tid);
|
||||
loadToSmem(svals, val, tid);
|
||||
|
||||
if (tid < N / 2)
|
||||
Unroll<N / 2, KP, KR, VP, VR, Cmp>::loop(skeys, key, svals, val, tid, cmp);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int N> struct GenericOptimized32
|
||||
{
|
||||
enum { M = N / 32 };
|
||||
|
||||
template <class KP, class KR, class VP, class VR, class Cmp>
|
||||
static __device__ void reduce(KP skeys, KR key, VP svals, VR val, unsigned int tid, Cmp cmp)
|
||||
{
|
||||
const unsigned int laneId = Warp::laneId();
|
||||
|
||||
#if 0 // __CUDA_ARCH__ >= 300
|
||||
Unroll<16, KP, KR, VP, VR, Cmp>::loopShfl(key, val, cmp, warpSize);
|
||||
|
||||
if (laneId == 0)
|
||||
{
|
||||
loadToSmem(skeys, key, tid / 32);
|
||||
loadToSmem(svals, val, tid / 32);
|
||||
}
|
||||
#else
|
||||
loadToSmem(skeys, key, tid);
|
||||
loadToSmem(svals, val, tid);
|
||||
|
||||
if (laneId < 16)
|
||||
Unroll<16, KP, KR, VP, VR, Cmp>::loop(skeys, key, svals, val, tid, cmp);
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (laneId == 0)
|
||||
{
|
||||
loadToSmem(skeys, key, tid / 32);
|
||||
loadToSmem(svals, val, tid / 32);
|
||||
}
|
||||
#endif
|
||||
|
||||
__syncthreads();
|
||||
|
||||
loadFromSmem(skeys, key, tid);
|
||||
|
||||
if (tid < 32)
|
||||
{
|
||||
#if 0 // __CUDA_ARCH__ >= 300
|
||||
loadFromSmem(svals, val, tid);
|
||||
|
||||
Unroll<M / 2, KP, KR, VP, VR, Cmp>::loopShfl(key, val, cmp, M);
|
||||
#else
|
||||
Unroll<M / 2, KP, KR, VP, VR, Cmp>::loop(skeys, key, svals, val, tid, cmp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <bool val, class T1, class T2> struct StaticIf;
|
||||
template <class T1, class T2> struct StaticIf<true, T1, T2>
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
template <class T1, class T2> struct StaticIf<false, T1, T2>
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
|
||||
template <unsigned int N> struct IsPowerOf2
|
||||
{
|
||||
enum { value = ((N != 0) && !(N & (N - 1))) };
|
||||
};
|
||||
|
||||
template <unsigned int N> struct Dispatcher
|
||||
{
|
||||
typedef typename StaticIf<
|
||||
(N <= 32) && IsPowerOf2<N>::value,
|
||||
WarpOptimized<N>,
|
||||
typename StaticIf<
|
||||
(N <= 1024) && IsPowerOf2<N>::value,
|
||||
GenericOptimized32<N>,
|
||||
Generic<N>
|
||||
>::type
|
||||
>::type reductor;
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif // __OPENCV_GPU_PRED_VAL_REDUCE_DETAIL_HPP__
|
||||
@@ -0,0 +1,395 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_TRANSFORM_DETAIL_HPP__
|
||||
#define __OPENCV_GPU_TRANSFORM_DETAIL_HPP__
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../vec_traits.hpp"
|
||||
#include "../functional.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace transform_detail
|
||||
{
|
||||
//! Read Write Traits
|
||||
|
||||
template <typename T, typename D, int shift> struct UnaryReadWriteTraits
|
||||
{
|
||||
typedef typename TypeVec<T, shift>::vec_type read_type;
|
||||
typedef typename TypeVec<D, shift>::vec_type write_type;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename D, int shift> struct BinaryReadWriteTraits
|
||||
{
|
||||
typedef typename TypeVec<T1, shift>::vec_type read_type1;
|
||||
typedef typename TypeVec<T2, shift>::vec_type read_type2;
|
||||
typedef typename TypeVec<D, shift>::vec_type write_type;
|
||||
};
|
||||
|
||||
//! Transform kernels
|
||||
|
||||
template <int shift> struct OpUnroller;
|
||||
template <> struct OpUnroller<1>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, UnOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src.x);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, BinOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src1.x, src2.x);
|
||||
}
|
||||
};
|
||||
template <> struct OpUnroller<2>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, UnOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src.x);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.y = op(src.y);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, BinOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src1.x, src2.x);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.y = op(src1.y, src2.y);
|
||||
}
|
||||
};
|
||||
template <> struct OpUnroller<3>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, const UnOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src.x);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.y = op(src.y);
|
||||
if (mask(y, x_shifted + 2))
|
||||
dst.z = op(src.z);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, const BinOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src1.x, src2.x);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.y = op(src1.y, src2.y);
|
||||
if (mask(y, x_shifted + 2))
|
||||
dst.z = op(src1.z, src2.z);
|
||||
}
|
||||
};
|
||||
template <> struct OpUnroller<4>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, const UnOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src.x);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.y = op(src.y);
|
||||
if (mask(y, x_shifted + 2))
|
||||
dst.z = op(src.z);
|
||||
if (mask(y, x_shifted + 3))
|
||||
dst.w = op(src.w);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, const BinOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.x = op(src1.x, src2.x);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.y = op(src1.y, src2.y);
|
||||
if (mask(y, x_shifted + 2))
|
||||
dst.z = op(src1.z, src2.z);
|
||||
if (mask(y, x_shifted + 3))
|
||||
dst.w = op(src1.w, src2.w);
|
||||
}
|
||||
};
|
||||
template <> struct OpUnroller<8>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T& src, D& dst, const Mask& mask, const UnOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.a0 = op(src.a0);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.a1 = op(src.a1);
|
||||
if (mask(y, x_shifted + 2))
|
||||
dst.a2 = op(src.a2);
|
||||
if (mask(y, x_shifted + 3))
|
||||
dst.a3 = op(src.a3);
|
||||
if (mask(y, x_shifted + 4))
|
||||
dst.a4 = op(src.a4);
|
||||
if (mask(y, x_shifted + 5))
|
||||
dst.a5 = op(src.a5);
|
||||
if (mask(y, x_shifted + 6))
|
||||
dst.a6 = op(src.a6);
|
||||
if (mask(y, x_shifted + 7))
|
||||
dst.a7 = op(src.a7);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __device__ __forceinline__ void unroll(const T1& src1, const T2& src2, D& dst, const Mask& mask, const BinOp& op, int x_shifted, int y)
|
||||
{
|
||||
if (mask(y, x_shifted))
|
||||
dst.a0 = op(src1.a0, src2.a0);
|
||||
if (mask(y, x_shifted + 1))
|
||||
dst.a1 = op(src1.a1, src2.a1);
|
||||
if (mask(y, x_shifted + 2))
|
||||
dst.a2 = op(src1.a2, src2.a2);
|
||||
if (mask(y, x_shifted + 3))
|
||||
dst.a3 = op(src1.a3, src2.a3);
|
||||
if (mask(y, x_shifted + 4))
|
||||
dst.a4 = op(src1.a4, src2.a4);
|
||||
if (mask(y, x_shifted + 5))
|
||||
dst.a5 = op(src1.a5, src2.a5);
|
||||
if (mask(y, x_shifted + 6))
|
||||
dst.a6 = op(src1.a6, src2.a6);
|
||||
if (mask(y, x_shifted + 7))
|
||||
dst.a7 = op(src1.a7, src2.a7);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static __global__ void transformSmart(const PtrStepSz<T> src_, PtrStep<D> dst_, const Mask mask, const UnOp op)
|
||||
{
|
||||
typedef TransformFunctorTraits<UnOp> ft;
|
||||
typedef typename UnaryReadWriteTraits<T, D, ft::smart_shift>::read_type read_type;
|
||||
typedef typename UnaryReadWriteTraits<T, D, ft::smart_shift>::write_type write_type;
|
||||
|
||||
const int x = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
const int y = threadIdx.y + blockIdx.y * blockDim.y;
|
||||
const int x_shifted = x * ft::smart_shift;
|
||||
|
||||
if (y < src_.rows)
|
||||
{
|
||||
const T* src = src_.ptr(y);
|
||||
D* dst = dst_.ptr(y);
|
||||
|
||||
if (x_shifted + ft::smart_shift - 1 < src_.cols)
|
||||
{
|
||||
const read_type src_n_el = ((const read_type*)src)[x];
|
||||
write_type dst_n_el = ((const write_type*)dst)[x];
|
||||
|
||||
OpUnroller<ft::smart_shift>::unroll(src_n_el, dst_n_el, mask, op, x_shifted, y);
|
||||
|
||||
((write_type*)dst)[x] = dst_n_el;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int real_x = x_shifted; real_x < src_.cols; ++real_x)
|
||||
{
|
||||
if (mask(y, real_x))
|
||||
dst[real_x] = op(src[real_x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
__global__ static void transformSimple(const PtrStepSz<T> src, PtrStep<D> dst, const Mask mask, const UnOp op)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < src.cols && y < src.rows && mask(y, x))
|
||||
{
|
||||
dst.ptr(y)[x] = op(src.ptr(y)[x]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __global__ void transformSmart(const PtrStepSz<T1> src1_, const PtrStep<T2> src2_, PtrStep<D> dst_,
|
||||
const Mask mask, const BinOp op)
|
||||
{
|
||||
typedef TransformFunctorTraits<BinOp> ft;
|
||||
typedef typename BinaryReadWriteTraits<T1, T2, D, ft::smart_shift>::read_type1 read_type1;
|
||||
typedef typename BinaryReadWriteTraits<T1, T2, D, ft::smart_shift>::read_type2 read_type2;
|
||||
typedef typename BinaryReadWriteTraits<T1, T2, D, ft::smart_shift>::write_type write_type;
|
||||
|
||||
const int x = threadIdx.x + blockIdx.x * blockDim.x;
|
||||
const int y = threadIdx.y + blockIdx.y * blockDim.y;
|
||||
const int x_shifted = x * ft::smart_shift;
|
||||
|
||||
if (y < src1_.rows)
|
||||
{
|
||||
const T1* src1 = src1_.ptr(y);
|
||||
const T2* src2 = src2_.ptr(y);
|
||||
D* dst = dst_.ptr(y);
|
||||
|
||||
if (x_shifted + ft::smart_shift - 1 < src1_.cols)
|
||||
{
|
||||
const read_type1 src1_n_el = ((const read_type1*)src1)[x];
|
||||
const read_type2 src2_n_el = ((const read_type2*)src2)[x];
|
||||
write_type dst_n_el = ((const write_type*)dst)[x];
|
||||
|
||||
OpUnroller<ft::smart_shift>::unroll(src1_n_el, src2_n_el, dst_n_el, mask, op, x_shifted, y);
|
||||
|
||||
((write_type*)dst)[x] = dst_n_el;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int real_x = x_shifted; real_x < src1_.cols; ++real_x)
|
||||
{
|
||||
if (mask(y, real_x))
|
||||
dst[real_x] = op(src1[real_x], src2[real_x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static __global__ void transformSimple(const PtrStepSz<T1> src1, const PtrStep<T2> src2, PtrStep<D> dst,
|
||||
const Mask mask, const BinOp op)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < src1.cols && y < src1.rows && mask(y, x))
|
||||
{
|
||||
const T1 src1_data = src1.ptr(y)[x];
|
||||
const T2 src2_data = src2.ptr(y)[x];
|
||||
dst.ptr(y)[x] = op(src1_data, src2_data);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool UseSmart> struct TransformDispatcher;
|
||||
template<> struct TransformDispatcher<false>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<D> dst, UnOp op, Mask mask, cudaStream_t stream)
|
||||
{
|
||||
typedef TransformFunctorTraits<UnOp> ft;
|
||||
|
||||
const dim3 threads(ft::simple_block_dim_x, ft::simple_block_dim_y, 1);
|
||||
const dim3 grid(divUp(src.cols, threads.x), divUp(src.rows, threads.y), 1);
|
||||
|
||||
transformSimple<T, D><<<grid, threads, 0, stream>>>(src, dst, mask, op);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static void call(PtrStepSz<T1> src1, PtrStepSz<T2> src2, PtrStepSz<D> dst, BinOp op, Mask mask, cudaStream_t stream)
|
||||
{
|
||||
typedef TransformFunctorTraits<BinOp> ft;
|
||||
|
||||
const dim3 threads(ft::simple_block_dim_x, ft::simple_block_dim_y, 1);
|
||||
const dim3 grid(divUp(src1.cols, threads.x), divUp(src1.rows, threads.y), 1);
|
||||
|
||||
transformSimple<T1, T2, D><<<grid, threads, 0, stream>>>(src1, src2, dst, mask, op);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
template<> struct TransformDispatcher<true>
|
||||
{
|
||||
template <typename T, typename D, typename UnOp, typename Mask>
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<D> dst, UnOp op, Mask mask, cudaStream_t stream)
|
||||
{
|
||||
typedef TransformFunctorTraits<UnOp> ft;
|
||||
|
||||
StaticAssert<ft::smart_shift != 1>::check();
|
||||
|
||||
if (!isAligned(src.data, ft::smart_shift * sizeof(T)) || !isAligned(src.step, ft::smart_shift * sizeof(T)) ||
|
||||
!isAligned(dst.data, ft::smart_shift * sizeof(D)) || !isAligned(dst.step, ft::smart_shift * sizeof(D)))
|
||||
{
|
||||
TransformDispatcher<false>::call(src, dst, op, mask, stream);
|
||||
return;
|
||||
}
|
||||
|
||||
const dim3 threads(ft::smart_block_dim_x, ft::smart_block_dim_y, 1);
|
||||
const dim3 grid(divUp(src.cols, threads.x * ft::smart_shift), divUp(src.rows, threads.y), 1);
|
||||
|
||||
transformSmart<T, D><<<grid, threads, 0, stream>>>(src, dst, mask, op);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename D, typename BinOp, typename Mask>
|
||||
static void call(PtrStepSz<T1> src1, PtrStepSz<T2> src2, PtrStepSz<D> dst, BinOp op, Mask mask, cudaStream_t stream)
|
||||
{
|
||||
typedef TransformFunctorTraits<BinOp> ft;
|
||||
|
||||
StaticAssert<ft::smart_shift != 1>::check();
|
||||
|
||||
if (!isAligned(src1.data, ft::smart_shift * sizeof(T1)) || !isAligned(src1.step, ft::smart_shift * sizeof(T1)) ||
|
||||
!isAligned(src2.data, ft::smart_shift * sizeof(T2)) || !isAligned(src2.step, ft::smart_shift * sizeof(T2)) ||
|
||||
!isAligned(dst.data, ft::smart_shift * sizeof(D)) || !isAligned(dst.step, ft::smart_shift * sizeof(D)))
|
||||
{
|
||||
TransformDispatcher<false>::call(src1, src2, dst, op, mask, stream);
|
||||
return;
|
||||
}
|
||||
|
||||
const dim3 threads(ft::smart_block_dim_x, ft::smart_block_dim_y, 1);
|
||||
const dim3 grid(divUp(src1.cols, threads.x * ft::smart_shift), divUp(src1.rows, threads.y), 1);
|
||||
|
||||
transformSmart<T1, T2, D><<<grid, threads, 0, stream>>>(src1, src2, dst, mask, op);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
} // namespace transform_detail
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_TRANSFORM_DETAIL_HPP__
|
||||
@@ -0,0 +1,187 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_TYPE_TRAITS_DETAIL_HPP__
|
||||
#define __OPENCV_GPU_TYPE_TRAITS_DETAIL_HPP__
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../vec_traits.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace type_traits_detail
|
||||
{
|
||||
template <bool, typename T1, typename T2> struct Select { typedef T1 type; };
|
||||
template <typename T1, typename T2> struct Select<false, T1, T2> { typedef T2 type; };
|
||||
|
||||
template <typename T> struct IsSignedIntergral { enum {value = 0}; };
|
||||
template <> struct IsSignedIntergral<schar> { enum {value = 1}; };
|
||||
template <> struct IsSignedIntergral<char1> { enum {value = 1}; };
|
||||
template <> struct IsSignedIntergral<short> { enum {value = 1}; };
|
||||
template <> struct IsSignedIntergral<short1> { enum {value = 1}; };
|
||||
template <> struct IsSignedIntergral<int> { enum {value = 1}; };
|
||||
template <> struct IsSignedIntergral<int1> { enum {value = 1}; };
|
||||
|
||||
template <typename T> struct IsUnsignedIntegral { enum {value = 0}; };
|
||||
template <> struct IsUnsignedIntegral<uchar> { enum {value = 1}; };
|
||||
template <> struct IsUnsignedIntegral<uchar1> { enum {value = 1}; };
|
||||
template <> struct IsUnsignedIntegral<ushort> { enum {value = 1}; };
|
||||
template <> struct IsUnsignedIntegral<ushort1> { enum {value = 1}; };
|
||||
template <> struct IsUnsignedIntegral<uint> { enum {value = 1}; };
|
||||
template <> struct IsUnsignedIntegral<uint1> { enum {value = 1}; };
|
||||
|
||||
template <typename T> struct IsIntegral { enum {value = IsSignedIntergral<T>::value || IsUnsignedIntegral<T>::value}; };
|
||||
template <> struct IsIntegral<char> { enum {value = 1}; };
|
||||
template <> struct IsIntegral<bool> { enum {value = 1}; };
|
||||
|
||||
template <typename T> struct IsFloat { enum {value = 0}; };
|
||||
template <> struct IsFloat<float> { enum {value = 1}; };
|
||||
template <> struct IsFloat<double> { enum {value = 1}; };
|
||||
|
||||
template <typename T> struct IsVec { enum {value = 0}; };
|
||||
template <> struct IsVec<uchar1> { enum {value = 1}; };
|
||||
template <> struct IsVec<uchar2> { enum {value = 1}; };
|
||||
template <> struct IsVec<uchar3> { enum {value = 1}; };
|
||||
template <> struct IsVec<uchar4> { enum {value = 1}; };
|
||||
template <> struct IsVec<uchar8> { enum {value = 1}; };
|
||||
template <> struct IsVec<char1> { enum {value = 1}; };
|
||||
template <> struct IsVec<char2> { enum {value = 1}; };
|
||||
template <> struct IsVec<char3> { enum {value = 1}; };
|
||||
template <> struct IsVec<char4> { enum {value = 1}; };
|
||||
template <> struct IsVec<char8> { enum {value = 1}; };
|
||||
template <> struct IsVec<ushort1> { enum {value = 1}; };
|
||||
template <> struct IsVec<ushort2> { enum {value = 1}; };
|
||||
template <> struct IsVec<ushort3> { enum {value = 1}; };
|
||||
template <> struct IsVec<ushort4> { enum {value = 1}; };
|
||||
template <> struct IsVec<ushort8> { enum {value = 1}; };
|
||||
template <> struct IsVec<short1> { enum {value = 1}; };
|
||||
template <> struct IsVec<short2> { enum {value = 1}; };
|
||||
template <> struct IsVec<short3> { enum {value = 1}; };
|
||||
template <> struct IsVec<short4> { enum {value = 1}; };
|
||||
template <> struct IsVec<short8> { enum {value = 1}; };
|
||||
template <> struct IsVec<uint1> { enum {value = 1}; };
|
||||
template <> struct IsVec<uint2> { enum {value = 1}; };
|
||||
template <> struct IsVec<uint3> { enum {value = 1}; };
|
||||
template <> struct IsVec<uint4> { enum {value = 1}; };
|
||||
template <> struct IsVec<uint8> { enum {value = 1}; };
|
||||
template <> struct IsVec<int1> { enum {value = 1}; };
|
||||
template <> struct IsVec<int2> { enum {value = 1}; };
|
||||
template <> struct IsVec<int3> { enum {value = 1}; };
|
||||
template <> struct IsVec<int4> { enum {value = 1}; };
|
||||
template <> struct IsVec<int8> { enum {value = 1}; };
|
||||
template <> struct IsVec<float1> { enum {value = 1}; };
|
||||
template <> struct IsVec<float2> { enum {value = 1}; };
|
||||
template <> struct IsVec<float3> { enum {value = 1}; };
|
||||
template <> struct IsVec<float4> { enum {value = 1}; };
|
||||
template <> struct IsVec<float8> { enum {value = 1}; };
|
||||
template <> struct IsVec<double1> { enum {value = 1}; };
|
||||
template <> struct IsVec<double2> { enum {value = 1}; };
|
||||
template <> struct IsVec<double3> { enum {value = 1}; };
|
||||
template <> struct IsVec<double4> { enum {value = 1}; };
|
||||
template <> struct IsVec<double8> { enum {value = 1}; };
|
||||
|
||||
template <class U> struct AddParameterType { typedef const U& type; };
|
||||
template <class U> struct AddParameterType<U&> { typedef U& type; };
|
||||
template <> struct AddParameterType<void> { typedef void type; };
|
||||
|
||||
template <class U> struct ReferenceTraits
|
||||
{
|
||||
enum { value = false };
|
||||
typedef U type;
|
||||
};
|
||||
template <class U> struct ReferenceTraits<U&>
|
||||
{
|
||||
enum { value = true };
|
||||
typedef U type;
|
||||
};
|
||||
|
||||
template <class U> struct PointerTraits
|
||||
{
|
||||
enum { value = false };
|
||||
typedef void type;
|
||||
};
|
||||
template <class U> struct PointerTraits<U*>
|
||||
{
|
||||
enum { value = true };
|
||||
typedef U type;
|
||||
};
|
||||
template <class U> struct PointerTraits<U*&>
|
||||
{
|
||||
enum { value = true };
|
||||
typedef U type;
|
||||
};
|
||||
|
||||
template <class U> struct UnConst
|
||||
{
|
||||
typedef U type;
|
||||
enum { value = 0 };
|
||||
};
|
||||
template <class U> struct UnConst<const U>
|
||||
{
|
||||
typedef U type;
|
||||
enum { value = 1 };
|
||||
};
|
||||
template <class U> struct UnConst<const U&>
|
||||
{
|
||||
typedef U& type;
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
template <class U> struct UnVolatile
|
||||
{
|
||||
typedef U type;
|
||||
enum { value = 0 };
|
||||
};
|
||||
template <class U> struct UnVolatile<volatile U>
|
||||
{
|
||||
typedef U type;
|
||||
enum { value = 1 };
|
||||
};
|
||||
template <class U> struct UnVolatile<volatile U&>
|
||||
{
|
||||
typedef U& type;
|
||||
enum { value = 1 };
|
||||
};
|
||||
} // namespace type_traits_detail
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_TYPE_TRAITS_DETAIL_HPP__
|
||||
@@ -0,0 +1,117 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_VEC_DISTANCE_DETAIL_HPP__
|
||||
#define __OPENCV_GPU_VEC_DISTANCE_DETAIL_HPP__
|
||||
|
||||
#include "../datamov_utils.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
namespace vec_distance_detail
|
||||
{
|
||||
template <int THREAD_DIM, int N> struct UnrollVecDiffCached
|
||||
{
|
||||
template <typename Dist, typename T1, typename T2>
|
||||
static __device__ void calcCheck(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, int ind)
|
||||
{
|
||||
if (ind < len)
|
||||
{
|
||||
T1 val1 = *vecCached++;
|
||||
|
||||
T2 val2;
|
||||
ForceGlob<T2>::Load(vecGlob, ind, val2);
|
||||
|
||||
dist.reduceIter(val1, val2);
|
||||
|
||||
UnrollVecDiffCached<THREAD_DIM, N - 1>::calcCheck(vecCached, vecGlob, len, dist, ind + THREAD_DIM);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Dist, typename T1, typename T2>
|
||||
static __device__ void calcWithoutCheck(const T1* vecCached, const T2* vecGlob, Dist& dist)
|
||||
{
|
||||
T1 val1 = *vecCached++;
|
||||
|
||||
T2 val2;
|
||||
ForceGlob<T2>::Load(vecGlob, 0, val2);
|
||||
vecGlob += THREAD_DIM;
|
||||
|
||||
dist.reduceIter(val1, val2);
|
||||
|
||||
UnrollVecDiffCached<THREAD_DIM, N - 1>::calcWithoutCheck(vecCached, vecGlob, dist);
|
||||
}
|
||||
};
|
||||
template <int THREAD_DIM> struct UnrollVecDiffCached<THREAD_DIM, 0>
|
||||
{
|
||||
template <typename Dist, typename T1, typename T2>
|
||||
static __device__ __forceinline__ void calcCheck(const T1*, const T2*, int, Dist&, int)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Dist, typename T1, typename T2>
|
||||
static __device__ __forceinline__ void calcWithoutCheck(const T1*, const T2*, Dist&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <int THREAD_DIM, int MAX_LEN, bool LEN_EQ_MAX_LEN> struct VecDiffCachedCalculator;
|
||||
template <int THREAD_DIM, int MAX_LEN> struct VecDiffCachedCalculator<THREAD_DIM, MAX_LEN, false>
|
||||
{
|
||||
template <typename Dist, typename T1, typename T2>
|
||||
static __device__ __forceinline__ void calc(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, int tid)
|
||||
{
|
||||
UnrollVecDiffCached<THREAD_DIM, MAX_LEN / THREAD_DIM>::calcCheck(vecCached, vecGlob, len, dist, tid);
|
||||
}
|
||||
};
|
||||
template <int THREAD_DIM, int MAX_LEN> struct VecDiffCachedCalculator<THREAD_DIM, MAX_LEN, true>
|
||||
{
|
||||
template <typename Dist, typename T1, typename T2>
|
||||
static __device__ __forceinline__ void calc(const T1* vecCached, const T2* vecGlob, int len, Dist& dist, int tid)
|
||||
{
|
||||
UnrollVecDiffCached<THREAD_DIM, MAX_LEN / THREAD_DIM>::calcWithoutCheck(vecCached, vecGlob + tid, dist);
|
||||
}
|
||||
};
|
||||
} // namespace vec_distance_detail
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_VEC_DISTANCE_DETAIL_HPP__
|
||||
@@ -0,0 +1,80 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_DYNAMIC_SMEM_HPP__
|
||||
#define __OPENCV_GPU_DYNAMIC_SMEM_HPP__
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
template<class T> struct DynamicSharedMem
|
||||
{
|
||||
__device__ __forceinline__ operator T*()
|
||||
{
|
||||
extern __shared__ int __smem[];
|
||||
return (T*)__smem;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ operator const T*() const
|
||||
{
|
||||
extern __shared__ int __smem[];
|
||||
return (T*)__smem;
|
||||
}
|
||||
};
|
||||
|
||||
// specialize for double to avoid unaligned memory access compile errors
|
||||
template<> struct DynamicSharedMem<double>
|
||||
{
|
||||
__device__ __forceinline__ operator double*()
|
||||
{
|
||||
extern __shared__ double __smem_d[];
|
||||
return (double*)__smem_d;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ operator const double*() const
|
||||
{
|
||||
extern __shared__ double __smem_d[];
|
||||
return (double*)__smem_d;
|
||||
}
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif // __OPENCV_GPU_DYNAMIC_SMEM_HPP__
|
||||
@@ -0,0 +1,138 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_GPU_EMULATION_HPP_
|
||||
#define OPENCV_GPU_EMULATION_HPP_
|
||||
|
||||
#include "warp_reduce.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
struct Emulation
|
||||
{
|
||||
|
||||
static __device__ __forceinline__ int syncthreadsOr(int pred)
|
||||
{
|
||||
#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 200)
|
||||
// just campilation stab
|
||||
return 0;
|
||||
#else
|
||||
return __syncthreads_or(pred);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<int CTA_SIZE>
|
||||
static __forceinline__ __device__ int Ballot(int predicate)
|
||||
{
|
||||
#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ >= 200)
|
||||
return __ballot(predicate);
|
||||
#else
|
||||
__shared__ volatile int cta_buffer[CTA_SIZE];
|
||||
|
||||
int tid = threadIdx.x;
|
||||
cta_buffer[tid] = predicate ? (1 << (tid & 31)) : 0;
|
||||
return warp_reduce(cta_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct smem
|
||||
{
|
||||
enum { TAG_MASK = (1U << ( (sizeof(unsigned int) << 3) - 5U)) - 1U };
|
||||
|
||||
template<typename T>
|
||||
static __device__ __forceinline__ T atomicInc(T* address, T val)
|
||||
{
|
||||
#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120)
|
||||
T count;
|
||||
unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U);
|
||||
do
|
||||
{
|
||||
count = *address & TAG_MASK;
|
||||
count = tag | (count + 1);
|
||||
*address = count;
|
||||
} while (*address != count);
|
||||
|
||||
return (count & TAG_MASK) - 1;
|
||||
#else
|
||||
return ::atomicInc(address, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static __device__ __forceinline__ T atomicAdd(T* address, T val)
|
||||
{
|
||||
#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120)
|
||||
T count;
|
||||
unsigned int tag = threadIdx.x << ( (sizeof(unsigned int) << 3) - 5U);
|
||||
do
|
||||
{
|
||||
count = *address & TAG_MASK;
|
||||
count = tag | (count + val);
|
||||
*address = count;
|
||||
} while (*address != count);
|
||||
|
||||
return (count & TAG_MASK) - val;
|
||||
#else
|
||||
return ::atomicAdd(address, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static __device__ __forceinline__ T atomicMin(T* address, T val)
|
||||
{
|
||||
#if defined (__CUDA_ARCH__) && (__CUDA_ARCH__ < 120)
|
||||
T count = ::min(*address, val);
|
||||
do
|
||||
{
|
||||
*address = count;
|
||||
} while (*address > count);
|
||||
|
||||
return count;
|
||||
#else
|
||||
return ::atomicMin(address, val);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
};
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif /* OPENCV_GPU_EMULATION_HPP_ */
|
||||
@@ -0,0 +1,278 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_FILTERS_HPP__
|
||||
#define __OPENCV_GPU_FILTERS_HPP__
|
||||
|
||||
#include "saturate_cast.hpp"
|
||||
#include "vec_traits.hpp"
|
||||
#include "vec_math.hpp"
|
||||
#include "type_traits.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
template <typename Ptr2D> struct PointFilter
|
||||
{
|
||||
typedef typename Ptr2D::elem_type elem_type;
|
||||
typedef float index_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ PointFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)
|
||||
: src(src_)
|
||||
{
|
||||
(void)fx;
|
||||
(void)fy;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ elem_type operator ()(float y, float x) const
|
||||
{
|
||||
return src(__float2int_rz(y), __float2int_rz(x));
|
||||
}
|
||||
|
||||
const Ptr2D src;
|
||||
};
|
||||
|
||||
template <typename Ptr2D> struct LinearFilter
|
||||
{
|
||||
typedef typename Ptr2D::elem_type elem_type;
|
||||
typedef float index_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ LinearFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)
|
||||
: src(src_)
|
||||
{
|
||||
(void)fx;
|
||||
(void)fy;
|
||||
}
|
||||
__device__ __forceinline__ elem_type operator ()(float y, float x) const
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
|
||||
|
||||
work_type out = VecTraits<work_type>::all(0);
|
||||
|
||||
const int x1 = __float2int_rd(x);
|
||||
const int y1 = __float2int_rd(y);
|
||||
const int x2 = x1 + 1;
|
||||
const int y2 = y1 + 1;
|
||||
|
||||
elem_type src_reg = src(y1, x1);
|
||||
out = out + src_reg * ((x2 - x) * (y2 - y));
|
||||
|
||||
src_reg = src(y1, x2);
|
||||
out = out + src_reg * ((x - x1) * (y2 - y));
|
||||
|
||||
src_reg = src(y2, x1);
|
||||
out = out + src_reg * ((x2 - x) * (y - y1));
|
||||
|
||||
src_reg = src(y2, x2);
|
||||
out = out + src_reg * ((x - x1) * (y - y1));
|
||||
|
||||
return saturate_cast<elem_type>(out);
|
||||
}
|
||||
|
||||
const Ptr2D src;
|
||||
};
|
||||
|
||||
template <typename Ptr2D> struct CubicFilter
|
||||
{
|
||||
typedef typename Ptr2D::elem_type elem_type;
|
||||
typedef float index_type;
|
||||
typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ CubicFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)
|
||||
: src(src_)
|
||||
{
|
||||
(void)fx;
|
||||
(void)fy;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ float bicubicCoeff(float x_)
|
||||
{
|
||||
float x = fabsf(x_);
|
||||
if (x <= 1.0f)
|
||||
{
|
||||
return x * x * (1.5f * x - 2.5f) + 1.0f;
|
||||
}
|
||||
else if (x < 2.0f)
|
||||
{
|
||||
return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
__device__ elem_type operator ()(float y, float x) const
|
||||
{
|
||||
const float xmin = ::ceilf(x - 2.0f);
|
||||
const float xmax = ::floorf(x + 2.0f);
|
||||
|
||||
const float ymin = ::ceilf(y - 2.0f);
|
||||
const float ymax = ::floorf(y + 2.0f);
|
||||
|
||||
work_type sum = VecTraits<work_type>::all(0);
|
||||
float wsum = 0.0f;
|
||||
|
||||
for (float cy = ymin; cy <= ymax; cy += 1.0f)
|
||||
{
|
||||
for (float cx = xmin; cx <= xmax; cx += 1.0f)
|
||||
{
|
||||
const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy);
|
||||
sum = sum + w * src(__float2int_rd(cy), __float2int_rd(cx));
|
||||
wsum += w;
|
||||
}
|
||||
}
|
||||
|
||||
work_type res = (!wsum)? VecTraits<work_type>::all(0) : sum / wsum;
|
||||
|
||||
return saturate_cast<elem_type>(res);
|
||||
}
|
||||
|
||||
const Ptr2D src;
|
||||
};
|
||||
// for integer scaling
|
||||
template <typename Ptr2D> struct IntegerAreaFilter
|
||||
{
|
||||
typedef typename Ptr2D::elem_type elem_type;
|
||||
typedef float index_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ IntegerAreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_)
|
||||
: src(src_), scale_x(scale_x_), scale_y(scale_y_), scale(1.f / (scale_x * scale_y)) {}
|
||||
|
||||
__device__ __forceinline__ elem_type operator ()(float y, float x) const
|
||||
{
|
||||
float fsx1 = x * scale_x;
|
||||
float fsx2 = fsx1 + scale_x;
|
||||
|
||||
int sx1 = __float2int_ru(fsx1);
|
||||
int sx2 = __float2int_rd(fsx2);
|
||||
|
||||
float fsy1 = y * scale_y;
|
||||
float fsy2 = fsy1 + scale_y;
|
||||
|
||||
int sy1 = __float2int_ru(fsy1);
|
||||
int sy2 = __float2int_rd(fsy2);
|
||||
|
||||
typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
|
||||
work_type out = VecTraits<work_type>::all(0.f);
|
||||
|
||||
for(int dy = sy1; dy < sy2; ++dy)
|
||||
for(int dx = sx1; dx < sx2; ++dx)
|
||||
{
|
||||
out = out + src(dy, dx) * scale;
|
||||
}
|
||||
|
||||
return saturate_cast<elem_type>(out);
|
||||
}
|
||||
|
||||
const Ptr2D src;
|
||||
float scale_x, scale_y ,scale;
|
||||
};
|
||||
|
||||
template <typename Ptr2D> struct AreaFilter
|
||||
{
|
||||
typedef typename Ptr2D::elem_type elem_type;
|
||||
typedef float index_type;
|
||||
|
||||
explicit __host__ __device__ __forceinline__ AreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_)
|
||||
: src(src_), scale_x(scale_x_), scale_y(scale_y_){}
|
||||
|
||||
__device__ __forceinline__ elem_type operator ()(float y, float x) const
|
||||
{
|
||||
float fsx1 = x * scale_x;
|
||||
float fsx2 = fsx1 + scale_x;
|
||||
|
||||
int sx1 = __float2int_ru(fsx1);
|
||||
int sx2 = __float2int_rd(fsx2);
|
||||
|
||||
float fsy1 = y * scale_y;
|
||||
float fsy2 = fsy1 + scale_y;
|
||||
|
||||
int sy1 = __float2int_ru(fsy1);
|
||||
int sy2 = __float2int_rd(fsy2);
|
||||
|
||||
float scale = 1.f / (fminf(scale_x, src.width - fsx1) * fminf(scale_y, src.height - fsy1));
|
||||
|
||||
typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
|
||||
work_type out = VecTraits<work_type>::all(0.f);
|
||||
|
||||
for (int dy = sy1; dy < sy2; ++dy)
|
||||
{
|
||||
for (int dx = sx1; dx < sx2; ++dx)
|
||||
out = out + src(dy, dx) * scale;
|
||||
|
||||
if (sx1 > fsx1)
|
||||
out = out + src(dy, (sx1 -1) ) * ((sx1 - fsx1) * scale);
|
||||
|
||||
if (sx2 < fsx2)
|
||||
out = out + src(dy, sx2) * ((fsx2 -sx2) * scale);
|
||||
}
|
||||
|
||||
if (sy1 > fsy1)
|
||||
for (int dx = sx1; dx < sx2; ++dx)
|
||||
out = out + src( (sy1 - 1) , dx) * ((sy1 -fsy1) * scale);
|
||||
|
||||
if (sy2 < fsy2)
|
||||
for (int dx = sx1; dx < sx2; ++dx)
|
||||
out = out + src(sy2, dx) * ((fsy2 -sy2) * scale);
|
||||
|
||||
if ((sy1 > fsy1) && (sx1 > fsx1))
|
||||
out = out + src( (sy1 - 1) , (sx1 - 1)) * ((sy1 -fsy1) * (sx1 -fsx1) * scale);
|
||||
|
||||
if ((sy1 > fsy1) && (sx2 < fsx2))
|
||||
out = out + src( (sy1 - 1) , sx2) * ((sy1 -fsy1) * (fsx2 -sx2) * scale);
|
||||
|
||||
if ((sy2 < fsy2) && (sx2 < fsx2))
|
||||
out = out + src(sy2, sx2) * ((fsy2 -sy2) * (fsx2 -sx2) * scale);
|
||||
|
||||
if ((sy2 < fsy2) && (sx1 > fsx1))
|
||||
out = out + src(sy2, (sx1 - 1)) * ((fsy2 -sy2) * (sx1 -fsx1) * scale);
|
||||
|
||||
return saturate_cast<elem_type>(out);
|
||||
}
|
||||
|
||||
const Ptr2D src;
|
||||
float scale_x, scale_y;
|
||||
int width, haight;
|
||||
};
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_FILTERS_HPP__
|
||||
@@ -0,0 +1,71 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_
|
||||
#define __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
template<class Func>
|
||||
void printFuncAttrib(Func& func)
|
||||
{
|
||||
|
||||
cudaFuncAttributes attrs;
|
||||
cudaFuncGetAttributes(&attrs, func);
|
||||
|
||||
printf("=== Function stats ===\n");
|
||||
printf("Name: \n");
|
||||
printf("sharedSizeBytes = %d\n", attrs.sharedSizeBytes);
|
||||
printf("constSizeBytes = %d\n", attrs.constSizeBytes);
|
||||
printf("localSizeBytes = %d\n", attrs.localSizeBytes);
|
||||
printf("maxThreadsPerBlock = %d\n", attrs.maxThreadsPerBlock);
|
||||
printf("numRegs = %d\n", attrs.numRegs);
|
||||
printf("ptxVersion = %d\n", attrs.ptxVersion);
|
||||
printf("binaryVersion = %d\n", attrs.binaryVersion);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif /* __OPENCV_GPU_DEVICE_FUNCATTRIB_HPP_ */
|
||||
@@ -0,0 +1,789 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_FUNCTIONAL_HPP__
|
||||
#define __OPENCV_GPU_FUNCTIONAL_HPP__
|
||||
|
||||
#include <functional>
|
||||
#include "saturate_cast.hpp"
|
||||
#include "vec_traits.hpp"
|
||||
#include "type_traits.hpp"
|
||||
#include "device_functions.h"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
// Function Objects
|
||||
template<typename Argument, typename Result> struct unary_function : public std::unary_function<Argument, Result> {};
|
||||
template<typename Argument1, typename Argument2, typename Result> struct binary_function : public std::binary_function<Argument1, Argument2, Result> {};
|
||||
|
||||
// Arithmetic Operations
|
||||
template <typename T> struct plus : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ plus() {}
|
||||
__host__ __device__ __forceinline__ plus(const plus&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct minus : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a - b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ minus() {}
|
||||
__host__ __device__ __forceinline__ minus(const minus&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct multiplies : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a * b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ multiplies() {}
|
||||
__host__ __device__ __forceinline__ multiplies(const multiplies&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct divides : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a / b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ divides() {}
|
||||
__host__ __device__ __forceinline__ divides(const divides&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct modulus : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a % b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ modulus() {}
|
||||
__host__ __device__ __forceinline__ modulus(const modulus&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct negate : unary_function<T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a) const
|
||||
{
|
||||
return -a;
|
||||
}
|
||||
__host__ __device__ __forceinline__ negate() {}
|
||||
__host__ __device__ __forceinline__ negate(const negate&) {}
|
||||
};
|
||||
|
||||
// Comparison Operations
|
||||
template <typename T> struct equal_to : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ equal_to() {}
|
||||
__host__ __device__ __forceinline__ equal_to(const equal_to&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct not_equal_to : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a != b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ not_equal_to() {}
|
||||
__host__ __device__ __forceinline__ not_equal_to(const not_equal_to&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct greater : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a > b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ greater() {}
|
||||
__host__ __device__ __forceinline__ greater(const greater&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct less : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ less() {}
|
||||
__host__ __device__ __forceinline__ less(const less&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct greater_equal : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a >= b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ greater_equal() {}
|
||||
__host__ __device__ __forceinline__ greater_equal(const greater_equal&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct less_equal : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a <= b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ less_equal() {}
|
||||
__host__ __device__ __forceinline__ less_equal(const less_equal&) {}
|
||||
};
|
||||
|
||||
// Logical Operations
|
||||
template <typename T> struct logical_and : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a && b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ logical_and() {}
|
||||
__host__ __device__ __forceinline__ logical_and(const logical_and&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct logical_or : binary_function<T, T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a || b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ logical_or() {}
|
||||
__host__ __device__ __forceinline__ logical_or(const logical_or&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct logical_not : unary_function<T, bool>
|
||||
{
|
||||
__device__ __forceinline__ bool operator ()(typename TypeTraits<T>::ParameterType a) const
|
||||
{
|
||||
return !a;
|
||||
}
|
||||
__host__ __device__ __forceinline__ logical_not() {}
|
||||
__host__ __device__ __forceinline__ logical_not(const logical_not&) {}
|
||||
};
|
||||
|
||||
// Bitwise Operations
|
||||
template <typename T> struct bit_and : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a & b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ bit_and() {}
|
||||
__host__ __device__ __forceinline__ bit_and(const bit_and&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct bit_or : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a | b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ bit_or() {}
|
||||
__host__ __device__ __forceinline__ bit_or(const bit_or&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct bit_xor : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType a,
|
||||
typename TypeTraits<T>::ParameterType b) const
|
||||
{
|
||||
return a ^ b;
|
||||
}
|
||||
__host__ __device__ __forceinline__ bit_xor() {}
|
||||
__host__ __device__ __forceinline__ bit_xor(const bit_xor&) {}
|
||||
};
|
||||
|
||||
template <typename T> struct bit_not : unary_function<T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType v) const
|
||||
{
|
||||
return ~v;
|
||||
}
|
||||
__host__ __device__ __forceinline__ bit_not() {}
|
||||
__host__ __device__ __forceinline__ bit_not(const bit_not&) {}
|
||||
};
|
||||
|
||||
// Generalized Identity Operations
|
||||
template <typename T> struct identity : unary_function<T, T>
|
||||
{
|
||||
__device__ __forceinline__ typename TypeTraits<T>::ParameterType operator()(typename TypeTraits<T>::ParameterType x) const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
__host__ __device__ __forceinline__ identity() {}
|
||||
__host__ __device__ __forceinline__ identity(const identity&) {}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2> struct project1st : binary_function<T1, T2, T1>
|
||||
{
|
||||
__device__ __forceinline__ typename TypeTraits<T1>::ParameterType operator()(typename TypeTraits<T1>::ParameterType lhs, typename TypeTraits<T2>::ParameterType rhs) const
|
||||
{
|
||||
return lhs;
|
||||
}
|
||||
__host__ __device__ __forceinline__ project1st() {}
|
||||
__host__ __device__ __forceinline__ project1st(const project1st&) {}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2> struct project2nd : binary_function<T1, T2, T2>
|
||||
{
|
||||
__device__ __forceinline__ typename TypeTraits<T2>::ParameterType operator()(typename TypeTraits<T1>::ParameterType lhs, typename TypeTraits<T2>::ParameterType rhs) const
|
||||
{
|
||||
return rhs;
|
||||
}
|
||||
__host__ __device__ __forceinline__ project2nd() {}
|
||||
__host__ __device__ __forceinline__ project2nd(const project2nd&) {}
|
||||
};
|
||||
|
||||
// Min/Max Operations
|
||||
|
||||
#define OPENCV_GPU_IMPLEMENT_MINMAX(name, type, op) \
|
||||
template <> struct name<type> : binary_function<type, type, type> \
|
||||
{ \
|
||||
__device__ __forceinline__ type operator()(type lhs, type rhs) const {return op(lhs, rhs);} \
|
||||
__host__ __device__ __forceinline__ name() {}\
|
||||
__host__ __device__ __forceinline__ name(const name&) {}\
|
||||
};
|
||||
|
||||
template <typename T> struct maximum : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType lhs, typename TypeTraits<T>::ParameterType rhs) const
|
||||
{
|
||||
return max(lhs, rhs);
|
||||
}
|
||||
__host__ __device__ __forceinline__ maximum() {}
|
||||
__host__ __device__ __forceinline__ maximum(const maximum&) {}
|
||||
};
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, uchar, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, schar, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, char, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, ushort, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, short, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, int, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, uint, ::max)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, float, ::fmax)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(maximum, double, ::fmax)
|
||||
|
||||
template <typename T> struct minimum : binary_function<T, T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType lhs, typename TypeTraits<T>::ParameterType rhs) const
|
||||
{
|
||||
return min(lhs, rhs);
|
||||
}
|
||||
__host__ __device__ __forceinline__ minimum() {}
|
||||
__host__ __device__ __forceinline__ minimum(const minimum&) {}
|
||||
};
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, uchar, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, schar, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, char, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, ushort, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, short, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, int, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, uint, ::min)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, float, ::fmin)
|
||||
OPENCV_GPU_IMPLEMENT_MINMAX(minimum, double, ::fmin)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_MINMAX
|
||||
|
||||
// Math functions
|
||||
|
||||
template <typename T> struct abs_func : unary_function<T, T>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType x) const
|
||||
{
|
||||
return abs(x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<unsigned char> : unary_function<unsigned char, unsigned char>
|
||||
{
|
||||
__device__ __forceinline__ unsigned char operator ()(unsigned char x) const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<signed char> : unary_function<signed char, signed char>
|
||||
{
|
||||
__device__ __forceinline__ signed char operator ()(signed char x) const
|
||||
{
|
||||
return ::abs((int)x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<char> : unary_function<char, char>
|
||||
{
|
||||
__device__ __forceinline__ char operator ()(char x) const
|
||||
{
|
||||
return ::abs((int)x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<unsigned short> : unary_function<unsigned short, unsigned short>
|
||||
{
|
||||
__device__ __forceinline__ unsigned short operator ()(unsigned short x) const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<short> : unary_function<short, short>
|
||||
{
|
||||
__device__ __forceinline__ short operator ()(short x) const
|
||||
{
|
||||
return ::abs((int)x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<unsigned int> : unary_function<unsigned int, unsigned int>
|
||||
{
|
||||
__device__ __forceinline__ unsigned int operator ()(unsigned int x) const
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<int> : unary_function<int, int>
|
||||
{
|
||||
__device__ __forceinline__ int operator ()(int x) const
|
||||
{
|
||||
return ::abs(x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<float> : unary_function<float, float>
|
||||
{
|
||||
__device__ __forceinline__ float operator ()(float x) const
|
||||
{
|
||||
return ::fabsf(x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
template <> struct abs_func<double> : unary_function<double, double>
|
||||
{
|
||||
__device__ __forceinline__ double operator ()(double x) const
|
||||
{
|
||||
return ::fabs(x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ abs_func() {}
|
||||
__host__ __device__ __forceinline__ abs_func(const abs_func&) {}
|
||||
};
|
||||
|
||||
#define OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(name, func) \
|
||||
template <typename T> struct name ## _func : unary_function<T, float> \
|
||||
{ \
|
||||
__device__ __forceinline__ float operator ()(typename TypeTraits<T>::ParameterType v) const \
|
||||
{ \
|
||||
return func ## f(v); \
|
||||
} \
|
||||
__host__ __device__ __forceinline__ name ## _func() {} \
|
||||
__host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \
|
||||
}; \
|
||||
template <> struct name ## _func<double> : unary_function<double, double> \
|
||||
{ \
|
||||
__device__ __forceinline__ double operator ()(double v) const \
|
||||
{ \
|
||||
return func(v); \
|
||||
} \
|
||||
__host__ __device__ __forceinline__ name ## _func() {} \
|
||||
__host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \
|
||||
};
|
||||
|
||||
#define OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR(name, func) \
|
||||
template <typename T> struct name ## _func : binary_function<T, T, float> \
|
||||
{ \
|
||||
__device__ __forceinline__ float operator ()(typename TypeTraits<T>::ParameterType v1, typename TypeTraits<T>::ParameterType v2) const \
|
||||
{ \
|
||||
return func ## f(v1, v2); \
|
||||
} \
|
||||
__host__ __device__ __forceinline__ name ## _func() {} \
|
||||
__host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \
|
||||
}; \
|
||||
template <> struct name ## _func<double> : binary_function<double, double, double> \
|
||||
{ \
|
||||
__device__ __forceinline__ double operator ()(double v1, double v2) const \
|
||||
{ \
|
||||
return func(v1, v2); \
|
||||
} \
|
||||
__host__ __device__ __forceinline__ name ## _func() {} \
|
||||
__host__ __device__ __forceinline__ name ## _func(const name ## _func&) {} \
|
||||
};
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(sqrt, ::sqrt)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(exp, ::exp)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(exp2, ::exp2)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(exp10, ::exp10)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(log, ::log)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(log2, ::log2)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(log10, ::log10)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(sin, ::sin)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(cos, ::cos)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(tan, ::tan)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(asin, ::asin)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(acos, ::acos)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(atan, ::atan)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(sinh, ::sinh)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(cosh, ::cosh)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(tanh, ::tanh)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(asinh, ::asinh)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(acosh, ::acosh)
|
||||
OPENCV_GPU_IMPLEMENT_UN_FUNCTOR(atanh, ::atanh)
|
||||
|
||||
OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR(hypot, ::hypot)
|
||||
OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR(atan2, ::atan2)
|
||||
OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR(pow, ::pow)
|
||||
|
||||
#undef OPENCV_GPU_IMPLEMENT_UN_FUNCTOR
|
||||
#undef OPENCV_GPU_IMPLEMENT_UN_FUNCTOR_NO_DOUBLE
|
||||
#undef OPENCV_GPU_IMPLEMENT_BIN_FUNCTOR
|
||||
|
||||
template<typename T> struct hypot_sqr_func : binary_function<T, T, float>
|
||||
{
|
||||
__device__ __forceinline__ T operator ()(typename TypeTraits<T>::ParameterType src1, typename TypeTraits<T>::ParameterType src2) const
|
||||
{
|
||||
return src1 * src1 + src2 * src2;
|
||||
}
|
||||
__host__ __device__ __forceinline__ hypot_sqr_func() {}
|
||||
__host__ __device__ __forceinline__ hypot_sqr_func(const hypot_sqr_func&) {}
|
||||
};
|
||||
|
||||
// Saturate Cast Functor
|
||||
template <typename T, typename D> struct saturate_cast_func : unary_function<T, D>
|
||||
{
|
||||
__device__ __forceinline__ D operator ()(typename TypeTraits<T>::ParameterType v) const
|
||||
{
|
||||
return saturate_cast<D>(v);
|
||||
}
|
||||
__host__ __device__ __forceinline__ saturate_cast_func() {}
|
||||
__host__ __device__ __forceinline__ saturate_cast_func(const saturate_cast_func&) {}
|
||||
};
|
||||
|
||||
// Threshold Functors
|
||||
template <typename T> struct thresh_binary_func : unary_function<T, T>
|
||||
{
|
||||
__host__ __device__ __forceinline__ thresh_binary_func(T thresh_, T maxVal_) : thresh(thresh_), maxVal(maxVal_) {}
|
||||
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType src) const
|
||||
{
|
||||
return (src > thresh) * maxVal;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ thresh_binary_func() {}
|
||||
__host__ __device__ __forceinline__ thresh_binary_func(const thresh_binary_func& other)
|
||||
: thresh(other.thresh), maxVal(other.maxVal) {}
|
||||
|
||||
const T thresh;
|
||||
const T maxVal;
|
||||
};
|
||||
|
||||
template <typename T> struct thresh_binary_inv_func : unary_function<T, T>
|
||||
{
|
||||
__host__ __device__ __forceinline__ thresh_binary_inv_func(T thresh_, T maxVal_) : thresh(thresh_), maxVal(maxVal_) {}
|
||||
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType src) const
|
||||
{
|
||||
return (src <= thresh) * maxVal;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ thresh_binary_inv_func() {}
|
||||
__host__ __device__ __forceinline__ thresh_binary_inv_func(const thresh_binary_inv_func& other)
|
||||
: thresh(other.thresh), maxVal(other.maxVal) {}
|
||||
|
||||
const T thresh;
|
||||
const T maxVal;
|
||||
};
|
||||
|
||||
template <typename T> struct thresh_trunc_func : unary_function<T, T>
|
||||
{
|
||||
explicit __host__ __device__ __forceinline__ thresh_trunc_func(T thresh_, T maxVal_ = 0) : thresh(thresh_) {(void)maxVal_;}
|
||||
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType src) const
|
||||
{
|
||||
return minimum<T>()(src, thresh);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ thresh_trunc_func() {}
|
||||
__host__ __device__ __forceinline__ thresh_trunc_func(const thresh_trunc_func& other)
|
||||
: thresh(other.thresh) {}
|
||||
|
||||
const T thresh;
|
||||
};
|
||||
|
||||
template <typename T> struct thresh_to_zero_func : unary_function<T, T>
|
||||
{
|
||||
explicit __host__ __device__ __forceinline__ thresh_to_zero_func(T thresh_, T maxVal_ = 0) : thresh(thresh_) {(void)maxVal_;}
|
||||
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType src) const
|
||||
{
|
||||
return (src > thresh) * src;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ thresh_to_zero_func() {}
|
||||
__host__ __device__ __forceinline__ thresh_to_zero_func(const thresh_to_zero_func& other)
|
||||
: thresh(other.thresh) {}
|
||||
|
||||
const T thresh;
|
||||
};
|
||||
|
||||
template <typename T> struct thresh_to_zero_inv_func : unary_function<T, T>
|
||||
{
|
||||
explicit __host__ __device__ __forceinline__ thresh_to_zero_inv_func(T thresh_, T maxVal_ = 0) : thresh(thresh_) {(void)maxVal_;}
|
||||
|
||||
__device__ __forceinline__ T operator()(typename TypeTraits<T>::ParameterType src) const
|
||||
{
|
||||
return (src <= thresh) * src;
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ thresh_to_zero_inv_func() {}
|
||||
__host__ __device__ __forceinline__ thresh_to_zero_inv_func(const thresh_to_zero_inv_func& other)
|
||||
: thresh(other.thresh) {}
|
||||
|
||||
const T thresh;
|
||||
};
|
||||
|
||||
// Function Object Adaptors
|
||||
template <typename Predicate> struct unary_negate : unary_function<typename Predicate::argument_type, bool>
|
||||
{
|
||||
explicit __host__ __device__ __forceinline__ unary_negate(const Predicate& p) : pred(p) {}
|
||||
|
||||
__device__ __forceinline__ bool operator()(typename TypeTraits<typename Predicate::argument_type>::ParameterType x) const
|
||||
{
|
||||
return !pred(x);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ unary_negate() {}
|
||||
__host__ __device__ __forceinline__ unary_negate(const unary_negate& other) : pred(other.pred) {}
|
||||
|
||||
const Predicate pred;
|
||||
};
|
||||
|
||||
template <typename Predicate> __host__ __device__ __forceinline__ unary_negate<Predicate> not1(const Predicate& pred)
|
||||
{
|
||||
return unary_negate<Predicate>(pred);
|
||||
}
|
||||
|
||||
template <typename Predicate> struct binary_negate : binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
|
||||
{
|
||||
explicit __host__ __device__ __forceinline__ binary_negate(const Predicate& p) : pred(p) {}
|
||||
|
||||
__device__ __forceinline__ bool operator()(typename TypeTraits<typename Predicate::first_argument_type>::ParameterType x,
|
||||
typename TypeTraits<typename Predicate::second_argument_type>::ParameterType y) const
|
||||
{
|
||||
return !pred(x,y);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ binary_negate() {}
|
||||
__host__ __device__ __forceinline__ binary_negate(const binary_negate& other) : pred(other.pred) {}
|
||||
|
||||
const Predicate pred;
|
||||
};
|
||||
|
||||
template <typename BinaryPredicate> __host__ __device__ __forceinline__ binary_negate<BinaryPredicate> not2(const BinaryPredicate& pred)
|
||||
{
|
||||
return binary_negate<BinaryPredicate>(pred);
|
||||
}
|
||||
|
||||
template <typename Op> struct binder1st : unary_function<typename Op::second_argument_type, typename Op::result_type>
|
||||
{
|
||||
__host__ __device__ __forceinline__ binder1st(const Op& op_, const typename Op::first_argument_type& arg1_) : op(op_), arg1(arg1_) {}
|
||||
|
||||
__device__ __forceinline__ typename Op::result_type operator ()(typename TypeTraits<typename Op::second_argument_type>::ParameterType a) const
|
||||
{
|
||||
return op(arg1, a);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ binder1st() {}
|
||||
__host__ __device__ __forceinline__ binder1st(const binder1st& other) : op(other.op), arg1(other.arg1) {}
|
||||
|
||||
const Op op;
|
||||
const typename Op::first_argument_type arg1;
|
||||
};
|
||||
|
||||
template <typename Op, typename T> __host__ __device__ __forceinline__ binder1st<Op> bind1st(const Op& op, const T& x)
|
||||
{
|
||||
return binder1st<Op>(op, typename Op::first_argument_type(x));
|
||||
}
|
||||
|
||||
template <typename Op> struct binder2nd : unary_function<typename Op::first_argument_type, typename Op::result_type>
|
||||
{
|
||||
__host__ __device__ __forceinline__ binder2nd(const Op& op_, const typename Op::second_argument_type& arg2_) : op(op_), arg2(arg2_) {}
|
||||
|
||||
__forceinline__ __device__ typename Op::result_type operator ()(typename TypeTraits<typename Op::first_argument_type>::ParameterType a) const
|
||||
{
|
||||
return op(a, arg2);
|
||||
}
|
||||
|
||||
__host__ __device__ __forceinline__ binder2nd() {}
|
||||
__host__ __device__ __forceinline__ binder2nd(const binder2nd& other) : op(other.op), arg2(other.arg2) {}
|
||||
|
||||
const Op op;
|
||||
const typename Op::second_argument_type arg2;
|
||||
};
|
||||
|
||||
template <typename Op, typename T> __host__ __device__ __forceinline__ binder2nd<Op> bind2nd(const Op& op, const T& x)
|
||||
{
|
||||
return binder2nd<Op>(op, typename Op::second_argument_type(x));
|
||||
}
|
||||
|
||||
// Functor Traits
|
||||
template <typename F> struct IsUnaryFunction
|
||||
{
|
||||
typedef char Yes;
|
||||
struct No {Yes a[2];};
|
||||
|
||||
template <typename T, typename D> static Yes check(unary_function<T, D>);
|
||||
static No check(...);
|
||||
|
||||
static F makeF();
|
||||
|
||||
enum { value = (sizeof(check(makeF())) == sizeof(Yes)) };
|
||||
};
|
||||
|
||||
template <typename F> struct IsBinaryFunction
|
||||
{
|
||||
typedef char Yes;
|
||||
struct No {Yes a[2];};
|
||||
|
||||
template <typename T1, typename T2, typename D> static Yes check(binary_function<T1, T2, D>);
|
||||
static No check(...);
|
||||
|
||||
static F makeF();
|
||||
|
||||
enum { value = (sizeof(check(makeF())) == sizeof(Yes)) };
|
||||
};
|
||||
|
||||
namespace functional_detail
|
||||
{
|
||||
template <size_t src_elem_size, size_t dst_elem_size> struct UnOpShift { enum { shift = 1 }; };
|
||||
template <size_t src_elem_size> struct UnOpShift<src_elem_size, 1> { enum { shift = 4 }; };
|
||||
template <size_t src_elem_size> struct UnOpShift<src_elem_size, 2> { enum { shift = 2 }; };
|
||||
|
||||
template <typename T, typename D> struct DefaultUnaryShift
|
||||
{
|
||||
enum { shift = UnOpShift<sizeof(T), sizeof(D)>::shift };
|
||||
};
|
||||
|
||||
template <size_t src_elem_size1, size_t src_elem_size2, size_t dst_elem_size> struct BinOpShift { enum { shift = 1 }; };
|
||||
template <size_t src_elem_size1, size_t src_elem_size2> struct BinOpShift<src_elem_size1, src_elem_size2, 1> { enum { shift = 4 }; };
|
||||
template <size_t src_elem_size1, size_t src_elem_size2> struct BinOpShift<src_elem_size1, src_elem_size2, 2> { enum { shift = 2 }; };
|
||||
|
||||
template <typename T1, typename T2, typename D> struct DefaultBinaryShift
|
||||
{
|
||||
enum { shift = BinOpShift<sizeof(T1), sizeof(T2), sizeof(D)>::shift };
|
||||
};
|
||||
|
||||
template <typename Func, bool unary = IsUnaryFunction<Func>::value> struct ShiftDispatcher;
|
||||
template <typename Func> struct ShiftDispatcher<Func, true>
|
||||
{
|
||||
enum { shift = DefaultUnaryShift<typename Func::argument_type, typename Func::result_type>::shift };
|
||||
};
|
||||
template <typename Func> struct ShiftDispatcher<Func, false>
|
||||
{
|
||||
enum { shift = DefaultBinaryShift<typename Func::first_argument_type, typename Func::second_argument_type, typename Func::result_type>::shift };
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Func> struct DefaultTransformShift
|
||||
{
|
||||
enum { shift = functional_detail::ShiftDispatcher<Func>::shift };
|
||||
};
|
||||
|
||||
template <typename Func> struct DefaultTransformFunctorTraits
|
||||
{
|
||||
enum { simple_block_dim_x = 16 };
|
||||
enum { simple_block_dim_y = 16 };
|
||||
|
||||
enum { smart_block_dim_x = 16 };
|
||||
enum { smart_block_dim_y = 16 };
|
||||
enum { smart_shift = DefaultTransformShift<Func>::shift };
|
||||
};
|
||||
|
||||
template <typename Func> struct TransformFunctorTraits : DefaultTransformFunctorTraits<Func> {};
|
||||
|
||||
#define OPENCV_GPU_TRANSFORM_FUNCTOR_TRAITS(type) \
|
||||
template <> struct TransformFunctorTraits< type > : DefaultTransformFunctorTraits< type >
|
||||
}}} // namespace cv { namespace gpu { namespace device
|
||||
|
||||
#endif // __OPENCV_GPU_FUNCTIONAL_HPP__
|
||||
@@ -0,0 +1,122 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_LIMITS_GPU_HPP__
|
||||
#define __OPENCV_GPU_LIMITS_GPU_HPP__
|
||||
|
||||
#include <limits.h>
|
||||
#include <float.h>
|
||||
#include "common.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
|
||||
template <class T> struct numeric_limits;
|
||||
|
||||
template <> struct numeric_limits<bool>
|
||||
{
|
||||
__device__ __forceinline__ static bool min() { return false; }
|
||||
__device__ __forceinline__ static bool max() { return true; }
|
||||
static const bool is_signed = false;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<signed char>
|
||||
{
|
||||
__device__ __forceinline__ static signed char min() { return SCHAR_MIN; }
|
||||
__device__ __forceinline__ static signed char max() { return SCHAR_MAX; }
|
||||
static const bool is_signed = true;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<unsigned char>
|
||||
{
|
||||
__device__ __forceinline__ static unsigned char min() { return 0; }
|
||||
__device__ __forceinline__ static unsigned char max() { return UCHAR_MAX; }
|
||||
static const bool is_signed = false;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<short>
|
||||
{
|
||||
__device__ __forceinline__ static short min() { return SHRT_MIN; }
|
||||
__device__ __forceinline__ static short max() { return SHRT_MAX; }
|
||||
static const bool is_signed = true;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<unsigned short>
|
||||
{
|
||||
__device__ __forceinline__ static unsigned short min() { return 0; }
|
||||
__device__ __forceinline__ static unsigned short max() { return USHRT_MAX; }
|
||||
static const bool is_signed = false;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<int>
|
||||
{
|
||||
__device__ __forceinline__ static int min() { return INT_MIN; }
|
||||
__device__ __forceinline__ static int max() { return INT_MAX; }
|
||||
static const bool is_signed = true;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<unsigned int>
|
||||
{
|
||||
__device__ __forceinline__ static unsigned int min() { return 0; }
|
||||
__device__ __forceinline__ static unsigned int max() { return UINT_MAX; }
|
||||
static const bool is_signed = false;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<float>
|
||||
{
|
||||
__device__ __forceinline__ static float min() { return FLT_MIN; }
|
||||
__device__ __forceinline__ static float max() { return FLT_MAX; }
|
||||
__device__ __forceinline__ static float epsilon() { return FLT_EPSILON; }
|
||||
static const bool is_signed = true;
|
||||
};
|
||||
|
||||
template <> struct numeric_limits<double>
|
||||
{
|
||||
__device__ __forceinline__ static double min() { return DBL_MIN; }
|
||||
__device__ __forceinline__ static double max() { return DBL_MAX; }
|
||||
__device__ __forceinline__ static double epsilon() { return DBL_EPSILON; }
|
||||
static const bool is_signed = true;
|
||||
};
|
||||
|
||||
}}} // namespace cv { namespace gpu { namespace device {
|
||||
|
||||
#endif // __OPENCV_GPU_LIMITS_GPU_HPP__
|
||||
@@ -0,0 +1,197 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_REDUCE_HPP__
|
||||
#define __OPENCV_GPU_REDUCE_HPP__
|
||||
|
||||
#include <thrust/tuple.h>
|
||||
#include "detail/reduce.hpp"
|
||||
#include "detail/reduce_key_val.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
template <int N, typename T, class Op>
|
||||
__device__ __forceinline__ void reduce(volatile T* smem, T& val, unsigned int tid, const Op& op)
|
||||
{
|
||||
reduce_detail::Dispatcher<N>::reductor::template reduce<volatile T*, T&, const Op&>(smem, val, tid, op);
|
||||
}
|
||||
template <int N,
|
||||
typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9,
|
||||
typename R0, typename R1, typename R2, typename R3, typename R4, typename R5, typename R6, typename R7, typename R8, typename R9,
|
||||
class Op0, class Op1, class Op2, class Op3, class Op4, class Op5, class Op6, class Op7, class Op8, class Op9>
|
||||
__device__ __forceinline__ void reduce(const thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9>& smem,
|
||||
const thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9>& val,
|
||||
unsigned int tid,
|
||||
const thrust::tuple<Op0, Op1, Op2, Op3, Op4, Op5, Op6, Op7, Op8, Op9>& op)
|
||||
{
|
||||
reduce_detail::Dispatcher<N>::reductor::template reduce<
|
||||
const thrust::tuple<P0, P1, P2, P3, P4, P5, P6, P7, P8, P9>&,
|
||||
const thrust::tuple<R0, R1, R2, R3, R4, R5, R6, R7, R8, R9>&,
|
||||
const thrust::tuple<Op0, Op1, Op2, Op3, Op4, Op5, Op6, Op7, Op8, Op9>&>(smem, val, tid, op);
|
||||
}
|
||||
|
||||
template <unsigned int N, typename K, typename V, class Cmp>
|
||||
__device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key, volatile V* svals, V& val, unsigned int tid, const Cmp& cmp)
|
||||
{
|
||||
reduce_key_val_detail::Dispatcher<N>::reductor::template reduce<volatile K*, K&, volatile V*, V&, const Cmp&>(skeys, key, svals, val, tid, cmp);
|
||||
}
|
||||
template <unsigned int N,
|
||||
typename K,
|
||||
typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9,
|
||||
class Cmp>
|
||||
__device__ __forceinline__ void reduceKeyVal(volatile K* skeys, K& key,
|
||||
const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& svals,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
unsigned int tid, const Cmp& cmp)
|
||||
{
|
||||
reduce_key_val_detail::Dispatcher<N>::reductor::template reduce<volatile K*, K&,
|
||||
const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>&,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>&,
|
||||
const Cmp&>(skeys, key, svals, val, tid, cmp);
|
||||
}
|
||||
template <unsigned int N,
|
||||
typename KP0, typename KP1, typename KP2, typename KP3, typename KP4, typename KP5, typename KP6, typename KP7, typename KP8, typename KP9,
|
||||
typename KR0, typename KR1, typename KR2, typename KR3, typename KR4, typename KR5, typename KR6, typename KR7, typename KR8, typename KR9,
|
||||
typename VP0, typename VP1, typename VP2, typename VP3, typename VP4, typename VP5, typename VP6, typename VP7, typename VP8, typename VP9,
|
||||
typename VR0, typename VR1, typename VR2, typename VR3, typename VR4, typename VR5, typename VR6, typename VR7, typename VR8, typename VR9,
|
||||
class Cmp0, class Cmp1, class Cmp2, class Cmp3, class Cmp4, class Cmp5, class Cmp6, class Cmp7, class Cmp8, class Cmp9>
|
||||
__device__ __forceinline__ void reduceKeyVal(const thrust::tuple<KP0, KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9>& skeys,
|
||||
const thrust::tuple<KR0, KR1, KR2, KR3, KR4, KR5, KR6, KR7, KR8, KR9>& key,
|
||||
const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>& svals,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>& val,
|
||||
unsigned int tid,
|
||||
const thrust::tuple<Cmp0, Cmp1, Cmp2, Cmp3, Cmp4, Cmp5, Cmp6, Cmp7, Cmp8, Cmp9>& cmp)
|
||||
{
|
||||
reduce_key_val_detail::Dispatcher<N>::reductor::template reduce<
|
||||
const thrust::tuple<KP0, KP1, KP2, KP3, KP4, KP5, KP6, KP7, KP8, KP9>&,
|
||||
const thrust::tuple<KR0, KR1, KR2, KR3, KR4, KR5, KR6, KR7, KR8, KR9>&,
|
||||
const thrust::tuple<VP0, VP1, VP2, VP3, VP4, VP5, VP6, VP7, VP8, VP9>&,
|
||||
const thrust::tuple<VR0, VR1, VR2, VR3, VR4, VR5, VR6, VR7, VR8, VR9>&,
|
||||
const thrust::tuple<Cmp0, Cmp1, Cmp2, Cmp3, Cmp4, Cmp5, Cmp6, Cmp7, Cmp8, Cmp9>&
|
||||
>(skeys, key, svals, val, tid, cmp);
|
||||
}
|
||||
|
||||
// smem_tuple
|
||||
|
||||
template <typename T0>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*>
|
||||
smem_tuple(T0* t0)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*>
|
||||
smem_tuple(T0* t0, T1* t1)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*, volatile T4*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*, volatile T4*, volatile T5*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*, volatile T4*, volatile T5*, volatile T6*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*, volatile T4*, volatile T5*, volatile T6*, volatile T7*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*, volatile T4*, volatile T5*, volatile T6*, volatile T7*, volatile T8*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7, T8* t8)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7, (volatile T8*) t8);
|
||||
}
|
||||
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
|
||||
__device__ __forceinline__
|
||||
thrust::tuple<volatile T0*, volatile T1*, volatile T2*, volatile T3*, volatile T4*, volatile T5*, volatile T6*, volatile T7*, volatile T8*, volatile T9*>
|
||||
smem_tuple(T0* t0, T1* t1, T2* t2, T3* t3, T4* t4, T5* t5, T6* t6, T7* t7, T8* t8, T9* t9)
|
||||
{
|
||||
return thrust::make_tuple((volatile T0*) t0, (volatile T1*) t1, (volatile T2*) t2, (volatile T3*) t3, (volatile T4*) t4, (volatile T5*) t5, (volatile T6*) t6, (volatile T7*) t7, (volatile T8*) t8, (volatile T9*) t9);
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif // __OPENCV_GPU_UTILITY_HPP__
|
||||
@@ -0,0 +1,284 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_SATURATE_CAST_HPP__
|
||||
#define __OPENCV_GPU_SATURATE_CAST_HPP__
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(uchar v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(schar v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(ushort v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(short v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(uint v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(int v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(float v) { return _Tp(v); }
|
||||
template<typename _Tp> __device__ __forceinline__ _Tp saturate_cast(double v) { return _Tp(v); }
|
||||
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(schar v)
|
||||
{
|
||||
uint res = 0;
|
||||
int vi = v;
|
||||
asm("cvt.sat.u8.s8 %0, %1;" : "=r"(res) : "r"(vi));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(short v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.u8.s16 %0, %1;" : "=r"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(ushort v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.u8.u16 %0, %1;" : "=r"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(int v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.u8.s32 %0, %1;" : "=r"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(uint v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.u8.u32 %0, %1;" : "=r"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(float v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.rni.sat.u8.f32 %0, %1;" : "=r"(res) : "f"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uchar saturate_cast<uchar>(double v)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 130
|
||||
uint res = 0;
|
||||
asm("cvt.rni.sat.u8.f64 %0, %1;" : "=r"(res) : "d"(v));
|
||||
return res;
|
||||
#else
|
||||
return saturate_cast<uchar>((float)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(uchar v)
|
||||
{
|
||||
uint res = 0;
|
||||
uint vi = v;
|
||||
asm("cvt.sat.s8.u8 %0, %1;" : "=r"(res) : "r"(vi));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(short v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.s8.s16 %0, %1;" : "=r"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(ushort v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.s8.u16 %0, %1;" : "=r"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(int v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.s8.s32 %0, %1;" : "=r"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(uint v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.s8.u32 %0, %1;" : "=r"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(float v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.rni.sat.s8.f32 %0, %1;" : "=r"(res) : "f"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ schar saturate_cast<schar>(double v)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 130
|
||||
uint res = 0;
|
||||
asm("cvt.rni.sat.s8.f64 %0, %1;" : "=r"(res) : "d"(v));
|
||||
return res;
|
||||
#else
|
||||
return saturate_cast<schar>((float)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> __device__ __forceinline__ ushort saturate_cast<ushort>(schar v)
|
||||
{
|
||||
ushort res = 0;
|
||||
int vi = v;
|
||||
asm("cvt.sat.u16.s8 %0, %1;" : "=h"(res) : "r"(vi));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ ushort saturate_cast<ushort>(short v)
|
||||
{
|
||||
ushort res = 0;
|
||||
asm("cvt.sat.u16.s16 %0, %1;" : "=h"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ ushort saturate_cast<ushort>(int v)
|
||||
{
|
||||
ushort res = 0;
|
||||
asm("cvt.sat.u16.s32 %0, %1;" : "=h"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ ushort saturate_cast<ushort>(uint v)
|
||||
{
|
||||
ushort res = 0;
|
||||
asm("cvt.sat.u16.u32 %0, %1;" : "=h"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ ushort saturate_cast<ushort>(float v)
|
||||
{
|
||||
ushort res = 0;
|
||||
asm("cvt.rni.sat.u16.f32 %0, %1;" : "=h"(res) : "f"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ ushort saturate_cast<ushort>(double v)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 130
|
||||
ushort res = 0;
|
||||
asm("cvt.rni.sat.u16.f64 %0, %1;" : "=h"(res) : "d"(v));
|
||||
return res;
|
||||
#else
|
||||
return saturate_cast<ushort>((float)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> __device__ __forceinline__ short saturate_cast<short>(ushort v)
|
||||
{
|
||||
short res = 0;
|
||||
asm("cvt.sat.s16.u16 %0, %1;" : "=h"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ short saturate_cast<short>(int v)
|
||||
{
|
||||
short res = 0;
|
||||
asm("cvt.sat.s16.s32 %0, %1;" : "=h"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ short saturate_cast<short>(uint v)
|
||||
{
|
||||
short res = 0;
|
||||
asm("cvt.sat.s16.u32 %0, %1;" : "=h"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ short saturate_cast<short>(float v)
|
||||
{
|
||||
short res = 0;
|
||||
asm("cvt.rni.sat.s16.f32 %0, %1;" : "=h"(res) : "f"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ short saturate_cast<short>(double v)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 130
|
||||
short res = 0;
|
||||
asm("cvt.rni.sat.s16.f64 %0, %1;" : "=h"(res) : "d"(v));
|
||||
return res;
|
||||
#else
|
||||
return saturate_cast<short>((float)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> __device__ __forceinline__ int saturate_cast<int>(uint v)
|
||||
{
|
||||
int res = 0;
|
||||
asm("cvt.sat.s32.u32 %0, %1;" : "=r"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ int saturate_cast<int>(float v)
|
||||
{
|
||||
return __float2int_rn(v);
|
||||
}
|
||||
template<> __device__ __forceinline__ int saturate_cast<int>(double v)
|
||||
{
|
||||
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 130
|
||||
return __double2int_rn(v);
|
||||
#else
|
||||
return saturate_cast<int>((float)v);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> __device__ __forceinline__ uint saturate_cast<uint>(schar v)
|
||||
{
|
||||
uint res = 0;
|
||||
int vi = v;
|
||||
asm("cvt.sat.u32.s8 %0, %1;" : "=r"(res) : "r"(vi));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uint saturate_cast<uint>(short v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.u32.s16 %0, %1;" : "=r"(res) : "h"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uint saturate_cast<uint>(int v)
|
||||
{
|
||||
uint res = 0;
|
||||
asm("cvt.sat.u32.s32 %0, %1;" : "=r"(res) : "r"(v));
|
||||
return res;
|
||||
}
|
||||
template<> __device__ __forceinline__ uint saturate_cast<uint>(float v)
|
||||
{
|
||||
return __float2uint_rn(v);
|
||||
}
|
||||
template<> __device__ __forceinline__ uint saturate_cast<uint>(double v)
|
||||
{
|
||||
#if defined __CUDA_ARCH__ && __CUDA_ARCH__ >= 130
|
||||
return __double2uint_rn(v);
|
||||
#else
|
||||
return saturate_cast<uint>((float)v);
|
||||
#endif
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif /* __OPENCV_GPU_SATURATE_CAST_HPP__ */
|
||||
@@ -0,0 +1,250 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_GPU_SCAN_HPP__
|
||||
#define __OPENCV_GPU_SCAN_HPP__
|
||||
|
||||
#include "opencv2/gpu/device/common.hpp"
|
||||
#include "opencv2/gpu/device/utility.hpp"
|
||||
#include "opencv2/gpu/device/warp.hpp"
|
||||
#include "opencv2/gpu/device/warp_shuffle.hpp"
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
enum ScanKind { EXCLUSIVE = 0, INCLUSIVE = 1 };
|
||||
|
||||
template <ScanKind Kind, typename T, typename F> struct WarpScan
|
||||
{
|
||||
__device__ __forceinline__ WarpScan() {}
|
||||
__device__ __forceinline__ WarpScan(const WarpScan& other) { (void)other; }
|
||||
|
||||
__device__ __forceinline__ T operator()( volatile T *ptr , const unsigned int idx)
|
||||
{
|
||||
const unsigned int lane = idx & 31;
|
||||
F op;
|
||||
|
||||
if ( lane >= 1) ptr [idx ] = op(ptr [idx - 1], ptr [idx]);
|
||||
if ( lane >= 2) ptr [idx ] = op(ptr [idx - 2], ptr [idx]);
|
||||
if ( lane >= 4) ptr [idx ] = op(ptr [idx - 4], ptr [idx]);
|
||||
if ( lane >= 8) ptr [idx ] = op(ptr [idx - 8], ptr [idx]);
|
||||
if ( lane >= 16) ptr [idx ] = op(ptr [idx - 16], ptr [idx]);
|
||||
|
||||
if( Kind == INCLUSIVE )
|
||||
return ptr [idx];
|
||||
else
|
||||
return (lane > 0) ? ptr [idx - 1] : 0;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ unsigned int index(const unsigned int tid)
|
||||
{
|
||||
return tid;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void init(volatile T *ptr){}
|
||||
|
||||
static const int warp_offset = 0;
|
||||
|
||||
typedef WarpScan<INCLUSIVE, T, F> merge;
|
||||
};
|
||||
|
||||
template <ScanKind Kind , typename T, typename F> struct WarpScanNoComp
|
||||
{
|
||||
__device__ __forceinline__ WarpScanNoComp() {}
|
||||
__device__ __forceinline__ WarpScanNoComp(const WarpScanNoComp& other) { (void)other; }
|
||||
|
||||
__device__ __forceinline__ T operator()( volatile T *ptr , const unsigned int idx)
|
||||
{
|
||||
const unsigned int lane = threadIdx.x & 31;
|
||||
F op;
|
||||
|
||||
ptr [idx ] = op(ptr [idx - 1], ptr [idx]);
|
||||
ptr [idx ] = op(ptr [idx - 2], ptr [idx]);
|
||||
ptr [idx ] = op(ptr [idx - 4], ptr [idx]);
|
||||
ptr [idx ] = op(ptr [idx - 8], ptr [idx]);
|
||||
ptr [idx ] = op(ptr [idx - 16], ptr [idx]);
|
||||
|
||||
if( Kind == INCLUSIVE )
|
||||
return ptr [idx];
|
||||
else
|
||||
return (lane > 0) ? ptr [idx - 1] : 0;
|
||||
}
|
||||
|
||||
__device__ __forceinline__ unsigned int index(const unsigned int tid)
|
||||
{
|
||||
return (tid >> warp_log) * warp_smem_stride + 16 + (tid & warp_mask);
|
||||
}
|
||||
|
||||
__device__ __forceinline__ void init(volatile T *ptr)
|
||||
{
|
||||
ptr[threadIdx.x] = 0;
|
||||
}
|
||||
|
||||
static const int warp_smem_stride = 32 + 16 + 1;
|
||||
static const int warp_offset = 16;
|
||||
static const int warp_log = 5;
|
||||
static const int warp_mask = 31;
|
||||
|
||||
typedef WarpScanNoComp<INCLUSIVE, T, F> merge;
|
||||
};
|
||||
|
||||
template <ScanKind Kind , typename T, typename Sc, typename F> struct BlockScan
|
||||
{
|
||||
__device__ __forceinline__ BlockScan() {}
|
||||
__device__ __forceinline__ BlockScan(const BlockScan& other) { (void)other; }
|
||||
|
||||
__device__ __forceinline__ T operator()(volatile T *ptr)
|
||||
{
|
||||
const unsigned int tid = threadIdx.x;
|
||||
const unsigned int lane = tid & warp_mask;
|
||||
const unsigned int warp = tid >> warp_log;
|
||||
|
||||
Sc scan;
|
||||
typename Sc::merge merge_scan;
|
||||
const unsigned int idx = scan.index(tid);
|
||||
|
||||
T val = scan(ptr, idx);
|
||||
__syncthreads ();
|
||||
|
||||
if( warp == 0)
|
||||
scan.init(ptr);
|
||||
__syncthreads ();
|
||||
|
||||
if( lane == 31 )
|
||||
ptr [scan.warp_offset + warp ] = (Kind == INCLUSIVE) ? val : ptr [idx];
|
||||
__syncthreads ();
|
||||
|
||||
if( warp == 0 )
|
||||
merge_scan(ptr, idx);
|
||||
__syncthreads();
|
||||
|
||||
if ( warp > 0)
|
||||
val = ptr [scan.warp_offset + warp - 1] + val;
|
||||
__syncthreads ();
|
||||
|
||||
ptr[idx] = val;
|
||||
__syncthreads ();
|
||||
|
||||
return val ;
|
||||
}
|
||||
|
||||
static const int warp_log = 5;
|
||||
static const int warp_mask = 31;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
__device__ T warpScanInclusive(T idata, volatile T* s_Data, unsigned int tid)
|
||||
{
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
const unsigned int laneId = cv::gpu::device::Warp::laneId();
|
||||
|
||||
// scan on shuffl functions
|
||||
#pragma unroll
|
||||
for (int i = 1; i <= (OPENCV_GPU_WARP_SIZE / 2); i *= 2)
|
||||
{
|
||||
const T n = cv::gpu::device::shfl_up(idata, i);
|
||||
if (laneId >= i)
|
||||
idata += n;
|
||||
}
|
||||
|
||||
return idata;
|
||||
#else
|
||||
unsigned int pos = 2 * tid - (tid & (OPENCV_GPU_WARP_SIZE - 1));
|
||||
s_Data[pos] = 0;
|
||||
pos += OPENCV_GPU_WARP_SIZE;
|
||||
s_Data[pos] = idata;
|
||||
|
||||
s_Data[pos] += s_Data[pos - 1];
|
||||
s_Data[pos] += s_Data[pos - 2];
|
||||
s_Data[pos] += s_Data[pos - 4];
|
||||
s_Data[pos] += s_Data[pos - 8];
|
||||
s_Data[pos] += s_Data[pos - 16];
|
||||
|
||||
return s_Data[pos];
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__device__ __forceinline__ T warpScanExclusive(T idata, volatile T* s_Data, unsigned int tid)
|
||||
{
|
||||
return warpScanInclusive(idata, s_Data, tid) - idata;
|
||||
}
|
||||
|
||||
template <int tiNumScanThreads, typename T>
|
||||
__device__ T blockScanInclusive(T idata, volatile T* s_Data, unsigned int tid)
|
||||
{
|
||||
if (tiNumScanThreads > OPENCV_GPU_WARP_SIZE)
|
||||
{
|
||||
//Bottom-level inclusive warp scan
|
||||
T warpResult = warpScanInclusive(idata, s_Data, tid);
|
||||
|
||||
//Save top elements of each warp for exclusive warp scan
|
||||
//sync to wait for warp scans to complete (because s_Data is being overwritten)
|
||||
__syncthreads();
|
||||
if ((tid & (OPENCV_GPU_WARP_SIZE - 1)) == (OPENCV_GPU_WARP_SIZE - 1))
|
||||
{
|
||||
s_Data[tid >> OPENCV_GPU_LOG_WARP_SIZE] = warpResult;
|
||||
}
|
||||
|
||||
//wait for warp scans to complete
|
||||
__syncthreads();
|
||||
|
||||
if (tid < (tiNumScanThreads / OPENCV_GPU_WARP_SIZE) )
|
||||
{
|
||||
//grab top warp elements
|
||||
T val = s_Data[tid];
|
||||
//calculate exclusive scan and write back to shared memory
|
||||
s_Data[tid] = warpScanExclusive(val, s_Data, tid);
|
||||
}
|
||||
|
||||
//return updated warp scans with exclusive scan results
|
||||
__syncthreads();
|
||||
|
||||
return warpResult + s_Data[tid >> OPENCV_GPU_LOG_WARP_SIZE];
|
||||
}
|
||||
else
|
||||
{
|
||||
return warpScanInclusive(idata, s_Data, tid);
|
||||
}
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif // __OPENCV_GPU_SCAN_HPP__
|
||||
@@ -0,0 +1,909 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of NVIDIA Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __OPENCV_GPU_SIMD_FUNCTIONS_HPP__
|
||||
#define __OPENCV_GPU_SIMD_FUNCTIONS_HPP__
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
/*
|
||||
This header file contains inline functions that implement intra-word SIMD
|
||||
operations, that are hardware accelerated on sm_3x (Kepler) GPUs. Efficient
|
||||
emulation code paths are provided for earlier architectures (sm_1x, sm_2x)
|
||||
to make the code portable across all GPUs supported by CUDA. The following
|
||||
functions are currently implemented:
|
||||
|
||||
vadd2(a,b) per-halfword unsigned addition, with wrap-around: a + b
|
||||
vsub2(a,b) per-halfword unsigned subtraction, with wrap-around: a - b
|
||||
vabsdiff2(a,b) per-halfword unsigned absolute difference: |a - b|
|
||||
vavg2(a,b) per-halfword unsigned average: (a + b) / 2
|
||||
vavrg2(a,b) per-halfword unsigned rounded average: (a + b + 1) / 2
|
||||
vseteq2(a,b) per-halfword unsigned comparison: a == b ? 1 : 0
|
||||
vcmpeq2(a,b) per-halfword unsigned comparison: a == b ? 0xffff : 0
|
||||
vsetge2(a,b) per-halfword unsigned comparison: a >= b ? 1 : 0
|
||||
vcmpge2(a,b) per-halfword unsigned comparison: a >= b ? 0xffff : 0
|
||||
vsetgt2(a,b) per-halfword unsigned comparison: a > b ? 1 : 0
|
||||
vcmpgt2(a,b) per-halfword unsigned comparison: a > b ? 0xffff : 0
|
||||
vsetle2(a,b) per-halfword unsigned comparison: a <= b ? 1 : 0
|
||||
vcmple2(a,b) per-halfword unsigned comparison: a <= b ? 0xffff : 0
|
||||
vsetlt2(a,b) per-halfword unsigned comparison: a < b ? 1 : 0
|
||||
vcmplt2(a,b) per-halfword unsigned comparison: a < b ? 0xffff : 0
|
||||
vsetne2(a,b) per-halfword unsigned comparison: a != b ? 1 : 0
|
||||
vcmpne2(a,b) per-halfword unsigned comparison: a != b ? 0xffff : 0
|
||||
vmax2(a,b) per-halfword unsigned maximum: max(a, b)
|
||||
vmin2(a,b) per-halfword unsigned minimum: min(a, b)
|
||||
|
||||
vadd4(a,b) per-byte unsigned addition, with wrap-around: a + b
|
||||
vsub4(a,b) per-byte unsigned subtraction, with wrap-around: a - b
|
||||
vabsdiff4(a,b) per-byte unsigned absolute difference: |a - b|
|
||||
vavg4(a,b) per-byte unsigned average: (a + b) / 2
|
||||
vavrg4(a,b) per-byte unsigned rounded average: (a + b + 1) / 2
|
||||
vseteq4(a,b) per-byte unsigned comparison: a == b ? 1 : 0
|
||||
vcmpeq4(a,b) per-byte unsigned comparison: a == b ? 0xff : 0
|
||||
vsetge4(a,b) per-byte unsigned comparison: a >= b ? 1 : 0
|
||||
vcmpge4(a,b) per-byte unsigned comparison: a >= b ? 0xff : 0
|
||||
vsetgt4(a,b) per-byte unsigned comparison: a > b ? 1 : 0
|
||||
vcmpgt4(a,b) per-byte unsigned comparison: a > b ? 0xff : 0
|
||||
vsetle4(a,b) per-byte unsigned comparison: a <= b ? 1 : 0
|
||||
vcmple4(a,b) per-byte unsigned comparison: a <= b ? 0xff : 0
|
||||
vsetlt4(a,b) per-byte unsigned comparison: a < b ? 1 : 0
|
||||
vcmplt4(a,b) per-byte unsigned comparison: a < b ? 0xff : 0
|
||||
vsetne4(a,b) per-byte unsigned comparison: a != b ? 1: 0
|
||||
vcmpne4(a,b) per-byte unsigned comparison: a != b ? 0xff: 0
|
||||
vmax4(a,b) per-byte unsigned maximum: max(a, b)
|
||||
vmin4(a,b) per-byte unsigned minimum: min(a, b)
|
||||
*/
|
||||
|
||||
namespace cv { namespace gpu { namespace device
|
||||
{
|
||||
// 2
|
||||
|
||||
static __device__ __forceinline__ unsigned int vadd2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vadd2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vadd.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vadd.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s;
|
||||
s = a ^ b; // sum bits
|
||||
r = a + b; // actual sum
|
||||
s = s ^ r; // determine carry-ins for each bit position
|
||||
s = s & 0x00010000; // carry-in to high word (= carry-out from low word)
|
||||
r = r - s; // subtract out carry-out from low word
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsub2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vsub2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vsub.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vsub.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s;
|
||||
s = a ^ b; // sum bits
|
||||
r = a - b; // actual sum
|
||||
s = s ^ r; // determine carry-ins for each bit position
|
||||
s = s & 0x00010000; // borrow to high word
|
||||
r = r + s; // compensate for borrow from low word
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vabsdiff2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vabsdiff2.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vabsdiff.u32.u32.u32.sat %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vabsdiff.u32.u32.u32.sat %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s, t, u, v;
|
||||
s = a & 0x0000ffff; // extract low halfword
|
||||
r = b & 0x0000ffff; // extract low halfword
|
||||
u = ::max(r, s); // maximum of low halfwords
|
||||
v = ::min(r, s); // minimum of low halfwords
|
||||
s = a & 0xffff0000; // extract high halfword
|
||||
r = b & 0xffff0000; // extract high halfword
|
||||
t = ::max(r, s); // maximum of high halfwords
|
||||
s = ::min(r, s); // minimum of high halfwords
|
||||
r = u | t; // maximum of both halfwords
|
||||
s = v | s; // minimum of both halfwords
|
||||
r = r - s; // |a - b| = max(a,b) - min(a,b);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vavg2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, s;
|
||||
|
||||
// HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==>
|
||||
// (a + b) / 2 = (a & b) + ((a ^ b) >> 1)
|
||||
s = a ^ b;
|
||||
r = a & b;
|
||||
s = s & 0xfffefffe; // ensure shift doesn't cross halfword boundaries
|
||||
s = s >> 1;
|
||||
s = r + s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vavrg2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vavrg2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
// HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==>
|
||||
// (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1)
|
||||
unsigned int s;
|
||||
s = a ^ b;
|
||||
r = a | b;
|
||||
s = s & 0xfffefffe; // ensure shift doesn't cross half-word boundaries
|
||||
s = s >> 1;
|
||||
r = r - s;
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vseteq2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset2.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
unsigned int c;
|
||||
r = a ^ b; // 0x0000 if a == b
|
||||
c = r | 0x80008000; // set msbs, to catch carry out
|
||||
r = r ^ c; // extract msbs, msb = 1 if r < 0x8000
|
||||
c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000
|
||||
c = r & ~c; // msb = 1, if r was 0x0000
|
||||
r = c >> 15; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpeq2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vseteq2(a, b);
|
||||
c = r << 16; // convert bool
|
||||
r = c - r; // into mask
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
r = a ^ b; // 0x0000 if a == b
|
||||
c = r | 0x80008000; // set msbs, to catch carry out
|
||||
r = r ^ c; // extract msbs, msb = 1 if r < 0x8000
|
||||
c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000
|
||||
c = r & ~c; // msb = 1, if r was 0x0000
|
||||
r = c >> 15; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetge2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset2.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2
|
||||
c = c & 0x80008000; // msb = carry-outs
|
||||
r = c >> 15; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpge2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetge2(a, b);
|
||||
c = r << 16; // convert bool
|
||||
r = c - r; // into mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavrg2(a, b); // (a + ~b + 1) / 2 = (a - b) / 2
|
||||
c = c & 0x80008000; // msb = carry-outs
|
||||
r = c >> 15; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetgt2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset2.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down]
|
||||
c = c & 0x80008000; // msbs = carry-outs
|
||||
r = c >> 15; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpgt2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetgt2(a, b);
|
||||
c = r << 16; // convert bool
|
||||
r = c - r; // into mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavg2(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down]
|
||||
c = c & 0x80008000; // msbs = carry-outs
|
||||
r = c >> 15; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetle2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset2.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2
|
||||
c = c & 0x80008000; // msb = carry-outs
|
||||
r = c >> 15; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmple2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetle2(a, b);
|
||||
c = r << 16; // convert bool
|
||||
r = c - r; // into mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavrg2(a, b); // (b + ~a + 1) / 2 = (b - a) / 2
|
||||
c = c & 0x80008000; // msb = carry-outs
|
||||
r = c >> 15; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetlt2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset2.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down]
|
||||
c = c & 0x80008000; // msb = carry-outs
|
||||
r = c >> 15; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmplt2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetlt2(a, b);
|
||||
c = r << 16; // convert bool
|
||||
r = c - r; // into mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavg2(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down]
|
||||
c = c & 0x80008000; // msb = carry-outs
|
||||
r = c >> 15; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetne2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm ("vset2.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
unsigned int c;
|
||||
r = a ^ b; // 0x0000 if a == b
|
||||
c = r | 0x80008000; // set msbs, to catch carry out
|
||||
c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000
|
||||
c = r | c; // msb = 1, if r was not 0x0000
|
||||
c = c & 0x80008000; // extract msbs
|
||||
r = c >> 15; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpne2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetne2(a, b);
|
||||
c = r << 16; // convert bool
|
||||
r = c - r; // into mask
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
r = a ^ b; // 0x0000 if a == b
|
||||
c = r | 0x80008000; // set msbs, to catch carry out
|
||||
c = c - 0x00010001; // msb = 0, if r was 0x0000 or 0x8000
|
||||
c = r | c; // msb = 1, if r was not 0x0000
|
||||
c = c & 0x80008000; // extract msbs
|
||||
r = c >> 15; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vmax2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vmax2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vmax.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmax.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s, t, u;
|
||||
r = a & 0x0000ffff; // extract low halfword
|
||||
s = b & 0x0000ffff; // extract low halfword
|
||||
t = ::max(r, s); // maximum of low halfwords
|
||||
r = a & 0xffff0000; // extract high halfword
|
||||
s = b & 0xffff0000; // extract high halfword
|
||||
u = ::max(r, s); // maximum of high halfwords
|
||||
r = t | u; // combine halfword maximums
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vmin2(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vmin2.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vmin.u32.u32.u32 %0.h0, %1.h0, %2.h0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmin.u32.u32.u32 %0.h1, %1.h1, %2.h1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s, t, u;
|
||||
r = a & 0x0000ffff; // extract low halfword
|
||||
s = b & 0x0000ffff; // extract low halfword
|
||||
t = ::min(r, s); // minimum of low halfwords
|
||||
r = a & 0xffff0000; // extract high halfword
|
||||
s = b & 0xffff0000; // extract high halfword
|
||||
u = ::min(r, s); // minimum of high halfwords
|
||||
r = t | u; // combine halfword minimums
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// 4
|
||||
|
||||
static __device__ __forceinline__ unsigned int vadd4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vadd4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vadd.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vadd.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vadd.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vadd.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s, t;
|
||||
s = a ^ b; // sum bits
|
||||
r = a & 0x7f7f7f7f; // clear msbs
|
||||
t = b & 0x7f7f7f7f; // clear msbs
|
||||
s = s & 0x80808080; // msb sum bits
|
||||
r = r + t; // add without msbs, record carry-out in msbs
|
||||
r = r ^ s; // sum of msb sum and carry-in bits, w/o carry-out
|
||||
#endif /* __CUDA_ARCH__ >= 300 */
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsub4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vsub4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vsub.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vsub.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vsub.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vsub.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s, t;
|
||||
s = a ^ ~b; // inverted sum bits
|
||||
r = a | 0x80808080; // set msbs
|
||||
t = b & 0x7f7f7f7f; // clear msbs
|
||||
s = s & 0x80808080; // inverted msb sum bits
|
||||
r = r - t; // subtract w/o msbs, record inverted borrows in msb
|
||||
r = r ^ s; // combine inverted msb sum bits and borrows
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vavg4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, s;
|
||||
|
||||
// HAKMEM #23: a + b = 2 * (a & b) + (a ^ b) ==>
|
||||
// (a + b) / 2 = (a & b) + ((a ^ b) >> 1)
|
||||
s = a ^ b;
|
||||
r = a & b;
|
||||
s = s & 0xfefefefe; // ensure following shift doesn't cross byte boundaries
|
||||
s = s >> 1;
|
||||
s = r + s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vavrg4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vavrg4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
// HAKMEM #23: a + b = 2 * (a | b) - (a ^ b) ==>
|
||||
// (a + b + 1) / 2 = (a | b) - ((a ^ b) >> 1)
|
||||
unsigned int c;
|
||||
c = a ^ b;
|
||||
r = a | b;
|
||||
c = c & 0xfefefefe; // ensure following shift doesn't cross byte boundaries
|
||||
c = c >> 1;
|
||||
r = r - c;
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vseteq4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset4.u32.u32.eq %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
unsigned int c;
|
||||
r = a ^ b; // 0x00 if a == b
|
||||
c = r | 0x80808080; // set msbs, to catch carry out
|
||||
r = r ^ c; // extract msbs, msb = 1 if r < 0x80
|
||||
c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80
|
||||
c = r & ~c; // msb = 1, if r was 0x00
|
||||
r = c >> 7; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpeq4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, t;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vseteq4(a, b);
|
||||
t = r << 8; // convert bool
|
||||
r = t - r; // to mask
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
t = a ^ b; // 0x00 if a == b
|
||||
r = t | 0x80808080; // set msbs, to catch carry out
|
||||
t = t ^ r; // extract msbs, msb = 1 if t < 0x80
|
||||
r = r - 0x01010101; // msb = 0, if t was 0x00 or 0x80
|
||||
r = t & ~r; // msb = 1, if t was 0x00
|
||||
t = r >> 7; // build mask
|
||||
t = r - t; // from
|
||||
r = t | r; // msbs
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetle4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset4.u32.u32.le %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2
|
||||
c = c & 0x80808080; // msb = carry-outs
|
||||
r = c >> 7; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmple4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetle4(a, b);
|
||||
c = r << 8; // convert bool
|
||||
r = c - r; // to mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavrg4(a, b); // (b + ~a + 1) / 2 = (b - a) / 2
|
||||
c = c & 0x80808080; // msbs = carry-outs
|
||||
r = c >> 7; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetlt4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset4.u32.u32.lt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down]
|
||||
c = c & 0x80808080; // msb = carry-outs
|
||||
r = c >> 7; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmplt4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetlt4(a, b);
|
||||
c = r << 8; // convert bool
|
||||
r = c - r; // to mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(a));
|
||||
c = vavg4(a, b); // (b + ~a) / 2 = (b - a) / 2 [rounded down]
|
||||
c = c & 0x80808080; // msbs = carry-outs
|
||||
r = c >> 7; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetge4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset4.u32.u32.ge %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavrg4(a, b); // (a + ~b + 1) / 2 = (a - b) / 2
|
||||
c = c & 0x80808080; // msb = carry-outs
|
||||
r = c >> 7; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpge4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, s;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetge4(a, b);
|
||||
s = r << 8; // convert bool
|
||||
r = s - r; // to mask
|
||||
#else
|
||||
asm ("not.b32 %0,%0;" : "+r"(b));
|
||||
r = vavrg4 (a, b); // (a + ~b + 1) / 2 = (a - b) / 2
|
||||
r = r & 0x80808080; // msb = carry-outs
|
||||
s = r >> 7; // build mask
|
||||
s = r - s; // from
|
||||
r = s | r; // msbs
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetgt4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset4.u32.u32.gt %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int c;
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down]
|
||||
c = c & 0x80808080; // msb = carry-outs
|
||||
r = c >> 7; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpgt4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetgt4(a, b);
|
||||
c = r << 8; // convert bool
|
||||
r = c - r; // to mask
|
||||
#else
|
||||
asm("not.b32 %0, %0;" : "+r"(b));
|
||||
c = vavg4(a, b); // (a + ~b) / 2 = (a - b) / 2 [rounded down]
|
||||
c = c & 0x80808080; // msb = carry-outs
|
||||
r = c >> 7; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vsetne4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vset4.u32.u32.ne %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
unsigned int c;
|
||||
r = a ^ b; // 0x00 if a == b
|
||||
c = r | 0x80808080; // set msbs, to catch carry out
|
||||
c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80
|
||||
c = r | c; // msb = 1, if r was not 0x00
|
||||
c = c & 0x80808080; // extract msbs
|
||||
r = c >> 7; // convert to bool
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vcmpne4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r, c;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
r = vsetne4(a, b);
|
||||
c = r << 8; // convert bool
|
||||
r = c - r; // to mask
|
||||
#else
|
||||
// inspired by Alan Mycroft's null-byte detection algorithm:
|
||||
// null_byte(x) = ((x - 0x01010101) & (~x & 0x80808080))
|
||||
r = a ^ b; // 0x00 if a == b
|
||||
c = r | 0x80808080; // set msbs, to catch carry out
|
||||
c = c - 0x01010101; // msb = 0, if r was 0x00 or 0x80
|
||||
c = r | c; // msb = 1, if r was not 0x00
|
||||
c = c & 0x80808080; // extract msbs
|
||||
r = c >> 7; // convert
|
||||
r = c - r; // msbs to
|
||||
r = c | r; // mask
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vabsdiff4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vabsdiff4.u32.u32.u32.sat %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vabsdiff.u32.u32.u32.sat %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vabsdiff.u32.u32.u32.sat %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vabsdiff.u32.u32.u32.sat %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vabsdiff.u32.u32.u32.sat %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s;
|
||||
s = vcmpge4(a, b); // mask = 0xff if a >= b
|
||||
r = a ^ b; //
|
||||
s = (r & s) ^ b; // select a when a >= b, else select b => max(a,b)
|
||||
r = s ^ r; // select a when b >= a, else select b => min(a,b)
|
||||
r = s - r; // |a - b| = max(a,b) - min(a,b);
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vmax4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vmax4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vmax.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmax.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmax.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmax.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s;
|
||||
s = vcmpge4(a, b); // mask = 0xff if a >= b
|
||||
r = a & s; // select a when b >= a
|
||||
s = b & ~s; // select b when b < a
|
||||
r = r | s; // combine byte selections
|
||||
#endif
|
||||
|
||||
return r; // byte-wise unsigned maximum
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ unsigned int vmin4(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int r = 0;
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
asm("vmin4.u32.u32.u32 %0, %1, %2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#elif __CUDA_ARCH__ >= 200
|
||||
asm("vmin.u32.u32.u32 %0.b0, %1.b0, %2.b0, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmin.u32.u32.u32 %0.b1, %1.b1, %2.b1, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmin.u32.u32.u32 %0.b2, %1.b2, %2.b2, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
asm("vmin.u32.u32.u32 %0.b3, %1.b3, %2.b3, %3;" : "=r"(r) : "r"(a), "r"(b), "r"(r));
|
||||
#else
|
||||
unsigned int s;
|
||||
s = vcmpge4(b, a); // mask = 0xff if a >= b
|
||||
r = a & s; // select a when b >= a
|
||||
s = b & ~s; // select b when b < a
|
||||
r = r | s; // combine byte selections
|
||||
#endif
|
||||
|
||||
return r;
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif // __OPENCV_GPU_SIMD_FUNCTIONS_HPP__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user