You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

594 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <cmath>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <cstdlib>
#include "Arith_Utils.h"
#include "Arith_SysStruct.h"
#ifdef __linux__
#include <unistd.h>
#define ACCESS access
#elif _WIN32
#include <windows.h>
#include <io.h>
#define ACCESS _access
#endif
void AddMat(double* A, double* B, int mn, double* AaddB)
{
for (size_t i = 0; i < mn; i++)
{
AaddB[i] = A[i] + B[i];
}
}
void MultiMatScalar(double scalar, double* A, double* sA, int mn)
{
for (size_t i = 0; i < mn; i++)
{
sA[i] = scalar * A[i];
}
}
void TransposeMat(double* A, int w, int h, double* AT)
{
for (int i = 0; i < h; i++)
{
for (int j = 0; j < w; j++)
{
AT[j * w + i] = A[i * h + j];
}
}
}
/* 1 0 0
0 cos sin
0 -sin cos
*/
void Rx(double omega, double* Opp)
{
double coso = cos(RADIAN(omega));
double sino = sin(RADIAN(omega));
Opp[0] = 1;
Opp[1] = 0;
Opp[2] = 0;
Opp[3] = 0;
Opp[4] = coso;
Opp[5] = sino;
Opp[6] = 0;
Opp[7] = -sino;
Opp[8] = coso;
}
/* cos 0 sin
0 1 0
-sin 0 cos
*/
void Ry(double omega, double* Opp)
{
double coso = cos(RADIAN(omega));
double sino = sin(RADIAN(omega));
Opp[0] = coso;
Opp[1] = 0;
Opp[2] = sino;
Opp[3] = 0;
Opp[4] = 1;
Opp[5] = 0;
Opp[6] = -sino;
Opp[7] = 0;
Opp[8] = coso;
}
/* cos sin 0
-sin cos 0
0 0 1
*/
void Rz(double omega, double* Opp)
{
double coso = cos(RADIAN(omega));
double sino = sin(RADIAN(omega));
Opp[0] = coso;
Opp[1] = sino;
Opp[2] = 0;
Opp[3] = -sino;
Opp[4] = coso;
Opp[5] = 0;
Opp[6] = 0;
Opp[7] = 0;
Opp[8] = 1;
}
// 镜面反射矩阵
void RMirror(PointXYZ normalVec, double* Opp)
{
// M = eye(3)-(2*N*N');
Opp[0] = 1 - 2 * normalVec.X * normalVec.X;
Opp[1] = -2 * normalVec.X * normalVec.Y;
Opp[2] = -2 * normalVec.X * normalVec.Z;
Opp[3] = -2 * normalVec.X * normalVec.Y;
Opp[4] = 1 - 2 * normalVec.Y * normalVec.Y;
Opp[5] = -2 * normalVec.Y * normalVec.Z;
Opp[6] = -2 * normalVec.X * normalVec.Z;
Opp[7] = -2 * normalVec.Y * normalVec.Z;
Opp[8] = 1 - 2 * normalVec.Z * normalVec.Z;
}
//*********************************************************************************************
// 矩阵乘法
//*********************************************************************************************
void MultiMat(double* A, double* B, double* AB, int m, int n, int p)
{
// Am*n ; Bn*p ;
int i, j, k;
double Multisum;
for (i = 0; i < m; i++)
{
for (j = 0; j < p; j++)
{
Multisum = 0;
for (k = 0; k < n; k++)
Multisum += A[i * n + k] * B[k * p + j];
AB[i * p + j] = Multisum;
}
}
}
//*********************************************************************************************
//
//*********************************************************************************************
void MultiMat33(double* A, double* B, double* AB)
{
MultiMat(A, B, AB, 3, 3, 3);
}
//*********************************************************************************************
//
//*********************************************************************************************
void MultiMat333(double* A, double* B, double* C, double* ABC)
{
double BC[9];
MultiMat(B, C, BC, 3, 3, 3);
MultiMat(A, BC, ABC, 3, 3, 3);
}
// 对点/矢量旋转
PointXYZ RtPoint(double* M, PointXYZ Point)
{
// M * [X,Y,Z]'
double A[3];
double G[3];
A[0] = Point.X;
A[1] = Point.Y;
A[2] = Point.Z;
MultiMat(M, A, G, 3, 3, 1);
PointXYZ result;
result.X = G[0];
result.Y = G[1];
result.Z = G[2];
return result;
}
// 标准化矢量
PointXYZ NormPoint(PointXYZ Point)
{
double Len = sqrt(Point.X * Point.X + Point.Y * Point.Y + Point.Z * Point.Z);
Point.X /= Len;
Point.Y /= Len;
Point.Z /= Len;
return Point;
}
void eye3(double* M)
{
memset(M, 0, sizeof(double) * 9);
M[0] = 1;
M[4] = 1;
M[8] = 1;
}
void invMat3(double* A, double* invA)
{
double a1 = A[0];
double a2 = A[1];
double a3 = A[2];
double b1 = A[3];
double b2 = A[4];
double b3 = A[5];
double c1 = A[6];
double c2 = A[7];
double c3 = A[8];
//A*
double Astar[9] = { 0 };
Astar[0] = b2 * c3 - c2 * b3;
Astar[1] = c1 * b3 - b1 * c3;
Astar[2] = b1 * c2 - c1 * b2;
Astar[3] = c2 * a3 - a2 * c3;
Astar[4] = a1 * c3 - c1 * a3;
Astar[5] = a2 * c1 - a1 * c2;
Astar[6] = a2 * b3 - b2 * a3;
Astar[7] = b1 * a3 - a1 * b3;
Astar[8] = a1 * b2 - a2 * b1;
double detA = a1 * (b2 * c3 - c2 * b3) - a2 * (b1 * c3 - c1 * b3) + a3 * (b1 * c2 - c1 * b2);
for (size_t i = 0; i < 9; i++)
{
invA[i] = Astar[i] / detA;
}
}
// 旋转向量转矩阵
void rotationVectorToMatrix(PointXYZ rotaVec_One, float rotaAgl, double* Mat)
{
//
PointXYZ vec_norm = NormPoint(rotaVec_One);
// K
double K[9] = { 0,-vec_norm.Z,vec_norm.Y,
vec_norm.Z,0,-vec_norm.X,
-vec_norm.Y,vec_norm.X,0 };
// eye(3)
double eye[9] = { 0 };
eye3(eye);
// eye + sind(r) * K + (1-cos(r)) * K * K
double sK[9] = { 0 };
MultiMatScalar(sin(RADIAN(rotaAgl)), K, sK, 9);
double KK[9] = { 0 };
MultiMat33(K, K, KK);
double scK[9] = { 0 };
MultiMatScalar(1 - cos(RADIAN(rotaAgl)), KK, scK, 9);
double tmp[9] = { 0 };
AddMat(eye, sK, 9, tmp);
AddMat(tmp, scK, 9, Mat);
}
// 初始化哈希表
void initHashMap(HashMap* map, int capacity)
{
map->entries = (HashEntry*)malloc(capacity * sizeof(HashEntry));
if (NULL == map->entries)
{
return;
}
map->capacity = capacity;
map->size = 0;
for (int i = 0; i < capacity; i++)
{
map->entries[i].key = 0;
map->entries[i].count = 0;
}
}
// 查找哈希表中的键
int findKey(HashMap* map, int key)
{
for (int i = 0; i < map->size; i++)
{
if (map->entries[i].key == key)
{
return i;
}
}
return -1;
}
// 插入键值对到哈希表
void insert(HashMap* map, int key)
{
int index = findKey(map, key);
if (index == -1)
{
if (map->size < map->capacity)
{
map->entries[map->size].key = key;
map->entries[map->size].count = 1;
map->size++;
}
else
{
printf("Hash map is full.\n");
}
}
else
{
map->entries[index].count++;
}
}
// 释放哈希表
void freeHashMap(HashMap* map)
{
free(map->entries);
}
int findMostFrequentNonZero(int arr[], int size, int *clsMaxNum, float *MostFrequentratio)
{
HashMap map;
initHashMap(&map, size); // 假设数组中的数字范围较小
// 记录每个非0数字出现的次数
for (int i = 0; i < size; i++)
{
if (arr[i] != 0)
{
insert(&map, arr[i]);
}
}
// 找到出现次数最多的数字
int mostFrequentNum = 0;
int maxFrequency = 0;
int totalNum = 0;
for (int i = 0; i < map.size; i++)
{
if (map.entries[i].count > maxFrequency)
{
mostFrequentNum = map.entries[i].key;
maxFrequency = map.entries[i].count;
}
if (map.entries[i].count > 0)
{
totalNum += map.entries[i].count;
}
}
*clsMaxNum = maxFrequency;
*MostFrequentratio = maxFrequency / (totalNum + FEPSILON);
freeHashMap(&map);
return mostFrequentNum;
}
int count2To0Transitions(int arr[], int size)
{
int count = 0;
for (int i = 0; i < size - 1; i++)
{
if (arr[i] == 2 && arr[i + 1] == 0)
{
count++;
}
}
return count;
}
bool checkXToYCondition(int arr[], int size, int x, int y, int frmThresh)
{
bool foundTransition = false;
int consecutiveOnes = 0;
for (int i = 0; i < size - 1; i++)
{
if (arr[i] == x && arr[i + 1] == y)
{
foundTransition = true;
consecutiveOnes = 1; // 从 1 开始计数
i++; // 跳过已经检查的 1
// 继续检查后续的 1
while (i < size - 1 && arr[i] == y)
{
consecutiveOnes++;
i++;
}
// 检查连续 1 的次数是否大于 阈值
if (consecutiveOnes > frmThresh)
{
return true;
}
}
}
return false;
}
int countNumberFreq(int arr[], int size, int number)
{
int count = 0;
for (int i = 0; i < size; i++)
{
if (arr[i] == 2)
{
count++;
}
}
return count;
}
static float get_dot_prod(float* A, float* B, int size)
{
int i;
float dot_prod = 0.f;
for (i = 0; i < size; i++)
{
dot_prod += A[i] * B[i];
}
return dot_prod;
}
static float get_eucl_magn(float* A, float* B, int size)
{
int i;
double A_len = 0;
double B_len = 0;
float eucl_magn = 0;
for (i = 0; i < size; i++)
{
A_len += pow(A[i], 2);
B_len += pow(B[i], 2);
}
eucl_magn = (float)sqrt(A_len * B_len);
return eucl_magn;
}
float Cosine_Similarity(float* A, float* B, int size)
{
// Vectors size can't be 0
if (size == 0)
{
//throw std::logic_error("Vector size can not be 0.");
return 0;
}
float value = 0;
float dot_prod = 0;
// 计算欧式距离
float eucl_magn = get_eucl_magn(A, B, size);
// If eucledian distance is 0 skip calculation
if (eucl_magn == 0)
{
value = 0;
}
else
{
dot_prod = get_dot_prod(A, B, size);
value = dot_prod / eucl_magn;
}
return value;
}
#ifdef _WIN32 // Windows平台
#include <Windows.h>
std::string GetDynamicLibraryPath()
{
HMODULE hModule = GetModuleHandle(NULL);
char path[MAX_PATH];
GetModuleFileName(hModule, path, MAX_PATH);
std::string fullPath(path);
size_t pos = fullPath.find_last_of("\\/");
return fullPath.substr(0, pos);
}
#elif __linux__ // Linux平台
#include <dlfcn.h>
#include <unistd.h>
std::string GetDynamicLibraryPath()
{
Dl_info dlInfo;
dladdr((void*)GetDynamicLibraryPath, &dlInfo);
char* path = realpath(dlInfo.dli_fname, NULL);
std::string fullPath(path);
free(path);
size_t pos = fullPath.find_last_of("/");
return fullPath.substr(0, pos);
}
#else
#error Unsupported platform
#endif
void Save_RunImg(GD_VIDEO_FRAME_S img, SINT32 nControlerFrmNum)
{
char resPath[256] = { 0 };
std::string path = GetDynamicLibraryPath();
snprintf(resPath, 256, "%s/%s", path.c_str(), "SaveImg");
if (ACCESS(resPath, 0) == 0)
{// SaveImg文件存在,写数据,默认在第10帧写数据
if (10 == nControlerFrmNum)
{
std::string filename = std::string(path) + "/frame_" + std::to_string(nControlerFrmNum);
std::ofstream outFile(filename, std::ios::binary);
if (!outFile)
{
std::cerr << "Failed to open file for writing: " << filename << std::endl;
}
switch (img.enPixelFormat)
{
case GD_PIXEL_FORMAT_GRAY_Y8:
for (unsigned int y = 0; y < img.u32Height; ++y)
{
outFile.write(reinterpret_cast<const char*>(img.u64VirAddr[0] + y * img.u32Stride[0]), img.u32Width);
}
break;
case GD_PIXEL_FORMAT_GRAY_Y16:
for (unsigned int y = 0; y < img.u32Height; ++y)
{
outFile.write(reinterpret_cast<const char*>(img.u64VirAddr[0] + y * img.u32Stride[0]), img.u32Width * 2);
}
break;
case GD_PIXEL_FORMAT_NV12:
// 写入Y平面
for (unsigned int y = 0; y < img.u32Height; ++y)
{
outFile.write(reinterpret_cast<const char*>(img.u64VirAddr[0] + y * img.u32Stride[0]), img.u32Width);
}
// 写入UV平面
for (unsigned int y = 0; y < img.u32Height / 2; ++y)
{
outFile.write(reinterpret_cast<const char*>(img.u64VirAddr[1] + y * img.u32Stride[1]), img.u32Stride[1]);
}
break;
case GD_PIXEL_FORMAT_RGB_PACKED:
for (unsigned int y = 0; y < img.u32Height; ++y)
{
outFile.write(reinterpret_cast<const char*>(img.u64VirAddr[0] + y * img.u32Stride[0]), img.u32Width * 3);
}
break;
default:
std::cerr << "Unsupported pixel format: " << img.enPixelFormat << std::endl;
outFile.close();
}
outFile.close();
}
}
}
FLOAT32 SERVO_CorrectAngleScale(FLOAT32 fAngle)
{
FLOAT32 fAngleCorrect = fAngle;
//若角度小于伺服角度下限(-180°则其实际值已经跨入0°180°范围的右侧
if (fAngle < SERVO_ANGLE_MIN)
fAngleCorrect = fAngle + SERVO_ANGLE_RANGE;
//若角度大于伺服角度上限180°则其实际值已经跨入-180°0°的范围左侧
if (fAngle >= SERVO_ANGLE_MAX)
fAngleCorrect = fAngle - SERVO_ANGLE_RANGE;
return fAngleCorrect;
}