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

📄 video.cpp

📁 一个由Mike Gashler完成的机器学习方面的includes neural net, naive bayesian classifier, decision tree, KNN, a genet
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// --------------------------------------------------------
// This demo file is dedicated to the Public Domain. See:
// http://creativecommons.org/licenses/publicdomain
// --------------------------------------------------------

#include "Video.h"
#ifdef WIN32
#include <direct.h>
#else // WIN32
#include <unistd.h>
#endif // !WIN32
#include "../GClasses/GBitTable.h"
#include "../GClasses/GTime.h"
#include "../GClasses/GMacros.h"
#include "../GClasses/GFile.h"
#include "../GClasses/GImage.h"
#include "../GClasses/GVideo.h"
#include "../GClasses/GBits.h"
#include "../GClasses/GPointerQueue.h"
#include "../GClasses/GThread.h"
#include "../GClasses/GRegion.h"
#include "../GClasses/GGraph.h"
#include "../GClasses/GKNN.h"
#include "../GClasses/GBezier.h"
#include "../GClasses/GArff.h"
#include "../GClasses/GCluster.h"
#include "../GClasses/GMorph.h"
#include "../GClasses/GXML.h"
#include "Interpolate.h"
#include <math.h>


#define VIDEO_TAB_COUNT 3
#define TOOL_AREA_SIZE 150
#define VIDEO_AREA_BACKGROUND_COLOR 0xff888888




class VideoTool
{
protected:
	VideoController* m_pController;

public:
	VideoTool(VideoController* pController)
	{
		m_pController = pController;
	}

	virtual ~VideoTool() {}

	virtual void OnSelect() {}
	virtual void OnMouseDown(int nFrame, GVideo* pVideo, GVideo* pSelection, int nButton, int x, int y) = 0;
	virtual void OnMouseUp(int nButton, int x, int y) {}
	virtual void OnMouseMove(int x, int y, bool bPressed) {}
};

class VideoToolPen : public VideoTool
{
protected:
	int m_prevX, m_prevY, m_nFrame;
	GVideo* m_pVideo;

public:
	VideoToolPen(VideoController* pController) : VideoTool(pController)
	{
		m_nFrame = -1;
		m_pVideo = NULL;
	}

	virtual ~VideoToolPen() {}

	virtual void OnMouseDown(int nFrame, GVideo* pVideo, GVideo* pSelection, int nButton, int x, int y)
	{
		m_pVideo = pVideo;
		m_nFrame = nFrame;
		m_prevX = x;
		m_prevY = y;
		pVideo->GetFrame(nFrame)->SafeSetPixel(x, y, 0xffff0000);
	}

	virtual void OnMouseMove(int x, int y, bool bPressed)
	{
		if(bPressed && (x != m_prevX || y != m_prevY))
		{
			m_pVideo->GetFrame(m_nFrame)->SafeDrawLine(m_prevX, m_prevY, x, y, 0xffff0000);
			m_prevX = x;
			m_prevY = y;
		}
	}
};


class VideoSmartSelectSeed
{
protected:
	VideoSmartSelectSeed* m_pNext;
	VideoSmartSelectSeed* m_pPrev;
	VideoSmartSelectSeed* m_pSibNext;
	VideoSmartSelectSeed* m_pSibPrev;
	bool m_bSource;
	int m_nRegion;
	int m_nFramesFromOrigin;
	int m_x, m_y;

public:
	VideoSmartSelectSeed(bool bSource, int x, int y, int nRegion, int nFramesFromOrigin)
	{
		m_pNext = NULL;
		m_pPrev = NULL;
		m_pSibNext = NULL;
		m_pSibPrev = NULL;
		m_bSource = bSource;
		m_x = x;
		m_y = y;
		m_nRegion = nRegion;
		m_nFramesFromOrigin = nFramesFromOrigin;
	}

	~VideoSmartSelectSeed()
	{
		VideoSmartSelectSeed* pCondemned;
		while(m_pSibNext)
		{
			pCondemned = m_pSibNext;
			m_pSibNext = pCondemned->m_pSibNext;
			pCondemned->m_pSibNext = NULL;
			delete(pCondemned);
		}
	}

	void ToXml(GXMLTag* pTag)
	{
		char szTmp[32];
		itoa(m_x, szTmp, 10);
		pTag->AddAttribute(new GXMLAttribute("x", szTmp));
		itoa(m_y, szTmp, 10);
		pTag->AddAttribute(new GXMLAttribute("y", szTmp));
		pTag->AddAttribute(new GXMLAttribute("source", m_bSource ? "true" : "false"));
	}

	void SaveSeedChain(GXMLTag* pTagVideo, int nFrame)
	{
		// Save the root seed
		GXMLTag* pSeedTag = new GXMLTag("Seed");
		pTagVideo->AddChildTag(pSeedTag);
		char szTmp[32];
		itoa(nFrame, szTmp, 10);
		pSeedTag->AddAttribute(new GXMLAttribute("Frame", szTmp));
		ToXml(pSeedTag);

		// Save the prev chain
		GXMLTag* pTagPrev = new GXMLTag("Prev");
		pSeedTag->AddChildTag(pTagPrev);
		VideoSmartSelectSeed* pSeed;
		for(pSeed = GetPrev(); pSeed; pSeed = pSeed->GetPrev())
		{
			GXMLTag* pNewSeedTag = new GXMLTag("Seed");
			pTagPrev->AddChildTag(pNewSeedTag);
			pSeed->ToXml(pNewSeedTag);
		}

		// Save the next chain
		GXMLTag* pTagNext = new GXMLTag("Next");
		pSeedTag->AddChildTag(pTagNext);
		for(pSeed = GetNext(); pSeed; pSeed = pSeed->GetNext())
		{
			GXMLTag* pNewSeedTag = new GXMLTag("Seed");
			pTagNext->AddChildTag(pNewSeedTag);
			pSeed->ToXml(pNewSeedTag);
		}
	}

	void SetPos(int x, int y, int nRegion)
	{
		m_x = x;
		m_y = y;
		m_nRegion = nRegion;
	}

	VideoSmartSelectSeed* GetNextSibling()
	{
		return m_pSibNext;
	}

	VideoSmartSelectSeed* GetPrevSibling()
	{
		return m_pSibPrev;
	}

	VideoSmartSelectSeed* GetNext()
	{
		return m_pNext;
	}

	VideoSmartSelectSeed* GetPrev()
	{
		return m_pPrev;
	}

	bool IsSource()
	{
		return m_bSource;
	}

	int GetFramesFromOrigin()
	{
		return m_nFramesFromOrigin;
	}

	int GetRegion()
	{
		return m_nRegion;
	}

	int GetX()
	{
		return m_x;
	}

	int GetY()
	{
		return m_y;
	}

	void LinkAtHead(VideoSmartSelectSeed* pOldHead, VideoSmartSelectSeed* pPrev, VideoSmartSelectSeed* pNext)
	{
		m_pSibNext = pOldHead;
		m_pSibPrev = NULL;
		if(pOldHead)
		{
			GAssert(!pOldHead->m_pSibPrev, "not really the head");
			pOldHead->m_pSibPrev = this;
		}
		m_pPrev = pPrev;
		if(pPrev)
		{
			GAssert(pPrev->m_nFramesFromOrigin < m_nFramesFromOrigin, "doesn't precede this seed");
			GAssert(!pPrev->m_pNext, "already has a next");
			pPrev->m_pNext = this;
		}
		m_pNext = pNext;
		if(pNext)
		{
			GAssert(pNext->m_nFramesFromOrigin > m_nFramesFromOrigin, "doesn't come after this seed");
			GAssert(!pNext->m_pPrev, "already has a prev");
			pNext->m_pPrev = this;
		}
	}

	VideoSmartSelectSeed* Unlink(VideoSmartSelectSeed* pOldFirst)
	{
		if(m_pPrev)
			m_pPrev->m_pNext = NULL;
		if(m_pNext)
			m_pNext->m_pPrev = NULL;
		m_pPrev = NULL;
		m_pNext = NULL;
		if(m_pSibPrev)
		{
			GAssert(m_pSibPrev->m_pSibNext == this, "problem");
			m_pSibPrev->m_pSibNext = m_pSibNext;
		}
		else
			pOldFirst = m_pSibNext;
		if(m_pSibNext)
		{
			GAssert(m_pSibNext->m_pSibPrev == this, "problem");
			m_pSibNext->m_pSibPrev = m_pSibPrev;
		}
		m_pSibNext = NULL;
		m_pSibPrev = NULL;
		return pOldFirst;
	}
};

#define SUB_IMAGE_SIZE 64
#define SOURCE_SEED_COLOR 0xff00ff00 // green
#define SINK_SEED_COLOR 0xffff0000 // red
#define SELECTED_COLOR 0xff8888ff // light purpley-blue

class VideoSmartSelectFrame
{
protected:
	VideoSmartSelectSeed* m_pSeeds;
	VideoSmartSelectSeed* m_pGrabbedSeed;
	G2DRegionGraph* m_pRegions;
	GImage* m_pImage;
	GImage* m_pSelection;
	VideoSmartSelectFrame* m_pNext;
	VideoSmartSelectFrame* m_pPrev;
	GSubImageFinder* m_pFinder;

public:
	VideoSmartSelectFrame()
	{
		m_pSeeds = NULL;
		m_pGrabbedSeed = NULL;
		m_pRegions = NULL;
		m_pImage = NULL;
		m_pSelection = NULL;
		m_pNext = NULL;
		m_pPrev = NULL;
		m_pFinder = NULL;
	}

	~VideoSmartSelectFrame()
	{
		delete(m_pSeeds);
		delete(m_pFinder);
	}

	static void ParseSeedTag(GXMLTag* pTagSeed, bool* pSource, int* pX, int* pY)
	{
		GXMLAttribute* pAttrSource = pTagSeed->GetAttribute("source");
		GXMLAttribute* pAttrX = pTagSeed->GetAttribute("x");
		GXMLAttribute* pAttrY = pTagSeed->GetAttribute("y");
		*pX = atoi(pAttrX->GetValue());
		*pY = atoi(pAttrY->GetValue());
		*pSource = (stricmp(pAttrSource->GetValue(), "true") == 0);
	}

	void LoadSeeds(GXMLTag* pTagSeed)
	{
		int x, y;
		bool bSource;

		// Make the new seed
		ParseSeedTag(pTagSeed, &bSource, &x, &y);
		int nRegion = m_pRegions->GetRegionMask()->GetPixel(x, y);
		VideoSmartSelectSeed* pNewSeed = new VideoSmartSelectSeed(bSource, x, y, nRegion, 0);
		pNewSeed->LinkAtHead(m_pSeeds, NULL, NULL);
		m_pSeeds = pNewSeed;

		// Load the Prev seeds
		GXMLTag* pTagPrev = pTagSeed->GetChildTag("Prev");
		GXMLTag* pTagChild;
		VideoSmartSelectSeed* pNeighbor = pNewSeed;
		VideoSmartSelectSeed* pChildSeed;
		VideoSmartSelectFrame* pFrame = m_pPrev;
		int nOffset = -1;
		for(pTagChild = pTagPrev->GetFirstChildTag(); pTagChild; pTagChild = pTagPrev->GetNextChildTag(pTagChild))
		{
			ParseSeedTag(pTagChild, &bSource, &x, &y);
			nRegion = pFrame->m_pRegions->GetRegionMask()->GetPixel(x, y);
			pChildSeed = new VideoSmartSelectSeed(bSource, x, y, nRegion, nOffset);
			pChildSeed->LinkAtHead(pFrame->m_pSeeds, NULL, pNeighbor);
			pFrame->m_pSeeds = pChildSeed;
			pFrame = pFrame->m_pPrev;
			pNeighbor = pChildSeed;
			nOffset--;
		}

		// Load the Next seeds
		GXMLTag* pTagNext = pTagSeed->GetChildTag("Next");
		pNeighbor = pNewSeed;
		pFrame = m_pNext;
		nOffset = 1;
		for(pTagChild = pTagNext->GetFirstChildTag(); pTagChild; pTagChild = pTagNext->GetNextChildTag(pTagChild))
		{
			ParseSeedTag(pTagChild, &bSource, &x, &y);
			nRegion = pFrame->m_pRegions->GetRegionMask()->GetPixel(x, y);
			pChildSeed = new VideoSmartSelectSeed(bSource, x, y, nRegion, nOffset);
			pChildSeed->LinkAtHead(pFrame->m_pSeeds, pNeighbor, NULL);
			pFrame->m_pSeeds = pChildSeed;
			pFrame = pFrame->m_pNext;
			pNeighbor = pChildSeed;
			nOffset++;
		}
	}

	void SaveSeeds(GXMLTag* pTagVideo, int nFrame)
	{
		VideoSmartSelectSeed* pSeed;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			if(pSeed->GetFramesFromOrigin() != 0)
				continue;
			pSeed->SaveSeedChain(pTagVideo, nFrame);
		}
	}

	void ConnectCornersToSink(GGraphCut* pGC, float fAmount)
	{
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		pGC->AddEdge(pRegionMask->GetPixel(0, 0), m_pRegions->GetRegionCount() + 1, fAmount);
		pGC->AddEdge(pRegionMask->GetPixel(pRegionMask->GetWidth() - 1, 0), m_pRegions->GetRegionCount() + 1, fAmount);
		pGC->AddEdge(pRegionMask->GetPixel(0, pRegionMask->GetHeight() - 1), m_pRegions->GetRegionCount() + 1, fAmount);
		pGC->AddEdge(pRegionMask->GetPixel(pRegionMask->GetWidth() - 1, pRegionMask->GetHeight() - 1), m_pRegions->GetRegionCount() + 1, fAmount);
	}

	void MakeRegions(GImage* pImage, GImage* pSelection, VideoSmartSelectFrame* pPrev, VideoSmartSelectFrame* pNext)
	{
		GAssert(!m_pRegions && !m_pSeeds && !m_pFinder, "already made");
		m_pImage = pImage;
		m_pSelection = pSelection;
		m_pNext = pNext;
		m_pPrev = pPrev;
		m_pRegions = new G2DRegionGraph(pImage->GetWidth(), pImage->GetHeight());
		m_pRegions->MakeWatershedRegions(pImage);
		while(m_pRegions->GetRegionCount() > 2500)
		{
			G2DRegionGraph* pNewRegionList = new G2DRegionGraph(pImage->GetWidth(), pImage->GetHeight());
			pNewRegionList->MakeCoarserRegions(m_pRegions);
			delete(m_pRegions);
			m_pRegions = pNewRegionList;
		}
		GImage tmp;
		tmp.CopyImage(pImage);
		tmp.QuickBlur(7);
		m_pFinder = new GSubImageFinder(pImage);
	}

	void UpdateSelection()
	{
		// Make a graph of the regions
		int nRegionCount = m_pRegions->GetRegionCount();
		GGraphCut gc(nRegionCount + 2);
		gc.GetEdgesFromRegionList(m_pRegions);

		// Weakly connect corners to background
		ConnectCornersToSink(&gc, 30);

		// Strongly connect seeds to the source orsink
		VideoSmartSelectSeed* pSeed;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			if(pSeed->IsSource())
				gc.AddEdge(pSeed->GetRegion(), nRegionCount, (float)1e30); // nRegionCount = the source node
			else
				gc.AddEdge(pSeed->GetRegion(), nRegionCount + 1, (float)1e30); // nRegionCount + 1 = the sink node
		}

		// Cut the graph
		gc.Cut(nRegionCount, nRegionCount + 1);

		// Select the foreground
		int x, y;
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		int nRegion;
		for(y = 0; y < m_pSelection->GetHeight(); y++)
		{
			for(x = 0;  x < m_pSelection->GetWidth(); x++)
			{
				nRegion = pRegionMask->GetPixel(x, y);
				if(gc.IsSource(nRegion))
					m_pSelection->SetPixel(x, y, SELECTED_COLOR);
				else
					m_pSelection->SetPixel(x, y, 0);
			}
		}

		// Select the seeds with a special color
		GColor c;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			c = pSeed->IsSource() ? SOURCE_SEED_COLOR : SINK_SEED_COLOR;
			GRegionAreaIterator itt(pRegionMask, pSeed->GetX(), pSeed->GetY());
			while(itt.GetNext(&x, &y))
				m_pSelection->SetPixel(x, y, c);
		}
	}

	VideoSmartSelectSeed* FindSeed(int nRegion)
	{
		VideoSmartSelectSeed* pSeed;
		for(pSeed = m_pSeeds; pSeed; pSeed = pSeed->GetNextSibling())
		{
			if(pSeed->GetRegion() == nRegion)
				return pSeed;
		}
		return NULL;
	}

⌨️ 快捷键说明

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