|
|
/*********版权所有(C)2013,武汉高德红外股份有限公司***************
|
|
|
* 文件名称: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;
|
|
|
} |