|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
|
|
#include <memory> |
|
|
#include <vector> |
|
|
#include <unordered_set> |
|
|
|
|
|
#include "../geometry.h" |
|
|
#include "../cuda_intellisense.cuh" |
|
|
#include "strided_quad.h" |
|
|
|
|
|
|
|
|
|
|
|
std::vector<torch::Tensor> quad_nms_from_adjacency( |
|
|
torch::Tensor quads, torch::Tensor probs, torch::Tensor adjacency, |
|
|
float probThreshold, float iouThreshold, |
|
|
int64_t maxRegions); |
|
|
|
|
|
template<typename T> |
|
|
struct EmbedQuad_ : public QuadBase_<T, EmbedQuad_<T> > { |
|
|
Point_<T> Vertices[4]; |
|
|
T Confidence; |
|
|
T NumQuads = 0; |
|
|
|
|
|
__device__ |
|
|
EmbedQuad_(T confidence = 0) |
|
|
{ |
|
|
Reset(); |
|
|
Confidence = confidence; |
|
|
} |
|
|
__device__ |
|
|
EmbedQuad_(const EmbedQuad_ &other) = default; |
|
|
|
|
|
__device__ |
|
|
void swap(EmbedQuad_ &other) noexcept { |
|
|
using std::swap; |
|
|
|
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
swap(Vertices[i], other.Vertices[i]); |
|
|
} |
|
|
|
|
|
SWAP(Confidence, other.Confidence); |
|
|
SWAP(NumQuads, other.NumQuads); |
|
|
} |
|
|
|
|
|
__device__ |
|
|
EmbedQuad_(EmbedQuad_ &&other) : EmbedQuad_() { |
|
|
other.swap(*this); |
|
|
} |
|
|
|
|
|
__device__ |
|
|
EmbedQuad_ &operator=(EmbedQuad_ other) { |
|
|
other.swap(*this); |
|
|
return *this; |
|
|
} |
|
|
|
|
|
__device__ |
|
|
void Append(const EmbedQuad_ &other) { |
|
|
Append(other, other.Confidence, other.NumQuads); |
|
|
} |
|
|
|
|
|
template<typename Derived> |
|
|
__device__ |
|
|
void Append(const QuadBase_<T, Derived> &q, T conf, T numQuads = 1) { |
|
|
Confidence *= NumQuads; |
|
|
|
|
|
if (Confidence > 0) { |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] *= Confidence; |
|
|
} |
|
|
} |
|
|
|
|
|
Confidence += conf * numQuads; |
|
|
|
|
|
auto qVertices = static_cast<const Derived *>(&q)->Vertices; |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] += conf * numQuads * qVertices[i]; |
|
|
Vertices[i] /= Confidence; |
|
|
} |
|
|
|
|
|
NumQuads += numQuads; |
|
|
Confidence /= NumQuads; |
|
|
} |
|
|
|
|
|
__device__ |
|
|
void Prepare() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
__device__ |
|
|
void Reset() { |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] = Point_<T>{0, 0}; |
|
|
} |
|
|
Confidence = 0.0f; |
|
|
NumQuads = 0; |
|
|
} |
|
|
|
|
|
__device__ |
|
|
const Point_<T> &operator[](size_t v) const { return Vertices[v]; } |
|
|
__device__ |
|
|
Point_<T> &operator[](size_t v) { return Vertices[v]; } |
|
|
}; |
|
|
|
|
|
struct ZeroInitTag {}; |
|
|
|
|
|
template<typename T> |
|
|
struct MergeQuad_ : public QuadBase_<T, MergeQuad_<T>> { |
|
|
Point_<T> Vertices[4]; |
|
|
T Confidence; |
|
|
T NumQuads; |
|
|
|
|
|
MergeQuad_() = default; |
|
|
|
|
|
__device__ |
|
|
MergeQuad_(ZeroInitTag) : Confidence(0), NumQuads(0) { |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] = Point_<T>{0, 0}; |
|
|
} |
|
|
} |
|
|
|
|
|
template<typename Derived> |
|
|
__device__ |
|
|
void Append(const QuadBase_<T, Derived> &q, T conf) { |
|
|
Confidence += conf; |
|
|
++NumQuads; |
|
|
|
|
|
auto &d = static_cast<const Derived&>(q); |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] += conf * d[i]; |
|
|
} |
|
|
} |
|
|
__device__ |
|
|
void Append(const EmbedQuad_<T> &q) { |
|
|
T qConf = q.NumQuads * q.Confidence; |
|
|
|
|
|
Confidence += qConf; |
|
|
NumQuads += q.NumQuads; |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] += qConf * q.Vertices[i]; |
|
|
} |
|
|
} |
|
|
__device__ |
|
|
void Append(const StridedEmbedQuad_<T> &q) { |
|
|
const T numQuads = q.NumQuads(); |
|
|
const T qConf = numQuads * q.Confidence(); |
|
|
|
|
|
Confidence += qConf; |
|
|
NumQuads += numQuads; |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
Vertices[i] += qConf * q[i]; |
|
|
} |
|
|
} |
|
|
|
|
|
__device__ |
|
|
EmbedQuad_<T> Commit() { |
|
|
EmbedQuad_<T> ret; |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
ret.Vertices[i] = Vertices[i] / Confidence; |
|
|
} |
|
|
ret.Confidence = Confidence / NumQuads; |
|
|
ret.NumQuads = NumQuads; |
|
|
|
|
|
return ret; |
|
|
} |
|
|
|
|
|
__device__ |
|
|
const Point_<T> &operator[](size_t v) const { return Vertices[v]; } |
|
|
__device__ |
|
|
Point_<T> &operator[](size_t v) { return Vertices[v]; } |
|
|
}; |
|
|
|
|
|
template<typename T, typename Intermediate=float> |
|
|
__device__ |
|
|
inline T triangle_root(T val) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Intermediate numer = Intermediate(-1) + sqrt(Intermediate(1) + Intermediate(8) * Intermediate(val)); |
|
|
Intermediate denom = Intermediate(2); |
|
|
|
|
|
Intermediate ret = floor(numer / denom); |
|
|
return T(ret); |
|
|
} |
|
|
|
|
|
template<typename T> |
|
|
void visit_node(const std::vector<EmbedQuad_<T>> &allQuads, size_t quadIdx, |
|
|
const std::vector<std::vector<size_t>> &adjIdxs, EmbedQuad_<T> &currQuad, |
|
|
std::unordered_set<size_t> &visited) |
|
|
{ |
|
|
if (visited.count(quadIdx) > 0) return; |
|
|
|
|
|
const EmbedQuad_<T> &vQuad = allQuads[quadIdx]; |
|
|
|
|
|
currQuad.Append(vQuad); |
|
|
visited.insert(quadIdx); |
|
|
|
|
|
for (size_t childIdx : adjIdxs[quadIdx]) { |
|
|
visit_node(allQuads, childIdx, adjIdxs, currQuad, visited); |
|
|
} |
|
|
} |
|
|
|
|
|
template<typename T, typename Derived, typename scalar_t> |
|
|
void copy_quad(const QuadBase_<T, Derived> &srcQuad, scalar_t *pDest) |
|
|
{ |
|
|
auto vertices = static_cast<const Derived*>(&srcQuad)->Vertices; |
|
|
for (size_t i = 0; i < 4; ++i) { |
|
|
const Point_<T> &v = vertices[i]; |
|
|
*pDest++ = v.X; |
|
|
*pDest++ = v.Y; |
|
|
} |
|
|
} |
|
|
|