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 + -
显示快捷键?