/*********版权所有(C)2013,武汉高德红外股份有限公司*************** * 文件名称:Arith_ImgOperate.cpp * 文件标识:图像处理 * 内容摘要:执行通用图像处理操作 * 其它说明:"ImgOperate"的函数、全局变量、宏定义,统一前缀为简写"IMGO"。 * 当前版本:固化V2.0 * 创建作者:MSSu * 创建日期:2015.03.16 *******************************************************************/ #include "Arith_ImgOperate.h" #ifdef NEON #include #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] = 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] = 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] = B[0] * (1 - u) * (1 - v) + B[1] * u * (1 - v) + B[2] * (1 - u) * v + B[3] * u * v; } } } 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; }