Untitled
unknown
plain_text
10 months ago
3.6 kB
14
Indexable
LONG CBaseMotionDetector::CompareFields(const LPBYTE pStreamData, const SIZE& sizeImage, const RECT* _prcDetectArea)
{
// only support legacy and adaptive legacy for now
assert(m_nMotionAlgorithm == MD_LEGACY || m_nMotionAlgorithm == MD_LEGACY_ADAPTIVE);
// if we're in adaptive mode, then the size of the m_pSimpleV vector must match the size of the (image / 2) since image (YUV) uses 2 bytes per pixel.
assert(m_nMotionAlgorithm != MD_LEGACY_ADAPTIVE || m_pSimpleV.size() == m_pPrevImageData.size() / 2);
LONG lTotalDiffFactor = 0;
for (int y = _prcDetectArea->top; y < _prcDetectArea->bottom; y += 1)
{
DWORD dwStartOffset = (y * (sizeImage.cx * 2)) + (_prcDetectArea->left * 2);
DWORD LineFactor = 0;
for (int x = 0; x < (_prcDetectArea->right - _prcDetectArea->left) / 2; x++)
{
// In the older code, LineFactor was incremented (diff1^2 + diff2^2) / 2048. Once you rearrange that,
// it's the same as (diff1^2 / 1024 + (diff2^2 / 1024). Because of integer division, until each diff exceeds 32,
// nothing is added. This is really just thresholding then.
//
// But if you consider the return value is compared against values based on sensitivity (from 1 to 576), and the old comments in
// Vault from 2009-2011 regarding taking the sqrt later, and that for a single motion box (10x10 grid and image of 320x180) 32x18 is
// 576 pixels. So it's clear we want to return values that are in the range of 1 to 576, or at least do not greatly exceed.
//
// In the code code, if the diff happened to be 128 then value from a single pixel is 16, if diff was 192, then the pixel is worth 36.
// This is why Sensitivity never really worked well, and Simple picked up so much extra noise.
//
// Switching to diff / 32 gives each pixel a value from 0 to 6 (YUV range is 219) which is perhaps a little sensitive, but due to
// historically over-sensitive motion detection, it fits expectations better.
//
int offset1 = dwStartOffset + 4 * x;
long diff1 = labs(static_cast<long>(m_pPrevImageData[offset1]) - static_cast<long>(pStreamData[offset1]));
int offset2 = offset1 + 2;
long diff2 = labs(static_cast<long>(m_pPrevImageData[offset2]) - static_cast<long>(pStreamData[offset2]));
if (m_nMotionAlgorithm == MD_LEGACY_ADAPTIVE)
{
// The adaptive mode simple requires the diff to exceed the value in m_pSimpleV before it's counted.
LineFactor += diff1 >= m_pSimpleV[offset1 / 2] ? diff1 / 32 : 0;
LineFactor += diff2 >= m_pSimpleV[offset2 / 2] ? diff2 / 32 : 0;
// just like SigmaDelta, m_pSimpleV trends to N * diff
static int N = 6;
if (m_pSimpleV[offset1 / 2] < N * diff1)
++m_pSimpleV[offset1 / 2];
else if (m_pSimpleV[offset1 / 2] > N * diff1)
--m_pSimpleV[offset1 / 2];
if (m_pSimpleV[offset2 / 2] < N * diff2)
++m_pSimpleV[offset2 / 2];
else if (m_pSimpleV[offset2 / 2] > N * diff2)
--m_pSimpleV[offset2 / 2];
}
else
{
LineFactor += diff1 / 32;
LineFactor += diff2 / 32;
}
#ifdef DEBUG_NAMED_PIPE_VIDEO
if (m_nMotionAlgorithm == MD_LEGACY_ADAPTIVE)
{
m_pSimpleDiff[offset1] = diff1 >= m_pSimpleV[offset1 / 2] ? diff1 + YUV_LUMA_MIN : YUV_LUMA_MIN;
m_pSimpleDiff[offset2] = diff2 >= m_pSimpleV[offset2 / 2] ? diff2 + YUV_LUMA_MIN : YUV_LUMA_MIN;
}
else
{
m_pSimpleDiff[offset1] = diff1 + YUV_LUMA_MIN;
m_pSimpleDiff[offset2] = diff2 + YUV_LUMA_MIN;
}
#endif
}
lTotalDiffFactor += (LineFactor * GridSizeScaleFactor() * 1.0);
}
return lTotalDiffFactor;
}Editor is loading...
Leave a Comment