⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video.cpp

📁 一个由Mike Gashler完成的机器学习方面的includes neural net, naive bayesian classifier, decision tree, KNN, a genet
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	bool FindSeed(VideoSmartSelectSeed* pThat)
	{
		VideoSmartSelectSeed* pSeed;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			if(pSeed == pThat)
				return true;
		}
		return false;
	}

	void RemoveSeed(VideoSmartSelectSeed* pSeed)
	{
		GAssert(FindSeed(pSeed), "Wrong frame for this seed");
		GAssert(pSeed != m_pGrabbedSeed, "shouldn't remove a grabbed seed");
		int nFramesFromOrigin = pSeed->GetFramesFromOrigin();
		VideoSmartSelectSeed* pNextSeed = pSeed->GetNext();
		VideoSmartSelectSeed* pPrevSeed = pSeed->GetPrev();
		VideoSmartSelectSeed* pNewHead = pSeed->Unlink(m_pSeeds);
		GAssert(pNewHead == m_pSeeds || pSeed == m_pSeeds, "head problem");
		m_pSeeds = pNewHead;
		if(nFramesFromOrigin >= 0 && pNextSeed)
		{
			GAssert(pNextSeed->GetFramesFromOrigin() > nFramesFromOrigin, "out of order");
			m_pNext->RemoveSeed(pNextSeed);
		}
		if(nFramesFromOrigin <= 0 && pPrevSeed)
		{
			GAssert(pPrevSeed->GetFramesFromOrigin() < nFramesFromOrigin, "out of order");
			m_pPrev->RemoveSeed(pPrevSeed);
		}
		GAssert(!pSeed->GetNextSibling(), "Not unlinked properly");
		delete(pSeed);
		UpdateSelection();
	}

	void ComputeNextFrameSeedPos(int x, int y, int* pOutX, int* pOutY, VideoSmartSelectFrame* pTargetFrame)
	{
/*
		*pOutX = x;
		*pOutY = y;
*/

		GAssert(m_pImage->GetWidth() >= SUB_IMAGE_SIZE && m_pImage->GetHeight() >= SUB_IMAGE_SIZE, "Not enough room for the sub-image");
		GRect r(x - SUB_IMAGE_SIZE / 2, y - SUB_IMAGE_SIZE / 2, SUB_IMAGE_SIZE, SUB_IMAGE_SIZE);
		if(r.x < 0)
			r.x = 0;
		if(r.y < 0)
			r.y = 0;
		if(r.x + r.w >= m_pImage->GetWidth())
			r.x = m_pImage->GetWidth() - r.w;
		if(r.y + r.h >= m_pImage->GetHeight())
			r.y = m_pImage->GetHeight() - r.h;
		GRect r2(r.x - SUB_IMAGE_SIZE / 8, r.y - SUB_IMAGE_SIZE / 8, SUB_IMAGE_SIZE / 4, SUB_IMAGE_SIZE / 4);
		GImage tmp;
		tmp.CopyImage(m_pImage);
		tmp.QuickBlur(7);
		pTargetFrame->m_pFinder->FindSubImage(pOutX, pOutY, &tmp, &r, &r2);
		(*pOutX) += (x - r.x);
		(*pOutY) += (y - r.y);
		if(*pOutX < 0)
			*pOutX = 0;
		if(*pOutY < 0)
			*pOutY = 0;
		if(*pOutX >= m_pImage->GetWidth())
			*pOutX = m_pImage->GetWidth() - 1;
		if(*pOutY >= m_pImage->GetHeight())
			*pOutY = m_pImage->GetHeight() - 1;

	}

	bool IsSelected(int x, int y)
	{
		GColor c = m_pSelection->GetPixel(x, y);
		if(gAlpha(c) > 0 && c != SINK_SEED_COLOR)
			return true;
		else
			return false;
	}

	bool GetSampleSelectedPoint(int* pX, int* pY)
	{
		VideoSmartSelectSeed* pSeed;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			if(pSeed->IsSource())
			{
				*pX = pSeed->GetX();
				*pY = pSeed->GetY();
				return true;
			}
		}
		return false;
	}

	void ComputeLocationWithinSelection(int* pWid, int* pHgt, float* pOutH, float* pOutV, VideoSmartSelectSeed* pSeed)
	{
		int x = pSeed->GetX();
		int y = pSeed->GetY();
		bool s = IsSelected(x, y);

		// Find the four distances to the edge of the selection
		int l, r, t, b;
		for(l = x; l > 0 && IsSelected(l - 1, y) == s; l--) {}
		for(r = x; r < m_pSelection->GetWidth() - 1 && IsSelected(r + 1, y) == s; r++) {}
		for(t = y; t > 0 && IsSelected(x, t - 1) == s; t--) {}
		for(b = y; b < m_pSelection->GetHeight() - 1 && IsSelected(x, b + 1) == s; b++) {}
		*pOutH = (float)(x - l) / (r - l + 1);
		*pOutV = (float)(y - t) / (b - t + 1);
		*pWid = r - l + 1;
		*pHgt = b - t + 1;
	}

	bool UpdateSeedPosition(VideoSmartSelectSeed* pSeed, int wid, int hgt, float h, float v)
	{
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		int x = pSeed->GetX();
		int y = pSeed->GetY();
		bool s = IsSelected(x, y);

		// Find the four distances to the edge of the selection
		int l, r, t, b;
		for(l = x; l > 0 && IsSelected(l - 1, y) == s; l--) {}
		for(r = x; r < m_pSelection->GetWidth() - 1 && IsSelected(r + 1, y) == s; r++) {}
		for(t = y; t > 0 && IsSelected(x, t - 1) == s; t--) {}
		for(b = y; b < m_pSelection->GetHeight() - 1 && IsSelected(x, b + 1) == s; b++) {}

		// Do sanity checks
		float fWidRatio = (float)wid / (r - l + 1);
		if(fWidRatio > (float)1.0)
			fWidRatio = (float)1 / fWidRatio;
		if(fWidRatio < (float).65)
			return false;
		float fHgtRatio = (float)hgt / (b - t + 1);
		if(fHgtRatio > (float)1.0)
			fHgtRatio = (float)1 / fHgtRatio;
		if(fHgtRatio < (float).65)
			return false;

		// Move the seed
		int nNewX = l + (int)(h * (r - l + 1) + .5);
		int nNewY = t + (int)(v * (b - t + 1) + .5);
		if(nNewX == x && nNewY == y)
			return false;
		pSeed->SetPos(nNewX, nNewY, pRegionMask->GetPixel(nNewX, nNewY));
		return true;
	}

	void PropagateSeeds()
	{
		float h, v;
		int wid, hgt;
		VideoSmartSelectSeed* pSeed;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			if(!pSeed->GetPrev())
			{
				ComputeLocationWithinSelection(&wid, &hgt, &h, &v, pSeed);
				Propagate(pSeed, false, wid, hgt, h, v);
			}
			if(!pSeed->GetNext())
			{
				ComputeLocationWithinSelection(&wid, &hgt, &h, &v, pSeed);
				Propagate(pSeed, true, wid, hgt, h, v);
			}
		}
	}

	void Propagate(VideoSmartSelectSeed* pSeed, bool bRight, int wid, int hgt, float h, float v)
	{
		int x, y, nRegion;
		VideoSmartSelectFrame* pTargetFrame = (bRight ? m_pNext : m_pPrev);
		while(pTargetFrame)
		{
			// Estimate the initial position with image correlation
			ComputeNextFrameSeedPos(pSeed->GetX(), pSeed->GetY(), &x, &y, pTargetFrame);

			// Make a new seed
			GImage* pRegionMask = pTargetFrame->m_pRegions->GetRegionMask();
			nRegion = pRegionMask->GetPixel(x, y);
			VideoSmartSelectSeed* pNewSeed = new VideoSmartSelectSeed(pSeed->IsSource(), x, y, nRegion, pSeed->GetFramesFromOrigin() + (bRight ? 1 : -1));
			pNewSeed->LinkAtHead(pTargetFrame->m_pSeeds, bRight ? pSeed : NULL, bRight ? NULL : pSeed);
			pTargetFrame->m_pSeeds = pNewSeed;

			// Converge to new position with graph cut
			int nSafety = 6;
			while(--nSafety >= 0)
			{
				pTargetFrame->UpdateSelection();
				if(!pTargetFrame->UpdateSeedPosition(pNewSeed, wid, hgt, h, v))
					break;
			}

			// Move on to the next frame
			pSeed = pNewSeed;
			pTargetFrame = (bRight ? pTargetFrame->m_pNext : pTargetFrame->m_pPrev);
		}
	}

	void SanityCheckSeeds()
	{
		VideoSmartSelectSeed* pPrevSib = NULL;
		VideoSmartSelectSeed* pSeed;
		VideoSmartSelectSeed* pSeed2;
		VideoSmartSelectSeed* pSeed3;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			GAssert(pSeed->GetPrevSibling() == pPrevSib, "sibling list corrupt");
			pSeed3 = pSeed;
			for(pSeed2 = pSeed->GetPrev(); pSeed2; pSeed2 = pSeed2->GetPrev())
			{
				GAssert(pSeed2->GetNext() == pSeed3, "next chain corrupt");
				GAssert(pSeed2->GetFramesFromOrigin() < pSeed->GetFramesFromOrigin(), "wrong order");
				pSeed3 = pSeed2;
			}
			pSeed3 = pSeed;
			for(pSeed2 = pSeed->GetNext(); pSeed2; pSeed2 = pSeed2->GetNext())
			{
				GAssert(pSeed2->GetPrev() == pSeed3, "prev chain corrupt");
				GAssert(pSeed2->GetFramesFromOrigin() > pSeed->GetFramesFromOrigin(), "wrong order");
				pSeed3 = pSeed2;
			}
			pPrevSib = pSeed;
		}
	}

	void OnMouseDown(int x, int y, bool bSource)
	{
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		if(x < 0 || y < 0 || x >= pRegionMask->GetWidth() || y >= pRegionMask->GetHeight())
			return;
		int nRegion = pRegionMask->GetPixel(x, y);
		VideoSmartSelectSeed* pSeed = FindSeed(nRegion);
		m_pGrabbedSeed = NULL;
		if(pSeed)
		{
			if(pSeed->IsSource() == bSource)
				m_pGrabbedSeed = pSeed;
			else
			{
				RemoveSeed(pSeed);
			}
		}
		else
		{
			// Make the new seed
			VideoSmartSelectSeed* pNewSeed = new VideoSmartSelectSeed(bSource, x, y, nRegion, 0);
			pNewSeed->LinkAtHead(m_pSeeds, NULL, NULL);
			m_pSeeds = pNewSeed;
		}
	}

	void OnMouseUp(int x, int y)
	{
		if(!m_pGrabbedSeed)
			return;
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		if(x >= 0 && x < pRegionMask->GetWidth() && y >= 0 && y < pRegionMask->GetHeight())
		{
			if(!FindSeed(m_pGrabbedSeed))
			{
				GAssert(false, "grabbed seed in another frame");
				m_pGrabbedSeed = NULL;
				return;
			}
			int nNewRegion = pRegionMask->GetPixel(x, y);
			if(nNewRegion != m_pGrabbedSeed->GetRegion())
			{
				m_pGrabbedSeed->SetPos(x, y, nNewRegion);
				if(m_pGrabbedSeed->GetFramesFromOrigin() >= 0 && m_pGrabbedSeed->GetNext())
					m_pNext->RemoveSeed(m_pGrabbedSeed->GetNext());
				if(m_pGrabbedSeed->GetFramesFromOrigin() <= 0 && m_pGrabbedSeed->GetPrev())
					m_pPrev->RemoveSeed(m_pGrabbedSeed->GetPrev());
				UpdateSelection();
			}
		}
		m_pGrabbedSeed = NULL;
	}
};



class VideoToolSmartSelect : public VideoTool
{
protected:
	VideoSmartSelectFrame* m_pFrames1;
	VideoSmartSelectFrame* m_pFrames2;
	VideoSmartSelectFrame* m_pFrames;
	int m_nCurrentButton;
	GVideo* m_pVideo1;
	GVideo* m_pVideo2;
	GVideo* m_pSelection1;
	GVideo* m_pSelection2;
	int m_nFrame;

public:
	VideoToolSmartSelect(VideoController* pController) : VideoTool(pController)
	{
		m_pFrames1 = NULL;
		m_pFrames2 = NULL;
		m_pFrames = NULL;
		m_nFrame = -1;
		m_pVideo1 = NULL;
		m_pVideo2 = NULL;
		m_pSelection1 = NULL;
		m_pSelection2 = NULL;
	}

	virtual ~VideoToolSmartSelect()
	{
		delete[] m_pFrames1;
		delete[] m_pFrames2;
	}

	virtual void OnSelect()
	{
		m_pVideo1 = m_pController->GetVideo1();
		m_pVideo2 = m_pController->GetVideo2();
		m_pSelection1 = m_pController->GetSelection1();
		m_pSelection2 = m_pController->GetSelection2();
		delete[] m_pFrames1;
		delete[] m_pFrames2;
		m_pFrames1 = new VideoSmartSelectFrame[m_pVideo1->GetFrameCount()];
		m_pFrames2 = new VideoSmartSelectFrame[m_pVideo2->GetFrameCount()];
		int i;
		for(i = 0; i < m_pVideo1->GetFrameCount(); i++)
			m_pFrames1[i].MakeRegions(m_pVideo1->GetFrame(i), m_pSelection1->GetFrame(i), i > 0 ? &m_pFrames1[i - 1] : NULL, i < m_pVideo1->GetFrameCount() - 1 ? &m_pFrames1[i + 1] : NULL);
		for(i = 0; i < m_pVideo2->GetFrameCount(); i++)
			m_pFrames2[i].MakeRegions(m_pVideo2->GetFrame(i), m_pSelection2->GetFrame(i), i > 0 ? &m_pFrames2[i - 1] : NULL, i < m_pVideo2->GetFrameCount() - 1 ? &m_pFrames2[i + 1] : NULL);
	}

	virtual void OnMouseDown(int nFrame, GVideo* pVideo, GVideo* pSelection, int nButton, int x, int y)
	{
		if(pVideo == m_pVideo1)
			m_pFrames = m_pFrames1;
		else if(pVideo == m_pVideo2)
			m_pFrames = m_pFrames2;
		else
			GAssert(false, "unrecognized video");
		m_nFrame = nFrame;
		m_nCurrentButton = nButton;
		bool bSource;
		if(nButton == 4)
		{
			m_pController->OnScrollWheel(false);
			return;
		}
		else if(nButton == 5)
		{
			m_pController->OnScrollWheel(true);
			return;
		}
		else if(nButton == 9 || nButton == 2) // middle button
		{
			m_pFrames[m_nFrame].PropagateSeeds();
			return;
		}
		else if(nButton == 1) // left button
			bSource = true;
		else if(nButton == 3) // right button
			bSource = false;
		else
			return;
		m_pFrames[m_nFrame].OnMouseDown(x, y, bSource);
		m_pFrames[m_nFrame].UpdateSelection();
	}

	virtual void OnMouseUp(int nButton, int x, int y)
	{
		if(nButton != 1 && nButton != 3)
			return;
		m_pFrames[m_nFrame].OnMouseUp(x, y);
	}
/*
	virtual void OnMouseMove(int x, int y, bool bPressed)
	{
	}
*/
	static GColor BlendColors(GColor a, GColor b, float fac)
	{
		float f2 = (float)1.0 - fac;
		return gARGB(
			0xff,
			(int)(gRed(a) * f2 + gRed(b) * fac),
			(int)(gGreen(a) * f2 + gGreen(b) * fac),
			(int)(gBlue(a) * f2 + gBlue(b) * fac)
			);
	}

	void LoadSeeds()
	{
		const char* szError;
		int nLine;
		GXMLTag* pTagRoot = GXMLTag::FromFile("seeds.xml", &szError, NULL, &nLine, NULL);
		Holder<GXMLTag*> hTagRoot(pTagRoot);
		GAssert(pTagRoot, "Failed to load");

		// Load video 1
		GXMLTag* pTagSeed;
		int nFrame;
		GXMLTag* pTagVideo1 = pTagRoot->GetChildTag("Video1");
		GAssert(pTagVideo1, "Expected a <Video1> tag");
		for(pTagSeed = pTagVideo1->GetFirstChildTag(); pTagSeed; pTagSeed = pTagVideo1->GetNextChildTag(pTagSeed))
		{
			GXMLAttribute* pFrameAttr = pTagSeed->GetAttribute("Frame");
			nFrame = atoi(pFrameAttr->GetValue());
			m_pFrames1[nFrame].LoadSeeds(pTagSeed);
		}

		// Load video 2
		GXMLTag* pTagVideo2 = pTagRoot->GetChildTag("Video2");
		GAssert(pTagVideo2, "Expected a <Video2> tag");
		for(pTagSeed = pTagVideo2->GetFirstChildTag(); pTagSeed; pTagSeed = pTagVideo2->GetNextChildTag(pTagSeed))
		{
			GXMLAttribute* pFrameAttr = pTagSeed->GetAttribute("Frame");
			nFrame = atoi(pFrameAttr->GetValue());
			m_pFrames2[nFrame].LoadSeeds(pTagSeed);
		}

		// Update all the selections
		int i;
		for(i = 0; i < m_pVideo1->GetFrameCount(); i++)
			m_pFrames1[i].UpdateSelection();
		for(i = 0; i < m_pVideo2->GetFrameCount(); i++)
			m_pFrames2[i].UpdateSelection();
	}

	void SaveSeeds()
	{
		int i;
		GXMLTag root("Seeds");
		GXMLTag* pTagVideo1 = new GXMLTag("Video1");
		root.AddChildTag(pTagVideo1);
		for(i = 0; i < m_pVideo1->GetFrameCount(); i++)
			m_pFrames1[i].SaveSeeds(pTagVideo1, i);
		GXMLTag* pTagVideo2 = new GXMLTag("Video2");
		root.AddChildTag(pTagVideo2);
		for(i = 0; i < m_pVideo2->GetFrameCount(); i++)
			m_pFrames2[i].SaveSeeds(pTagVideo2, i);
		bool bOK = root.ToFile("seeds.xml");
		GAssert(bOK, "failed to save");
	}

	void Morph()
	{
#ifdef WIN32
		mkdir("output");
#else // WIN32
		mkdir("output", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
#endif // !WIN32
		chdir("output");

		// Make a blank video of the right size
printf("Allocating space for the video...\n");
		GAssert(m_pVideo1->GetWidth() == m_pVideo2->GetWidth() && m_pVideo1->GetHeight() == m_pVideo2->GetHeight(), "videos are different sizes");
		GVideo morphVideo(m_pVideo1->GetWidth(), m_pVideo1->GetHeight());
		int nFrames = MIN(m_pVideo1->GetFrameCount(), m_pVideo2->GetFrameCount());
		int i;
		for(i = 0; i < nFrames; i++)
			morphVideo.AddBlankFrame();

		// Change source seed selection areas to selection color
printf("Changing selection color...\n");
		int x, y, z;
		GImage* pSel1;
		GImage* pSel2;
		for(z = 0; z < nFrames; z++)
		{
			pSel1 = m_pSelection1->GetFrame(z);
			pSel2 = m_pSelection2->GetFrame(z);
			for(y = 0; y < morphVideo.GetHeight(); y++)
			{
				for(x = 0; x < morphVideo.GetWidth(); x++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -