evaluation/UAV-benchmark-MOTD_v1.0/utils/costBlockMex.cpp (154 lines of code) (raw):
#include <matrix.h>
#include "mex.h"
#include <cmath>
#include <omp.h>
#include <algorithm>
using namespace std;
inline int index(int i, int j, int numRows) // 1-indexed to C
{
return (j-1)*numRows + i-1;
}
void correspondingFrames(double* frames1, int N, double* frames2, int M, int* loc)
{
int pos = 0;
int i = 0;
while (i < N && pos < M) {
while (pos < M) {
if (frames1[i] == frames2[pos]) {
loc[i] = pos; pos++; i++;
break;
}
else if (frames1[i] < frames2[pos]) {
loc[i] = -1; i++;
if (i == N) break;
}
else pos++;
}
}
}
void computeDistances(double* tr1, double* tr2, int numPoints1, int numPoints2, int* position, bool world, double* distance)
{
if (world)
{
double* wx1 = &tr1[index(1, 7, numPoints1)];
double* wy1 = &tr1[index(1, 8, numPoints1)];
double* wx2 = &tr2[index(1, 7, numPoints2)];
double* wy2 = &tr2[index(1, 8, numPoints2)];
for (int i = 0; i < numPoints1; i++)
{
if (position[i] == -1)
distance[i] = 1e9;
else
{
double dx = wx1[i] - wx2[position[i]];
double dy = wy1[i] - wy2[position[i]];
distance[i] = sqrt(dx*dx + dy*dy);
}
}
}
else
{
double* l1 = &tr1[index(1, 3, numPoints1)];
double* t1 = &tr1[index(1, 4, numPoints1)];
double* w1 = &tr1[index(1, 5, numPoints1)];
double* h1 = &tr1[index(1, 6, numPoints1)];
double* l2 = &tr2[index(1, 3, numPoints2)];
double* t2 = &tr2[index(1, 4, numPoints2)];
double* w2 = &tr2[index(1, 5, numPoints2)];
double* h2 = &tr2[index(1, 6, numPoints2)];
for (int i = 0; i < numPoints1; i++)
{
if (position[i] == -1)
distance[i] = 0;
else
{
double area1 = w1[i] * h1[i];
double area2 = w2[position[i]] * h2[position[i]];
double x_overlap = max(0.0, min(l1[i] + w1[i], l2[position[i]] + w2[position[i]]) - max(l1[i], l2[position[i]]));
double y_overlap = max(0.0, min(t1[i] + h1[i], t2[position[i]] + h2[position[i]]) - max(t1[i], t2[position[i]]));
double intersectionArea = x_overlap*y_overlap;
double unionArea = area1 + area2 - intersectionArea;
double iou = intersectionArea / unionArea;
distance[i] = iou;
}
}
}
}
void compute(double* tr1, double* tr2, const int* dim1, const int* dim2, double threshold, bool world, double& cost, double& fp, double& fn)
{
int numPoints1 = dim1[0];
int numPoints2 = dim2[0];
int numCols1 = dim1[1];
int numCols2 = dim2[1];
int tr1start, tr1end, tr2start, tr2end;
tr1start = tr1[index(1,1, numPoints1)];
tr1end = tr1[index(numPoints1,1, numPoints1)];
tr2start = tr2[index(1,1, numPoints2)];
tr2end = tr2[index(numPoints2,1, numPoints2)];
bool overlapTest = ((tr1start >= tr2start && tr1start <= tr2end) ||
(tr1end >= tr2start && tr1end <= tr2end) ||
(tr2start >= tr1start && tr2start <= tr1end) ||
(tr2end >= tr1start && tr2end <= tr1end));
if (!overlapTest)
{
fp = numPoints2;
fn = numPoints1;
cost = numPoints1 + numPoints2;
return;
}
int* positionGT = new int[numPoints1];
int* positionPred = new int[numPoints2];
for (int i = 0; i < numPoints1; i++) positionGT[i] = -1;
for (int i = 0; i < numPoints2; i++) positionPred[i] = -1;
double* distanceGT = new double[numPoints1];
double* distancePred = new double[numPoints2];
double* frames1 = &tr1[index(1, 1, numPoints1)];
double* frames2 = &tr2[index(1, 1, numPoints2)];
correspondingFrames(frames1, numPoints1, frames2, numPoints2, positionGT);
correspondingFrames(frames2, numPoints2, frames1, numPoints1, positionPred);
computeDistances(tr1, tr2, numPoints1, numPoints2, positionGT, world, distanceGT);
computeDistances(tr2, tr1, numPoints2, numPoints1, positionPred, world, distancePred);
fp = 0; fn = 0;
if (world) {
for (int i = 0; i < numPoints1; i++) if (distanceGT[i] > threshold) fn++;
for (int i = 0; i < numPoints2; i++) if (distancePred[i] > threshold) fp++;
}
else {
for (int i = 0; i < numPoints1; i++) if (distanceGT[i] < threshold) fn++;
for (int i = 0; i < numPoints2; i++) if (distancePred[i] < threshold) fp++;
}
cost = fp + fn;
delete[] positionGT;
delete[] positionPred;
delete[] distanceGT;
delete[] distancePred;
}
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int numGT = mxGetNumberOfElements(prhs[0]);
int numPred = mxGetNumberOfElements(prhs[1]);
int numEl = numGT + numPred;
double threshold = (double)mxGetScalar(prhs[2]);
bool world = (bool)mxGetScalar(prhs[3]);
double *cost, *fp, *fn;
plhs[0] = mxCreateDoubleMatrix(numGT, numPred, mxREAL);
plhs[1] = mxCreateDoubleMatrix(numGT, numPred, mxREAL);
plhs[2] = mxCreateDoubleMatrix(numGT, numPred, mxREAL);
cost = mxGetPr(plhs[0]);
fp = mxGetPr(plhs[1]);
fn = mxGetPr(plhs[2]);
#pragma omp parallel for
for (int i = 0; i < numGT; i++) {
#pragma omp parallel for
for (int j = 0; j < numPred; j++) {
const int *dim1, *dim2;
dim1 = (int *)mxGetDimensions(mxGetCell(prhs[0], i));
dim2 = (int *)mxGetDimensions(mxGetCell(prhs[1], j));
double* tr1 = mxGetPr(mxGetCell(prhs[0],i));
double* tr2 = mxGetPr(mxGetCell(prhs[1],j));
int ind = j*numGT+ i;
compute(tr1, tr2, dim1, dim2, threshold, world, cost[ind], fp[ind], fn[ind]);
}
}
}