Files
gray_match/sum.cpp
2025-02-24 22:31:42 +08:00

142 lines
4.9 KiB
C++

#include "sum.h"
#include <opencv2/core/hal/intrin.hpp>
inline cv::v_uint32x4 v_add_expand(const cv::v_uint16x8 &src) {
cv::v_uint32x4 low;
cv::v_uint32x4 high;
cv::v_expand(src, low, high);
return cv::v_add(low, high);
}
inline cv::v_uint64x2 v_add_expand(const cv::v_uint32x4 &src) {
cv::v_uint64x2 low;
cv::v_uint64x2 high;
cv::v_expand(src, low, high);
return cv::v_add(low, high);
}
inline void computeSum(const cv::v_uint8x16 &src, cv::v_uint32x4 &sum, cv::v_uint64x2 &sqSum) {
cv::v_uint16x8 low;
cv::v_uint16x8 high;
cv::v_expand(src, low, high);
sum = cv::v_add(sum, v_add_expand(cv::v_add(low, high)));
auto dot = cv::v_dotprod_expand_fast(src, src);
sqSum = cv::v_add(sqSum, v_add_expand(dot));
}
void computeSum(const cv::Mat &src, const HRegion &hRegion, uint64 &sum, uint64 &sqSum) {
constexpr auto blockSize = simdSize(cv::v_uint8);
cv::v_uint32x4 vSum = cv::v_setzero_u32();
cv::v_uint64x2 vSqSum = cv::v_setzero_u64();
uint32_t partSum = 0;
uint64 partSqSum = 0;
for (const auto &rle : hRegion) {
auto *ptr = src.ptr<uchar>(rle.row) + rle.startColumn;
int i = 0;
for (; i < rle.length - blockSize; i += blockSize) {
computeSum(cv::v_load(ptr + i), vSum, vSqSum);
}
// TODO aligned fill 0
for (; i < rle.length; i++) {
auto val = ptr[ i ];
partSum += val;
partSqSum += (ushort)val * (ushort)val;
}
}
sum = cv::v_reduce_sum(vSum) + partSum;
sqSum = cv::v_reduce_sum(vSqSum) + partSqSum;
}
inline void computeSumDiff(const cv::v_uint8x16 &start, const cv::v_uint8x16 &end,
cv::v_int32x4 &diff0, cv::v_int32x4 &diff1, cv::v_int32x4 &diff2,
cv::v_int32x4 &diff3) {}
inline void computeSqSumDiff(const cv::v_uint8x16 &start, const cv::v_uint8x16 &end,
cv::v_int32x4 &diff0, cv::v_int32x4 &diff1, cv::v_int32x4 &diff2,
cv::v_int32x4 &diff3) {}
inline void v_expand_store(double *ptr, const cv::v_int32x4 &val, double &base) {
auto vBase = cv::v_setall_f64(base);
}
void shiftH(const cv::Mat &src, const HRegion &hRegion, int row, cv::Mat &sum, cv::Mat &sqSum) {
constexpr auto blockSize = simdSize(cv::v_uint8);
auto *srcPtr = src.ptr<uchar>();
auto *sumPtr = sum.ptr<double>(row);
auto *sqSumPtr = sqSum.ptr<double>(row);
double sumBase = *sumPtr;
double sqSumBase = *sqSumPtr;
int i = 1;
for (; i < sum.cols - blockSize; i += blockSize) {
cv::v_int32x4 diff0 = cv::v_setzero_s32();
cv::v_int32x4 diff1 = cv::v_setzero_s32();
cv::v_int32x4 diff2 = cv::v_setzero_s32();
cv::v_int32x4 diff3 = cv::v_setzero_s32();
cv::v_int32x4 diff10 = cv::v_setzero_s32();
cv::v_int32x4 diff11 = cv::v_setzero_s32();
cv::v_int32x4 diff12 = cv::v_setzero_s32();
cv::v_int32x4 diff13 = cv::v_setzero_s32();
for (const auto &rle : hRegion) {
auto *startPtr = srcPtr + (row + rle.row) * src.step + rle.startColumn;
auto *endPtr = startPtr + rle.length;
auto vStart = cv::v_load(startPtr);
auto vEnd = cv::v_load(endPtr);
computeSumDiff(vStart, vEnd, diff0, diff1, diff2, diff3);
computeSumDiff(vStart, vEnd, diff10, diff11, diff12, diff13);
}
auto *sumPtrStart = sumPtr + i;
v_expand_store(sumPtrStart, diff0, sumBase);
v_expand_store(sumPtrStart + 4, diff1, sumBase);
v_expand_store(sumPtrStart + 8, diff2, sumBase);
v_expand_store(sumPtrStart + 12, diff3, sumBase);
auto *sqSumPtrStart = sqSumPtr + i;
v_expand_store(sqSumPtrStart, diff10, sumBase);
v_expand_store(sqSumPtrStart + 4, diff11, sumBase);
v_expand_store(sqSumPtrStart + 8, diff12, sumBase);
v_expand_store(sqSumPtrStart + 12, diff13, sumBase);
}
for (; i < sum.cols; i++) {}
}
void shiftV(const cv::Mat &src, const VRegion &vRegion, int row, cv::Mat &sum, cv::Mat &sqSum) {}
void integralSum(const cv::Mat &src, cv::Mat &sum, cv::Mat &sqSum, const cv::Size &templateSize,
const HRegion &hRegion, const VRegion &vRegion) {
const auto size = src.size() - templateSize + cv::Size(1, 1);
sum.create(size, CV_64FC1);
sqSum.create(size, CV_64FC1);
auto sumPtr = sum.ptr<double>();
auto sqSumPtr = sqSum.ptr<double>();
// compute first
uint64 sum0;
uint64 sqSum0;
computeSum(src, hRegion, sum0, sqSum0);
sumPtr[ 0 ] = static_cast<double>(sum0);
sqSumPtr[ 0 ] = static_cast<double>(sqSum0);
for (int y = 0; y < size.height; y++) {
shiftH(src, hRegion, y, sum, sqSum);
if (y + 1 < size.height) {
shiftV(src, vRegion, y + 1, sum, sqSum);
}
}
}