Untitled
unknown
plain_text
a year ago
4.3 kB
12
Indexable
HRESULT CBaseMotionDetector::VarianceMaskGenrator(const LPBYTE pStreamData, const SIZE& m_sizeImage, bool* frameReceived)
{
if (pStreamData == NULL) return -1;
#ifdef MOTIONDETECTION_LOG_PERFORMANCE
shared_ptr<ReportDuration>reportDuration(new ReportDuration("VarianceMaskGenerator:"));
#endif
ResetEvent(m_DestroyClassEvent);
DBG_NM_PIPE(
if (settled == 1 && (k_size != k_size_prev || (float)*(reinterpret_cast<int*>(&m_gaussianSigma)) != gauss_sigma_prev))
{
InitDiffusionKernel();
printKernel();
}
)
const int imageSize = m_sizeImage.cx * m_sizeImage.cy * 2; // YUV = 2 bytes / pixel
// Previously, for simplicity these SigmaDelta variables were 2 bytes per pixel for simplicity, but we only need 1 byte per pixel
// since we're working with grayscale images. So we'll use half the size for these arrays and save some memory.
//
if (m_pSigmaDeltaM.size() != imageSize / 2)
{
// start with the "background" copied from the current image. otherwise we startup with it looking like there is
// motion everywhere until the true background emerges from averaging.
//
m_pSigmaDeltaM.resize(imageSize / 2);
m_pSigmaDeltaV.resize(imageSize / 2);
m_pSigmaDeltaE.resize(imageSize / 2);
m_pSigmaDeltaTemp.resize(imageSize / 2);
m_pSigmaDeltaNoiseMask.resize(imageSize / 2);
for (int i = 0; i < imageSize; i += 2)
{
m_pSigmaDeltaM[i / 2] = pStreamData[i];
m_pSigmaDeltaV[i / 2] = 0;
m_pSigmaDeltaE[i / 2] = BACKGROUND_PIXEL;
}
InitDiffusionKernel();
//printKernel();
}
#ifdef DEBUG_NAMED_PIPE_VIDEO
vector<BYTE> diff(imageSize);
vector<BYTE> variance(imageSize);
#endif
// N is the variance diff to test for diff O exceeding V.
// Make larger makes so that minor fluctations in the background brightness are ignored.
//
static int N = 6;
// iterate over the Luma bytes skipping over the Chroma bytes....
//
int count_foreground = 0;
bool has_color = false;
for (INT i = 0; i < imageSize; i += 2)
{
// reduce the number of times we access the array by index by using a local variable
BYTE M = m_pSigmaDeltaM[i / 2];
int V = m_pSigmaDeltaV[i / 2];
// O is the abs diff of current and background, range YUV_LUMA_MIN to YUV_LUMA_MAX
const int O = abs(M - pStreamData[i]);
// check for color in the image, if so then it's not purely black&white
if (!has_color && pStreamData[i + 1] != YUV_CHROMA_ZERO)
has_color = true;
// V is the dispersion background
if (V < N * O)
V++;
else if (V > N * O)
V--;
// update background M incrementally.
if (M < pStreamData[i])
M++;
else if (M > pStreamData[i])
M--;
// finally, E is the estimated motion. Although we can simply use 0/1 values for motion detect,
// I am using YUV values so that rendering the intermediate stages for visualization works well.
//
bool isForeground = O > V && O > 8;
count_foreground += isForeground ? 1 : 0;
m_pSigmaDeltaV[i / 2] = V;
//m_pSigmaDeltaVDiffused[i / 2 ] = Vd;
m_pSigmaDeltaM[i / 2] = M;
#ifdef DEBUG_NAMED_PIPE_VIDEO
diff[i] = O + BACKGROUND_PIXEL;
diff[i + 1] = YUV_CHROMA_ZERO;
variance[i] = V;
variance[i + 1] = YUV_CHROMA_ZERO;
#endif
}
bool nightMode = !has_color;
bool day_to_night_transition = nightMode && !m_bNightVisionMode;
m_bNightVisionMode = nightMode;
// if more than %large% of the image is foreground, then the background is not stable.
bool invalid_background = count_foreground > 0.90 * imageSize / 2;
// if the background is invalid or we are transitioning from day to night, then reset the background.
if (invalid_background || day_to_night_transition)
{
// reset the background to the current image, declare no motion
for (int i = 0; i < imageSize; i += 2)
{
m_pSigmaDeltaM[i / 2] = pStreamData[i];
m_pSigmaDeltaV[i / 2] = 0;
}
}
#ifdef DEBUG_NAMED_PIPE_VIDEO
if (m_nCameraID == camid)
{
prevDataSender.SendData(&pStreamData[0], imageSize);
//if(m_nCameraID == 0xff0003)
diffDataSender.SendData(variance);
/*vector<BYTE> E(imageSize);
for (int i = 0; i < imageSize; i += 2)
{
E[i] = m_pSigmaDeltaE[i / 2];
E[i + 1] = YUV_CHROMA_ZERO;
}
finalDataSender.SendData(E);*/
}
#endif
}Editor is loading...
Leave a Comment