paint.cpp

来自「一个由Mike Gashler完成的机器学习方面的includes neural」· C++ 代码 · 共 1,283 行 · 第 1/3 页

CPP
1,283
字号
// --------------------------------------------------------
// This demo file is dedicated to the Public Domain. See:
// http://creativecommons.org/licenses/publicdomain
// --------------------------------------------------------

#include "Paint.h"
#ifdef WIN32
#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/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 "Interpolate.h"
#include <math.h>


#define PAINT_TAB_COUNT 3
#define TOOL_AREA_SIZE 150
#define PAINT_AREA_BACKGROUND_COLOR 0xff888888

// todo: remove me
#define OCR_HALF_VEC_SIZE 20


class PaintTool
{
protected:
	GImage* m_pImage;

public:
	PaintTool(GImage* pImage)
	{
		m_pImage = pImage;
	}

	virtual ~PaintTool()
	{
	}

	virtual void OnSelect() {}
	virtual void OnMouseDown(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 PaintToolPen : public PaintTool
{
protected:
	int m_prevX, m_prevY;

public:
	PaintToolPen(GImage* pImage) : PaintTool(pImage) {}
	virtual ~PaintToolPen() {}

	virtual void OnMouseDown(int nButton, int x, int y)
	{
		m_prevX = x;
		m_prevY = y;
		m_pImage->SafeSetPixel(x, y, 0xffff0000);
	}

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

class PaintToolBorder : public PaintTool
{
protected:

public:
	PaintToolBorder(GImage* pImage) : PaintTool(pImage) {}
	virtual ~PaintToolBorder() {}

	virtual void OnMouseDown(int nButton, int x, int y)
	{
		GImage tmp;
		tmp.SetSize(m_pImage->GetWidth(), m_pImage->GetHeight());
		tmp.Clear(0xff000000);
		int xx, yy, dd;
		GRegionBorderIterator itt(m_pImage, x, y);
		while(itt.GetNext(&xx, &yy, &dd))
			tmp.SetPixel(xx, yy, 0xffffffff);
		m_pImage->SwapData(&tmp);
	}
};

class PaintToolStretch : public PaintTool
{
protected:
	GImage m_imageDown;
	int m_downX, m_downY, m_prevX, m_prevY;

public:
	PaintToolStretch(GImage* pImage) : PaintTool(pImage) {}
	virtual ~PaintToolStretch() {}

	virtual void OnMouseDown(int nButton, int x, int y)
	{
		m_imageDown.CopyImage(m_pImage);
		m_downX = x;
		m_downY = y;
	}

	virtual void OnMouseMove(int x, int y, bool bPressed)
	{
		if(bPressed && (x != m_prevX || y != m_prevY))
		{
			m_pImage->CopyImage(&m_imageDown);
			m_pImage->Stretch(m_downX, m_downY, x, y);
			m_prevX = x;
			m_prevY = y;
		}
	}
};

class PaintToolBezier : public PaintTool
{
protected:
	GIntArray m_points;

public:
	PaintToolBezier(GImage* pImage) : PaintTool(pImage), m_points(32) {}
	virtual ~PaintToolBezier() {}

	virtual void OnMouseDown(int nButton, int x, int y)
	{
		if(nButton == 1)
		{
			m_points.AddInt(x);
			m_points.AddInt(y);
			m_pImage->SetPixel(x, y, 0xff00ff00);
		}
		else
		{
			// Construct the GBezier object
			struct Point3D point;
			GBezier bez(m_points.GetSize() / 2);
			int i;
			for(i = 0; i < m_points.GetSize(); i += 2)
			{
				point.m_vals[0] = m_points.GetInt(i);
				point.m_vals[1] = m_points.GetInt(i + 1);
				bez.SetControlPoint(i / 2, &point, 1);
			}
			m_points.Clear();

			// Draw the curve
			for(i = 0; i < 1000; i++)
			{
				bez.GetPoint((double)i / 1000, &point);
				m_pImage->SafeSetPixel((int)point.m_vals[0], (int)point.m_vals[1], 0xff0000ff);
			}
		}
	}
};


class PaintToolSmartSelect : public PaintTool
{
protected:
	G2DRegionGraph* m_pRegions;
	GImage* m_pSelection;
	GBitTable* m_pForeground;
	GBitTable* m_pBackground;
	int m_nCurrentButton;

public:
	PaintToolSmartSelect(GImage* pImage, GImage* pSelection) : PaintTool(pImage)
	{
		m_pRegions = NULL;
		m_pSelection = pSelection;
		m_pForeground = NULL;
		m_pBackground = NULL;
	}

	virtual ~PaintToolSmartSelect()
	{
		delete(m_pRegions);
		delete(m_pForeground);
		delete(m_pBackground);
	}

	virtual void OnSelect()
	{
		delete(m_pRegions);
		m_pRegions = new G2DRegionGraph(m_pImage->GetWidth(), m_pImage->GetHeight());
		m_pRegions->MakeWatershedRegions(m_pImage);
 		while(m_pRegions->GetRegionCount() > 2000)
		{
			G2DRegionGraph* pNewRegionList = new G2DRegionGraph(m_pImage->GetWidth(), m_pImage->GetHeight());
			pNewRegionList->MakeCoarserRegions(m_pRegions);
			delete(m_pRegions);
			m_pRegions = pNewRegionList;
		}
/*
GImage colorRegion;
colorRegion.CopyImage(m_pRegions->GetRegionMask());
colorRegion.ColorizeRegionMap();
colorRegion.SavePNGFile("/home/mike/regions.png");
*/
		delete(m_pForeground);
		delete(m_pBackground);
		m_pForeground = new GBitTable(m_pRegions->GetRegionCount());
		m_pBackground = new GBitTable(m_pRegions->GetRegionCount());
	}

	virtual void OnMouseDown(int nButton, int x, int y)
	{
		m_nCurrentButton = nButton;
		OnMouseMove(x, y, true);
	}

	void SelectSourceRegions(GGraphCut* pGC)
	{
		int x, y;
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		unsigned int nRegion;
		for(y = 0; y < (int)m_pSelection->GetHeight(); y++)
		{
			for(x = 0;  x < (int)m_pSelection->GetWidth(); x++)
			{
				nRegion = pRegionMask->GetPixel(x, y);
				if(pGC->IsSource(nRegion))
					m_pSelection->SetPixel(x, y, GBits::GetRandomUint() | 0xff000000);
				else
					m_pSelection->SetPixel(x, y, 0);
			}
		}
	}

	void SetEdgeRegionsAsBackground(GGraphCut* pGC, float fCapacity)
	{
		unsigned int nRegion[6];
		int i;
		for(i = 0; i < 6; i++)
			nRegion[i] = (unsigned int)-1;
		int nRegionCount = m_pRegions->GetRegionCount();
		GImage* pRegionMask = m_pRegions->GetRegionMask();
		for(i = 0; i < (int)pRegionMask->GetWidth(); i++)
		{
			nRegion[0] = pRegionMask->GetPixel(i, 0);
			if(nRegion[0] != nRegion[1] && nRegion[0] != nRegion[2])
			{
				pGC->AddEdge(nRegion[0], nRegionCount + 1, fCapacity);
				nRegion[2] = nRegion[1];
				nRegion[1] = nRegion[0];
			}
			nRegion[3] = pRegionMask->GetPixel(i, pRegionMask->GetHeight() - 1);
			if(nRegion[3] != nRegion[4] && nRegion[3] != nRegion[5])
			{
				pGC->AddEdge(nRegion[3], nRegionCount + 1, fCapacity);
				nRegion[5] = nRegion[4];
				nRegion[4] = nRegion[3];
			}
		}
		for(i = 1; i < (int)pRegionMask->GetHeight() - 1; i++)
		{
			nRegion[0] = pRegionMask->GetPixel(0, i);
			if(nRegion[0] != nRegion[1] && nRegion[0] != nRegion[2])
			{
				pGC->AddEdge(nRegion[0], nRegionCount + 1, fCapacity);
				nRegion[2] = nRegion[1];
				nRegion[1] = nRegion[0];
			}
			nRegion[3] = pRegionMask->GetPixel(pRegionMask->GetWidth() - 1, i);
			if(nRegion[3] != nRegion[4] && nRegion[3] != nRegion[5])
			{
				pGC->AddEdge(nRegion[3], nRegionCount + 1, fCapacity);
				nRegion[5] = nRegion[4];
				nRegion[4] = nRegion[3];
			}
		}
	}

	virtual void OnMouseUp(int nButton, int x, int y)
	{
		// Make a graph of the regions
		int nRegionCount = m_pRegions->GetRegionCount();
		GGraphCut gc(nRegionCount + 2);
		gc.GetEdgesFromRegionList(m_pRegions); // (where edges refers to graph edges between vertices)

		// Connect frame border regions to background
		SetEdgeRegionsAsBackground(&gc, 30); // (where edges refers to the borders of the frame)

		// Connect foreground to the source and background to the sink
		int nForeCount = 0;
		int nBackCount = 0;
		int i;
		for(i = 0; i < nRegionCount; i++)
		{
			if(m_pForeground->GetBit(i))
			{
				gc.AddEdge(i, nRegionCount, (float)1e30);
				nForeCount++;
			}
			else if(m_pBackground->GetBit(i))
			{
				gc.AddEdge(i, nRegionCount + 1, (float)1e30);
				nBackCount++;
			}
		}
		//if(nForeCount <= 0 || nBackCount <= 0)
		//	return;

		// Cut the graph and select the foreground
		gc.Cut(nRegionCount, nRegionCount + 1);
		SelectSourceRegions(&gc);
	}

	virtual void OnMouseMove(int x, int y, bool bPressed)
	{
		if(!bPressed)
			return;
		unsigned int nRegion = m_pRegions->GetRegionMask()->GetPixel(x, y);
		if(m_nCurrentButton == 1)
		{
			m_pForeground->SetBit(nRegion, true);
			m_pBackground->SetBit(nRegion, false);
		}
		else if(m_nCurrentButton == 3)
		{
			m_pForeground->SetBit(nRegion, false);
			m_pBackground->SetBit(nRegion, true);
		}
	}
};

// ----------------------------------------------------------------------------

class PaintDialog : public GWidgetDialog
{
friend class PaintController;
protected:
	GImage* m_pImage;
	GImage* m_pSelection;
	PaintController* m_pController;
	GWidgetTextTab** m_pTabs;
	GWidgetCanvas* m_pCanvas;
	GWidgetHorizScrollBar* m_pHorizScrollBar;
	GWidgetVertScrollBar* m_pVertScrollBar;
	PaintTool* m_pCurrentTool;

public:
	PaintDialog(PaintController* pController, int w, int h, GImage* pImage, GImage* pSelection)
	: GWidgetDialog(w, h, PAINT_AREA_BACKGROUND_COLOR)
	{
		m_pCurrentTool = NULL;
		m_pImage = pImage;
		m_pSelection = pSelection;
		m_pController = pController;
		m_pTabs = new GWidgetTextTab*[PAINT_TAB_COUNT];
		m_pTabs[0] = new GWidgetTextTab(this, 0, 0, 50, 20, "Open", 0xff008800);
		m_pTabs[1] = NULL; //new GWidgetTextTab(this, 50, 0, 50, 20, "Mask", 0xff008800);
		m_pTabs[2] = new GWidgetTextTab(this, 50, 0, 50, 20, "Tools", 0xff008800);
		m_pTabs[0]->SetSelected(true);

		m_pCanvas = new GWidgetCanvas(this, 0, 20, w - 16, h - 36, pImage);
		m_pCanvas->SetSelectionMask(m_pSelection);
		m_pHorizScrollBar = new GWidgetHorizScrollBar(this, 0, h - 16, w - 16, 16, w - 16, pImage->GetWidth());
		m_pVertScrollBar = new GWidgetVertScrollBar(this, w - 16, 0, 16, h, h - 36, pImage->GetHeight());
	}

	virtual ~PaintDialog()
	{
		delete[] m_pTabs;
	}

	virtual void OnSelectTextTab(GWidgetTextTab* pTab)
	{
		pTab->SetSelected(true);
		int i;
		for(i = 0; i < PAINT_TAB_COUNT; i++)
		{
			if(!m_pTabs[i])
				continue;
			if(m_pTabs[i] == pTab)
				m_pController->OnSelectTab(i);
			else
				m_pTabs[i]->SetSelected(false);
		}
	}

	void OnLoadImage()
	{
		m_pCanvas->ZoomToFit();
		CleanCanvas();
	}

	void CleanCanvas()
	{
		// This is just a cosmetic thing so that the edges of an old
		// larger image don't clutter up the edges around the new smaller image
//		m_pCanvas->GetOutImage()->Clear(PAINT_AREA_BACKGROUND_COLOR);
		m_pHorizScrollBar->SetModelSize((int)(m_pCanvas->GetZoom() * m_pImage->GetWidth()));
		m_pVertScrollBar->SetModelSize((int)(m_pCanvas->GetZoom() * m_pImage->GetHeight()));
	}

	inline void RedrawCanvas()
	{
		m_pCanvas->SetDirty();
	}

	virtual void OnHorizScroll(GWidgetHorizScrollBar* pScrollBar)
	{
		m_pCanvas->SetHorizScroll(pScrollBar->GetPos());
		RedrawCanvas();
	}

	virtual void OnVertScroll(GWidgetVertScrollBar* pScrollBar)

⌨️ 快捷键说明

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