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

/*********版权所有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()
* ,CENTERRECTMINMAXRECT32S
* 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()
* ,MINMAXRECT32SCENTERRECT
* 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()
* pSrcpDst
* 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()
* pSrcpDst
* UINT16 *pSrc --
* SINT16 nWidth --
* SINT16 nHeight --
* RECT32S rRect --
* UINT16 *pDst --
*
*
* NCCRECT32S
**********************************************************/
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()
* pSrcpDst
* 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()
* pSrcpDst
* 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()
* pSrcpDst
* 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()
* pSrc2pDst
* UINT16 *pSrc --
* SINT32 nWidth --
* SINT32 nHeight --
* MINMAXRECT32S mrnRect --
* SINT32 nMode -- 1-2*20-
* 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()
* pSrc2pDst
* UINT16 *pSrc --
* SINT32 nWidth --
* SINT32 nHeight --
* MINMAXRECT32S mrnRect --
* SINT32 nMode -- 1-2*20-
* 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()
* pSrcpDst
* 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()
* pSrcpDst
* 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 --
*
*
* fggf110
* g(i,j)f(0,0)f(i,j)
* 0 <= i <= sImgSize.h, 0 <= j <= sImgSize.w
*
* 1000
* g(0,j) = 0;
* g(i,0) = 0;
* 2i = (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 --
*
*
* fggf110
* g(i,j)f(0,0)f(i,j)
* 1(i,j)(i+1,j+1)
* ABCDabcd
* - - - - - - - - -
* - - A - - B E - -
* - - - a - - b - -
* - - C - - D - - -
* - - F c - - d - -
* - - - - - - - - -
* 2abcd
* 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*300450*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;
}