Commit 6f1b6eb4 authored by jaco's avatar jaco

Objectness porting partially computed

parent 071b7ae1
......@@ -43,6 +43,12 @@
#define __OPENCV_SALIENCY_SPECIALIZED_CLASSES_HPP_
#include "saliencyBaseClasses.hpp"
#include "kyheader.h"
#include "ValStructVec.h"
#include "FilterTIG.h"
#include <cstdio>
#include <string>
#include <iostream>
//TODO delete
//#define SALIENCY_DEBUG true
......@@ -134,25 +140,72 @@ class CV_EXPORTS_W MotionSaliencyPBAS : public MotionSaliency
class CV_EXPORTS_W ObjectnessBING : public Objectness
{
public:
/*struct CV_EXPORTS Params
{
Params();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
}; */
//ObjectnessBING( const ObjectnessBING::Params &parameters = ObjectnessBING::Params() );
ObjectnessBING();
~ObjectnessBING();
void read( const FileNode& fn );
void write( FileStorage& fs ) const;
// Load trained model.
int loadTrainedModel(std::string modelName = ""); // Return -1, 0, or 1 if partial, none, or all loaded
// Get potential bounding boxes, each of which is represented by a Vec4i for (minX, minY, maxX, maxY).
// The trained model should be prepared before calling this function: loadTrainedModel() or trainStageI() + trainStageII().
// Use numDet to control the final number of proposed bounding boxes, and number of per size (scale and aspect ratio)
void getObjBndBoxes(CMat &img3u, ValStructVec<float, Vec4i> &valBoxes, int numDetPerSize = 120);
void getObjBndBoxesForImage(Mat img, ValStructVec<float, Vec4i> &boxes, int numDetPerSize);
void setColorSpace(int clr = MAXBGR);
// Read matrix from binary file
static bool matRead( const std::string& filename, Mat& M);
enum {MAXBGR, HSV, G};
inline static float LoG(float x, float y, float delta) {float d = -(x*x+y*y)/(2*delta*delta); return -1.0f/((float)(CV_PI)*pow(delta, 4)) * (1+d)*exp(d);} // Laplacian of Gaussian
protected:
bool computeSaliencyImpl( const InputArray& src, OutputArray& dst );
AlgorithmInfo* info() const; //{ return 0; }
private:
//Params params;
private: // Parameters
const double _base, _logBase; // base for window size quantization
const int _W; // As described in the paper: #Size, Size(_W, _H) of feature window.
const int _NSS; // Size for non-maximal suppress
const int _maxT, _minT, _numT; // The minimal and maximal dimensions of the template
int _Clr; //
static const char* _clrName[3];
//DataSetVOC &_voc; // The dataset for training, testing
std:: string _modelName, _trainDirSI, _bbResDir;
vecI _svmSzIdxs; // Indexes of active size. It's equal to _svmFilters.size() and _svmReW1f.rows
Mat _svmFilter; // Filters learned at stage I, each is a _H by _W CV_32F matrix
FilterTIG _tigF; // TIG filter
Mat _svmReW1f; // Re-weight parameters learned at stage II.
private: // Help functions
bool filtersLoaded() {int n = _svmSzIdxs.size(); return n > 0 && _svmReW1f.size() == Size(2, n) && _svmFilter.size() == Size(_W, _W);}
void predictBBoxSI(CMat &mag3u, ValStructVec<float, Vec4i> &valBoxes, vecI &sz, int NUM_WIN_PSZ = 100, bool fast = true);
void predictBBoxSII(ValStructVec<float, Vec4i> &valBoxes, const vecI &sz);
// Calculate the image gradient: center option as in VLFeat
void gradientMag(CMat &imgBGR3u, Mat &mag1u);
static void gradientRGB(CMat &bgr3u, Mat &mag1u);
static void gradientGray(CMat &bgr3u, Mat &mag1u);
static void gradientHSV(CMat &bgr3u, Mat &mag1u);
static void gradientXY(CMat &x1i, CMat &y1i, Mat &mag1u);
static inline int bgrMaxDist(const Vec3b &u, const Vec3b &v) {int b = abs(u[0]-v[0]), g = abs(u[1]-v[1]), r = abs(u[2]-v[2]); b = max(b,g); return max(b,r);}
static inline int vecDist3b(const Vec3b &u, const Vec3b &v) {return abs(u[0]-v[0]) + abs(u[1]-v[1]) + abs(u[2]-v[2]);}
//Non-maximal suppress
static void nonMaxSup(CMat &matchCost1f, ValStructVec<float, Point> &matchCost, int NSS = 1, int maxPoint = 50, bool fast = true);
};
......
......@@ -15,7 +15,7 @@ static void help()
{
cout << "\nThis example shows the functionality of \"Saliency \""
"Call:\n"
"./example_saliency_computeSaliency <saliencyAlgorithmType.[saliencyAlgorithmTypeSubType]> <video_name> <start_frame> \n"
"./example_saliency_computeSaliency <SALIENCY.[saliencyAlgorithmSubType]> <video_name> <start_frame> \n"
<< endl;
}
......
#pragma once
#ifndef CMTIMER_H
#define CMTIMER_H
#include "kyheader.h"
class CmTimer
{
public:
CmTimer(CStr t):title(t) { is_started = false; start_clock = 0; cumulative_clock = 0; n_starts = 0; }
~CmTimer(){ if (is_started) printf("CmTimer '%s' is started and is being destroyed.\n", title.c_str()); }
inline void Start();
inline void Stop();
inline void Reset();
inline bool Report();
inline bool StopAndReport() { Stop(); return Report(); }
inline float TimeInSeconds();
private:
CStr title;
bool is_started;
clock_t start_clock;
clock_t cumulative_clock;
unsigned int n_starts;
};
/************************************************************************/
/* Implementations */
/************************************************************************/
void CmTimer::Start()
{
if (is_started){
printf("CmTimer '%s' is already started. Nothing done.\n", title.c_str());
return;
}
is_started = true;
n_starts++;
start_clock = clock();
}
void CmTimer::Stop()
{
if (!is_started){
printf("CmTimer '%s' is started. Nothing done\n", title.c_str());
return;
}
cumulative_clock += clock() - start_clock;
is_started = false;
}
void CmTimer::Reset()
{
if (is_started) {
printf("CmTimer '%s'is started during reset request.\n Only reset cumulative time.\n");
return;
}
cumulative_clock = 0;
}
bool CmTimer::Report()
{
if (is_started){
printf("CmTimer '%s' is started.\n Cannot provide a time report.", title.c_str());
return false;
}
float timeUsed = TimeInSeconds();
printf("[%s] CumuTime: %gs, #run: %d, AvgTime: %gs\n", title.c_str(), timeUsed, n_starts, timeUsed/n_starts);
return true;
}
float CmTimer::TimeInSeconds()
{
if (is_started){
printf("CmTimer '%s' is started. Nothing done\n", title.c_str());
return 0;
}
return float(cumulative_clock) / CLOCKS_PER_SEC;
}
#endif // CMTIMER_H
#include "kyheader.h"
#include "FilterTIG.h"
#include "CmShow.h"
void FilterTIG::update(CMat &w1f){
CV_Assert(w1f.cols * w1f.rows == D && w1f.type() == CV_32F && w1f.isContinuous());
float b[D], residuals[D];
memcpy(residuals, w1f.data, sizeof(float)*D);
for (int i = 0; i < NUM_COMP; i++){
float avg = 0;
for (int j = 0; j < D; j++){
b[j] = residuals[j] >= 0.0f ? 1.0f : -1.0f;
avg += residuals[j] * b[j];
}
avg /= D;
_coeffs1[i] = avg, _coeffs2[i] = avg*2, _coeffs4[i] = avg*4, _coeffs8[i] = avg*8;
for (int j = 0; j < D; j++)
residuals[j] -= avg*b[j];
UINT64 tig = 0;
for (int j = 0; j < D; j++)
tig = (tig << 1) | (b[j] > 0 ? 1 : 0);
_bTIGs[i] = tig;
}
}
void FilterTIG::reconstruct(Mat &w1f){
w1f = Mat::zeros(8, 8, CV_32F);
float *weight = (float*)w1f.data;
for (int i = 0; i < NUM_COMP; i++){
UINT64 tig = _bTIGs[i];
for (int j = 0; j < D; j++)
weight[j] += _coeffs1[i] * (((tig >> (63-j)) & 1) ? 1 : -1);
}
}
// For a W by H gradient magnitude map, find a W-7 by H-7 CV_32F matching score map
// Please refer to my paper for definition of the variables used in this function
Mat FilterTIG::matchTemplate(const Mat &mag1u){
const int H = mag1u.rows, W = mag1u.cols;
const Size sz(W+1, H+1); // Expand original size to avoid dealing with boundary conditions
Mat_<INT64> Tig1 = Mat_<INT64>::zeros(sz), Tig2 = Mat_<INT64>::zeros(sz);
Mat_<INT64> Tig4 = Mat_<INT64>::zeros(sz), Tig8 = Mat_<INT64>::zeros(sz);
Mat_<byte> Row1 = Mat_<byte>::zeros(sz), Row2 = Mat_<byte>::zeros(sz);
Mat_<byte> Row4 = Mat_<byte>::zeros(sz), Row8 = Mat_<byte>::zeros(sz);
Mat_<float> scores(sz);
for(int y = 1; y <= H; y++){
const byte* G = mag1u.ptr<byte>(y-1);
INT64* T1 = Tig1.ptr<INT64>(y); // Binary TIG of current row
INT64* T2 = Tig2.ptr<INT64>(y);
INT64* T4 = Tig4.ptr<INT64>(y);
INT64* T8 = Tig8.ptr<INT64>(y);
INT64* Tu1 = Tig1.ptr<INT64>(y-1); // Binary TIG of upper row
INT64* Tu2 = Tig2.ptr<INT64>(y-1);
INT64* Tu4 = Tig4.ptr<INT64>(y-1);
INT64* Tu8 = Tig8.ptr<INT64>(y-1);
byte* R1 = Row1.ptr<byte>(y);
byte* R2 = Row2.ptr<byte>(y);
byte* R4 = Row4.ptr<byte>(y);
byte* R8 = Row8.ptr<byte>(y);
float *s = scores.ptr<float>(y);
for (int x = 1; x <= W; x++) {
byte g = G[x-1];
R1[x] = (R1[x-1] << 1) | ((g >> 4) & 1);
R2[x] = (R2[x-1] << 1) | ((g >> 5) & 1);
R4[x] = (R4[x-1] << 1) | ((g >> 6) & 1);
R8[x] = (R8[x-1] << 1) | ((g >> 7) & 1);
T1[x] = (Tu1[x] << 8) | R1[x];
T2[x] = (Tu2[x] << 8) | R2[x];
T4[x] = (Tu4[x] << 8) | R4[x];
T8[x] = (Tu8[x] << 8) | R8[x];
s[x] = dot(T1[x], T2[x], T4[x], T8[x]);
}
}
Mat matchCost1f;
scores(Rect(8, 8, W-7, H-7)).copyTo(matchCost1f);
return matchCost1f;
}
#pragma once
#include "kyheader.h"
class FilterTIG
{
public:
void update(CMat &w);
// For a W by H gradient magnitude map, find a W-7 by H-7 CV_32F matching score map
Mat matchTemplate(const Mat &mag1u);
inline float dot(const INT64 tig1, const INT64 tig2, const INT64 tig4, const INT64 tig8);
public:
void reconstruct(Mat &w); // For illustration purpose
private:
static const int NUM_COMP = 2; // Number of components
static const int D = 64; // Dimension of TIG
INT64 _bTIGs[NUM_COMP]; // Binary TIG features
float _coeffs1[NUM_COMP]; // Coefficients of binary TIG features
// For efficiently deals with different bits in CV_8U gradient map
float _coeffs2[NUM_COMP], _coeffs4[NUM_COMP], _coeffs8[NUM_COMP];
};
inline float FilterTIG::dot(const INT64 tig1, const INT64 tig2, const INT64 tig4, const INT64 tig8)
{
INT64 bcT1 = __builtin_popcountll(tig1);
INT64 bcT2 = __builtin_popcountll(tig2);
INT64 bcT4 = __builtin_popcountll(tig4);
INT64 bcT8 = __builtin_popcountll(tig8);
INT64 bc01 = (__builtin_popcountll(_bTIGs[0] & tig1) << 1) - bcT1;
INT64 bc02 = ((__builtin_popcountll(_bTIGs[0] & tig2) << 1) - bcT2) << 1;
INT64 bc04 = ((__builtin_popcountll(_bTIGs[0] & tig4) << 1) - bcT4) << 2;
INT64 bc08 = ((__builtin_popcountll(_bTIGs[0] & tig8) << 1) - bcT8) << 3;
INT64 bc11 = (__builtin_popcountll(_bTIGs[1] & tig1) << 1) - bcT1;
INT64 bc12 = ((__builtin_popcountll(_bTIGs[1] & tig2) << 1) - bcT2) << 1;
INT64 bc14 = ((__builtin_popcountll(_bTIGs[1] & tig4) << 1) - bcT4) << 2;
INT64 bc18 = ((__builtin_popcountll(_bTIGs[1] & tig8) << 1) - bcT8) << 3;
return _coeffs1[0] * (bc01 + bc02 + bc04 + bc08) + _coeffs1[1] * (bc11 + bc12 + bc14 + bc18);
}
#pragma once
/************************************************************************/
/* A value struct vector that supports efficient sorting */
/************************************************************************/
template<typename VT, typename ST>
struct ValStructVec
{
ValStructVec(){clear();}
inline int size() const {return sz;}
inline void clear() {sz = 0; structVals.clear(); valIdxes.clear();}
inline void reserve(int resSz){clear(); structVals.reserve(resSz); valIdxes.reserve(resSz); }
inline void pushBack(const VT& val, const ST& structVal) {valIdxes.push_back(make_pair(val, sz)); structVals.push_back(structVal); sz++;}
inline const VT& operator ()(int i) const {return valIdxes[i].first;} // Should be called after sort
inline const ST& operator [](int i) const {return structVals[valIdxes[i].second];} // Should be called after sort
inline VT& operator ()(int i) {return valIdxes[i].first;} // Should be called after sort
inline ST& operator [](int i) {return structVals[valIdxes[i].second];} // Should be called after sort
void sort(bool descendOrder = true);
const vector<ST> &getSortedStructVal();
void append(const ValStructVec<VT, ST> &newVals, int startV = 0);
vector<ST> structVals; // struct values
private:
int sz; // size of the value struct vector
vector<pair<VT, int>> valIdxes; // Indexes after sort
bool smaller() {return true;};
vector<ST> sortedStructVals;
};
template<typename VT, typename ST>
void ValStructVec<VT, ST>::append(const ValStructVec<VT, ST> &newVals, int startV)
{
int sz = newVals.size();
for (int i = 0; i < sz; i++)
pushBack((float)((i+300)*startV)/*newVals(i)*/, newVals[i]);
}
template<typename VT, typename ST>
void ValStructVec<VT, ST>::sort(bool descendOrder /* = true */)
{
if (descendOrder)
std::sort(valIdxes.begin(), valIdxes.end(), std::greater<pair<VT, int>>());
else
std::sort(valIdxes.begin(), valIdxes.end(), std::less<pair<VT, int>>());
}
template<typename VT, typename ST>
const vector<ST>& ValStructVec<VT, ST>::getSortedStructVal()
{
sortedStructVals.resize(sz);
for (int i = 0; i < sz; i++)
sortedStructVals[i] = structVals[valIdxes[i].second];
return sortedStructVals;
}
/*
void valStructVecDemo()
{
ValStructVec<int, string> sVals;
sVals.pushBack(3, "String 3");
sVals.pushBack(5, "String 5");
sVals.pushBack(4, "String 4");
sVals.pushBack(1, "String 1");
sVals.sort(false);
for (int i = 0; i < sVals.size(); i++)
printf("%d, %s\n", sVals(i), _S(sVals[i]));
}
*/
#ifndef KYHEADER_H
#define KYHEADER_H
#include <assert.h>
#include <string>
#include <vector>
#include <functional>
#include <list>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <time.h>
#include <fstream>
#include <random>
//#include <atlstr.h>
//#include <atltypes.h>
#include <omp.h>
#include <strstream>
// TODO: reference additional headers your program requires here
//#include "LibLinear/linear.h"
//#include <opencv2/opencv.hpp>
#include "opencv2/core.hpp"
#define CV_VERSION_ID CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)
#ifdef _DEBUG
#define cvLIB(name) "opencv_" name CV_VERSION_ID "d"
#else
#define cvLIB(name) "opencv_" name CV_VERSION_ID
#endif
#pragma comment( lib, cvLIB("core"))
#pragma comment( lib, cvLIB("imgproc"))
#pragma comment( lib, cvLIB("highgui"))
using namespace cv;
using namespace std;
#ifdef WIN32
/* windows stuff */
#else
typedef unsigned long DWORD;
typedef unsigned short WORD;
typedef unsigned int UNINT32;
typedef bool BOOL;
typedef void *HANDLE;
typedef unsigned char byte;
#endif
typedef std::vector<int> vecI;
typedef const std::string CStr;
typedef const Mat CMat;
typedef std::vector<std::string> vecS;
typedef std::vector<Mat> vecM;
typedef std::vector<float> vecF;
typedef std::vector<double> vecD;
enum{CV_FLIP_BOTH = -1, CV_FLIP_VERTICAL = 0, CV_FLIP_HORIZONTAL = 1};
#define _S(str) ((str).c_str())
#define CHK_IND(p) ((p).x >= 0 && (p).x < _w && (p).y >= 0 && (p).y < _h)
#define CV_Assert_(expr, args) \
{\
if(!(expr)) {\
String msg = cv::format args; \
printf("%s in %s:%d\n", msg.c_str(), __FILE__, __LINE__); \
cv::error(cv::Exception(CV_StsAssert, msg, __FUNCTION__, __FILE__, __LINE__) ); }\
}
using namespace std;
// Return -1 if not in the list
template<typename T>
static inline int findFromList(const T &word, const vector<T> &strList) {
//TODO delete test code
//cout << "\n\n" << "word" <<" "<< word << endl;
for(int i=0; i<strList.size(); i++) {
//cout <<"test word:"<< word << " " << endl;
//cout << "Size w " << word.size() << " Size L "<< strList[i].size() << endl;
}
auto it = std::find(strList.begin(),strList.end(), word);
if (it == strList.end())
{
return -1;
} else
{
auto index = std::distance(strList.begin(), it);
//cout << "index" <<" "<< index << endl;
return index;
}
}
/*template<typename T>
static inline int findFromList(const string &word, const vector<T> &strList) {
//for(int i=0; i<strList.size(); i++){
//cout <<"element: " <<strList[i]<<" "<<word << endl;
//if (std::strcmp(word.c_str(),strList[i].c_str())==0) return i;
}
return -1;
}
*/
template<typename T> inline T sqr(T x) { return x * x; } // out of range risk for T = byte, ...
template<class T, int D> inline T vecSqrDist(const Vec<T, D> &v1, const Vec<T, D> &v2) {T s = 0; for (int i=0; i<D; i++) s += sqr(v1[i] - v2[i]); return s;} // out of range risk for T = byte, ...
template<class T, int D> inline T vecDist(const Vec<T, D> &v1, const Vec<T, D> &v2) { return sqrt(vecSqrDist(v1, v2)); } // out of range risk for T = byte, ...
inline Rect Vec4i2Rect(Vec4i &v){return Rect(Point(v[0] - 1, v[1] - 1), Point(v[2], v[3])); }
#ifdef __WIN32
#define INT64 long long
#else
#define INT64 long
typedef unsigned long UINT64;
#endif
/////
#if (_MSC_VER >= 1500)
# include <intrin.h>
# define POPCNT(x) __popcnt(x)
# define POPCNT64(x) __popcnt64(x)
#endif
#if defined(__GNUC__)
# define POPCNT(x) __builtin_popcount(x)
# define POPCNT64(x) __builtin_popcountll(x)
#endif
inline int popcnt64(register uint64_t u)
{
u = (u & 0x5555555555555555) + ((u >> 1) & 0x5555555555555555);
u = (u & 0x3333333333333333) + ((u >> 2) & 0x3333333333333333);
u = (u & 0x0f0f0f0f0f0f0f0f) + ((u >> 4) & 0x0f0f0f0f0f0f0f0f);
u = (u & 0x00ff00ff00ff00ff) + ((u >> 8) & 0x00ff00ff00ff00ff);
u = (u & 0x0000ffff0000ffff) + ((u >>16) & 0x0000ffff0000ffff);
u = (u & 0x00000000ffffffff) + ((u >>32) & 0x00000000ffffffff);
return u;
}
inline int popcnt(register uint32_t u)
{
u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
u = (u & 0x0f0f0f0f) + ((u >> 4) & 0x0f0f0f0f);
u = (u & 0x00ff00ff) + ((u >> 8) & 0x00ff00ff);
u = (u & 0x0000ffff) + ((u >>16) & 0x0000ffff);
return u;
}
inline int popcnt64_nibble(register uint64_t u)
{
static const uint8_t Table[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
};
int c = 0;
while (u)
{
c += Table[u & 0xf];
u >>= 4;
}
return c;
}
inline int popcnt_nibble(register uint32_t u)
{
static const uint8_t Table[] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
};
int c = 0;
while (u)
{
c += Table[u & 0xf];
u >>= 4;
}
return c;
}
inline int popcnt64_byte(register uint64_t u)
{
#define B2(k) k, k+1, k+1, k+2
#define B4(k) B2(k), B2(k+1), B2(k+1), B2(k+2)
#define B6(k) B4(k), B4(k+1), B4(k+1), B4(k+2)
static const uint8_t Table[] = {
B6(0), B6(1), B6(1), B6(2)
};
#undef B6
#undef B4
#undef B2
int c = 0;
while (u)
{
c += Table[u & 0xff];
u >>= 8;
}
return c;
}
inline int popcnt_byte(register uint32_t u)
{
#define B2(k) k, k+1, k+1, k+2
#define B4(k) B2(k), B2(k+1), B2(k+1), B2(k+2)
#define B6(k) B4(k), B4(k+1), B4(k+1), B4(k+2)
static const uint8_t Table[] = {
B6(0), B6(1), B6(1), B6(2)
};
#undef B6
#undef B4
#undef B2
int c = 0;
while (u)
{
c += Table[u & 0xff];
u >>= 8;
}
return c;
}
/////
#include "CmTimer.h"
#include "CmFile.h"
#endif // KYHEADER_H
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment