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.

3255 lines
99 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.

/*********版权所有C2013武汉高德红外股份有限公司***************
* 文件名称Arith_ImgOperate.cpp
* 文件标识:图像处理
* 内容摘要:执行通用图像处理操作
* 其它说明:"ImgOperate"的函数、全局变量、宏定义,统一前缀为简写"IMGO"。
* 当前版本固化V2.0
* 创建作者MSSu
* 创建日期2015.03.16
*******************************************************************/
#include "Arith_ImgOperate.h"
#ifdef NEON
#include <arm_neon.h>
#endif
void GD_FRAME_pyrDownToY16(GD_VIDEO_FRAME_S img, UINT16* pDst, SINT32 nDSmpScale, RECT32S roi, MINMAXRECT& mRect)
{
UINT16* pLine = NULL;
FLOAT32 fDSmpScale2 = 1.0f / (nDSmpScale * nDSmpScale);
SINT32 nImageW = img.u32Width;
SINT32 nImageH = img.u32Height;
// 裁剪区边界保护
mRect.minX = MAX(0, MIN(roi.x, nImageW - 1));
mRect.minY = MAX(0, MIN(roi.y, nImageH - 1));
mRect.maxX = MIN(nImageW - 1, MAX(0, roi.x + roi.w));
mRect.maxY = MIN(nImageH - 1, MAX(0, roi.y + roi.h));
// 调整后的裁剪区域
roi.w = mRect.maxX - mRect.minX;
roi.h = mRect.maxY - mRect.minY;
roi.x = mRect.minX;
roi.y = mRect.minY;
// 降采样后的目标图像大小
SIZE32S SizeDst = { 0 };
SizeDst.w = roi.w / nDSmpScale;
SizeDst.h = roi.h / nDSmpScale;
// 后续处理不再考虑越界问题
if (nDSmpScale == 1)
{
// 按照不同的数据类型进行处理
switch (img.enPixelFormat)
{
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16:
IMGO_GDSGetSubRect((UINT16*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8:
IMGO_GDSGetSubRectY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED:
IMGO_GDSGetSubRectRGB(img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12:
IMGO_GDSGetSubRectY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
default:
break;
}
}
else
{
// 按照不同的数据类型进行处理
switch (img.enPixelFormat)
{
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16:
IMGO_GetSubImg((UINT16*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8:
IMGO_GetSubImgY8((UBYTE8*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED:
IMGO_GetSubImgRGB((UBYTE8*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12:
IMGO_GetSubImgY8((UBYTE8*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
default:
break;
}
}
}
void GD_FRAME_pyrDownToY8(GD_VIDEO_FRAME_S img, UBYTE8* pDst, SINT32 nDSmpScale, RECT32S roi, MINMAXRECT& mRect)
{
UINT16* pLine = NULL;
SINT32 nImageW = img.u32Width;
SINT32 nImageH = img.u32Height;
// 裁剪区边界保护
mRect.minX = MAX(0, MIN(roi.x, nImageW - 1));
mRect.minY = MAX(0, MIN(roi.y, nImageH - 1));
mRect.maxX = MIN(nImageW - 1, MAX(0, roi.x + roi.w));
mRect.maxY = MIN(nImageH - 1, MAX(0, roi.y + roi.h));
// 调整后的裁剪区域
roi.w = mRect.maxX - mRect.minX;
roi.h = mRect.maxY - mRect.minY;
roi.x = mRect.minX;
roi.y = mRect.minY;
// 降采样后的目标图像大小
SIZE32S SizeDst = { 0 };
SizeDst.w = roi.w / nDSmpScale;
SizeDst.h = roi.h / nDSmpScale;
// 后续处理不再考虑越界问题
if (nDSmpScale == 1)
{
// 按照不同的数据类型进行处理
switch (img.enPixelFormat)
{
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8:
IMGO_GDSGetSubRectFromY8ToY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED:
IMGO_GDSGetSubRectRGBToY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12:
IMGO_GDSGetSubRectFromY8ToY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
default:
break;
}
}
}
void GD_FRAME_pyrUpToY16(GD_VIDEO_FRAME_S img, UINT16* pDst, SINT32 nDSmpScale, RECT32S roi, MINMAXRECT& mRect)
{
UINT16* pLine = NULL;
FLOAT32 fDSmpScale2 = 1.0f / (nDSmpScale * nDSmpScale);
SINT32 nImageW = img.u32Width;
SINT32 nImageH = img.u32Height;
// 裁剪区边界保护
mRect.minX = MAX(0, MIN(roi.x, nImageW - 1));
mRect.minY = MAX(0, MIN(roi.y, nImageH - 1));
mRect.maxX = MIN(nImageW - 1, MAX(0, roi.x + roi.w));
mRect.maxY = MIN(nImageH - 1, MAX(0, roi.y + roi.h));
// 调整后的裁剪区域
roi.w = mRect.maxX - mRect.minX;
roi.h = mRect.maxY - mRect.minY;
roi.x = mRect.minX;
roi.y = mRect.minY;
// 上采样后的目标图像大小
SIZE32S SizeDst = { 0 };
SizeDst.w = roi.w * nDSmpScale;
SizeDst.h = roi.h * nDSmpScale;
// 后续处理不再考虑越界问题
if (nDSmpScale == 1)
{
// 按照不同的数据类型进行处理
switch (img.enPixelFormat)
{
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16:
IMGO_GDSGetSubRect((UINT16*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8:
IMGO_GDSGetSubRectY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED:
IMGO_GDSGetSubRectRGB(img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12:
IMGO_GDSGetSubRectY8((UBYTE8*)img.u64VirAddr[0], pDst, img.u32Width, img.u32Height, &mRect, roi);
break;
default:
break;
}
}
else
{
// 按照不同的数据类型进行处理
switch (img.enPixelFormat)
{
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16:
IMGO_GetSubImg((UINT16*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8:
IMGO_GetSubImgY8((UBYTE8*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED:
IMGO_GetSubImgRGB((UBYTE8*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
case GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12:
IMGO_GetSubImgY8((UBYTE8*)img.u64VirAddr[0], img.u32Width, img.u32Height, roi, pDst, SizeDst.w, SizeDst.h);
break;
default:
break;
}
}
}
#ifdef NEON
void Pyramid(unsigned short* imgIn, unsigned short* imgOut, int wid, int hei)
{
unsigned short* pIn0 = imgIn;
unsigned short* pIn1 = pIn0 + wid;
unsigned short* pOut = imgOut;
int widT = wid / 2;
uint16x8x2_t vIn0, vIn1;
if (wid >= 16)
{
for (int j = 0; j < hei - 1; j += 2)
{
for (int i = 0, s = 0; i < wid; i += 16, s += 8)
{
vIn0 = vld2q_u16((pIn0 + i));
vIn1 = vld2q_u16((pIn1 + i));
vst1q_u16((pOut + s), vhaddq_u16(vhaddq_u16(vIn0.val[0], vIn0.val[1]), vhaddq_u16(vIn1.val[0], vIn1.val[1])));
}
pIn0 = pIn1 + wid;
pIn1 = pIn0 + wid;
pOut = pOut + widT;
}
}
else
{
for (int j = 0; j < hei - 1; j += 2)
{
for (int i = 0, s = 0; i < wid; i += 2, s++)
{
pOut[s] = (pIn0[i] + pIn0[i + 1] + pIn1[i] + pIn1[i + 1]) >> 2;
}
pIn0 = pIn1 + wid;
pIn1 = pIn0 + wid;
pOut = pOut + widT;
}
}
}
#endif
#ifdef NEON
void Pyramid2(unsigned short* imgIn, unsigned short* imgOut, int wid, int hei, MINMAXRECT mRect)
{
unsigned short* pIn0 = imgIn + mRect.minY * wid + mRect.minX;
unsigned short* pIn1 = pIn0 + wid;
unsigned short* pOut = imgOut;
uint16x8x2_t vIn0, vIn1;
int h_sub = mRect.maxY - mRect.minY;
int w_sub = mRect.maxX - mRect.minX;
int widT = w_sub / 2;
for (int j = 0; j < h_sub - 1; j += 2)
{
for (int i = 0, s = 0; i < w_sub; i += 16, s += 8)
{
vIn0 = vld2q_u16((pIn0 + i));
vIn1 = vld2q_u16((pIn1 + i));
vst1q_u16((pOut + s), vhaddq_u16(vhaddq_u16(vIn0.val[0], vIn0.val[1]), vhaddq_u16(vIn1.val[0], vIn1.val[1])));
}
pIn0 = pIn1 + wid;
pIn1 = pIn0 + wid;
pOut = pOut + widT;
}
}
void Pyramid4(unsigned short* imgIn, unsigned short* imgOut, int wid, int hei, MINMAXRECT mRect)
{
unsigned short* pIn0 = imgIn + mRect.minY * wid + mRect.minX;
unsigned short* pIn1 = pIn0 + wid;
unsigned short* pIn2 = pIn1 + wid;
unsigned short* pIn3 = pIn2 + wid;
unsigned short* pOut = imgOut;
uint16x8x4_t vIn0, vIn1, vIn2, vIn3;
int h_sub = mRect.maxY - mRect.minY;
int w_sub = mRect.maxX - mRect.minX;
int widT = w_sub / 4;
for (int j = 0; j < h_sub - 3; j += 4)
{
for (int i = 0, s = 0; i < w_sub; i += 32, s += 8)
{
//vIn0 = vld2q_u16((pIn0 + i));
//vIn1 = vld2q_u16((pIn1 + i));
//vst1q_u16((pOut + s), vhaddq_u16(vhaddq_u16(vIn0.val[0], vIn0.val[1]), vhaddq_u16(vIn1.val[0], vIn1.val[1])));
vIn0 = vld4q_u16(pIn0 + i);
vIn1 = vld4q_u16((pIn1 + i));
vIn2 = vld4q_u16((pIn2 + i));
vIn3 = vld4q_u16((pIn3 + i));
uint16x8_t L1 = vhaddq_u16(vhaddq_u16(vIn0.val[0], vIn0.val[1]), vhaddq_u16(vIn0.val[2], vIn0.val[3]));
uint16x8_t L2 = vhaddq_u16(vhaddq_u16(vIn1.val[0], vIn1.val[1]), vhaddq_u16(vIn1.val[2], vIn1.val[3]));
uint16x8_t L3 = vhaddq_u16(vhaddq_u16(vIn2.val[0], vIn2.val[1]), vhaddq_u16(vIn2.val[2], vIn2.val[3]));
uint16x8_t L4 = vhaddq_u16(vhaddq_u16(vIn3.val[0], vIn3.val[1]), vhaddq_u16(vIn3.val[2], vIn3.val[3]));
uint16x8_t vsum = vhaddq_u16(vhaddq_u16(L1, L2), vhaddq_u16(L3, L4));
vst1q_u16((pOut + s), vsum);
}
pIn0 = pIn1 + wid;
pIn1 = pIn0 + wid;
pIn2 = pIn1 + wid;
pIn3 = pIn2 + wid;
pOut = pOut + widT;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////
//--函数定义
////////////////////////////////////////////////////////////////////////////////
/****************************************************
* 函数名称IMGO_Resize
* 功能描述:双线性插值
* 输入参数UINT16 *pSrc -- 输入图像
SIZE32S szSrc -- 输入图像尺寸
SIZE32S szDst -- 输出图像尺寸
* 输出参数UINT16 *pDst -- 插值后图像
* 返 回 值:
* 调用关系:
* 其它说明:
*****************************************************/
void IMGO_Resize(UINT16 *pSrc, SIZE32S szSrc, UINT16 *pDst, SIZE32S szDst)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
fZoomH = szSrc.h / (FLOAT32)szDst.h;
fZoomW = szSrc.w / (FLOAT32)szDst.w;
for (i = 0; i < szDst.h; i++)
{
for (j = 0; j < szDst.w; j++)
{
x = fZoomW * j; //映射回原图坐标
y = fZoomH * i;
x = MIN(x, szSrc.w-2); //nWidth-1存在越界
y = MIN(y, szSrc.h-2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0+1;
y1 = y0+1;
u = x - x0;//权重
v = y - y0;
pDst[i*szDst.w + j] = UINT16(pSrc[szSrc.w * y0+ x0] * (1-u)*(1-v)
+ pSrc[szSrc.w * y0 + x1] * u * (1-v)
+ pSrc[szSrc.w * y1+ x0] * (1-u) * v
+ pSrc[szSrc.w * y1+ x1] * u * v);
}
}
return;
}
/**********************************************************
* 函数名称IMGO_gcABCLin()
* 功能描述:线性自动亮度对比度
* 输入参数UINT16 *pSrc -- 原始图像
* SINT32 nLen -- 图像尺寸
* 输出参数UBYTE8 *pDst -- 处理后图像,调光后
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_gcABCLin(UINT16 *pSrc, UBYTE8 *pDst, SINT32 nLen)
{
SINT32 i;
//SINT32 nContrast;
//SINT32 nBright;
SINT32 nSigma;
SINT32 nSum;
SINT32 nMin;
SINT32 nMax;
SINT32 nMid;
SINT32 nValue;
FLOAT32 K;
FLOAT32 C;
//指向直方图的数据指针
SINT32 *pHist = new SINT32[65536];
memset((void*)pHist, 0, 65536 * sizeof(SINT32));
for (i = 0; i < nLen; i++)
{
pHist[pSrc[i]]++;
}
//求映射的最大最小值
nSigma = (SINT32)(0.03 * nLen); //设置高低端抛点数
nSum = 0;
nMin = 0;
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;
}
}
//计算对比度、亮度
//K = (FLOAT32)(256.0 / (nMax-nMin+1));
//C = (FLOAT32)(-K * nMin);
K = (FLOAT32)((226.0 - 30) / (nMax-nMin+1));
C = (FLOAT32)(128 - K * (nMin + nMax) / 2);
//设置对比度上限,若超出上限,重新计算亮度
if (K > 1.8)
{
K = (FLOAT32)1.8;
nSigma = (SINT32)(0.5 * nLen); //设置高低端抛点数
nSum = 0;
nMid = 0;
//求映射的中值
for (i = 0; i < 65536; i++)
{
nSum += pHist[i];
if (nSum >= nSigma)
{
nMid = i;
break;
}
}
C = (FLOAT32)(128 - K * nMid);
}
for (i = 0; i < nLen; i++)
{
nValue = (SINT32)(K * pSrc[i] + C);
if (nValue < 0)
{
pDst[i] = 0;
}
else if (nValue > 255)
{
pDst[i] = 255;
}
else
{
pDst[i] = (BYTE8)nValue;
}
}
delete []pHist;
}
/**********************************************************
* 函数名称IMGO_gcABCLin()
* 功能描述:线性自动亮度对比度
* 输入参数UINT16 *pSrc -- 原始图像
* SINT32 nLen -- 图像尺寸
* 输出参数UBYTE8 *pDst -- 处理后图像,调光后
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_gcABCLinRoi(UINT16* pSrc, UBYTE8* pDst, SINT32 nLen)
{
SINT32 i;
//SINT32 nContrast;
//SINT32 nBright;
SINT32 nSigmaLow;
SINT32 nSigmaHigh;
SINT32 nSum;
SINT32 nMin;
SINT32 nMax;
SINT32 nMid;
SINT32 nValue;
FLOAT32 K;
FLOAT32 C;
//指向直方图的数据指针
SINT32* pHist = new SINT32[65536];
memset((void*)pHist, 0, 65536 * sizeof(SINT32));
for (i = 0; i < nLen; i++)
{
pHist[pSrc[i]]++;
}
//求映射的最大最小值
nSigmaLow = (SINT32)(0 * nLen); //设置低端抛点数
nSigmaHigh = (SINT32)(0.2 * nLen); //设置高端抛点数
nSum = 0;
nMin = 0;
nMax = 0;
for (i = 0; i < 65536; i++)
{
nSum += pHist[i];
if (nSum >= nSigmaLow)
{
nMin = i;
break;
}
}
nSum = 0;
for (i = 65535; i >= 0; i--)
{
nSum += pHist[i];
if (nSum >= nSigmaHigh)
{
nMax = i;
break;
}
}
//计算对比度、亮度
//K = (FLOAT32)(256.0 / (nMax-nMin+1));
//C = (FLOAT32)(-K * nMin);
K = (FLOAT32)((226.0 - 30) / (nMax - nMin + 1));
C = (FLOAT32)(128 - K * (nMin + nMax) / 2);
//设置对比度上限,若超出上限,重新计算亮度
if (K > 1.8)
{
K = (FLOAT32)1.8;
nSigmaLow = (SINT32)(0.5 * nLen); //设置高端抛点数
nSum = 0;
nMid = 0;
//求映射的中值
for (i = 0; i < 65536; i++)
{
nSum += pHist[i];
if (nSum >= nSigmaLow)
{
nMid = i;
break;
}
}
C = (FLOAT32)(128 - K * nMid);
}
for (i = 0; i < nLen; i++)
{
nValue = (SINT32)(K * pSrc[i] + C);
if (nValue < 0)
{
pDst[i] = 0;
}
else if (nValue > 255)
{
pDst[i] = 255;
}
else
{
pDst[i] = (BYTE8)nValue;
}
}
delete[]pHist;
}
/**********************************************************
* 函数名称IMGO_CenRect16S2MMRect32S()
* 功能描述:转换矩形类型,从CENTERRECT中心型转换到MINMAXRECT32S左上角及右下角型
* 输入参数CENTERRECT crnRect -- 中心型矩阵结构体整型16位
* 输出参数MINMAXRECT32S *pmrnRect -- 四边型矩形结构体整型32位
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_CenRect16S2MMRect32S(CENTERRECT crnRect, MINMAXRECT32S *pmrnRect, SINT32 nWidth, SINT32 nHeight)
{
SINT16 nRadiusW = crnRect.w >> 1;
SINT16 nRadiusH = crnRect.h >> 1;
pmrnRect->minX =MAX(1, (SINT32)(crnRect.cx - nRadiusW));
pmrnRect->maxX = MIN((SINT32)(pmrnRect->minX + crnRect.w - 1), nWidth - 2);
pmrnRect->minY = MAX(1, (SINT32)(crnRect.cy - nRadiusH));
pmrnRect->maxY = MIN((SINT32)(pmrnRect->minY + crnRect.h - 1), nHeight - 2); //zy修改20170929
//pmrnRect->minX =(SINT32)(crnRect.cx - nRadiusW);
//pmrnRect->maxX = (SINT32)(pmrnRect->minX + crnRect.w - 1);
//pmrnRect->minY = (SINT32)(crnRect.cy - nRadiusH);
//pmrnRect->maxY = (SINT32)(pmrnRect->minY + crnRect.h - 1);
}
/**********************************************************
* 函数名称IMGO_MMRect32S2CenRect16S()
* 功能描述:转换矩形类型,从MINMAXRECT32S左上角及右下角型到CENTERRECT中心型
* 输入参数MINMAXRECT pmrnRect -- 四边型矩形结构体整型16位
* 输出参数CENTERRECT32S *crnRect -- 中心型矩阵结构体整型32位
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_MMRect32S2CenRect16S(MINMAXRECT32S pmrnRect, CENTERRECT *crnRect)
{
crnRect->cx = (SINT16)((pmrnRect.minX + pmrnRect.maxX) >> 1);
crnRect->cy = (SINT16)((pmrnRect.minY + pmrnRect.maxY) >> 1);
crnRect->w = (SINT16)(pmrnRect.maxX - pmrnRect.minX + 1);
crnRect->h = (SINT16)(pmrnRect.maxY - pmrnRect.minY + 1);
crnRect->s = (SINT32)crnRect->w * (SINT32)crnRect->h;
}
/**********************************************************
* 函数名称IMGO_GDSGetSubRect()
* 功能描述从pSrc中提取一个矩形区域保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* RECT16S rRect -- 矩形区域参数
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubRect(UINT16 *pSrc, UINT16 *pDst, SINT16 nWidth, SINT16 nHeight, RECT16S rRect)
{
SINT16 i, j;
SINT32 nCounter; //SINT16 可能越界!!
UINT16 *pLine = NULL;
//边界限制
rRect.x = MAX(rRect.x, 0);
rRect.x = MIN(rRect.x, nWidth - 1);
rRect.y = MAX(rRect.y, 0);
rRect.y = MIN(rRect.y, nHeight - 1);
//区域提取
nCounter= 0;
pLine = (UINT16*)(pSrc + rRect.y * nWidth + rRect.x);//图像行指针
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = pLine[j];
}
pLine += nWidth;
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubRect()
* 功能描述从pSrc中提取一个矩形区域保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* RECT32S rRect -- 矩形区域参数
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明为了兼容NCC捕获版本添加RECT32S
**********************************************************/
void IMGO_GDSGetSubRect(UINT16 *pSrc, UINT16 *pDst, SINT16 nWidth, SINT16 nHeight, RECT32S rRect)
{
SINT16 i, j;
SINT32 nCounter; //SINT16 可能越界!!
UINT16 *pLine = NULL;
//边界限制
rRect.x = MAX(rRect.x, 0);
rRect.x = MIN(rRect.x, nWidth - 1);
rRect.y = MAX(rRect.y, 0);
rRect.y = MIN(rRect.y, nHeight - 1);
//区域提取
nCounter= 0;
pLine = (UINT16*)(pSrc + rRect.y * nWidth + rRect.x);//图像行指针
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = pLine[j];
}
pLine += nWidth;
}
}
/****************************************************
* 函数名称IMGO_GetSubImg
* 功能描述:从图像中获取指定区域,并插值到指定尺寸
* 输入参数:
* 输出参数UINT16 *pDst
* 返 回 值:
* 调用关系:
* 其它说明:双线性插值,边缘复制
*****************************************************/
void IMGO_GetSubImg(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UINT16 *pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth-2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight-2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0+1;
y1 = y0+1;
u = x - x0;//权重
v = y - y0;
pDst[i*nDstW + j] = UINT16(pSrc[nWidth * y0+ x0] * (1-u)*(1-v)
+ pSrc[nWidth * y0+ x1] * u * (1-v)
+ pSrc[nWidth * y1+ x0] * (1-u) * v
+ pSrc[nWidth * y1+ x1] * u * v);
}
}
}
/****************************************************
* 函数名称IMGO_GetSubImg
* 功能描述:从图像中获取指定区域,并插值到指定尺寸
* 输入参数:
* 输出参数UINT16 *pDst
* 返 回 值:
* 调用关系:
* 其它说明:双线性插值,边缘复制
*****************************************************/
void IMGO_FromUINT16GetSubImgY16(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UINT16* pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth - 2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight - 2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0 + 1;
y1 = y0 + 1;
u = x - x0;//权重
v = y - y0;
pDst[i * nDstW + j] = UINT16(img.u64VirAddr[0][nWidth * y0 + x0] * (1 - u) * (1 - v)
+ img.u64VirAddr[0][nWidth * y0 + x1] * u * (1 - v)
+ img.u64VirAddr[0][nWidth * y1 + x0] * (1 - u) * v
+ img.u64VirAddr[0][nWidth * y1 + x1] * u * v);
}
}
}
/****************************************************
* 函数名称IMGO_GetSubImgY8
* 功能描述:从图像中获取指定区域,并插值到指定尺寸
* 输入参数:
* 输出参数UINT16 *pDst
* 返 回 值:
* 调用关系:
* 其它说明:双线性插值,边缘复制
*****************************************************/
void IMGO_GetSubImgY8(UBYTE8* pSrc, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UINT16* pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth - 2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight - 2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0 + 1;
y1 = y0 + 1;
u = x - x0;//权重
v = y - y0;
pDst[i * nDstW + j] = UINT16(pSrc[nWidth * y0 + x0] * (1 - u) * (1 - v)
+ pSrc[nWidth * y0 + x1] * u * (1 - v)
+ pSrc[nWidth * y1 + x0] * (1 - u) * v
+ pSrc[nWidth * y1 + x1] * u * v);
}
}
}
/****************************************************
* 函数名称IMGO_GetSubImgY8
* 功能描述:从图像中获取指定区域,并插值到指定尺寸
* 输入参数:
* 输出参数UINT16 *pDst
* 返 回 值:
* 调用关系:
* 其它说明:双线性插值,边缘复制
*****************************************************/
void IMGO_GetSubImgYUV422(UBYTE8* pSrc, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UINT16* pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth - 2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight - 2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0 + 1;
y1 = y0 + 1;
u = x - x0;//权重
v = y - y0;
pDst[i * nDstW + j] = UINT16(pSrc[2 *(nWidth * y0 + x0) + 1] * (1 - u) * (1 - v)
+ pSrc[2 * (nWidth * y0 + x1) + 1] * u * (1 - v)
+ pSrc[2 * (nWidth * y1 + x0) + 1] * (1 - u) * v
+ pSrc[2 * (nWidth * y1 + x1) + 1] * u * v);
}
}
}
/****************************************************
* 函数名称IMGO_GetSubImgRGB
* 功能描述:从图像中获取指定区域,并插值到指定尺寸
* 输入参数:
* 输出参数UINT16 *pDst
* 返 回 值:
* 调用关系:
* 其它说明:双线性插值,边缘复制
*****************************************************/
void IMGO_GetSubImgRGB(UBYTE8* pSrc, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UINT16* pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
UBYTE8 R[4] = {0};
UBYTE8 G[4] = { 0 };
UBYTE8 B[4] = { 0 };
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth - 2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight - 2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0 + 1;
y1 = y0 + 1;
u = x - x0;//权重
v = y - y0;
R[0] = pSrc[3 * (nWidth * y0 + x0) + 0];
R[1] = pSrc[3 * (nWidth * y0 + x1) + 0];
R[2] = pSrc[3 * (nWidth * y1 + x0) + 0];
R[3] = pSrc[3 * (nWidth * y1 + x1) + 0];
G[0] = pSrc[3 * (nWidth * y0 + x0) + 1];
G[1] = pSrc[3 * (nWidth * y0 + x1) + 1];
G[2] = pSrc[3 * (nWidth * y1 + x0) + 1];
G[3] = pSrc[3 * (nWidth * y1 + x1) + 1];
B[0] = pSrc[3 * (nWidth * y0 + x0) + 2];
B[1] = pSrc[3 * (nWidth * y0 + x1) + 2];
B[2] = pSrc[3 * (nWidth * y1 + x0) + 2];
B[3] = pSrc[3 * (nWidth * y1 + x1) + 2];
pDst[i * nDstW + j] = UINT16((R[0] + G[0] + B[0]) / 3 * (1 - u) * (1 - v)
+ (R[1] + G[1] + B[1]) / 3 * u * (1 - v)
+ (R[2] + G[2] + B[2]) / 3 * (1 - u) * v
+ (R[3] + G[3] + B[3]) / 3 * u * v);
}
}
}
/****************************************************
* 函数名称IMGO_GetRGBSubImg2RGB
* 功能描述:从图像中获取指定区域,并插值到指定尺寸
* 输入参数:
* 输出参数UBYTE8 *pDst:三通道的局部图像
* 返 回 值:
* 调用关系:
* 其它说明:双线性插值,边缘复制
*****************************************************/
void IMGO_GetRGBSubImg2RGB(UBYTE8* pSrc, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UBYTE8* pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
UBYTE8 R[4] = { 0 };
UBYTE8 G[4] = { 0 };
UBYTE8 B[4] = { 0 };
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth - 2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight - 2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0 + 1;
y1 = y0 + 1;
u = x - x0;//权重
v = y - y0;
R[0] = pSrc[3 * (nWidth * y0 + x0) + 0];
R[1] = pSrc[3 * (nWidth * y0 + x1) + 0];
R[2] = pSrc[3 * (nWidth * y1 + x0) + 0];
R[3] = pSrc[3 * (nWidth * y1 + x1) + 0];
G[0] = pSrc[3 * (nWidth * y0 + x0) + 1];
G[1] = pSrc[3 * (nWidth * y0 + x1) + 1];
G[2] = pSrc[3 * (nWidth * y1 + x0) + 1];
G[3] = pSrc[3 * (nWidth * y1 + x1) + 1];
B[0] = pSrc[3 * (nWidth * y0 + x0) + 2];
B[1] = pSrc[3 * (nWidth * y0 + x1) + 2];
B[2] = pSrc[3 * (nWidth * y1 + x0) + 2];
B[3] = pSrc[3 * (nWidth * y1 + x1) + 2];
pDst[3 * (i * nDstW + j) + 0] = UBYTE8(R[0] * (1 - u) * (1 - v) + R[1] * u * (1 - v)
+ R[2] * (1 - u) * v + R[3] * u * v);
pDst[3 * (i * nDstW + j) + 1] = UBYTE8(G[0] * (1 - u) * (1 - v) + G[1] * u * (1 - v)
+ G[2] * (1 - u) * v + G[3] * u * v);
pDst[3 * (i * nDstW + j) + 2] = UBYTE8(B[0] * (1 - u) * (1 - v) + B[1] * u * (1 - v)
+ B[2] * (1 - u) * v + B[3] * u * v);
}
}
}
void IMGO_GetNV12SubImg2RGB(UBYTE8* pSrcY, UBYTE8* pSrcUV, SINT32 nWidth, SINT32 nHeight, RECT32S roi, UBYTE8* pDst, SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
SINT32 x0, y0, x1, y1;
FLOAT32 fZoomH, fZoomW; //缩放系数
FLOAT32 x, y, u, v;
UINT16 R[4] = { 0 };
UINT16 G[4] = { 0 };
UINT16 B[4] = { 0 };
fZoomH = roi.h / (FLOAT32)nDstH;
fZoomW = roi.w / (FLOAT32)nDstW;
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
x = fZoomW * j; //映射回原矩形框
y = fZoomH * i;
x += roi.x; //映射到源图像
y += roi.y;
x = MINMAX_NUM(x, 0, nWidth - 2); //nWidth-1存在越界
y = MINMAX_NUM(y, 0, nHeight - 2);
x0 = (SINT32)x;
y0 = (SINT32)y;
x1 = x0 + 1;
y1 = y0 + 1;
u = x - x0;//权重
v = y - y0;
R[0] = pSrcY[nWidth * y0 + x0] + ((351 * (pSrcUV[nWidth * (y0 / 2) + (x0 / 2) * 2 + 1] - 128)) >> 8);
R[1] = pSrcY[nWidth * y0 + x1] + ((351 * (pSrcUV[nWidth * (y0 / 2) + (x1 / 2) * 2 + 1] - 128)) >> 8);
R[2] = pSrcY[nWidth * y1 + x0] + ((351 * (pSrcUV[nWidth * (y1 / 2) + (x0 / 2) * 2 + 1] - 128)) >> 8);
R[3] = pSrcY[nWidth * y1 + x1] + ((351 * (pSrcUV[nWidth * (y1 / 2) + (x1 / 2) * 2 + 1] - 128)) >> 8);
G[0] = pSrcY[nWidth * y0 + x0] - ((179 * (pSrcUV[nWidth * (y0 / 2) + (x0 / 2) * 2 + 1] - 128) + 86 * (pSrcUV[nWidth * (y0 / 2) + (x0 / 2) * 2] - 128)) >> 8);
G[1] = pSrcY[nWidth * y0 + x1] - ((179 * (pSrcUV[nWidth * (y0 / 2) + (x1 / 2) * 2 + 1] - 128) + 86 * (pSrcUV[nWidth * (y0 / 2) + (x1 / 2) * 2] - 128)) >> 8);
G[2] = pSrcY[nWidth * y1 + x0] - ((179 * (pSrcUV[nWidth * (y1 / 2) + (x0 / 2) * 2 + 1] - 128) + 86 * (pSrcUV[nWidth * (y1 / 2) + (x0 / 2) * 2] - 128)) >> 8);
G[3] = pSrcY[nWidth * y1 + x1] - ((179 * (pSrcUV[nWidth * (y1 / 2) + (x1 / 2) * 2 + 1] - 128) + 86 * (pSrcUV[nWidth * (y1 / 2) + (x1 / 2) * 2] - 128)) >> 8);
B[0] = pSrcY[nWidth * y0 + x0] + ((443 * (pSrcUV[nWidth * (y0 / 2) + (x0 / 2) * 2] - 128)) >> 8);
B[1] = pSrcY[nWidth * y0 + x1] + ((443 * (pSrcUV[nWidth * (y0 / 2) + (x1 / 2) * 2] - 128)) >> 8);
B[2] = pSrcY[nWidth * y1 + x0] + ((443 * (pSrcUV[nWidth * (y1 / 2) + (x0 / 2) * 2] - 128)) >> 8);
B[3] = pSrcY[nWidth * y1 + x1] + ((443 * (pSrcUV[nWidth * (y1 / 2) + (x1 / 2) * 2] - 128)) >> 8);
pDst[3 * (i * nDstW + j) + 0] = UBYTE8(R[0] * (1 - u) * (1 - v) + R[1] * u * (1 - v)
+ R[2] * (1 - u) * v + R[3] * u * v);
pDst[3 * (i * nDstW + j) + 1] = UBYTE8(G[0] * (1 - u) * (1 - v) + G[1] * u * (1 - v)
+ G[2] * (1 - u) * v + G[3] * u * v);
pDst[3 * (i * nDstW + j) + 2] = UBYTE8(B[0] * (1 - u) * (1 - v) + B[1] * u * (1 - v)
+ B[2] * (1 - u) * v + B[3] * u * v);
//剪裁到0-255范围
pDst[3 * (i * nDstW + j) + 0] = (pDst[3 * (i * nDstW + j) + 0] < 0) ? 0 : ((pDst[3 * (i * nDstW + j) + 0] > 255) ? 255 : pDst[3 * (i * nDstW + j) + 0]);
pDst[3 * (i * nDstW + j) + 1] = (pDst[3 * (i * nDstW + j) + 1] < 0) ? 0 : ((pDst[3 * (i * nDstW + j) + 1] > 255) ? 255 : pDst[3 * (i * nDstW + j) + 1]);
pDst[3 * (i * nDstW + j) + 2] = (pDst[3 * (i * nDstW + j) + 2] < 0) ? 0 : ((pDst[3 * (i * nDstW + j) + 2] > 255) ? 255 : pDst[3 * (i * nDstW + j) + 2]);
}
}
}
void IMGO_GDSGetSubRect(UINT16* pSrc, UINT16* pDst, SINT16 nWidth, SINT16 nHeight, MINMAXRECT* mRect, RECT32S rRect)
{
SINT16 i, j;
UINT32 nCounter;
UINT16* pLine = NULL;
SINT32 nMinX, nMinY, nMaxX, nMaxY;
//边界限制
nMinX = MAX(0, MIN(rRect.x, nWidth - 1));
nMinY = MAX(0, MIN(rRect.y, nHeight - 1));
nMaxX = MIN(nWidth - 1, MAX(0, rRect.x + rRect.w));
nMaxY = MIN(nHeight - 1, MAX(0, rRect.y + rRect.h));
mRect->minX = nMinX;
mRect->minY = nMinY;
mRect->maxX = nMaxX;
mRect->maxY = nMaxY;
rRect.w = nMaxX - nMinX;
rRect.h = nMaxY - nMinY;
//区域提取
nCounter = 0;
//pLine = (PIXELTYPE*)(pSrc + (rRect.cy - rRect.h / 2) * nWidth + rRect.cx - rRect.w / 2);//图像行指针
pLine = (UINT16*)(pSrc + (nMinY * nWidth + nMinX));
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = pLine[j];
}
pLine += nWidth;
}
}
void IMGO_GDSGetSubRectY8(UBYTE8* pSrc, UINT16* pDst, SINT16 nWidth, SINT16 nHeight, MINMAXRECT* mRect, RECT32S rRect)
{
SINT16 i, j;
UINT32 nCounter;
UBYTE8* pLine = NULL;
SINT32 nMinX, nMinY, nMaxX, nMaxY;
//边界限制
nMinX = MAX(0, MIN(rRect.x, nWidth - 1));
nMinY = MAX(0, MIN(rRect.y, nHeight - 1));
nMaxX = MIN(nWidth - 1, MAX(0, rRect.x + rRect.w));
nMaxY = MIN(nHeight - 1, MAX(0, rRect.y + rRect.h));
mRect->minX = nMinX;
mRect->minY = nMinY;
mRect->maxX = nMaxX;
mRect->maxY = nMaxY;
rRect.w = nMaxX - nMinX;
rRect.h = nMaxY - nMinY;
//区域提取
nCounter = 0;
//pLine = (PIXELTYPE*)(pSrc + (rRect.cy - rRect.h / 2) * nWidth + rRect.cx - rRect.w / 2);//图像行指针
pLine = (UBYTE8*)(pSrc + (nMinY * nWidth + nMinX));
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = pLine[j];
}
pLine += nWidth;
}
}
void IMGO_GDSGetSubRectFromY8ToY8(UBYTE8* pSrc, UBYTE8* pDst, SINT16 nWidth, SINT16 nHeight, MINMAXRECT* mRect, RECT32S rRect)
{
SINT16 i, j;
UINT32 nCounter;
UBYTE8* pLine = NULL;
SINT32 nMinX, nMinY, nMaxX, nMaxY;
//边界限制
nMinX = MAX(0, MIN(rRect.x, nWidth - 1));
nMinY = MAX(0, MIN(rRect.y, nHeight - 1));
nMaxX = MIN(nWidth - 1, MAX(0, rRect.x + rRect.w));
nMaxY = MIN(nHeight - 1, MAX(0, rRect.y + rRect.h));
mRect->minX = nMinX;
mRect->minY = nMinY;
mRect->maxX = nMaxX;
mRect->maxY = nMaxY;
rRect.w = nMaxX - nMinX;
rRect.h = nMaxY - nMinY;
//区域提取
nCounter = 0;
//pLine = (PIXELTYPE*)(pSrc + (rRect.cy - rRect.h / 2) * nWidth + rRect.cx - rRect.w / 2);//图像行指针
pLine = (UBYTE8*)(pSrc + (nMinY * nWidth + nMinX));
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = pLine[j];
}
pLine += nWidth;
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubRect()
* 功能描述从pSrc中提取一个矩形区域保存到pDst
* 输入参数PIXELTYPE *pSrc -- 输入原始图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* RECT16S rRect -- 矩形区域参数
* 输出参数PIXELTYPE *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubRectRGB(UBYTE8* pSrc, UINT16* pDst, SINT16 nWidth, SINT16 nHeight, MINMAXRECT* mRect, RECT32S rRect)
{
SINT16 i, j;
UINT32 nCounter;
UBYTE8* pLine = NULL;
SINT32 nMinX, nMinY, nMaxX, nMaxY;
//边界限制
nMinX = MAX(0, MIN(rRect.x, nWidth - 1));
nMinY = MAX(0, MIN(rRect.y , nHeight - 1));
nMaxX = MIN(nWidth - 1, MAX(0, rRect.x + rRect.w));
nMaxY = MIN(nHeight - 1, MAX(0, rRect.y + rRect.h));
mRect->minX = nMinX;
mRect->minY = nMinY;
mRect->maxX = nMaxX;
mRect->maxY = nMaxY;
rRect.w = nMaxX - nMinX;
rRect.h = nMaxY - nMinY;
//区域提取
nCounter = 0;
//pLine = (PIXELTYPE*)(pSrc + (rRect.cy - rRect.h / 2) * nWidth + rRect.cx - rRect.w / 2);//图像行指针
pLine = (UBYTE8*)(pSrc + 3 * (nMinY * nWidth + nMinX));
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = (pLine[j * 3] + pLine[j * 3 + 1] + pLine[j * 3 + 2]) / 3;
}
pLine += nWidth * 3;
}
}
void IMGO_GDSGetSubRectRGBToY8(UBYTE8* pSrc, UBYTE8* pDst, SINT16 nWidth, SINT16 nHeight, MINMAXRECT* mRect, RECT32S rRect)
{
SINT16 i, j;
UINT32 nCounter;
UBYTE8* pLine = NULL;
SINT32 nMinX, nMinY, nMaxX, nMaxY;
//边界限制
nMinX = MAX(0, MIN(rRect.x, nWidth - 1));
nMinY = MAX(0, MIN(rRect.y, nHeight - 1));
nMaxX = MIN(nWidth - 1, MAX(0, rRect.x + rRect.w));
nMaxY = MIN(nHeight - 1, MAX(0, rRect.y + rRect.h));
mRect->minX = nMinX;
mRect->minY = nMinY;
mRect->maxX = nMaxX;
mRect->maxY = nMaxY;
rRect.w = nMaxX - nMinX;
rRect.h = nMaxY - nMinY;
//区域提取
nCounter = 0;
//pLine = (PIXELTYPE*)(pSrc + (rRect.cy - rRect.h / 2) * nWidth + rRect.cx - rRect.w / 2);//图像行指针
pLine = (UBYTE8*)(pSrc + 3 * (nMinY * nWidth + nMinX));
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
pDst[nCounter++] = (pLine[j * 3] + pLine[j * 3 + 1] + pLine[j * 3 + 2]) / 3;
}
pLine += nWidth * 3;
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubMMRect()
* 功能描述从pSrc中提取一个矩形区域保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* MINMAXRECT mmrRect -- 矩形区域参数
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubMMRect(UINT16 *pSrc, UINT16 *pDst, SINT16 nWidth,
SINT16 nHeight, MINMAXRECT mrnRect)
{
SINT16 i, j;
SINT32 nCounter; //=====20180419zy: SINT16修改为SINT32======
SINT32 nLine;
//边界限制
mrnRect.minY = MAX(0, MIN(mrnRect.minY, nHeight - 1));
mrnRect.maxY = MAX(0, MIN(mrnRect.maxY, nHeight - 1));
mrnRect.minX = MAX(0, MIN(mrnRect.minX, nWidth - 1));
mrnRect.maxX = MAX(0, MIN(mrnRect.maxX, nWidth - 1));
//区域提取
nCounter = 0;
nLine = mrnRect.minY * nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY; i++)
{
for (j = mrnRect.minX; j <= mrnRect.maxX; j++)
{
pDst[nCounter++] = pSrc[nLine + j];
}
nLine += nWidth;
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubMMRect()
* 功能描述从pSrc中提取一个矩形区域保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* MINMAXRECT mmrRect -- 矩形区域参数
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubMMRect(GD_VIDEO_FRAME_S img, UINT16* pDst, SINT16 nWidth,
SINT16 nHeight, MINMAXRECT mrnRect)
{
SINT16 i, j;
SINT32 nCounter; //=====20180419zy: SINT16修改为SINT32======
SINT32 nLine;
//边界限制
mrnRect.minY = MAX(0, MIN(mrnRect.minY, nHeight - 1));
mrnRect.maxY = MAX(0, MIN(mrnRect.maxY, nHeight - 1));
mrnRect.minX = MAX(0, MIN(mrnRect.minX, nWidth - 1));
mrnRect.maxX = MAX(0, MIN(mrnRect.maxX, nWidth - 1));
//区域提取
nCounter = 0;
nLine = mrnRect.minY * nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY; i++)
{
for (j = mrnRect.minX; j <= mrnRect.maxX; j++)
{
//pDst[nCounter++] = pSrc[nLine + j];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
pDst[nCounter++] = (UINT16)((UBYTE8*)img.u64VirAddr[0])[nLine + j];
}
else
{
pDst[nCounter++] = (UINT16)((UINT16*)img.u64VirAddr[0])[nLine + j];
}
}
nLine += nWidth;
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubMMRect2DownSample()
* 功能描述从pSrc中提取一个矩形区域2倍降采样后保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT32 nWidth -- 输入图像宽度
* SINT32 nHeight -- 输入图像高度
* MINMAXRECT32S mrnRect -- 矩形区域参数
* SINT32 nMode -- 降采样方式。1-2*2均值0-抽点
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubMMRect2DownSample(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight,
UINT16 *pDst, MINMAXRECT32S mrnRect,
SINT32 nDSmpMode)
{
SINT32 i, j;
SINT32 nCounter;
SINT32 nLine;
SINT32 nLineNext;
SINT32 nDSmpValue;
SINT32 nIndex;
SINT32 nIndexNext;
//边界限制
mrnRect.minY = MAX(0, MIN(mrnRect.minY, nHeight - 2));
mrnRect.maxY = MAX(0, MIN(mrnRect.maxY, nHeight - 2));
mrnRect.minX = MAX(0, MIN(mrnRect.minX, nWidth - 2));
mrnRect.maxX = MAX(0, MIN(mrnRect.maxX, nWidth - 2));
//降采样方式2*2均值
if (1 == nDSmpMode)
{
nCounter = 0;
nLine = mrnRect.minY * nWidth;
nLineNext = nLine + nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY; i += 2)
{
for (j = mrnRect.minX; j <= mrnRect.maxX; j += 2)
{
nIndex = nLine + j;
nIndexNext = nLineNext + j;
nDSmpValue = pSrc[nIndex] + pSrc[nIndex + 1]
+ pSrc[nIndexNext] + pSrc[nIndexNext + 1];
pDst[nCounter++] = nDSmpValue >> 2;
}
nLine += (nWidth << 1);
nLineNext += (nWidth << 1);
}
}
//降采样方式:抽点
else
{
nCounter = 0;
nLine = mrnRect.minY * nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY; i += 2)
{
for (j = mrnRect.minX; j <= mrnRect.maxX; j += 2)
{
nIndex = nLine + j;
pDst[nCounter++] = pSrc[nIndex];
}
nLine += (nWidth << 1);
}
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubMMRect2DownSample()
* 功能描述从pSrc中提取一个矩形区域2倍降采样后保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT32 nWidth -- 输入图像宽度
* SINT32 nHeight -- 输入图像高度
* MINMAXRECT32S mrnRect -- 矩形区域参数
* SINT32 nMode -- 降采样方式。1-2*2均值0-抽点
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubMMRect2DownSample(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
UINT16* pDst, MINMAXRECT32S mrnRect,
SINT32 nDSmpMode)
{
SINT32 i, j;
SINT32 nCounter;
SINT32 nLine;
SINT32 nLineNext;
SINT32 nDSmpValue;
SINT32 nIndex;
SINT32 nIndexNext;
//边界限制
mrnRect.minY = MAX(0, MIN(mrnRect.minY, nHeight - 2));
mrnRect.maxY = MAX(0, MIN(mrnRect.maxY, nHeight - 2));
mrnRect.minX = MAX(0, MIN(mrnRect.minX, nWidth - 2));
mrnRect.maxX = MAX(0, MIN(mrnRect.maxX, nWidth - 2));
//降采样方式2*2均值
if (1 == nDSmpMode)
{
nCounter = 0;
nLine = mrnRect.minY * nWidth;
nLineNext = nLine + nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY; i += 2)
{
for (j = mrnRect.minX; j <= mrnRect.maxX; j += 2)
{
nIndex = nLine + j;
nIndexNext = nLineNext + j;
//nDSmpValue = pSrc[nIndex] + pSrc[nIndex + 1]
// + pSrc[nIndexNext] + pSrc[nIndexNext + 1];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
nDSmpValue = (SINT32)((UBYTE8*)img.u64VirAddr[0])[nIndex] + ((UBYTE8*)img.u64VirAddr[0])[nIndex + 1]
+ ((UBYTE8*)img.u64VirAddr[0])[nIndexNext] + ((UBYTE8*)img.u64VirAddr[0])[nIndexNext + 1];
}
else
{
nDSmpValue = (SINT32)((UINT16*)img.u64VirAddr[0])[nIndex] + ((UINT16*)img.u64VirAddr[0])[nIndex + 1]
+ ((UINT16*)img.u64VirAddr[0])[nIndexNext] + ((UINT16*)img.u64VirAddr[0])[nIndexNext + 1];
}
pDst[nCounter++] = nDSmpValue >> 2;
}
nLine += (nWidth << 1);
nLineNext += (nWidth << 1);
}
}
//降采样方式:抽点
else
{
nCounter = 0;
nLine = mrnRect.minY * nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY; i += 2)
{
for (j = mrnRect.minX; j <= mrnRect.maxX; j += 2)
{
nIndex = nLine + j;
//pDst[nCounter++] = pSrc[nIndex];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
pDst[nCounter++] = (UINT16)((UBYTE8*)img.u64VirAddr[0])[nIndex];
}
else
{
pDst[nCounter++] = (UINT16)((UINT16*)img.u64VirAddr[0])[nIndex];
}
}
nLine += (nWidth << 1);
}
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubMMRectDownSample()
* 功能描述从pSrc中提取一个矩形区域降采样后保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT32 nWidth -- 输入图像宽度
* SINT32 nHeight -- 输入图像高度
* MINMAXRECT32S mrnRect -- 矩形区域参数
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubMMRectDownSample(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight,
UINT16 *pDst, MINMAXRECT32S mrnRect, SINT32 nDSmpScale)
{
SINT32 i, j;
SINT32 nCounter;
SINT32 nLine;
//SINT32 nLineNext;
/* SINT32 nLineNextNext;*/
SINT32 nDSmpValue;
SINT32 nIndex;
/*SINT32 nIndexNext;*/
/*SINT32 nIndexNextNext;*/
FLOAT32 fDSmpScale2 = 1.0f / (nDSmpScale * nDSmpScale);
//边界限制
mrnRect.minY = MAX(0, MIN(mrnRect.minY, nHeight - 2));
mrnRect.maxY = MAX(0, MIN(mrnRect.maxY, nHeight -2));
mrnRect.minX = MAX(0, MIN(mrnRect.minX, nWidth - 2));
mrnRect.maxX = MAX(0, MIN(mrnRect.maxX, nWidth -2));
SINT32 k;
SINT32 p;
//区域提取
nCounter = 0;
nLine = mrnRect.minY * nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY - nDSmpScale + 1; i += nDSmpScale)
{
for (j = mrnRect.minX; j <= mrnRect.maxX -nDSmpScale + 1; j += nDSmpScale)
{
nIndex = nLine + j;
nDSmpValue = 0;
for (k = 0; k < nDSmpScale; k++)
{
for (p = 0; p < nDSmpScale; p++)
{
nDSmpValue += pSrc[nIndex + k*nWidth + p];
}
}
//pDst[nCounter++] = (UINT16)(nDSmpValue * fDSmpScale2);
pDst[nCounter++] = (UINT16)(nDSmpValue * fDSmpScale2); //20180118图像定义成short型
}
nLine += (nWidth * nDSmpScale);
}
}
/**********************************************************
* 函数名称IMGO_GDSGetSubMMRectDownSample()
* 功能描述从pSrc中提取一个矩形区域降采样后保存到pDst
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT32 nWidth -- 输入图像宽度
* SINT32 nHeight -- 输入图像高度
* MINMAXRECT32S mrnRect -- 矩形区域参数
* 输出参数UINT16 *pDst -- 提取的矩形区域图像
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GDSGetSubMMRectDownSample(GD_VIDEO_FRAME_S img, SINT32 nWidth, SINT32 nHeight,
UINT16* pDst, MINMAXRECT32S mrnRect, SINT32 nDSmpScale)
{
SINT32 i, j;
SINT32 nCounter;
SINT32 nLine;
//SINT32 nLineNext;
/* SINT32 nLineNextNext;*/
SINT32 nDSmpValue;
SINT32 nIndex;
/*SINT32 nIndexNext;*/
/*SINT32 nIndexNextNext;*/
FLOAT32 fDSmpScale2 = 1.0f / (nDSmpScale * nDSmpScale);
//边界限制
mrnRect.minY = MAX(0, MIN(mrnRect.minY, nHeight - 2));
mrnRect.maxY = MAX(0, MIN(mrnRect.maxY, nHeight - 2));
mrnRect.minX = MAX(0, MIN(mrnRect.minX, nWidth - 2));
mrnRect.maxX = MAX(0, MIN(mrnRect.maxX, nWidth - 2));
SINT32 k;
SINT32 p;
//区域提取
nCounter = 0;
nLine = mrnRect.minY * nWidth;
for (i = mrnRect.minY; i <= mrnRect.maxY - nDSmpScale + 1; i += nDSmpScale)
{
for (j = mrnRect.minX; j <= mrnRect.maxX - nDSmpScale + 1; j += nDSmpScale)
{
nIndex = nLine + j;
nDSmpValue = 0;
for (k = 0; k < nDSmpScale; k++)
{
for (p = 0; p < nDSmpScale; p++)
{
//nDSmpValue += pSrc[nIndex + k * nWidth + p];
if (GD_PIXEL_FORMAT_GRAY_Y8 == img.enPixelFormat)
{
nDSmpValue += (SINT32)((UBYTE8*)img.u64VirAddr[0])[nIndex + k * nWidth + p];
}
else
{
nDSmpValue += (SINT32)((UINT16*)img.u64VirAddr[0])[nIndex + k * nWidth + p];
}
}
}
//pDst[nCounter++] = (UINT16)(nDSmpValue * fDSmpScale2);
pDst[nCounter++] = (UINT16)(nDSmpValue * fDSmpScale2); //20180118图像定义成short型
}
nLine += (nWidth * nDSmpScale);
}
}
/**********************************************************
* 函数名称IMGO_ProjectObject()
* 功能描述:投影法目标分割
* 输入参数UINT16 *pSrc -- 输入图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* MINMAXRECT *pmrObjRect -- 分割出的目标上下左右边界
* 输出参数:无
* 返 回 值:目标大小
* 调用关系:无
* 其它说明:无
**********************************************************/
SINT32 IMGO_ProjectObject(UINT16 *pSrc, SINT16 nWidth, SINT16 nHeight, MINMAXRECT *pmrObjRect,
SINT16 *pnProjectHz, SINT16 *pnProjectVt)
{
SINT16 i;
SINT16 nPrjHzMax; //水平投影最大值
SINT16 nPrjVtMax; //垂直投影最大值
SINT16 nPrjHzThres; //水平投影分割阈值
SINT16 nPrjVtThres; //垂直投影分割阈值
SINT32 nCnt;
//SINT16 *pnProjectHz = (SINT16*)malloc(nWidth*sizeof(SINT16));
//SINT16 *pnProjectVt = (SINT16*)malloc(nHeight*sizeof(SINT16));
//初始化
pmrObjRect->minX = 0;
pmrObjRect->maxX = nWidth - 1;
pmrObjRect->minY = 0;
pmrObjRect->maxY = nHeight - 1;
memset(pnProjectHz, 0, nWidth*sizeof(SINT16));
memset(pnProjectVt, 0, nHeight*sizeof(SINT16));
//计算图像水平投影
IMGO_Project_Horizental(pSrc, nWidth, nHeight, pnProjectHz, &nPrjHzMax);
//计算目标左右边界分割阈值
nPrjHzThres = nPrjHzMax / 2;
//nPrjHzThres = nPrjHzMax / 3;
//根据水平投影统计目标左边界
for (i = 0; i < nWidth; i++)
{
//if (pnProjectHz[i] > nPrjHzThres)
if ((pnProjectHz[i] > nPrjHzThres) || (pnProjectHz[i] >= nPrjHzThres && nPrjHzThres != 0))
{
pmrObjRect->minX = i;
break;
}
}
//根据水平投影统计目标右边界
for (i = nWidth-1; i >= 0; i--)
{
//if (pnProjectHz[i] > nPrjHzThres)
if ((pnProjectHz[i] > nPrjHzThres) || (pnProjectHz[i] >= nPrjHzThres && nPrjHzThres != 0))
{
pmrObjRect->maxX = i;
break;
}
}
//对指定左、右边界区域进行垂直投影
IMGO_Project_Vertical(pSrc, nWidth, nHeight, pnProjectVt,
pmrObjRect->minX, pmrObjRect->maxX, &nPrjVtMax);
//计算目标上相边界分割阈值
nPrjVtThres = nPrjVtMax / 2;
//根据垂直投影统计目标上边界
for (i = 0; i < nHeight; i++)
{
//if (pnProjectVt[i] > nPrjVtThres)
if ((pnProjectVt[i] > nPrjVtThres) ||(pnProjectVt[i] >= nPrjVtThres && nPrjVtThres != 0))
{
pmrObjRect->minY = i;
break;
}
}
//根据垂直投影统计目标下边界
for (i = nHeight-1; i >= 0; i--)
{
//if (pnProjectVt[i] > nPrjVtThres)
if ((pnProjectVt[i] > nPrjVtThres) ||(pnProjectVt[i] >= nPrjVtThres && nPrjVtThres != 0))
{
pmrObjRect->maxY = i;
break;
}
}
//统计目标大小
nCnt = 0;
for (i = pmrObjRect->minY; i <= pmrObjRect->maxY; i++)
{
nCnt += pnProjectVt[i];
}
//释放内存
//free(pnProjectHz);
//free(pnProjectVt);
return nCnt;
}
/**********************************************************
* 函数名称IMGO_Project_Horizental()
* 功能描述:水平投影(垂直向下投影),并统计投影最大值
* 输入参数UINT16 *pSrc -- 输入图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像高度
* SINT16 *pnProject -- 输入图像每列数据的累加和
* SINT16 *pnPrjMax -- 输入图像每列数据累加的最大值
* 输出参数:无
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_Project_Horizental(UINT16 *pSrc, SINT16 nWidth, SINT16 nHeight,
SINT16 *pnProject, SINT16 *pnPrjMax)
{
SINT16 i, j;
SINT16 nSum;
//初始化
*pnPrjMax = 0;
memset(pnProject, 0, nWidth * sizeof(SINT16));
//计算每一列的投影
for (i = 0; i < nWidth; i++)
{
//初始化
nSum = 0;
//遍历第i列图像进行像素值累加
for (j = 0; j < nHeight; j++)
{
pnProject[i] += pSrc[j*nWidth+i];
}
//统计水平投影最大值
*pnPrjMax = MAX(*pnPrjMax, pnProject[i]);
}
}
/**********************************************************
* 函数名称IMGO_Project_Vertical()
* 功能描述:指定行区间的垂直投影(水平向右投影),并统计投影最大值
* 输入参数UINT16 *pSrc -- 输入图像
* SINT16 nWidth -- 输入图像宽度
* SINT16 nHeight -- 输入图像宽度
* SINT16 nXStart -- 输入图像指定统计时起始列位置
* SINT16 nXEnd -- 输入图像指定统计时终止列位置
* 输出参数SINT16 *pnProject -- 输入图像指定列区域内每行数据累加和
* SINT16 *pnPrjMax -- 输入图像指定列区域内每行数据累加的最大值
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_Project_Vertical(UINT16 *pSrc, SINT16 nWidth, SINT16 nHeight,
SINT16 *pnProject, SINT16 nXStart, SINT16 nXEnd, SINT16 *pnPrjMax)
{
SINT16 i, j;
SINT16 nLineStart;
SINT16 nSum;
//初始化
*pnPrjMax = 0;
memset(pnProject, 0, nHeight*sizeof(SINT16));
//预防出错
nXStart = MAX(0, MIN(nXStart, nWidth - 1));
nXEnd = MAX(0, MIN(nXEnd, nWidth - 1));
if (nXStart > nXEnd)
{
return;
}
//计算每一列的投影
for (i = 0; i < nHeight; i++)
{
//初始化
nSum = 0;
nLineStart = i * nWidth;
//遍历第i列图像进行像素值累加
for (j = nXStart; j <= nXEnd; j++)
{
pnProject[i] += pSrc[nLineStart+j];
}
//统计垂直投影最大值
*pnPrjMax = MAX(*pnPrjMax, pnProject[i]);
}
}
/**********************************************************
* 函数名称IMGO_CalcImgHistY16()
* 功能描述:统计直方图 - Y16图像
* 输入参数UINT16 *pSrc -- 输入图像
* SINT32 nWidth -- 图像宽度
* SINT32 nHeight -- 图像高度
* SINT32 nMoveBit -- 移位位数
* 输出参数SINT32 *pnHist -- 图像直方图
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_CalcImgHistY16(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight,
SINT32 nMoveBit, SINT32 *pnHist)
{
SINT32 i;
SINT32 nLen = nWidth * nHeight;
SINT32 nMoveBitAbs = ABS(nMoveBit);
//左移nMoveBit位
if (nMoveBit > 0)
{
for (i = 0; i < nLen; i++)
{
pnHist[pSrc[i] >> nMoveBitAbs]++;
}
}
//右移nMoveBit位
else if (nMoveBit > 0)
{
for (i = 0; i < nLen; i++)
{
pnHist[pSrc[i] << nMoveBitAbs]++;
}
}
//不移位
else
{
for (i = 0; i < nLen; i++)
{
pnHist[pSrc[i]]++;
}
}
}
/**********************************************************
* 函数名称IMGO_CalcImgHistInRectY16()
* 功能描述:统计矩形区域内的直方图 - Y16图像
* 输入参数UINT16 *pSrc -- 输入图像
* SINT32 nWidth -- 图像宽度
* SINT32 nHeight -- 图像高度
* MINMAXRECT32S *pmrnRect -- 矩形区域
* SINT32 nMoveBit -- 移位位数
* 输出参数SINT32 *pnHist -- 图像直方图
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_CalcImgHistInRectY16(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight,
MINMAXRECT32S *pmrnRect, SINT32 nMoveBit, SINT32 *pnHist)
{
SINT32 i, j;
SINT32 nLine = pmrnRect->minY * nWidth;
SINT32 nMoveBitAbs = ABS(nMoveBit);
//右移nMoveBit位
if (nMoveBit > 0)
{
for (i = pmrnRect->minY; i <= pmrnRect->maxY; i++)
{
for (j = pmrnRect->minX; j <= pmrnRect->maxX; j++)
{
pnHist[pSrc[nLine + j] >> nMoveBitAbs]++;
}
nLine += nWidth;
}
}
//左移nMoveBit位
else if (nMoveBit < 0)
{
for (i = pmrnRect->minY; i <= pmrnRect->maxY; i++)
{
for (j = pmrnRect->minX; j <= pmrnRect->maxX; j++)
{
pnHist[pSrc[nLine + j] << nMoveBitAbs]++;
}
nLine += nWidth;
}
}
//不移位
else
{
for (i = pmrnRect->minY; i <= pmrnRect->maxY; i++)
{
for (j = pmrnRect->minX; j <= pmrnRect->maxX; j++)
{
pnHist[pSrc[nLine + j]]++;
}
nLine += nWidth;
}
}
}
/**********************************************************
* 函数名称IMGO_IsPoint16SOutImg()
* 功能描述:判断坐标点是否超出图像边界 - POINT16S
* 输入参数POINT16S ptPnt -- 坐标点
* SINT32 nWidth -- 图像宽度
* SINT32 nHeight -- 图像高度
* 输出参数1-坐标点超出图像边界0-未超出图像边界。
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
BBOOL IMGO_IsPoint16SOutImg(SINT32 nWidth, SINT32 nHeight, POINT16S ptPnt)
{
// 20171114zy目标在图像边界时则认为目标不在视场作为情况管道的一种条件
SINT32 nBorderR = 10;
if ((ptPnt.x < nBorderR) || (nWidth - nBorderR <= ptPnt.x)
|| (ptPnt.y < nBorderR) || (nHeight - nBorderR <= ptPnt.y))
{
return TRUE;
}
else
{
return FALSE;
}
}
/**********************************************************
* 函数名称IMGO_IsPoint32FOutImg()
* 功能描述:判断坐标点是否超出图像边界 - POINT32F
* 输入参数POINT32F ptPnt -- 坐标点
* SINT32 nWidth -- 图像宽度
* SINT32 nHeight -- 图像高度
* 输出参数1-坐标点超出图像边界0-未超出图像边界。
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
BBOOL IMGO_IsPoint32FOutImg(SINT32 nWidth, SINT32 nHeight, POINT32F ptPnt)
{
if ((ptPnt.x < 0) || (nWidth <= ptPnt.x)
|| (ptPnt.y < 0) || (nHeight <= ptPnt.y))
{
return TRUE;
}
else
{
return FALSE;
}
}
/**********************************************************
* 函数名称IMGO_IsMMRect32SOutImg()
* 功能描述:判断矩形是否超出图像边界 - MINMAXRECT32S
* 输入参数SINT32 nWidth -- 图像宽度
* SINT32 nHeight -- 图像高度
* MINMAXRECT32S *pmrnRect -- 四边型矩形
* 输出参数1-矩形超出图像边界0-未超出图像边界。
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
BBOOL IMGO_IsMMRect32SOutImg(SINT32 nWidth, SINT32 nHeight, MINMAXRECT32S *pmrnRect)
{
if ((pmrnRect->minX < 0) || (nWidth <= pmrnRect->maxX)
|| (pmrnRect->minY < 0) || (nHeight <= pmrnRect->maxY))
{
return TRUE;
}
else
{
return FALSE;
}
}
/**********************************************************
* 函数名称IMGO_CalcGradImg()
* 功能描述:计算输入图像的梯度幅值图
* 输入参数UINT16 *pScrImg -- 输入的图像
* SINT32 nWidth -- 图像宽
* SINT32 nHeight -- 图像高
* 输出参数UINT16 *pnMagImg -- 输出的梯度幅值矩阵
* 返 回 值:无
* 调用关系GaussianFilterMag()
* 其它说明使用sobel算子
* X方向: 1 0 -1 Y方向: 1 2 1
* 2 0 -2 0 0 0
* 1 0 -1 -1 -2 -1
**********************************************************/
void IMGO_CalcGradImg(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight, UINT16 *pnMagImg)
{
SINT32 i, j;
SINT32 nLen = nWidth * nHeight;
SINT32 nHStart, nHEnd; //参与梯度计算的起始行、终止行
SINT32 nWStart, nWEnd; //参与梯度计算的起始列、终止列
SINT32 nIndex; //当前像素的坐标
SINT32 nLine; //当前像素的行起始坐标
SINT32 nLinePre, nLineNext; //上侧、下侧像素的坐标
SINT32 nIndexPre, nIndexNext; //左侧、右侧像素的坐标
SINT32 nGradX, nGradY; //像素点在X、Y方向梯度
SINT32 nGradSum; //像素点的梯度方向
SINT32 nGradThresMax = 65534; //最大不超过16bit由(UINT16 *pnMagImg)限制
SINT32 nGradThresMin = 30;
// SINT32 *pnGradX = (SINT32*)DSP_IMGO_pnGradX;
// SINT32 *pnGradY = (SINT32*)DSP_IMGO_pnGradY;
SINT32 pnGradX[2000] = {0};
SINT32 pnGradY[2000] = {0};
memset(pnGradX, 0, sizeof(SINT32) * nWidth);
memset(pnGradY, 0, sizeof(SINT32) * nWidth);
memset(pnMagImg, 0, nLen * sizeof(UINT16));
//参数设置
nHStart = 1; //序列标号,表示图像的第2行
nHEnd = nHeight - 2; //序列标号,表示图像的倒数第2行,20171110zy
nWStart = 1;
nWEnd = nWidth - 2;
//使用sobel滤波算子求梯度图像
nLine = nHStart * nWidth;
for (i = nHStart; i <= nHEnd; i++)
{
//一次性计算当前行像素所用到的X、Y方向梯度临时数据
for (j = 0; j < nWidth; j++) //20171110zy: 全图像的nWidth, 没有减2
{
//计算当前像素、上侧像素、下侧像素的坐标
nIndex = nLine + j;
nLinePre = nIndex - nWidth;
nLineNext = nIndex + nWidth;
//X方向梯度中间结果
pnGradX[j] = pSrc[nLinePre] + 2*pSrc[nIndex] + pSrc[nLineNext]; //上一行 + 2*当前行 + 下一行
pnGradY[j] = pSrc[nLinePre] - pSrc[nLineNext]; //上一行 - 下一行
}
//计算第(i,j)个像素的梯度幅值和方向
for (j = nWStart; j <= nWEnd; j++)
{
//计算当前像素、上侧像素、下侧像素的坐标
nIndex = nLine + j;
nIndexPre = j - 1;
nIndexNext = j + 1;
//计算X、Y方向梯度值
nGradX = pnGradX[nIndexPre] - pnGradX[nIndexNext]; //公式中的第1列 - 第3列
nGradY = pnGradY[nIndexPre] + 2*pnGradY[j] + pnGradY[nIndexNext]; //公式中的第1行 - 第3行
//计算梯度幅值
nGradSum = MIN(ABS(nGradX) + ABS(nGradY), nGradThresMax); //【处理16位数据时需调整】
//剔除弱梯度杂波
if (nGradSum < nGradThresMin)
{
pnMagImg[nIndex] = 0;
}
else
{
pnMagImg[nIndex] = (UINT16)(nGradSum); //取X、Y方向梯度绝对值和作为该点的梯度幅值
}
}
//更新下一行起始坐标
nLine += nWidth;
}//end of for (i = nHStart; i <= nHEnd; i++)...
}
/**********************************************************
* 函数名称IMGO_CalcIntegralImg()
* 功能描述:计算积分图(integral image, 简写IntImg)
* 输入参数UINT16 *pFrame -- 输入图像
* SIZE32S sImgSize -- 图像尺寸
* SIZE32S sIntImgSize -- 积分图尺寸
* 输出参数SINT32 *pnIntImg -- 积分图
* 返 回 值:无
* 调用关系:无
* 其它说明设输入图像f积分图g其中g比f的上侧、左侧分别多补1行和1列0
* g(i,j)的积分值等于以f(0,0)、f(i,j)点所成矩形内像素值累加和。
* 其中0 <= i <= sImgSize.h, 0 <= j <= sImgSize.w。
* 计算方式:
* 1初始化第0行、第0列像素的积分值为0
* g(0,j) = 0;
* g(i,0) = 0;
* 2计算第i = (1 ~ sImgSize.h)行像素的积分值:
* A.先算当前行累加积分图:
* l(i,0) = f(i-1,0)。
* l(i,j) = l(i,j-1) + f(i-1,j)。
* B.再计算当前像素积分值:
* g(i,j) = g(i-1,j) + l(i,j)。
* 注:输入图像(i,j)点,对应于积分图像上的(i+1,j+1)点。
**********************************************************/
void IMGO_CalcIntegralImg(UINT16 *pFrame, SIZE32S sImgSize,
SINT32 *pnIntImg, SIZE32S sIntImgSize)
{
SINT32 i, j;
SINT32 nIntImgPxlSize = sIntImgSize.w * sIntImgSize.h;
SINT32 nLnSum = 0; //输入图像当前行的累加结果
UINT16 *pnPxl = NULL; //指向输入图像当前像素
SINT32 *pnIntPxl = NULL; //指向积分图当前像素
SINT32 *pnIntPxlUp = NULL; //指向积分图当前像素的上一行像素
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//初始化
//注仅初始化第0行、第0列积分图全图清零较耗时
memset(pnIntImg, 0, sizeof(SINT32) * sIntImgSize.w);
for (i = sIntImgSize.w; i < nIntImgPxlSize; i += sIntImgSize.w)
{
pnIntImg[i] = 0;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//计算第[0, sImgSize.h-1]行、第[0, sImgSize.h-1]列图像像素的积分值,
//分别存入第[1 ~ sImgSize.h]行、第[1, sImgSize.h]列积分图。
pnPxl = (UINT16*)pFrame;
pnIntPxl = (SINT32*)pnIntImg + sIntImgSize.w;
pnIntPxlUp = (SINT32*)pnIntImg;
for (i = 0; i < sImgSize.h; i++)
{
//初始化当前行累加结果
nLnSum = 0;
//跳过积分图第1列像素
pnIntPxl++;
pnIntPxlUp++;
//行内每个像素
for (j = 0; j < sImgSize.w; j++)
{
//对当前行图像像素值累加
nLnSum += (*pnPxl++);
//将"当前行图像累加值+上一行对应点的积分值"存入积分图
(*pnIntPxl++) = nLnSum + (*pnIntPxlUp++);
}
}
}
/**********************************************************
* 函数名称IMGO_CalcIntegralImg()
* 功能描述:计算积分图内矩形像素和
* 输入参数SINT32 *pnIntImg -- 积分图
* SIZE32S sIntImgSize -- 积分图尺寸
* MINMAXRECT32S mrnRect -- 四边型矩形
* 输出参数SINT32 nRectSum -- 矩形内像素和
* 返 回 值:无
* 调用关系:无
* 其它说明设输入图像f积分图g其中g比f的上侧、左侧分别多补1行和1列0
* g(i,j)的积分值等于以f(0,0)、f(i,j)点所成矩形内像素值累加和。
* 1输入图像(i,j)点,对应于积分图像上的(i+1,j+1)点。
* 因此输入图像上的矩形ABCD对应于积分图上的矩形abcd。
* - - - - - - - - -
* - - A - - B E - -
* - - - a - - b - -
* - - C - - D - - -
* - - F c - - d - -
* - - - - - - - - -
* 2积分图上矩形abcd内的像素和如下计算
* nSum = g(A) - g(E) - g(F) + g(d)
**********************************************************/
SINT32 IMGO_CalcIntegralInMMRect(SINT32 *pnIntImg, SIZE32S sIntImgSize, MINMAXRECT32S mrnRect)
{
SINT32 nRectSum = 0; //矩形内像素值累加和
MINMAXRECT32S mrnRectInt; //积分图内矩形
SINT32 nLineMin; //起始行坐标
SINT32 nLineMax; //结束行坐标
//将矩形坐标从原始图像映射到积分图上
mrnRectInt = mrnRect;
mrnRectInt.maxX += 1;
mrnRectInt.maxY += 1;
//统计矩形内像素和
nLineMin = mrnRectInt.minY * sIntImgSize.w;
nLineMax = mrnRectInt.maxY * sIntImgSize.w;
nRectSum = pnIntImg[nLineMin + mrnRectInt.minX]
- pnIntImg[nLineMin + mrnRectInt.maxX]
- pnIntImg[nLineMax + mrnRectInt.minX]
+ pnIntImg[nLineMax + mrnRectInt.maxX];
return nRectSum;
}
FLOAT32 IMGO_RectOverlap(RECT32S *prtA, RECT32S *prtB)
{
if (prtA->x > prtB->x+prtB->w) { return 0.0; }
if (prtA->y > prtB->y+prtB->h) { return 0.0; }
if (prtB->x > prtA->x+prtA->w) { return 0.0; }
if (prtB->y > prtA->y+prtA->h) { return 0.0; }
FLOAT32 colInt = MIN(prtA->x+prtA->w-1, prtB->x+prtB->w-1) - MAX(prtA->x, prtB->x) + 1.0f;
FLOAT32 rowInt = MIN(prtA->y+prtA->h-1, prtB->y+prtB->h-1) - MAX(prtA->y, prtB->y) + 1.0f;
FLOAT32 intersection = colInt * rowInt;
SINT32 area1 = prtA->w * prtA->h;
SINT32 area2 = prtB->w * prtB->h;
return intersection / (area1 + area2 - intersection);
}
/**********************************************************
* 函数名称IMGO_CalculateMeanSquared()
* 功能描述:计算输入图像的均值、灰度和、灰度平方和
* 输入参数UINT16 *pSrc -- 输入原始图像
* SINT32 nLen -- 图像尺寸
* 输出参数FLOAT32 *Mean -- 图像均值
* FLOAT32 *Sum -- 图像灰度和
* FLOAT32 *SquaredSum -- 图像灰度平方和
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_CalculateMeanSquared(UINT16 *pSrc, SINT32 nLen, FLOAT32 *fMean,
FLOAT32 *fSum, DOUBLE64 *fSquaredSum)
{
double pixelvalue;
double dSum = 0.0;
double dSquaredSum = 0.0;
double dMean = 0.0;
SINT32 i;
for (i = 0; i < nLen; i++)
{
pixelvalue = (double)pSrc[i];
dSum += pixelvalue;
//dSquaredSum += pixelvalue*pixelvalue;
}
dMean = dSum / nLen;
*fMean = (FLOAT32)dMean;
*fSum = (FLOAT32)dSum;
for (i = 0; i < nLen; i++)
{
pixelvalue = (double)pSrc[i];
dSquaredSum += (pixelvalue ) * (pixelvalue);
}
*fSquaredSum= (FLOAT32)dSquaredSum;
}
SINT32 FindMinOfFour(SINT32 *pa)
{
SINT32 min1 = 0;
SINT32 min2 = 0;
SINT32 min = 0;
if (pa[0] < pa[1])
{
min1 = pa[0];
}
else
{
min1 = pa[1];
}
if (pa[2] < pa[3])
{
min2 = pa[2];
}
else
{
min2 = pa[3];
}
if (min1 < min2)
{
min = min1;
}
else
{
min = min2;
}
return min;
}
SINT32 FindMaxOfFour(SINT32 *pa)
{
SINT32 max1 = 0;
SINT32 max2 = 0;
SINT32 max = 0;
if (pa[0] > pa[1])
{
max1 = pa[0];
}
else
{
max1 = pa[1];
}
if (pa[2] > pa[3])
{
max2 = pa[2];
}
else
{
max2 = pa[3];
}
if (max1 > max2)
{
max = max1;
}
else
{
max = max2;
}
return max;
}
/**********************************************************
* 函数名称IMGO_GcABCLin()
* 功能描述:线性自动亮度对比度
* 输入参数UINT16 *pSrc -- 原始图像
* SINT32 nLen -- 图像尺寸
* 输出参数UBYTE8 *pDst -- 处理后图像,调光后
* 返 回 值:无
* 调用关系:无
* 其它说明:无
**********************************************************/
void IMGO_GcABCLin(UINT16 *pSrc, UBYTE8 *pDst, SINT32 nLen)
{
SINT32 i;
//SINT32 nContrast;
//SINT32 nBright;
SINT32 nSigma;
SINT32 nSum;
SINT32 nMin;
SINT32 nMax;
SINT32 nMid;
SINT32 nValue;
FLOAT32 K;
FLOAT32 C;
SINT32 *pHist = new SINT32[65536];
UINT16 *pSrcUINT16 = new UINT16[nLen]; //20180122注意pSrc更改为有符号型
//20180122
for (i = 0; i < nLen; i++)
{
pSrcUINT16[i] = (UINT16)(pSrc[i] + 32768);
}
//统计直方图
memset((void*)pHist, 0, 65536 * sizeof(SINT32));
for (i = 0; i < nLen; i++)
{
//pHist[pSrc[i]]++;
pHist[pSrcUINT16[i]]++;//20180122
}
//求映射的最大最小值
nSigma = (SINT32)(0.05 * nLen); //设置高低端抛点数
nSum = 0;
nMin = 0;
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;
}
}
//计算对比度、亮度
//K = (FLOAT32)(256.0 / (nMax-nMin+1));
//C = (FLOAT32)(-K * nMin);
//K = (FLOAT32)((226.0 - 30) / (nMax-nMin+1));
//C = (FLOAT32)(128 - K * (nMin + nMax) / 2);
SINT32 nBrightMean = 118;
SINT32 nB = 50;
K = (FLOAT32)(200.f / (nMax - nMin + nB));
C = (FLOAT32)(nBrightMean - K * (nMin + nMax) / 2);
//设置对比度上限,若超出上限,重新计算亮度
if (K > 1.8)
{
K = 1.8f;
nSigma = (SINT32)(0.5 * nLen); //设置高低端抛点数
nSum = 0;
nMid = 0;
//求映射的中值
for (i = 0; i < 65536; i++)
{
nSum += pHist[i];
if (nSum >= nSigma)
{
nMid = i;
break;
}
}
//C = (FLOAT32)(128 - K * nMid);
C = (FLOAT32)(nBrightMean - K * nMid);
}
for (i = 0; i < nLen; i++)
{
//nValue = (SINT32)(K * pSrc[i] + C);
nValue = (SINT32)(K * pSrcUINT16[i] + C);//20180122
if (nValue < 0)
{
pDst[i] = 0;
}
else if (nValue > 255)
{
pDst[i] = 255;
}
else
{
pDst[i] = (BYTE8)nValue;
}
}
delete []pHist;
delete []pSrcUINT16;
}
/****************************************************
* 函数名称getAngleVectors
* 功能描述:计算两个向量的夹角
* 输入参数ANGLE32F fAngleVector1, ANGLE32F fAngleVector2
* 输出参数FLOAT32 fAngle
* 返 回 值:
* 调用关系:
* 其它说明:
*****************************************************/
FLOAT32 getAngleVectors(ANGLE32F fAngleVector1, ANGLE32F fAngleVector2)
{
FLOAT32 fAngle = 0.0;
//提前计算公式中的向量分量
FLOAT32 fVector1OffsetX = fAngleVector1.fAz;
FLOAT32 fVector1OffsetY = fAngleVector1.fPt;
FLOAT32 fVector2OffsetX = fAngleVector2.fAz;
FLOAT32 fVector2OffsetY = fAngleVector2.fPt;
FLOAT32 fVector1Offset1Sqr = fVector1OffsetX * fVector1OffsetX + fVector1OffsetY * fVector1OffsetY;
FLOAT32 fVector2Offset2Sqr = fVector2OffsetX * fVector2OffsetX + fVector2OffsetY * fVector2OffsetY;
if (fVector1Offset1Sqr < 1e-8 || fVector2Offset2Sqr < 1e-8)
{
return 0.0;
}
fAngle = FLOAT32((fVector1OffsetX * fVector2OffsetX + fVector1OffsetY * fVector2OffsetY)
/ sqrt(fVector1Offset1Sqr * fVector2Offset2Sqr));
return FLOAT32(acos(fAngle) * 57.2957795785f);
}
/****************************************************
* 函数名称IMGO_RotateImg
* 功能描述:图像旋转并截取中心图像块
* 输入参数UINT16 *pSrc -- 原始图像
SINT32 nWidth -- pSrc尺寸
FLOAT32 fAngle -- 图像旋转角度dyt横滚
SINT32 nDstW -- pDst尺寸
SINT32 nDstH
* 输出参数UINT16 *pDst
* 返 回 值:无
* 调用关系:
* 其它说明如果nDstW*nDstH 任意角度旋转都在
nWidth*nHeight包络内不需要考虑边界
比如300*300旋转一定在450*450范围内
*****************************************************/
void IMGO_RotateImg(UINT16 *pSrc, SINT32 nWidth, SINT32 nHeight, FLOAT32 fAngle,
UINT16 *pDst,SINT32 nDstW, SINT32 nDstH)
{
SINT32 i, j;
FLOAT32 cosa, sina;
FLOAT32 u, v;
SINT32 px0, py0, px1, py1;
cosa = FLOAT32(cos(fAngle/180*PI));
sina = FLOAT32(sin(fAngle/180*PI));
for (i = 0; i < nDstH; i++)
{
for (j = 0; j < nDstW; j++)
{
//水平坐标
float y = FLOAT32(nDstH/2 - i);
float x = FLOAT32(j - nDstW/2);
//旋转
float y1 = cosa * y - sina * x;
float x1 = cosa * x + sina * y;
//图像坐标
y1 = nHeight/2 - y1;
x1 += nWidth/2;
//越界处理
//y1 = MINMAX_NUM(y1, 0, nHeight-2);
//x1 = MINMAX_NUM(x1, 0, nWidth-2);
u = x1 - SINT32(x1);
v = y1 - SINT32(y1);
px0 = (SINT32)x1;
py0 = (SINT32)y1;
px1 = px0+1;
py1 = py0+1;
//对x1,y1进行双线性插值
pDst[i*nDstW + j] = UINT16(pSrc[nWidth * py0+ px0] * (1-u)*(1-v)
+ pSrc[nWidth * py0+ px1] * u * (1-v)
+ pSrc[nWidth * py1+ px0] * (1-u) * v
+ pSrc[nWidth * py1+ px1] * u * v);
}
}
}
// 截取图像块,越界部分复制填充
void IMGO_GDSGetSubRect_FILLIN(UINT16 *pSrc, UINT16 *pDst, SINT16 nWidth, SINT16 nHeight, RECT32S rRect)
{
SINT32 i, j, x, y;
SINT32 nCounter = 0;
//截取区完全位于图像内
if (rRect.x >= 0 && rRect.y >= 0 && (rRect.x + rRect.w) <= nWidth && (rRect.y + rRect.h)<= nHeight)
{
IMGO_GDSGetSubRect(pSrc, pDst, nWidth, nHeight, rRect);
return;
}
//边界限制,复制填充
for (i = 0; i < rRect.h; i++)
{
for (j = 0; j < rRect.w; j++)
{
x = MINMAX_NUM(j+rRect.x, 0, nWidth-1);
y = MINMAX_NUM(i+rRect.y, 0, nHeight-2);//
pDst[nCounter++] = pSrc[y * nWidth+x];
}
}
}
/*****************************函数功能*****************************
计算目标的平均信息熵
------------------------输入参数------------------------
pSrc 输入图像
detectedTarget 检测目标点信息
inbox_size 保护框内框大小
outbox_size 保护框外框大小
-----------------------输出参数-------------------------
返回值
*********************************************************************/
#define SO_TGINBOXSIZE 10
#define DST_OBJ_EntropyHist 256
DOUBLE64 SO_CalcuTargetEntropy(UINT16* pSrc, TARGET_OBJECT* detectedTarget ,SINT32 nWidth, SINT32 nHeight,
SINT32 inbox_size, SINT32 outbox_size,DOUBLE64 K,DOUBLE64 C)// DETECTEDTARGET//检测到的目标结果
{
DOUBLE64 Sx = detectedTarget->pfCenPos.x;
DOUBLE64 Sy = detectedTarget->pfCenPos.y;
//20210820yy,边界保护
if (Sx < outbox_size/2 || ABS(nWidth - Sx) < outbox_size/2 ||
Sy < outbox_size/2 || ABS(nHeight - Sy) < outbox_size/2)
{
return 0;
}
SINT32 ROW = nHeight;
SINT32 COL = nWidth;
//----------------------对中心点进行3*3均值滤波剔除坏点坏点值对信息熵影响大---------------------
SINT32 istart ,iend;
SINT32 jstart ,jend;
SINT32 centerX ,centerY;
SINT32 i,j;
istart = MAX(0, (SINT32)Sy - 1);
jstart = MAX(0, (SINT32)Sx - 1);
iend = MIN(nHeight - 1, (SINT32)Sy + 1);
jend = MIN(nWidth - 1, (SINT32)Sx + 1);
SINT16 len = (iend - istart + 1)*(jend - jstart + 1) - 1;
UINT32 Sum = 0;
for (i = istart; i<= iend; ++i)
{
for (j = jstart; j<=jend;++j)
{
Sum += pSrc[i*COL+j];
}
}
Sum -= pSrc[(SINT32)Sy*COL+(SINT32)Sx];
Sum = Sum / len;
pSrc[(SINT32)Sy*COL+(SINT32)Sx] = Sum;
istart =(SINT32)((Sy < outbox_size/2)? 0:Sy - outbox_size/2);
iend = (SINT32)((istart == 0)? outbox_size:Sy + outbox_size/2);
if (iend > ROW )
{
iend = ROW;
istart = ROW -outbox_size;
}
jstart = SINT32((Sx < outbox_size/2)? 0:Sx - outbox_size/2);
jend = SINT32((jstart == 0)? outbox_size:Sx + outbox_size/2);
if (jend > COL)
{
jend = COL;
jstart = COL - outbox_size;
}
centerX = (SINT32)(jstart + jend)/2;//检测框区域的中心点
centerY = (SINT32)(istart + iend)/2;
DOUBLE64 EntropyArray[SO_TGINBOXSIZE][SO_TGINBOXSIZE];//内框点的信息熵矩阵
for (i = 0 ;i < SO_TGINBOXSIZE; i++)
{
memset(EntropyArray[i] ,0 ,SO_TGINBOXSIZE*sizeof(DOUBLE64));//对二位数组初始化
}
//DOUBLE64 *EntropyArray = (DOUBLE64*)DSP_DST_EntropyArray;//滑窗区域的直方图矩阵
//memset(EntropyArray, 0, SO_TGINBOXSIZE*SO_TGINBOXSIZE * sizeof(DOUBLE64));//直方图初始化
SINT32 M = SINT32(floor((DOUBLE64)(outbox_size - inbox_size)/4));//尺寸数
SINT32 N = SINT32(floor((DOUBLE64)(outbox_size - inbox_size)/4));
//去除求信息熵区域灰度最大值和最小值防止坏点影响信息熵计算20190310qxj
UINT16 tempMaxValue = 0;
POINT16S MaxValueIndex;
MaxValueIndex.x = 0;
MaxValueIndex.y = 0;
UINT16 tempMinValue = 65535;
POINT16S MinValueIndex;
MinValueIndex.x = 0;
MinValueIndex.y = 0;
for (i = centerY - inbox_size/2;i < centerY + inbox_size/2 ; i++)
{
for ( j = centerX - inbox_size/2;j < centerX + inbox_size/2 ; j++)
{
UINT16 tempValue = pSrc[i*COL+j];
if (tempValue > tempMaxValue)
{
tempMaxValue = tempValue;
MaxValueIndex.x = j;
MaxValueIndex.y = i;
}
if (tempValue < tempMinValue)
{
tempMinValue = tempValue;
MinValueIndex.x = j;
MinValueIndex.y = i;
}
}
}
if ((MaxValueIndex.x > 10)&&(MaxValueIndex.x < nWidth-10)
&&(MaxValueIndex.y > 10)&&(MaxValueIndex.y < nHeight-10))
{
pSrc[MaxValueIndex.y*COL+MaxValueIndex.x] = pSrc[MaxValueIndex.y*COL+MaxValueIndex.x + 1];
}
if ((MinValueIndex.x > 10)&&(MinValueIndex.x < nWidth-10)
&&(MinValueIndex.y > 10)&&(MinValueIndex.y < nHeight-10))
{
pSrc[MinValueIndex.y*COL + MinValueIndex.x] = pSrc[MinValueIndex.y*COL + MinValueIndex.x + 1];
}
//--------------------------------------------------------------------------------
DOUBLE64 PixelNum = (2*M+1)*(2*N+1);//滑窗内的像素个数计数
DOUBLE64 DSP_DST_TgEntropyHist[DST_OBJ_EntropyHist] = {0}; //DST: 目标信息熵
//DOUBLE64 DSP_DST_BgEntropyHist[DST_OBJ_EntropyHist] = {0}; //DST: 背景信息熵
DOUBLE64 *EntropyHist = (DOUBLE64*)DSP_DST_TgEntropyHist;//滑窗区域的直方图矩阵
SINT32 MaxValue = 0;
SINT32 MinValue = 255;
for (i = centerY - inbox_size/2;i < centerY + inbox_size/2 ; i++)
{
for ( j = centerX - inbox_size/2;j < centerX + inbox_size/2 ; j++)
{
//DOUBLE64 EntropyHist[256];//滑窗区域的直方图矩阵
//memset(EntropyHist ,0 ,256*sizeof(DOUBLE64));//直方图初始化
memset(EntropyHist, 0, DST_OBJ_EntropyHist * sizeof(DOUBLE64));//直方图初始化
MaxValue = 0;
MinValue = 255;
//计算以目标点为中心的局部M*N范围直方图
SINT32 p,q;
for (p = i - M ;p <=i + M; p++)
{
for (q = j - N;q <= j + N;q++)
{
SINT32 PixValue = (SINT32)(K*pSrc[p*COL+q] + C);// 调光??
if (PixValue < 0 )
{
PixValue = 0;
}
if (PixValue > 255)
{
PixValue = 255;
}
if (MaxValue < PixValue)
{
MaxValue = PixValue;
}
if (MinValue > PixValue)
{
MinValue = PixValue;
}
EntropyHist[PixValue] += 1;//直方图统计
//PixelNum++;
}
}
SINT32 g = i - ( centerY - inbox_size/2);
SINT32 h = j - ( centerX - inbox_size/2);
for (p = MinValue;p <=MaxValue; p++)
{
if (EntropyHist[p] != 0)
{
EntropyHist[p] = EntropyHist[p]/PixelNum;//不同灰度等级的概率密度灰度级p的像素个数与区域总像素的比
SINT32 CurrentPixValue = (SINT32)(K*pSrc[i*COL+j] + C);//调光
if (CurrentPixValue < 0 )
{
CurrentPixValue = 0;
}
if (CurrentPixValue > 255)
{
CurrentPixValue = 255;
}
EntropyArray[g][h] += pow((DOUBLE64)(p - CurrentPixValue) ,2) * EntropyHist[p] *log10((DOUBLE64)1/EntropyHist[p])/log10(2.0);
}
}
}
}
DOUBLE64 targetEntropy = 0; //所求目标点的信息熵
SINT32 entropyPixelNum = 0; //内框的像素总个数
for (i = 0;i < inbox_size ;i++)
{
for (j = 0;j < inbox_size ;j++)
{
if (EntropyArray[i][j] > 0.000001)//进度判断求得的信息熵大于0.000001均视为有效,可参与计算
{
entropyPixelNum++;
}
targetEntropy += EntropyArray[i][j];//统计区域内所有点的信息熵和
}
}
targetEntropy = targetEntropy/(inbox_size * inbox_size);//将区域内所有点的信息熵求均值赋给当前点
targetEntropy = MAX(1.0,targetEntropy);
return targetEntropy;
}
/*****************************函数功能*****************************
计算背景的平均信息熵
------------------------输入参数------------------------
pSrc 输入图像
diffImage 输入差分图
inbox_size 保护框内框大小
outbox_size 保护框外框大小
-----------------------输出参数-------------------------
detectedTarget
*********************************************************************/
DOUBLE64 SO_CalcuBackGroundEntropy(UINT16* pSrc, TARGET_OBJECT* detectedTarget ,SINT32 nWidth, SINT32 nHeight,
SINT32 inbox_size, SINT32 outbox_size,DOUBLE64 K,DOUBLE64 C)
{
DOUBLE64 Sx = detectedTarget->pfCenPos.x;
DOUBLE64 Sy = detectedTarget->pfCenPos.y;
//20210820yy,边界保护
if (Sx < outbox_size/2 || ABS(nWidth - Sx) < outbox_size/2 ||
Sy < outbox_size/2 || ABS(nHeight - Sy) < outbox_size/2)
{
return 0;
}
SINT32 ROW = nHeight;
SINT32 COL = nWidth;
SINT32 istart ,iend;
SINT32 jstart ,jend;
SINT32 centerX ,centerY;
SINT32 i,j;
//DOUBLE64 EntropyHist[256];//直方图统计矩阵
//memset(EntropyHist,0,256*sizeof(DOUBLE64));
DOUBLE64 DSP_DST_BgEntropyHist[DST_OBJ_EntropyHist] = {0}; //DST: 背景信息熵
DOUBLE64 *EntropyHist = (DOUBLE64*)DSP_DST_BgEntropyHist;//滑窗区域的直方图矩阵
memset(EntropyHist, 0, DST_OBJ_EntropyHist * sizeof(DOUBLE64));//直方图初始化
SINT32 EntropyPixelNum = 0;//像素个数
DOUBLE64 backgroundEntropy = 0;
//确定外框的位置,防止出边界
istart = (SINT32)((Sy < outbox_size)? 0:Sy - outbox_size/2);
iend = (SINT32)((istart == 0)? outbox_size:Sy + outbox_size/2);
if (iend > ROW )
{
iend = ROW;
istart = ROW -outbox_size;
}
jstart = SINT32((Sx < outbox_size)? 0:Sx - outbox_size/2);
jend = SINT32((jstart == 0)? outbox_size:Sx + outbox_size/2);
if (jend > COL)
{
jend = COL;
jstart = COL - outbox_size;
}
centerX = (SINT32)(jstart + jend)/2;//检测框区域的中心点
centerY = (SINT32)(istart + iend)/2;
// FLOAT32 g_GLB_STH_coeffK = (FLOAT32)256 / (pixelValueMax - pixelValueMin + 1); //老版本调光
// FLOAT32 g_GLB_STH_coeffC = (FLOAT32)-Ratio_K1*pixelValueMin;
for (i = istart;i < iend ; i++)
{
for ( j = jstart;j < jend ; j++)
{
if ( i < centerY + inbox_size/2 && i > centerY - inbox_size/2 && j > centerX -inbox_size/2 && j < centerX + inbox_size/2)
{
continue;
}
SINT32 PixelValue = (SINT32)(K*pSrc[i*COL+j] + C);//2位图16位图
if (PixelValue < 0)
{
PixelValue = 0;
}
if (PixelValue > 255)
{
PixelValue = 255;
}
EntropyHist[PixelValue] +=1;
EntropyPixelNum++;
}
}
for (i = 0;i < 256;i++)
{
EntropyHist[i] = EntropyHist[i]/EntropyPixelNum;//不同灰度等级的概率密度
if (EntropyHist[i] > 0.0001f)
{
backgroundEntropy += EntropyHist[i]*log10(1.0/EntropyHist[i])/log10(2.0);
}
}
backgroundEntropy = MAX(0.01, backgroundEntropy);
return backgroundEntropy;
}
bool Bicubic(unsigned short* src, int iSrcWidth, int iSrcHeight, unsigned short* dst, int iDstWidth, int iDstHeight)
{
int i = 0;
float scale_y = (float)iSrcHeight / iDstHeight;
float scale_x = (float)iSrcWidth / iDstWidth;
int dx, dy;
for (dy = 0; dy < iDstHeight; dy++)
{
for (dx = 0; dx < iDstWidth; dx++)
{
double sx, sy;//小数部分
int sxi, syi;//整数部分
sy = (dy)*scale_y;
syi = FLOOR(sy);//取整
sy -= syi; //小数部分
syi = MAX(1, syi);
syi = MIN((iSrcHeight - 3), syi);
// sy-=syi; //小数部分
sx = (dx)*scale_x;
sxi = FLOOR(sx);//取整
sx -= sxi; //小数部分
sxi = MAX(1, sxi);
sxi = MIN((iSrcWidth - 3), sxi);
//sx-= sxi; //小数部分
//16邻域模板
int temp[4][4] = { 0 };
temp[0][0] = src[(syi - 1) * iSrcWidth + sxi - 1];
temp[0][1] = src[(syi - 1) * iSrcWidth + sxi];
temp[0][2] = src[(syi - 1) * iSrcWidth + sxi + 1];
temp[0][3] = src[(syi - 1) * iSrcWidth + sxi + 2];
temp[1][0] = src[syi * iSrcWidth + sxi - 1];
temp[1][1] = src[syi * iSrcWidth + sxi];
temp[1][2] = src[syi * iSrcWidth + sxi + 1];
temp[1][3] = src[syi * iSrcWidth + sxi + 2];
temp[2][0] = src[(syi + 1) * iSrcWidth + sxi - 1];
temp[2][1] = src[(syi + 1) * iSrcWidth + sxi];
temp[2][2] = src[(syi + 1) * iSrcWidth + sxi + 1];
temp[2][3] = src[(syi + 1) * iSrcWidth + sxi + 2];
temp[3][0] = src[(syi + 2) * iSrcWidth + sxi - 1];
temp[3][1] = src[(syi + 2) * iSrcWidth + sxi];
temp[3][2] = src[(syi + 2) * iSrcWidth + sxi + 1];
temp[3][3] = src[(syi + 2) * iSrcWidth + sxi + 2];
double TA[4] = { 1.0,0.0,-1.0,-2.0 };
double TD[4] = { 1.0,0.0,-1.0,-2.0 };
double A[4] = { 0.0 };
double D[4] = { 0.0 };
//double temp(0.0);
for (i = 0; i < 4; i++)
{
A[i] = fabs((sy + TA[i]));
if (A[i] >= 0 && A[i] < 1)
{
A[i] = ICV_CUBIC_1(A[i]);//p3*A[i]*A[i]*A[i]+p2*A[i]*A[i]+p0;
}
else if (A[i] >= 1 && A[i] < 2)
{
/*temp = A[i];*/
A[i] = ICV_CUBIC_2(A[i]);//q3*A[i]*A[i]*A[i]+q2*A[i]*A[i]+q1*A[i]+q0;
}
else
A[i] = 0;
D[i] = fabs((sx + TD[i]));
if (D[i] >= 0 && D[i] < 1)
{
D[i] = ICV_CUBIC_1(D[i]);//p3*D[i]*D[i]*D[i]+p2*D[i]*D[i]+p0;
}
else if (D[i] >= 1 && D[i] < 2)
{
D[i] = ICV_CUBIC_2(D[i]);//q3*D[i]*D[i]*D[i]+q2*D[i]*D[i]+q1*D[i]+q0;
}
else
D[i] = 0;
}
double value[4] = { 0.0 };
int v = 0;
for (i = 0; i < 4; i++)
{
value[i] = A[0] * temp[0][i] + A[1] * temp[1][i] + A[2] * temp[2][i] + A[3] * temp[3][i];
}
v = (int)(value[0] * D[0] + value[1] * D[1] + value[2] * D[2] + value[3] * D[3] + 0.5);
if (v > 255)
{
dst[dy * iDstWidth + dx] = 255;
}
else if (v < 0)
{
dst[dy * iDstWidth + dx] = 0;
}
else
{
dst[dy * iDstWidth + dx] = v;
}
}
}
return 1;
}
/**********************************************************
* 函数名称IMGO_CalcSqSumImg()
* 功能描述:计算积分图同时计算平方积分
* 输入参数PIXELTYPE *pnFrame -- 输入图像
* SIZE32S snImgSize -- 图像尺寸
* 输出参数SINT32 *pnIntImg -- 积分图
DOUBLE64 *pdSqImg -- 平方积分图
* 返 回 值:无
* 调用关系:无
* 其它说明同IMGO_CalcIntegralImg
**********************************************************/
void IMGO_CalcSqSumImg(UINT16* pnFrame, SIZE32S snImgSize,
UINT32* pnIntImg, DOUBLE64* pdSqImg)
{
SINT32 i, j;
SIZE32S snIntImgSize;
snIntImgSize.h = snImgSize.h + 1;
snIntImgSize.w = snImgSize.w + 1;
SINT32 nIntImgPxlSize = snIntImgSize.w * snIntImgSize.h;
UINT32 nLnSum = 0; //输入图像当前行的累加结果
DOUBLE64 nLsqSum = 0; //当前行的平方累加结果
UINT16* pnPxl = NULL; //指向输入图像当前像素
UINT32* pnIntPxl = NULL; //指向积分图当前像素
UINT32* pnIntPxlUp = NULL; //指向积分图当前像素的上一行像素
DOUBLE64* pdSqPxl = NULL;
DOUBLE64* pdSqPxlUp = NULL;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//初始化
//注仅初始化第0行、第0列积分图全图清零较耗时
memset(pnIntImg, 0, sizeof(DOUBLE64) * snIntImgSize.w);
memset(pdSqImg, 0, sizeof(DOUBLE64) * snIntImgSize.w);
for (i = snIntImgSize.w; i < nIntImgPxlSize; i += snIntImgSize.w)
{
pnIntImg[i] = 0;
pdSqImg[i] = 0;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
//计算第[0, snImgSize.h-1]行、第[0, snImgSize.h-1]列图像像素的积分值,
//分别存入第[1 ~ snImgSize.h]行、第[1, snImgSize.h]列积分图。
pnPxl = (UINT16*)pnFrame;
pnIntPxl = (UINT32*)pnIntImg + snIntImgSize.w;
pnIntPxlUp = (UINT32*)pnIntImg;
pdSqPxl = (DOUBLE64*)pdSqImg + snIntImgSize.w;
pdSqPxlUp = (DOUBLE64*)pdSqImg;
for (i = 0; i < snImgSize.h; i++)
{
//初始化当前行累加结果
nLnSum = 0;
nLsqSum = 0;
//跳过积分图第1列像素
pnIntPxl++;
pnIntPxlUp++;
pdSqPxl++;
pdSqPxlUp++;
//行内每个像素
for (j = 0; j < snImgSize.w; j++)
{
//对当前行图像像素值累加
nLsqSum += (double)(*pnPxl) * (*pnPxl);
nLnSum += (*pnPxl++);
//将"当前行图像累加值+上一行对应点的积分值"存入积分图
*pdSqPxl++ = nLsqSum + (*pdSqPxlUp++);
(*pnIntPxl++) = nLnSum + (*pnIntPxlUp++);
}
}
}
/****************************************************
* 函数名称IMGO_MeanFilter
* 功能描述:均值滤波
* 输入参数PIXELTYPE *pSrc -- 原始图像
SINT32 nWidth -- 宽
SINT32 nHeight -- 高
SINT32 *pIntImg -- 积分图像
SINT32 nRadius -- 滤波半径
* 输出参数PIXELTYPE *pDst -- 滤波图像
* 返 回 值:无
* 调用关系:
* 其它说明:边缘部分是否需要考虑?TLD用不到暂不考虑
*****************************************************/
void IMGO_MeanFilter(UINT16* pSrc, SINT32 nWidth, SINT32 nHeight, UINT32* pIntImg, SINT32 nRadius, UINT16* pDst)
{
SINT32 i, j;
SINT32 nIntWidth, nIntHeight;
SINT32 nLeftTop, nLeftBotm, nRightTop, nRightBotm, nArea;
memcpy(pDst, pSrc, sizeof(UINT16) * nWidth * nHeight);
if (nRadius < 1)
{
return;
}
nIntHeight = nHeight + 1; //积分图大小
nIntWidth = nWidth + 1;
nArea = (nRadius * 2 + 1) * (nRadius * 2 + 1); //窗口面积
for (i = nRadius; i < nHeight - nRadius; i++)
{
for (j = nRadius; j < nWidth - nRadius; j++)
{
nLeftTop = pIntImg[(i - nRadius) * nIntWidth + j - nRadius];
nLeftBotm = pIntImg[(i + nRadius + 1) * nIntWidth + j - nRadius];
nRightTop = pIntImg[(i - nRadius) * nIntWidth + j + nRadius + 1];
nRightBotm = pIntImg[(i + nRadius + 1) * nIntWidth + j + nRadius + 1];
pDst[i * nWidth + j] = (nRightBotm + nLeftTop - nLeftBotm - nRightTop) / nArea;
}
}
return;
}
/****************************************************
* 函数名称IMGO_GetVar
* 功能描述:计算图像给定区域的方差
* 输入参数SINT32 *pIntImg -- 积分图
DOUBLE64 *pSqIntImg -- 平方积分图
SIZE32S snImgSize -- 积分图尺寸
RECT32S rsRect -- 矩形区
* 输出参数:
* 返 回 值rsRect区域方差
* 调用关系:
* 其它说明:
*****************************************************/
DOUBLE64 IMGO_GetVar(UINT32* pIntImg, DOUBLE64* pSqIntImg, SIZE32S snImgSize, RECT32S rsRect)
{
SINT32 w = snImgSize.w; //积分图宽度
SINT32 s = (rsRect.w - 1) * (rsRect.h - 1); //面积
POINT32S tl, tr, bl, br; //积分区域四角
FLOAT32 fMean;
DOUBLE64 dSqMean;
tl.x = rsRect.x + 1; tl.y = rsRect.y + 1;
tr.x = rsRect.x + rsRect.w; tr.y = rsRect.y + 1;
bl.x = rsRect.x + 1; bl.y = rsRect.y + rsRect.h;
br.x = rsRect.x + rsRect.w; br.y = rsRect.y + rsRect.h;
fMean = (pIntImg[tl.y * w + tl.x] + pIntImg[br.y * w + br.x] - pIntImg[tr.y * w + tr.x] - pIntImg[bl.y * w + bl.x]) / (FLOAT32)s;
dSqMean = (pSqIntImg[tl.y * w + tl.x] + pSqIntImg[br.y * w + br.x] - pSqIntImg[tr.y * w + tr.x] - pSqIntImg[bl.y * w + bl.x]) / s;
return (dSqMean - fMean * fMean);
}
//求解两目标框之间的交并比
DOUBLE64 IMGO_CalcObjIou(MINMAXRECT bb_pre, MINMAXRECT bb_Obj)
{
SINT32 x1, y1, x2, y2;
SINT32 w, h, s;
DOUBLE64 iou;
x1 = MAX(bb_pre.minX, bb_Obj.minX);
x2 = MIN(bb_pre.maxX, bb_Obj.maxX);
y1 = MAX(bb_pre.minY, bb_Obj.minY);
y2 = MIN(bb_pre.maxY, bb_Obj.maxY);
w = MAX(0, x2 - x1);
h = MAX(0, y2 - y1);
s = w * h;
iou = (DOUBLE64)s / (DOUBLE64)((bb_pre.maxX - bb_pre.minX) * (bb_pre.maxY - bb_pre.minY) + (bb_Obj.maxX - bb_Obj.minX) * (bb_Obj.maxY - bb_Obj.minY) - s);
return iou;
}
void calculateCentroid(GD_VIDEO_FRAME_S img, OBJECTSTATUS* ObjStatus, FLOAT32 fGray)
{
int i;
int j;
DOUBLE64 sumX = 0;
DOUBLE64 sumY = 0;
DOUBLE64 count = 0;
for (i = int(ObjStatus->ptPos.y - ObjStatus->sfSize.h / 2); i < int(ObjStatus->ptPos.y + ObjStatus->sfSize.h / 2); ++i)
{
for (j = int(ObjStatus->ptPos.x - ObjStatus->sfSize.w / 2); j < int(ObjStatus->ptPos.x + ObjStatus->sfSize.w / 2); ++j)
{ // 检查像素是否在图像范围内
if (i >= 0 && i < (int)img.u32Height && j >= 0 && j < (int)img.u32Width)
{
int pixelValue = 0;
if (GD_PIXEL_FORMAT_GRAY_Y16 == img.enPixelFormat)
{
pixelValue = ((UINT16*)img.u64VirAddr[0])[i * img.u32Width + j]; // 获取像素值
}
else
{
pixelValue = 255 - ((UBYTE8*)img.u64VirAddr[0])[i * img.u32Width + j]; // 获取像素值
//fGray = 255 - fGray;
fGray = 128;
}
if (pixelValue > fGray)
{ // 如果像素值非零,累加其坐标
sumX += (DOUBLE64)j * pixelValue;
sumY += (DOUBLE64)i * pixelValue;
count += pixelValue;
}
}
}
}
if (count < 0.1)
{
ObjStatus->ptCentroid.x = -1; // 如果没有有效像素,返回-1表示无效质心
ObjStatus->ptCentroid.y = -1;
}
else
{
ObjStatus->ptCentroid.x = (FLOAT32)(sumX / count);
ObjStatus->ptCentroid.y = (FLOAT32)(sumY / count);
}
return;
}