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.

399 lines
9.9 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 <memory>
#include "utils.h"
#include "opencv2/opencv.hpp"
#include <random> // 添加随机数生成相关头文件
using namespace std;
using namespace cv;
SimTargetImage_Y16::SimTargetImage_Y16(int w, int h)
{
pSrc = new unsigned short[w * h];
Y8Mat = cv::Mat(h,w,CV_8UC1);
nImageWidth = w;
nImageHeight = h;
}
SimTargetImage_Y16::~SimTargetImage_Y16()
{
if (pSrc)
{
delete[]pSrc;
pSrc = nullptr;
}
}
void SimTargetImage_Y16::setBackGround(int gray, int std)
{
for (size_t i = 0; i < nImageHeight; i++)
{
for (size_t j = 0; j < nImageWidth; j++)
{
pSrc[i * nImageWidth + j] = rand() % std + gray;
}
}
}
void SimTargetImage_Y16::addTarget(int x, int y, int w, int h, int gray)
{
for (size_t i = y - h/2; i < y + h/2; i++)
{
for (size_t j = x - w/2; j < x+w/2; j++)
{
pSrc[i * nImageWidth + j] = gray;
}
}
}
unsigned short* SimTargetImage_Y16::getImageData()
{
return pSrc;
}
cv::Mat SimTargetImage_Y16::getMatRGB()
{
Map16BitTo8Bit(pSrc, nImageHeight * nImageWidth, Y8Mat.data);
cv::Mat rgb;
cv::cvtColor(Y8Mat,rgb,COLOR_GRAY2RGB);
return rgb.clone();
}
SimTargetImage::SimTargetImage(int w,int h)
{
m_BaseMat = cv::Mat(h,w,CV_8UC3);
m_CurMat = m_BaseMat.clone();
m_imgW = w;
m_imgH = h;
}
void SimTargetImage::update()
{
m_CurMat = m_BaseMat.clone();
// 绘制目标
for (int i = 0; i < m_targetList.size(); ++i)
{
Target* target = &m_targetList[i];
// 更新目标位置
target->updatePosition(m_imgW, m_imgH);
target->updateTexture();
//target->color = cv::Scalar(target->color[0] + target->vc, target->color[0] + target->vc, target->color[0] + target->vc);
drawObj(*target);
}
// 绘制遮挡
for (int i = 0; i < m_OccList.size(); ++i)
{
Target* target = &m_OccList[i];
// 绘制目标
drawOcc(*target);
}
}
void SimTargetImage::setBackGround(int gray, int std)
{
cv::Mat noise(m_BaseMat.size(), CV_8UC3);
cv::randn(noise, cv::Scalar::all(gray), cv::Scalar::all(std)); // 高斯噪声
m_BaseMat = noise;
m_CurMat = noise.clone();
}
void SimTargetImage::addTarget(Target t)
{
m_targetList.push_back(t);
}
void SimTargetImage::addOcc(Target t)
{
m_OccList.push_back(t);
}
cv::Mat SimTargetImage::getImageRGB()
{
return m_CurMat;
}
cv::Mat SimTargetImage::getImageY16()
{
cvtColor(m_CurMat,matY8,COLOR_BGR2GRAY);
matY8.convertTo(matY16,CV_16UC1);
return matY16*3+4000;
}
cv::Mat SimTargetImage::getImageY8()
{
cvtColor(m_CurMat,matY8,COLOR_BGR2GRAY);
return matY8;
}
cv::Mat SimTargetImage::getImageNV12()
{
matNV12 = cv::Mat(m_imgH*1.5, m_imgW, CV_8UC1);
cv::Mat matYUV_I420(m_imgH*1.5, m_imgW, CV_8UC1);
cvtColor(m_CurMat, matYUV_I420, COLOR_BGR2YUV_I420);
int nLenY = m_imgW * m_imgH;
int nLenU = nLenY / 4;
uchar* pNV12 = matNV12.data;
uchar* pUV = matNV12.data + nLenY;
uchar* pI420 = matYUV_I420.data;
memcpy(pNV12, pI420, nLenY);
for (int i = 0; i < nLenU; i++)
{
pUV[2 * i] = pI420[nLenY + i]; // U
pUV[2 * i + 1] = pI420[nLenY + nLenU + i]; // V
}
return matNV12;
}
Target* SimTargetImage::getTarget(int id)
{
if (m_targetList.size() > 0)
{
return &m_targetList[id];
}
else
{
return nullptr;
}
}
void SimTargetImage::drawObj(Target t)
{
if (t.useTexture)
{
// 设置叠加位置
int offsetX = t.x - t.width/2, offsetY = t.y - t.height/2;
cv::Rect roi(offsetX, offsetY, t.width, t.height);
// // 将前景叠加到背景,使用 Alpha 通道作为掩码
t.texture_cur.copyTo(m_CurMat(roi),t.alaph_cur);
return;
}
if (t.bGrayComplex)
{
cv::Rect rect(t.x - t.width / 2, t.y - t.height / 2, t.width, t.height/2);
cv::rectangle(m_CurMat, rect, cv::Scalar(t.color), cv::FILLED);
cv::Rect rect2(t.x - t.width / 2, t.y - t.height / 4, t.width, t.height/2);
cv::rectangle(m_CurMat, rect2, cv::Scalar(t.color2), cv::FILLED);
}
else
{
cv::Rect rect(t.x - t.width / 2, t.y - t.height / 2, t.width, t.height);
cv::rectangle(m_CurMat, rect, cv::Scalar(t.color), cv::FILLED);
}
}
void SimTargetImage::drawOcc(Target t)
{
cv::Rect rect(t.x - t.width/2, t.y - t.height/2, t.width, t.height);
cv::rectangle(m_CurMat, rect, cv::Scalar(t.color), cv::FILLED);
}
void SimTargetImage::setCheckerboardBackGround(int gray1, int gray2, int blockSize)
{
m_BaseMat = cv::Mat(m_imgH, m_imgW, CV_8UC3);
for (int y = 0; y < m_imgH; ++y)
{
for (int x = 0; x < m_imgW; ++x)
{
int bx = x / blockSize;
int by = y / blockSize;
bool isWhite = (bx + by) % 2 == 0;
int gray = isWhite ? gray1 : gray2;
m_BaseMat.at<cv::Vec3b>(y, x) = cv::Vec3b(gray, gray, gray);
}
}
m_CurMat = m_BaseMat.clone();
}
void Map16BitTo8Bit(unsigned short* psh16BitData, long lDataLen, unsigned char* pby8BitData)
{
if (psh16BitData == NULL || pby8BitData == NULL || lDataLen <= 0)
{
return;
}
//指向直方图的数据指针
int* pHist = new int[65536];
memset(pHist, 0, 65536 * sizeof(int));
int i = 0;
for (i = 0; i < lDataLen; i += 10)
{
pHist[psh16BitData[i]]++;
}
//设置阈值大小为: AreaSigma*图象大小/100
int nSigma = (int)(0.03 * lDataLen);
int nSum = 0;
int nMin = 0;
int nMax = 0;
//求映射的最大最小值
for (i = 0; i < 65536; i++)
{
nSum += pHist[i];
if (nSum >= nSigma)
{
nMin = i;
break;
}
}
nSum = 0;
for (i = 65535; i >= 0; i--)
{
nSum += pHist[i];
if (nSum >= nSigma)
{
nMax = i;
break;
}
}
//计算对比度亮度
float K = (float)(120.0 / (nMax - nMin + 1));
float C = (float)(-K * nMin);
//图像映射
for (i = 0; i < lDataLen; i++)
{
int nValue = (int)(K * psh16BitData[i] + C);
if (nValue < 0)
{
pby8BitData[i] = 0;
}
else if (nValue > 255)
{
pby8BitData[i] = 255;
}
else
{
pby8BitData[i] = nValue;
}
}
delete[] pHist;
}
void showArithInfo(cv::Mat src, ARIDLL_OUTPUT * stOutput)
{
auto detNum = stOutput->nAlarmObjCnts;
auto detObjs = stOutput->stAlarmObjs;
for (size_t i = 0; i < detNum; i++)
{
cv::Rect outRect;
outRect.width = MAX(15,int(detObjs[i].nObjW));
outRect.height= MAX(15,int(detObjs[i].nObjH));
outRect.x = detObjs[i].nX-outRect.width/2.0;
outRect.y = detObjs[i].nY-outRect.height/2.0;
cv::rectangle(src,outRect,cv::Scalar(255,0,0),2);
cv::putText(src,to_string(detObjs[i].nOutputID),cv::Point(outRect.x - 10,outRect.y),1,2,cv::Scalar(255,255,0));
}
auto trackerOut = stOutput->stTrackers[0];
cv::Rect outRect;
outRect.width = MAX(25,int(trackerOut.nObjW));
outRect.height= MAX(25,int(trackerOut.nObjH));
outRect.x = trackerOut.nX-outRect.width/2.0;
outRect.y = trackerOut.nY-outRect.height/2.0;
cv::rectangle(src,outRect,cv::Scalar(0,0,255),2);
char str[100];
sprintf(str,"%d,%d,%d,%d",int(trackerOut.nX),int(trackerOut.nY),int(trackerOut.nObjW),int(trackerOut.nObjH));
cv::putText(src,cv::String(str),cv::Point(outRect.x - 10,outRect.y),1,2,cv::Scalar(255,255,0));
}
std::vector<int> generateRandomLockUnlockSequence(int totalFrames, int minLockDuration, int maxLockDuration)
{
std::vector<int> sequence(totalFrames, 0); // 初始化为全0
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> actionDist(0, 1); // 0:普通帧, 1:锁定
std::uniform_int_distribution<> durationDist(1, 5); // 连续动作的持续时间
std::uniform_int_distribution<> unlockProbDist(0, 100); // 解锁概率分布
std::uniform_int_distribution<> waitFramesDist(1, 3); // 锁定后等待帧数
std::uniform_int_distribution<> waitProbDist(0, 100); // 是否等待的概率分布
int currentFrame = 0;
bool isLocked = false; // 当前是否处于锁定状态
bool justLocked = false; // 是否刚刚执行了锁定操作
while (currentFrame < totalFrames)
{
if (isLocked)
{
// 如果当前是锁定状态有20%的概率解锁
if (unlockProbDist(gen) < 20)
{
sequence[currentFrame] = 2; // 解锁
isLocked = false;
currentFrame++;
continue;
}
}
// 如果刚刚执行了锁定操作有50%的概率添加等待帧
if (justLocked && waitProbDist(gen) < 50)
{
int waitFrames = waitFramesDist(gen);
for (int i = 0; i < waitFrames && currentFrame < totalFrames; i++)
{
sequence[currentFrame] = 0; // 等待帧
currentFrame++;
}
}
justLocked = false;
// 随机决定当前帧的动作类型
int action = actionDist(gen);
// 随机决定这个动作持续多少帧
int duration = durationDist(gen);
// 确保不会超出总帧数
if (currentFrame + duration > totalFrames)
{
duration = totalFrames - currentFrame;
}
// 填充动作序列
for (int i = 0; i < duration && currentFrame < totalFrames; i++)
{
sequence[currentFrame] = action;
if (action == 1)
{
isLocked = true;
justLocked = true; // 标记刚刚执行了锁定操作
}
currentFrame++;
}
}
return sequence;
}