Untitled

 avatar
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