📄 video.cpp
字号:
{
if(pSel1->GetPixel(x, y) == SOURCE_SEED_COLOR)
pSel1->SetPixel(x, y, SELECTED_COLOR);
if(pSel2->GetPixel(x, y) == SOURCE_SEED_COLOR)
pSel2->SetPixel(x, y, SELECTED_COLOR);
}
}
}
// Fill in the background of the video
printf("Filling background...\n");
float fac;
GColor c1 = 0xff808080;
GColor c2 = 0xff808080;
GImage* pFrame1;
GImage* pFrame2;
GImage* pMorphFrame;
for(z = 0; z < nFrames; z++)
{
fac = (float)z / (nFrames - (float).99998) + (float).00001;
pFrame1 = m_pVideo1->GetFrame(z);
pFrame2 = m_pVideo2->GetFrame(z);
pSel1 = m_pSelection1->GetFrame(z);
pSel2 = m_pSelection2->GetFrame(z);
pMorphFrame = morphVideo.GetFrame(z);
for(y = 0; y < morphVideo.GetHeight(); y++)
{
for(x = 0; x < morphVideo.GetWidth(); x++)
{
if(pSel1->GetPixel(x, y) == SELECTED_COLOR)
{
if(pSel2->GetPixel(x, y) == SELECTED_COLOR)
{
pMorphFrame->SetPixel(x, y, 0xff808080);
}
else
{
c2 = pFrame2->GetPixel(x, y);
pMorphFrame->SetPixel(x, y, c2);
}
}
else
{
if(pSel2->GetPixel(x, y) == SELECTED_COLOR)
{
c1 = pFrame1->GetPixel(x, y);
pMorphFrame->SetPixel(x, y, c1);
}
else
{
c1 = pFrame1->GetPixel(x, y);
c2 = pFrame2->GetPixel(x, y);
pMorphFrame->SetPixel(x, y, BlendColors(c1, c2, fac));
}
}
}
}
}
// Do the morphing
printf("Morphing...\n");
int x1, y1, x2, y2, u, v, w, nCount1, nCount2, meanX1, meanY1, meanX2, meanY2;
for(z = 0; z < nFrames; z++)
{
printf("Working on frame %d/%d...\n", z + 1, nFrames);
// Find the highest selected point, the mean, and the length of both borders
fac = (float)z / (nFrames - (float).99998) + (float).00001;
pFrame1 = m_pVideo1->GetFrame(z);
pFrame2 = m_pVideo2->GetFrame(z);
pSel1 = m_pSelection1->GetFrame(z);
pSel2 = m_pSelection2->GetFrame(z);
pMorphFrame = morphVideo.GetFrame(z);
if(!m_pFrames1[z].GetSampleSelectedPoint(&x1, &y1))
GAssert(false, "failed to get sample point");
if(!m_pFrames2[z].GetSampleSelectedPoint(&x2, &y2))
GAssert(false, "failed to get sample point");
{
nCount1 = 0;
meanX1 = 0;
meanY1 = 0;
GRegionBorderIterator itt(pSel1, x1, y1);
while(itt.GetNext(&u, &v, &w))
{
if(v < y1)
{
x1 = u;
y1 = v;
}
meanX1 += u;
meanY1 += v;
nCount1++;
}
meanX1 /= nCount1;
meanY1 /= nCount1;
}
{
nCount2 = 0;
meanX2 = 0;
meanY2 = 0;
GRegionBorderIterator itt(pSel2, x2, y2);
while(itt.GetNext(&u, &v, &w))
{
if(v < y2)
{
x2 = u;
y2 = v;
}
meanX2 += u;
meanY2 += v;
nCount2++;
}
meanX2 /= nCount2;
meanY2 /= nCount2;
}
// Store the border data
GArffData mag1(nCount1);
int* px1 = new int[nCount1 * 2];
ArrayHolder<int*> hx1(px1);
int* py1 = &px1[nCount1];
double* pVector;
i = 0;
int hackfix1;
{
GRegionBorderIterator itt(pSel1, x1, y1);
while(itt.GetNext(&px1[i], &py1[i], &u))
{
pVector = new double[2];
pVector[0] = i;
pVector[1] = (px1[i] - meanX1) * (px1[i] - meanX1) + (py1[i] - meanY1) * (py1[i] - meanY1);
mag1.AddVector(pVector);
if(i == 0)
hackfix1 = py1[0];
i++;
}
}
py1[0] = hackfix1;
double min, range;
mag1.GetMinAndRange(1, &min, &range);
mag1.Normalize(1, min, range, 0, 1);
GArffData mag2(nCount2);
int* px2 = new int[nCount2 * 2];
ArrayHolder<int*> hx2(px2);
int* py2 = &px2[nCount2];
i = 0;
int hackfix2;
{
GRegionBorderIterator itt(pSel2, x2, y2);
while(itt.GetNext(&px2[i], &py2[i], &u))
{
pVector = new double[2];
pVector[0] = i;
pVector[1] = (px2[i] - meanX2) * (px2[i] - meanX2) + (py2[i] - meanY2) * (py2[i] - meanY2);
mag2.AddVector(pVector);
if(i == 0)
hackfix2 = py2[0];
i++;
}
}
py2[0] = hackfix2;
mag2.GetMinAndRange(1, &min, &range);
mag2.Normalize(1, min, range, 0, 1);
// Find the correspondence points
printf(" Finding correspondence points...\n");
int* pCorr1;
int* pCorr2;
int nCorrCount = 0;
{
GArffRelation rel;
rel.AddAttribute(new GArffAttribute(true, 0, NULL));
rel.AddAttribute(new GArffAttribute(false, 0, NULL));
GIntArray points(mag1.GetSize() + mag2.GetSize());
GMorph::GetCorrespondingPoints(&rel, &mag1, &mag2, 1.0 * mag1.GetSize(), &points); // 1.0 is the output to input ratio
pCorr1 = new int[points.GetSize() + 2];
pCorr2 = new int[points.GetSize() + 2];
int min1 = 0;
int min2 = 0;
int j, cor1, cor2;
pCorr1[0] = 0;
pCorr2[0] = 0;
nCorrCount++;
for(i = 0; i < points.GetSize(); i++)
{
j = points.GetInt(i);
cor1 = j / mag2.GetSize();
cor2 = j % mag2.GetSize();
//if(cor1 > min1 + 6 && cor2 > min2 + 6)
{
min1 = cor1;
min2 = cor2;
pCorr1[nCorrCount] = cor1;
pCorr2[nCorrCount] = cor2;
nCorrCount++;
}
}
pCorr1[nCorrCount] = 0;//nCount1 - 1;
pCorr2[nCorrCount] = 0;//nCount2 - 1;
nCorrCount++;
}
Holder<int*> hCorr1(pCorr1);
Holder<int*> hCorr2(pCorr2);
// Compute the interpolation points
printf(" Interpolating...\n");
float* pInterpX = new float[nCorrCount * 2];
ArrayHolder<float*> hInterpX(pInterpX);
float* pInterpY = &pInterpX[nCorrCount];
for(i = 0; i < nCorrCount; i++)
{
pInterpX[i] = ((float)1.0 - fac) * px1[pCorr1[i]] + fac * px2[pCorr2[i]];
pInterpY[i] = ((float)1.0 - fac) * py1[pCorr1[i]] + fac * py2[pCorr2[i]];
}
float fMeanX = ((float)1.0 - fac) * meanX1 + fac * meanX2;
float fMeanY = ((float)1.0 - fac) * meanY1 + fac * meanY2;
// Draw the morphing object
float w0, w1, w2;
for(y = 0; y < pMorphFrame->GetHeight(); y++)
{
for(x = 0; x < pMorphFrame->GetWidth(); x++)
{
for(i = 1; i < nCorrCount; i++)
{
GImage::Compute2DTriangleWeights(&w0, &w1, &w2, (float)x, (float)y, fMeanX, fMeanY,
pInterpX[i - 1], pInterpY[i - 1], pInterpX[i], pInterpY[i]);
if(w0 < 0 || w1 < 0 || w2 < 0)
continue;
c1 = pFrame1->InterpolateWithinTriangle(w0, w1, w2, (float)meanX1, (float)meanY1,
(float)px1[pCorr1[i - 1]], (float)py1[pCorr1[i - 1]], (float)px1[pCorr1[i]], (float)py1[pCorr1[i]]);
c2 = pFrame2->InterpolateWithinTriangle(w0, w1, w2, (float)meanX2, (float)meanY2,
(float)px2[pCorr2[i - 1]], (float)py2[pCorr2[i - 1]], (float)px2[pCorr2[i]], (float)py2[pCorr2[i]]);
pMorphFrame->SetPixel(x, y, BlendColors(c1, c2, fac));
break;
}
}
}
printf(" Saving Frame...\n");
char szTmp[32];
sprintf(szTmp, "%08d.png", z + 1);
pMorphFrame->SavePNGFile(szTmp);
}
chdir("..");
printf("Done...\n");
}
};
// ----------------------------------------------------------------------------
class VideoDialog : public GWidgetDialog
{
friend class VideoController;
protected:
VideoController* m_pController;
GWidgetTextTab** m_pTabs;
GWidgetCanvas* m_pCanvas1;
GWidgetCanvas* m_pCanvas2;
GWidgetHorizScrollBar* m_pScrollBar1;
GWidgetHorizScrollBar* m_pScrollBar2;
VideoTool* m_pCurrentTool;
int m_nFrame1, m_nFrame2;
public:
VideoDialog(VideoController* pController, int w, int h)
: GWidgetDialog(w, h, VIDEO_AREA_BACKGROUND_COLOR)
{
m_pController = pController;
m_pCurrentTool = NULL;
m_pTabs = new GWidgetTextTab*[VIDEO_TAB_COUNT];
m_pTabs[0] = new GWidgetTextTab(this, 0, 0, 50, 20, "Open1", 0xff008800);
m_pTabs[1] = new GWidgetTextTab(this, 50, 0, 50, 20, "Open2", 0xff008800);
m_pTabs[2] = new GWidgetTextTab(this, 100, 0, 50, 20, "Tools", 0xff008800);
m_pTabs[0]->SetSelected(true);
m_pCanvas1 = new GWidgetCanvas(this, 0, 20, w / 2 - 5, h - 36, NULL);
m_pCanvas2 = new GWidgetCanvas(this, w / 2 + 5, 20, w / 2 - 5, h - 36, NULL);
m_pScrollBar1 = new GWidgetHorizScrollBar(this, 0, h - 16, w / 2 - 5, 16, 1, 133); // todo: change 133 to the number of frames
m_pScrollBar2 = new GWidgetHorizScrollBar(this, w / 2 + 5, h - 16, w / 2 - 5, 16, 1, 133); // todo: change 133 to the number of frames
m_nFrame1 = 0;
m_nFrame2 = 0;
}
virtual ~VideoDialog()
{
delete[] m_pTabs;
}
void ChangeFrame1(int nFrame)
{
m_nFrame1 = nFrame;
m_pCanvas1->SetImage(m_pController->GetVideo1() ? m_pController->GetVideo1()->GetFrame(m_nFrame1) : NULL);
m_pCanvas1->SetSelectionMask(m_pController->GetSelection1() ? m_pController->GetSelection1()->GetFrame(m_nFrame1) : NULL);
// m_pCanvas1->GetOutImage()->Clear(VIDEO_AREA_BACKGROUND_COLOR);
}
void ChangeFrame2(int nFrame)
{
m_nFrame2 = nFrame;
m_pCanvas2->SetImage(m_pController->GetVideo2() ? m_pController->GetVideo2()->GetFrame(m_nFrame2) : NULL);
m_pCanvas2->SetSelectionMask(m_pController->GetSelection2() ? m_pController->GetSelection2()->GetFrame(m_nFrame2) : NULL);
// m_pCanvas2->GetOutImage()->Clear(VIDEO_AREA_BACKGROUND_COLOR);
}
void PlayFrame()
{
int i = 0;
if(m_nFrame1 < m_pController->GetVideo1()->GetFrameCount() - 1)
{
ChangeFrame1(m_nFrame1 + 1);
i++;
}
if(m_nFrame2 < m_pController->GetVideo2()->GetFrameCount() - 1)
{
ChangeFrame2(m_nFrame2 + 1);
i++;
}
if(i <= 0)
{
m_pController->Stop();
return;
}
RedrawCanvas();
GThread::sleep(20);
}
void OnScrollWheel(bool bDirection)
{
/*
m_pScrollBar1->SetPos(m_pScrollBar1->GetPos() + (bDirection ? 1 : -1));
m_pScrollBar2->SetPos(m_pScrollBar2->GetPos() + (bDirection ? 1 : -1));
RedrawCanvas();
*/
}
void SetVideo1(GVideo* pVideo, GVideo* pSelection)
{
m_pScrollBar1->SetPos(0);
m_pScrollBar1->SetModelSize(pVideo->GetFrameCount());
m_nFrame1 = 0;
m_pCanvas1->SetImage(pVideo->GetFrame(m_nFrame1));
m_pCanvas1->SetSelectionMask(pSelection ? pSelection->GetFrame(m_nFrame1) : NULL);
m_pCanvas1->ZoomToFit();
}
void SetVideo2(GVideo* pVideo, GVideo* pSelection)
{
m_pScrollBar2->SetPos(0);
m_pScrollBar2->SetModelSize(pVideo->GetFrameCount());
m_nFrame2 = 0;
m_pCanvas2->SetImage(pVideo->GetFrame(m_nFrame2));
m_pCanvas2->SetSelectionMask(pSelection ? pSelection->GetFrame(m_nFrame2) : NULL);
m_pCanvas2->ZoomToFit();
}
virtual void OnSelectTextTab(GWidgetTextTab* pTab)
{
pTab->SetSelected(true);
int i;
for(i = 0; i < VIDEO_TAB_COUNT; i++)
{
if(m_pTabs[i] == pTab)
m_pController->OnSelectTab(i);
else
m_pTabs[i]->SetSelected(false);
}
}
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_pCanvas1->GetOutImage()->Clear(VIDEO_AREA_BACKGROUND_COLOR);
// m_pCanvas2->GetOutImage()->Clear(VIDEO_AREA_BACKGROUND_COLOR);
}
inline void RedrawCanvas()
{
m_pCanvas1->SetDirty();
m_pCanvas2->SetDirty();
}
virtual void OnHorizScroll(GWidgetHorizScrollBar* pScrollBar)
{
if(pScrollBar == m_pScrollBar1)
ChangeFrame1(pScrollBar->GetPos());
else if(pScrollBar == m_pScrollBar2)
ChangeFrame2(pScrollBar->GetPos());
else
GAssert(false, "Unknown scroll bar");
RedrawCanvas();
}
virtual void OnCanvasMouseDown(GWidgetCanvas* pCanvas, int nButton, int x, int y)
{
if(pCanvas == m_pCanvas1)
m_pCurrentTool->OnMouseDown(m_nFrame1, m_pController->GetVideo1(), m_pController->GetSelection1(), nButton, x, y);
else if(pCanvas == m_pCanvas2)
m_pCurrentTool->OnMouseDown(m_nFrame2, m_pController->GetVideo2(), m_pController->GetSelection2(), nButton, x, y);
else
GAssert(false, "unrecognized canvas");
RedrawCanvas();
}
virtual void OnCanvasMouseUp(GWidgetCanvas* pCanvas, int nButton, int x, int y)
{
m_pCurrentTool->OnMouseUp(nButton, x, y);
RedrawCanvas();
}
virtual void OnCanvasMouseMove(GWidgetCanvas* pCanvas, int x, int y, bool bPressed)
{
// if(x < (int)m_pImage->GetWidth() && y < (int)m_pImage->GetHeight())
m_pCurrentTool->OnMouseMove(x, y, bPressed);
if(bPressed)
RedrawCanvas();
}
void SetCurrentTool(VideoTool* pTool)
{
m_pCurrentTool = pTool;
}
};
// ----------------------------------------------------------------------------
class VideoTabDialog : public GWidgetDialog
{
protected:
VideoController* m_pController;
GWidgetImageButton* m_pButtonManual;
public:
VideoTabDialog(VideoController* pController, int w)
: GWidgetDialog(w, TOOL_AREA_SIZE, VIDEO_AREA_BACKGROUND_COLOR)
{
m_pController = pController;
// Make the manual button
GImage* pManualImage = ControllerBase::GetManualImage();
m_pButtonManual = new GWidgetImageButton(this, w - pManualImage->GetWidth() / 2 - 5, 5, pManualImage);
}
virtual ~VideoTabDialog()
{
}
virtual void OnReleaseImageButton(GWidgetImageButton* pButton)
{
if(pButton == m_pButtonManual)
OpenAppFile("../doc/Waffles/Video.html");
else
GAssert(false, "unrecognized image button");
}
};
// ----------------------------------------------------------------------------
class VideoTabOpen1 : public VideoTabDialog
{
protected:
GWidgetFileSystemBrowser* m_pFileSystemBrowser;
public:
VideoTabOpen1(VideoController* pController, int w)
: VideoTabDialog(pController, w)
{
m_pFileSystemBrowser = new GWidgetFileSystemBrowser(this, 0, 0, 500, TOOL_AREA_SIZE, ".png;.bmp;.pgm;.ppm");
}
virtual ~VideoTabOpen1()
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -