#include "StdAfx.h"
|
#include <math.h>
|
#include "CornerCut.h"
|
#include "EdgeProc.h"
|
|
#define CORNERIMAGE_PATEH _T("D:\\Image\\LogCorner")
|
#define USE_ADAPTIVETHRESHOLD 0
|
#define SAVE_IMAGE
|
|
const double g_dRatio = 0.2;
|
const int g_nContiCnt = 2;
|
|
CCornerCut::CCornerCut(void)
|
{
|
ZeroMemory(m_nCornerPoint,sizeof(sCoPoint)*3);
|
m_pInsImg = NULL;
|
|
m_pOuterLineH = m_pOuterLineV = NULL;
|
m_nOuterCountH = m_nOuterCountV = 0;
|
}
|
|
CCornerCut::~CCornerCut(void)
|
{
|
if(m_pInsImg != NULL)
|
delete[] m_pInsImg, m_pInsImg=NULL;
|
if(m_pOuterLineH != NULL)
|
delete[] m_pOuterLineH, m_pOuterLineH=NULL;
|
if(m_pOuterLineV != NULL)
|
delete[] m_pOuterLineV, m_pOuterLineV=NULL;
|
}
|
|
ERRCODE_CORNERCUT CCornerCut::Inspection(LPBYTE pImg,CSize szImg,CRect &rectIns,int iFrame,int nLowThres,int nHighThres,CORNERCUR_DIR nDir, CString strHPanelID,BOOL bSaveImage
|
,COwnerBuffer &pOrg,double &dResWidth,double &dResHeight)
|
{
|
|
ZeroMemory(m_nCornerPoint,sizeof(CPoint)*3);
|
dResWidth = dResHeight = 0.;
|
|
if(pImg == NULL)
|
{
|
return ERR_CO_IMAGENULL;
|
}
|
|
pOrg.SetSize(szImg.cx,szImg.cy);
|
CopyMemory(pOrg.GetDataAddress(),pImg,pOrg.GetDataSize());
|
|
AssertOnFrameRect(rectIns,szImg);
|
if(rectIns.Width()*rectIns.Height() <= 0)
|
{
|
return ERR_CO_INSRECTNULL;
|
}
|
|
if(bSaveImage == TRUE)
|
{
|
CreateDirectory(CORNERIMAGE_PATEH,NULL);
|
|
CString strFile;
|
CSISBuffer mosis1(pImg, rectIns.Width(), rectIns.Height());
|
strFile.Format(_T("%s\\%s_OrgImg_%d.bmp"),CORNERIMAGE_PATEH,strHPanelID, iFrame);
|
CBufferAttach attch1(strFile);
|
if(mosis1.IsValidBuffer() == TRUE)
|
attch1.AttachToFile(mosis1);
|
|
/*CHMBitmap BmpSave;
|
CString strFile;
|
if(rectIns.Width() > 0 && rectIns.Height() > 0)
|
{
|
BmpSave.SetBitmap(pImg, rectIns.Width(), rectIns.Height());
|
strFile.Format("%s\\%s_OrgImg_%d.bmp",CORNERIMAGE_PATEH,strHPanelID, iFrame);
|
LPBYTE pBuffer = BmpSave.GetBuffer();
|
if(pBuffer != NULL)
|
BmpSave.SaveBitmapFile(strFile);
|
}*/
|
}
|
|
CSISBuffer pBuf(pImg,szImg.cx,szImg.cy);
|
ThresholdProcLowHigh(pBuf,nLowThres,nHighThres);
|
|
//CEdgeProc EdgeProc;
|
|
//EdgeProc.ThresholdByIntegralImage(pImg,szImg.cx,szImg.cy,szImg.cx,10,pImg);
|
|
//EdgeProc.Adaptive_Binarization(pImg,szImg.cx,szImg.cy,szImg.cx,10,0.2,pImg,rectIns);
|
|
|
if(bSaveImage == TRUE)
|
{
|
CSISBuffer mosis2(pImg, rectIns.Width(), rectIns.Height());
|
CString strFile;
|
strFile.Format(_T("%s\\%s_ThresImg_%d.bmp"),CORNERIMAGE_PATEH,strHPanelID, iFrame);
|
CBufferAttach attch2(strFile);
|
if(mosis2.IsValidBuffer() == TRUE)
|
attch2.AttachToFile(mosis2);
|
|
/*CHMBitmap BmpSave2;
|
if(rectIns.Width() > 0 && rectIns.Height() > 0)
|
{
|
BmpSave2.SetBitmap(pImg, rectIns.Width(), rectIns.Height());
|
strFile.Format("%s\\%s_ThresImg_%d.bmp",CORNERIMAGE_PATEH,strHPanelID, iFrame);
|
LPBYTE pBuffer = BmpSave2.GetBuffer();
|
if(pBuffer != NULL)
|
BmpSave2.SaveBitmapFile(strFile);
|
}*/
|
}
|
|
int nVertLine,nHorLine;
|
|
if(FindVerticalLine(pImg,rectIns,nVertLine,nDir) == FALSE)
|
{
|
return ERR_CO_FINDVERT;
|
}
|
|
if(FindHorizontalLine(pImg,rectIns,nHorLine,nDir) == FALSE)
|
{
|
return ERR_CO_FINDHOR;
|
}
|
|
m_nCornerPoint[0].x = nVertLine;
|
m_nCornerPoint[0].y = nHorLine;
|
|
FindCornerPoint(pImg,rectIns,m_nCornerPoint[0],nDir);
|
|
FindOuterLine(pImg,rectIns,nDir);
|
|
if(m_nOuterCountH >= 20 && m_nOuterCountV >= 20)
|
{
|
FindFirstPoint(rectIns);
|
}
|
|
CalculateLenght(dResWidth,dResHeight);
|
|
if(m_pOuterLineH != NULL)
|
delete[] m_pOuterLineH, m_pOuterLineH=NULL;
|
if(m_pOuterLineV != NULL)
|
delete[] m_pOuterLineV, m_pOuterLineV=NULL;
|
|
|
if(pOrg.IsValidBuffer() == TRUE)
|
{
|
CPoint pointDraw[3];
|
|
pointDraw[0] = CPoint((int)m_nCornerPoint[0].x,(int)m_nCornerPoint[0].y);
|
pointDraw[1] = CPoint((int)m_nCornerPoint[1].x,(int)m_nCornerPoint[1].y);
|
pointDraw[2] = CPoint((int)m_nCornerPoint[2].x,(int)m_nCornerPoint[2].y);
|
|
bresenham_Line(&pOrg,pointDraw[0],pointDraw[1],0);
|
bresenham_Line(&pOrg,pointDraw[2],pointDraw[0],0);
|
|
SaveMarkImage(pOrg.GetDataAddress(0,0),rectIns);
|
|
// LPBYTE pBuffer = pOrg.GetDataAddress(0,0);
|
// if(pBuffer != NULL)
|
// {
|
// //SaveMarkImage(pBuffer,rectIns);
|
// }
|
}
|
|
|
return ERR_CO_SUCCESS;
|
}
|
|
void CCornerCut::SaveMarkImage(LPBYTE pBuffer,CRect &rectIns)
|
{
|
int nStartH,nStartV,nEndH,nEndV,x,y;
|
int nDiv = 5,nBright = 128;
|
|
// 0 Position
|
nStartH = (int)m_nCornerPoint[0].x-nDiv;
|
nEndH = (int)m_nCornerPoint[0].x+nDiv;
|
if(nStartH < 0) nStartH = 0;
|
if(nEndH >= rectIns.Width()) nEndH = rectIns.Width()-1;
|
y=(int)m_nCornerPoint[0].y;
|
for(x=nStartH;x<=nEndH;x++)
|
pBuffer[y*rectIns.Width()+x] = nBright;
|
|
nStartV = (int)m_nCornerPoint[0].y-nDiv;
|
nEndV = (int)m_nCornerPoint[0].y+nDiv;
|
if(nStartV < 0) nStartV = 0;
|
if(nEndV >= rectIns.Height()) nEndV = rectIns.Height()-1;
|
x=(int)m_nCornerPoint[0].x;
|
for(y=nStartV;y<=nEndV;y++)
|
pBuffer[y*rectIns.Width()+x] = nBright;
|
|
// 1 Position
|
nStartH = (int)m_nCornerPoint[1].x-nDiv;
|
nEndH = (int)m_nCornerPoint[1].x+nDiv;
|
if(nStartH < 0) nStartH = 0;
|
if(nEndH >= rectIns.Width()) nEndH = rectIns.Width()-1;
|
y=(int)m_nCornerPoint[1].y;
|
for(x=nStartH;x<=nEndH;x++)
|
pBuffer[y*rectIns.Width()+x] = nBright;
|
|
nStartV = (int)m_nCornerPoint[1].y-nDiv;
|
nEndV = (int)m_nCornerPoint[1].y+nDiv;
|
if(nStartV < 0) nStartV = 0;
|
if(nEndV >= rectIns.Height()) nEndV = rectIns.Height()-1;
|
x=(int)m_nCornerPoint[1].x;
|
for(y=nStartV;y<=nEndV;y++)
|
pBuffer[y*rectIns.Width()+x] = nBright;
|
|
// 2 Position
|
nStartH = (int)m_nCornerPoint[2].x-nDiv;
|
nEndH = (int)m_nCornerPoint[2].x+nDiv;
|
if(nStartH < 0) nStartH = 0;
|
if(nEndH >= rectIns.Width()) nEndH = rectIns.Width()-1;
|
y=(int)m_nCornerPoint[2].y;
|
for(x=nStartH;x<=nEndH;x++)
|
pBuffer[y*rectIns.Width()+x] = nBright;
|
|
nStartV = (int)m_nCornerPoint[2].y-nDiv;
|
nEndV = (int)m_nCornerPoint[2].y+nDiv;
|
if(nStartV < 0) nStartV = 0;
|
if(nEndV >= rectIns.Height()) nEndV = rectIns.Height()-1;
|
x=(int)m_nCornerPoint[2].x;
|
for(y=nStartV;y<=nEndV;y++)
|
pBuffer[y*rectIns.Width()+x] = nBright;
|
}
|
|
void CCornerCut::CalculateLenght(double &dResWidth,double &dResHeight)
|
{
|
dResWidth = sqrt(pow((m_nCornerPoint[0].x-m_nCornerPoint[1].x),2)+pow((m_nCornerPoint[0].y-m_nCornerPoint[1].y),2));
|
dResHeight = sqrt(pow((m_nCornerPoint[0].x-m_nCornerPoint[2].x),2)+pow((m_nCornerPoint[0].y-m_nCornerPoint[2].y),2));
|
|
// dResWidth = fabs(m_nCornerPoint[1].x-m_nCornerPoint[2].x)+1;
|
// dResHeight = fabs(m_nCornerPoint[1].y-m_nCornerPoint[2].y)+1;
|
}
|
|
BOOL CCornerCut::FindOuterHori(LPBYTE pImg,CRect rectIns,double nYPos,double nStartX,CORNERCUR_DIR nDir)
|
{
|
const int nMargin = 5;
|
BOOL bReverse = FALSE;
|
int nStartY,nEndY;
|
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_RT:
|
nStartY = (int)nYPos-nMargin;
|
nEndY = (int)nYPos+nMargin;
|
if(nStartY < 0) nStartY = 0;
|
if(nEndY >= rectIns.Height()) nEndY = rectIns.Height()-1;
|
break;
|
case CO_LB:
|
case CO_RB:
|
bReverse = TRUE;
|
nStartY = (int)nYPos+nMargin;
|
nEndY = (int)nYPos-nMargin;
|
if(nEndY < 0) nEndY = 0;
|
if(nStartY >= rectIns.Height()) nStartY = rectIns.Height()-1;
|
break;
|
}
|
|
if(nStartX < 0) nStartX = 0;
|
|
int iX,iY;
|
if(bReverse == FALSE)
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_LB:
|
for(iX=(int)nStartX;iX<rectIns.Width();iX++)
|
{
|
for(iY=nStartY;iY<=nEndY;iY++)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineH[m_nOuterCountH].x = iX;
|
m_pOuterLineH[m_nOuterCountH].y = iY;
|
m_nOuterCountH++;
|
break;
|
}
|
}
|
}
|
break;
|
case CO_RT:
|
case CO_RB:
|
for(iX=0;iX<(int)nStartX;iX++)
|
{
|
for(iY=nStartY;iY<=nEndY;iY++)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineH[m_nOuterCountH].x = iX;
|
m_pOuterLineH[m_nOuterCountH].y = iY;
|
m_nOuterCountH++;
|
break;
|
}
|
}
|
}
|
break;
|
}
|
}
|
else
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_LB:
|
for(iX=(int)nStartX;iX<rectIns.Width();iX++)
|
{
|
for(iY=nStartY;iY>=nEndY;iY--)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineH[m_nOuterCountH].x = iX;
|
m_pOuterLineH[m_nOuterCountH].y = iY;
|
m_nOuterCountH++;
|
break;
|
}
|
}
|
}
|
break;
|
case CO_RT:
|
case CO_RB:
|
for(iX=0;iX<(int)nStartX;iX++)
|
{
|
for(iY=nStartY;iY>=nEndY;iY--)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineH[m_nOuterCountH].x = iX;
|
m_pOuterLineH[m_nOuterCountH].y = iY;
|
m_nOuterCountH++;
|
break;
|
}
|
}
|
}
|
break;
|
}
|
}
|
|
return TRUE;
|
}
|
|
BOOL CCornerCut::FindOuterVert(LPBYTE pImg,CRect rectIns,double nYPos,double nXPos,CORNERCUR_DIR nDir)
|
{
|
const int nMargin = 5;
|
BOOL bReverse = FALSE;
|
int nStartX,nEndX;
|
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_LB:
|
nStartX = (int)nXPos-nMargin;
|
nEndX = (int)nXPos+nMargin;
|
if(nStartX < 0) nStartX = 0;
|
if(nEndX >= rectIns.Width()) nEndX = rectIns.Width()-1;
|
break;
|
case CO_RT:
|
case CO_RB:
|
bReverse = TRUE;
|
nStartX = (int)nXPos+nMargin;
|
nEndX = (int)nXPos-nMargin;
|
if(nEndX < 0) nEndX = 0;
|
if(nStartX >= rectIns.Width()) nStartX = rectIns.Width()-1;
|
break;
|
}
|
|
if(nYPos < 0) nYPos = 0;
|
|
int iX,iY;
|
if(bReverse == FALSE)
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_RT:
|
for(iY=(int)nYPos;iY<rectIns.Height();iY++)
|
{
|
for(iX=nStartX;iX<=nEndX;iX++)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineV[m_nOuterCountV].x = iX;
|
m_pOuterLineV[m_nOuterCountV].y = iY;
|
m_nOuterCountV++;
|
break;
|
}
|
}
|
}
|
break;
|
case CO_LB:
|
case CO_RB:
|
for(iY=0;iY<(int)nYPos;iY++)
|
{
|
for(iX=nStartX;iX<=nEndX;iX++)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineV[m_nOuterCountV].x = iX;
|
m_pOuterLineV[m_nOuterCountV].y = iY;
|
m_nOuterCountV++;
|
break;
|
}
|
}
|
}
|
break;
|
}
|
}
|
else
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_RT:
|
for(iY=(int)nYPos;iY<rectIns.Height();iY++)
|
{
|
for(iX=nStartX;iX>=nEndX;iX--)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineV[m_nOuterCountV].x = iX;
|
m_pOuterLineV[m_nOuterCountV].y = iY;
|
m_nOuterCountV++;
|
break;
|
}
|
}
|
}
|
break;
|
case CO_LB:
|
case CO_RB:
|
for(iY=0;iY<(int)nYPos;iY++)
|
{
|
for(iX=nStartX;iX>=nEndX;iX--)
|
{
|
if(pImg[iY*rectIns.Width()+iX] == 255)
|
{
|
m_pOuterLineV[m_nOuterCountV].x = iX;
|
m_pOuterLineV[m_nOuterCountV].y = iY;
|
m_nOuterCountV++;
|
break;
|
}
|
}
|
}
|
break;
|
}
|
}
|
|
return TRUE;
|
}
|
|
BOOL CCornerCut::FindOuterLine(LPBYTE pImg,CRect rectIns,CORNERCUR_DIR nDir)
|
{
|
if(m_pOuterLineH != NULL)
|
delete[] m_pOuterLineH, m_pOuterLineH=NULL;
|
if(m_pOuterLineV != NULL)
|
delete[] m_pOuterLineV, m_pOuterLineV=NULL;
|
m_nOuterCountH = m_nOuterCountV = 0;
|
|
if(pImg == NULL || rectIns.Width()*rectIns.Height() <= 0)
|
return FALSE;
|
|
m_pOuterLineH = new sCoPoint[rectIns.Width()+1];
|
m_pOuterLineV = new sCoPoint[rectIns.Height()+1];
|
|
FindOuterHori(pImg,rectIns,m_nCornerPoint[1].y,m_nCornerPoint[1].x,nDir);
|
|
FindOuterVert(pImg,rectIns,m_nCornerPoint[2].y,m_nCornerPoint[2].x,nDir);
|
|
return TRUE;
|
}
|
|
BOOL CCornerCut::FindCornerPoint(LPBYTE pImg,CRect rectIns,sCoPoint point,CORNERCUR_DIR nDir)
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
DetectLine(pImg,rectIns,point,TRUE,FALSE,nDir,m_nCornerPoint[1]);
|
DetectLine(pImg,rectIns,point,FALSE,FALSE,nDir,m_nCornerPoint[2]);
|
break;
|
case CO_LB:
|
DetectLine(pImg,rectIns,point,TRUE,FALSE,nDir,m_nCornerPoint[1]);
|
DetectLine(pImg,rectIns,point,FALSE,TRUE,nDir,m_nCornerPoint[2]);
|
break;
|
case CO_RT:
|
DetectLine(pImg,rectIns,point,TRUE,TRUE,nDir,m_nCornerPoint[1]);
|
DetectLine(pImg,rectIns,point,FALSE,FALSE,nDir,m_nCornerPoint[2]);
|
break;
|
case CO_RB:
|
DetectLine(pImg,rectIns,point,TRUE,TRUE,nDir,m_nCornerPoint[1]);
|
DetectLine(pImg,rectIns,point,FALSE,TRUE,nDir,m_nCornerPoint[2]);
|
break;
|
}
|
|
return TRUE;
|
}
|
|
int CCornerCut::GetVertCount(LPBYTE pImg,int u,sCoPoint point,BOOL bDir,int nWidth,int nHeight,int nSetCount)
|
{
|
int nDetLine = -1;
|
int nCount = 0;
|
int v;
|
|
if(bDir == FALSE)
|
{
|
for(v=(int)point.y;v<nHeight;v++)
|
{
|
if(*(pImg+v*nWidth+u) == 255)
|
nCount++;
|
else
|
nCount = 0;
|
if(nCount >= nSetCount)
|
{
|
nDetLine = v-nCount;
|
break;
|
}
|
}
|
}
|
else
|
{
|
for(v=(int)point.y;v>=0;v--)
|
{
|
if(*(pImg+v*nWidth+u) == 255)
|
nCount++;
|
else
|
nCount = 0;
|
if(nCount >= nSetCount)
|
{
|
nDetLine = v+nCount;
|
break;
|
}
|
}
|
}
|
|
return nDetLine;
|
}
|
|
int CCornerCut::GetHorCount(LPBYTE pImg,int v,sCoPoint point,BOOL bDir,int nWidth,int nSetCount)
|
{
|
int nDetLine = -1;
|
int nCount = 0;
|
int u;
|
|
if(bDir == FALSE)
|
{
|
for(u=(int)point.x;u<nWidth;u++)
|
{
|
if(*(pImg+v*nWidth+u) == 255)
|
nCount++;
|
else
|
nCount = 0;
|
if(nCount >= nSetCount)
|
{
|
nDetLine = u-nCount;
|
break;
|
}
|
}
|
}
|
else
|
{
|
for(u=(int)point.x;u>=0;u--)
|
{
|
if(*(pImg+v*nWidth+u) == 255)
|
nCount++;
|
else
|
nCount = 0;
|
if(nCount >= nSetCount)
|
{
|
nDetLine = u+nCount;
|
break;
|
}
|
}
|
}
|
|
|
return nDetLine;
|
}
|
|
void CCornerCut::GetRegionInfo(sCoPoint point,CORNERCUR_DIR nDir,BOOL bDir,int &nStart,int &nEnd,BOOL &bReverse,int nWidth,int nHeight)
|
{
|
int nSize = g_nContiCnt*2;
|
bReverse = FALSE;
|
if(bDir == TRUE) // Horizontal
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_RT:
|
nStart = (int)point.y-nSize*2;
|
nEnd = (int)point.y+nSize;
|
break;
|
case CO_LB:
|
case CO_RB:
|
bReverse = TRUE;
|
nStart = (int)point.y-nSize;
|
nEnd = (int)point.y+nSize*2;
|
break;
|
}
|
if(nStart < 0)
|
nStart = 0;
|
if(nEnd >= nHeight)
|
nEnd = nHeight-1;
|
}
|
else
|
{
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_LB:
|
nStart = (int)point.x-nSize*2;
|
nEnd = (int)point.x+nSize;
|
break;
|
case CO_RT:
|
case CO_RB:
|
bReverse = TRUE;
|
nStart = (int)point.x-nSize;
|
nEnd = (int)point.x+nSize*2;
|
break;
|
}
|
if(nStart < 0)
|
nStart = 0;
|
if(nEnd >= nWidth)
|
nEnd = nWidth-1;
|
}
|
}
|
|
int CCornerCut::DetectLine(LPBYTE pImg,CRect rectIns,sCoPoint point,BOOL bDir,BOOL bReverse,CORNERCUR_DIR nDir,sCoPoint &pointResult)
|
{
|
int nWidth = rectIns.Width();
|
int nHeight = rectIns.Height();
|
int u,v;
|
int nCount;
|
const int nSetCount = 2;
|
const int nSetDet = 8;
|
int nStart,nEnd,nDetPos,iLoop;
|
BOOL bConvert;
|
CPoint pointDet,pointFirst;
|
CArray<CPoint,CPoint> nPos;
|
|
|
nCount = 0;
|
GetRegionInfo(point,nDir,bDir,nStart,nEnd,bConvert,nWidth,nHeight);
|
|
if(bDir == TRUE) // Horizontal
|
{
|
if(nStart > nEnd) swapN(nStart,nEnd);
|
if(bConvert == FALSE)
|
{
|
for(v=nEnd;v>=nStart;v--)
|
{
|
nDetPos = GetHorCount(pImg,v,point,bReverse,nWidth,nSetCount);
|
nPos.Add(CPoint(nDetPos,v));
|
}
|
}
|
else
|
{
|
for(v=nStart;v<nEnd;v++)
|
{
|
nDetPos = GetHorCount(pImg,v,point,bReverse,nWidth,nSetCount);
|
nPos.Add(CPoint(nDetPos,v));
|
}
|
}
|
|
for(iLoop=0;iLoop<nPos.GetCount();iLoop++)
|
{
|
pointDet = nPos.GetAt(iLoop);
|
if(iLoop == 0)
|
{
|
pointFirst = pointDet;
|
continue;
|
}
|
if(abs(pointDet.x-pointFirst.x) >= nSetDet)
|
{
|
pointResult.x = pointFirst.x;
|
pointResult.y = pointFirst.y;
|
break;
|
}
|
pointFirst = pointDet;
|
}
|
}
|
else
|
{
|
if(nStart > nEnd) swapN(nStart,nEnd);
|
if(bConvert == FALSE)
|
{
|
for(u=nEnd;u>=nStart;u--)
|
{
|
nDetPos = GetVertCount(pImg,u,point,bReverse,nWidth,nHeight,nSetCount);
|
nPos.Add(CPoint(u,nDetPos));
|
}
|
}
|
else
|
{
|
for(u=nStart;u<nEnd;u++)
|
{
|
nDetPos = GetVertCount(pImg,u,point,bReverse,nWidth,nHeight,nSetCount);
|
nPos.Add(CPoint(u,nDetPos));
|
}
|
}
|
|
for(iLoop=0;iLoop<nPos.GetCount();iLoop++)
|
{
|
pointDet = nPos.GetAt(iLoop);
|
if(iLoop == 0)
|
{
|
pointFirst = pointDet;
|
continue;
|
}
|
if(abs(pointDet.y-pointFirst.y) >= nSetDet)
|
{
|
pointResult.x = pointFirst.x;
|
pointResult.y = pointFirst.y;
|
break;
|
}
|
pointFirst = pointDet;
|
}
|
}
|
|
return 0;
|
}
|
|
BOOL CCornerCut::FindHorizontalLine(LPBYTE pImg,CRect rectIns,int &nHorLine,CORNERCUR_DIR nDir)
|
{
|
if(rectIns.Height() <= 0)
|
return FALSE;
|
|
nHorLine = -1;
|
|
int *pPoint;
|
int u,v;
|
int nMax,nLevel;
|
int nWidth = rectIns.Width();
|
int nHeight = rectIns.Height();
|
int nCount;
|
|
//////////////////////////////////////////////////////////////////////////
|
// vertical
|
pPoint = new int[nHeight];
|
ZeroMemory(pPoint,sizeof(int)*nHeight);
|
|
nMax = INT_MIN;
|
for(v=0;v<nHeight;v++)
|
{
|
for(u=0;u<nWidth;u++)
|
{
|
if(*(pImg+v*nWidth+u) == 255)
|
pPoint[v]++;
|
}
|
if(nMax < pPoint[v]) nMax = pPoint[v];
|
}
|
nLevel = (int)((double)nMax * g_dRatio);
|
|
nCount = 0;
|
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_RT:
|
for(v=0;v<nHeight;v++)
|
{
|
if(pPoint[v] >= nLevel)
|
nCount++;
|
else
|
nCount = 0;
|
|
if(nCount >= g_nContiCnt)
|
{
|
nHorLine = v-nCount;
|
break;
|
}
|
}
|
break;
|
case CO_LB:
|
case CO_RB:
|
for(v=nHeight-1;v>=0;v--)
|
{
|
if(pPoint[v] >= nLevel)
|
nCount++;
|
else
|
nCount = 0;
|
|
if(nCount >= g_nContiCnt)
|
{
|
nHorLine = v+nCount;
|
break;
|
}
|
}
|
break;
|
}
|
|
delete[] pPoint, pPoint=NULL;
|
|
return TRUE;
|
}
|
|
BOOL CCornerCut::FindVerticalLine(LPBYTE pImg,CRect rectIns,int &nVertLine,CORNERCUR_DIR nDir)
|
{
|
if(rectIns.Width() <= 0)
|
return FALSE;
|
|
nVertLine = -1;
|
|
int *pPoint;
|
int u,v;
|
int nMax,nLevel;
|
int nWidth = rectIns.Width();
|
int nHeight = rectIns.Height();
|
int nCount;
|
|
//////////////////////////////////////////////////////////////////////////
|
// vertical
|
pPoint = new int[nWidth];
|
ZeroMemory(pPoint,sizeof(int)*nWidth);
|
|
nMax = INT_MIN;
|
for(u=0;u<nWidth;u++)
|
{
|
for(v=0;v<nHeight;v++)
|
{
|
if(*(pImg+v*nWidth+u) == 255)
|
pPoint[u]++;
|
}
|
if(nMax < pPoint[u]) nMax = pPoint[u];
|
}
|
nLevel = (int)((double)nMax * g_dRatio);
|
|
nCount = 0;
|
|
switch(nDir)
|
{
|
case CO_LT:
|
case CO_LB:
|
for(u=0;u<nWidth;u++)
|
{
|
if(pPoint[u] >= nLevel)
|
nCount++;
|
else
|
nCount = 0;
|
|
if(nCount >= g_nContiCnt)
|
{
|
nVertLine = u-nCount;
|
break;
|
}
|
}
|
break;
|
case CO_RT:
|
case CO_RB:
|
for(u=nWidth-1;u>=0;u--)
|
{
|
if(pPoint[u] >= nLevel)
|
nCount++;
|
else
|
nCount = 0;
|
|
if(nCount >= g_nContiCnt)
|
{
|
nVertLine = u+nCount;
|
break;
|
}
|
}
|
break;
|
}
|
|
delete[] pPoint, pPoint=NULL;
|
|
return TRUE;
|
}
|
|
BOOL CCornerCut::CopyEdgeImg(LPBYTE pImg,CSize szImg,CRect &rectIns)
|
{
|
if(m_pInsImg != NULL)
|
delete[] m_pInsImg, m_pInsImg = NULL;
|
m_pInsImg = new BYTE[rectIns.Width()*(rectIns.Height()+1)];
|
ZeroMemory(m_pInsImg,sizeof(BYTE)*rectIns.Width()*(rectIns.Height()+1));
|
|
int v;
|
int dv = 0;
|
|
for(v=rectIns.top;v<rectIns.bottom;v++,dv++)
|
{
|
CopyMemory(m_pInsImg+dv*rectIns.Width(),pImg+v*szImg.cx+rectIns.left,rectIns.Width());
|
}
|
|
return TRUE;
|
}
|
|
void CCornerCut::AssertOnFrameRect(CRect &rect,CSize szImg)
|
{
|
if(rect.left < 0) rect.left = 0;
|
if(rect.left > szImg.cx) rect.left = szImg.cx-1;
|
if(rect.right < 0) rect.right = 0;
|
if(rect.right > szImg.cx) rect.right = szImg.cx-1;
|
if(rect.left > rect.right) swapN(rect.left,rect.right);
|
if(rect.top < 0) rect.top = 0;
|
if(rect.top > szImg.cy) rect.top = szImg.cy-1;
|
if(rect.bottom < 0) rect.bottom = 0;
|
if(rect.bottom > szImg.cy) rect.bottom = szImg.cy-1;
|
if(rect.top > rect.bottom) swapN(rect.top,rect.bottom);
|
}
|
|
float CCornerCut::AdaptiveThreshold(BYTE* pImageData, int nWidth, int nHeight, int nStep, int nThresValue)
|
{
|
if (pImageData==NULL) return 0;
|
|
float fThresValue =(float) nThresValue;
|
float fNewThresValue = 0;
|
|
for (int i=0; i<1000; i++)
|
{
|
fNewThresValue = GetThresholdValue(pImageData, nWidth, nHeight, nStep, (int)fThresValue);
|
|
if (fNewThresValue==fThresValue) break;
|
|
fThresValue = fNewThresValue;
|
}
|
|
return fNewThresValue;
|
}
|
|
float CCornerCut::GetThresholdValue(BYTE* pImageData, int nWidth, int nHeight, int nStep, int nThresValue)
|
{
|
if (pImageData==NULL) return 0;
|
|
ULONG fore = 0;
|
int fore_cnt = 0;
|
ULONG back = 0;
|
int back_cnt = 0;
|
|
int nIndex;
|
for (int i=0; i<nHeight; i++)
|
{
|
for (int j=0; j<nWidth; j++)
|
{
|
nIndex = (i*nStep)+j;
|
|
if (pImageData[nIndex]==0) continue;
|
|
if (pImageData[nIndex] > nThresValue)
|
{
|
fore += pImageData[nIndex];
|
fore_cnt++;
|
}
|
else
|
{
|
back += pImageData[nIndex];
|
back_cnt++;
|
}
|
}
|
}
|
|
float fore_avg = 0.0f;
|
if (fore_cnt!=0) fore_avg = float(fore) / float(fore_cnt);
|
|
float back_avg = 0.0f;
|
if (back_cnt!=0) back_avg = float(back) / float(back_cnt);
|
|
if (fore_cnt==0 || back_cnt==0)
|
{
|
if (nThresValue>=128)
|
return float(nThresValue)/2.0f;
|
else
|
return float(nThresValue)*2.0f;
|
}
|
|
return (fore_avg+back_avg)/2.0f;
|
}
|
|
void CCornerCut::ThresholdProcLowHigh(CSISBuffer &pImg,int nLowThres,int nHighThres)
|
{
|
LPBYTE pBuf = pImg.GetDataAddress();
|
for (int i=0; i<pImg.GetDataSize(); i++,pBuf++)
|
{
|
if(*pBuf <= nLowThres || *pBuf >= nHighThres)
|
*pBuf = 255;
|
else
|
*pBuf = 0;
|
}
|
}
|
|
void CCornerCut::ThresholdProcessing(LPBYTE pImg,CSize szImg,int nThres,int nDir)
|
{
|
|
float fNewThresValue = float(nThres);
|
|
// threshold and invert
|
int nIndex;
|
int nFinThres = (int)(fNewThresValue);
|
for (int i=0; i<szImg.cy; i++)
|
{
|
for (int j=0; j<szImg.cx; j++)
|
{
|
nIndex = (i*szImg.cx)+j;
|
if(nDir == 1)
|
{
|
if (pImg[nIndex] > nFinThres)
|
{
|
pImg[nIndex] = 255;
|
}
|
else
|
{
|
pImg[nIndex] = 0;
|
}
|
}
|
else
|
{
|
if (pImg[nIndex] < nFinThres)
|
{
|
pImg[nIndex] = 255;
|
}
|
else
|
{
|
pImg[nIndex] = 0;
|
}
|
}
|
}
|
}
|
}
|
|
// ·Î¹öÆ®ÆÐ³ÊÀÇ ±³Â÷Á¡ ±¸Çϱâ¶ó´Âµ¥..
|
BOOL CCornerCut::LineInterSection(CPoint p1,CPoint p2,CPoint p3,CPoint p4,double &dInterX,double &dInterY)
|
{
|
double x1 = p1.x;
|
double y1 = p1.y;
|
double x4 = p4.x;
|
double y4 = p4.y;
|
|
dInterX = dInterY = 0.;
|
|
double dx1 = p2.x - x1;
|
double dx2 = p3.x - x4;
|
if (!(dx1 || dx2)) return FALSE;
|
|
double m1 = (p2.y - y1) / dx1;
|
double m2 = (p3.y - y4) / dx2;
|
|
if (!dx1)
|
{
|
// infinity
|
dInterX = x1;
|
dInterY = m2 * (x1 - x4) + y4;
|
return FALSE;
|
}
|
else if (!dx2)
|
{
|
// infinity
|
dInterX = x4;
|
dInterY = m1 * (x4 - x1) + y1;
|
return FALSE;
|
}
|
|
dInterX = (-m2 * x4 + y4 + m1 * x1 - y1) / (m1 - m2);
|
dInterY = m1 * (dInterX - x1) + y1;
|
|
return TRUE;
|
}
|
|
BOOL CCornerCut::FindFirstPoint(CRect &rectIns)
|
{
|
CPoint HPoint[2],VPoint[2];
|
int iLoop;
|
int nSetCount = 10;
|
int nSumF,nSumS;
|
double dslope,dAvgF,dAvgS;
|
|
nSumF = nSumS = 0;
|
for(iLoop=0;iLoop<nSetCount;iLoop++)
|
nSumF += (int)m_pOuterLineH[iLoop].y;
|
|
for(iLoop=m_nOuterCountH-nSetCount;iLoop<m_nOuterCountH;iLoop++)
|
nSumS += (int)m_pOuterLineH[iLoop].y;
|
|
dAvgF = (double)nSumF/(double)nSetCount;
|
dAvgS = (double)nSumS/(double)nSetCount;
|
dslope = (dAvgS-dAvgF)/(double)rectIns.Width();
|
|
HPoint[0].x = 0;
|
HPoint[0].y = (int)dAvgF;
|
HPoint[1].x = rectIns.right;
|
HPoint[1].y = (int)dAvgS;
|
|
|
nSumF = nSumS = 0;
|
for(iLoop=0;iLoop<nSetCount;iLoop++)
|
nSumF += (int)m_pOuterLineV[iLoop].x;
|
|
for(iLoop=m_nOuterCountV-nSetCount;iLoop<m_nOuterCountV;iLoop++)
|
nSumS += (int)m_pOuterLineV[iLoop].x;
|
|
dAvgF = (double)nSumF/(double)nSetCount;
|
dAvgS = (double)nSumS/(double)nSetCount;
|
dslope = (dAvgS-dAvgF)/(double)rectIns.Height();
|
|
VPoint[0].x = (int)dAvgF;
|
VPoint[0].y = 0;
|
VPoint[1].x = (int)dAvgS;
|
VPoint[1].y = rectIns.bottom;
|
|
double interX=0,interY=0;
|
if(LineInterSection(HPoint[0],HPoint[1],VPoint[0],VPoint[1],interX,interY) == TRUE)
|
{
|
m_nCornerPoint[0].x = interX;
|
m_nCornerPoint[0].y = interY;
|
}
|
|
/*
|
sCoLine lineH,lineV;
|
double costH = ransac_line_fitting (m_pOuterLineH, m_nOuterCountH, lineH, 10);
|
double costV = ransac_line_fitting (m_pOuterLineV, m_nOuterCountV, lineV, 10);
|
|
if (100. < costH && 100. < costV)
|
{
|
HPoint[0].x = 0;
|
HPoint[0].y = (int)(lineH.sy-(double)rectIns.Height()*lineH.my);
|
HPoint[1].x = rectIns.right;
|
HPoint[1].y = (int)(lineH.sy+(double)rectIns.Height()*lineH.my);
|
|
VPoint[0].x = (int)(lineV.sx-(double)rectIns.Width()*lineV.mx);
|
VPoint[0].y = 0;
|
VPoint[1].x = (int)(lineV.sx+(double)rectIns.Width()*lineV.mx);
|
VPoint[1].y = rectIns.bottom;
|
}*/
|
|
return TRUE;
|
}
|
|
double CCornerCut::ransac_line_fitting(sCoPoint *data, int no_data, sCoLine &model, double distance_threshold)
|
{
|
const int no_samples = 2;
|
|
if (no_data < no_samples) {
|
return 0.;
|
}
|
|
sCoPoint *samples = new sCoPoint[no_samples];
|
|
int no_inliers = 0;
|
sCoPoint *inliers = new sCoPoint[no_data];
|
|
sCoLine estimated_model;
|
double max_cost = 0.;
|
|
int max_iteration = (int)(1 + log(1. - 0.99)/log(1. - pow(0.5, no_samples)));
|
|
for (int i = 0; i<max_iteration; i++) {
|
// 1. hypothesis
|
|
// ¿øº» µ¥ÀÌÅÍ¿¡¼ ÀÓÀÇ·Î N°³ÀÇ ¼ÀÇà µ¥ÀÌÅ͸¦ °í¸¥´Ù.
|
get_samples (samples, no_samples, data, no_data);
|
|
// ÀÌ µ¥ÀÌÅ͸¦ Á¤»óÀûÀÎ µ¥ÀÌÅÍ·Î º¸°í ¸ðµ¨ ÆÄ¶ó¸ÞÅ͸¦ ¿¹ÃøÇÑ´Ù.
|
compute_model_parameter (samples, no_samples, estimated_model);
|
|
// 2. Verification
|
|
// ¿øº» µ¥ÀÌÅͰ¡ ¿¹ÃøµÈ ¸ðµ¨¿¡ Àß ¸Â´ÂÁö °Ë»çÇÑ´Ù.
|
double cost = model_verification (inliers, &no_inliers, estimated_model, data, no_data, distance_threshold);
|
|
// ¸¸ÀÏ ¿¹ÃøµÈ ¸ðµ¨ÀÌ Àß ¸Â´Â´Ù¸é, ÀÌ ¸ðµ¨¿¡ ´ëÇÑ À¯È¿ÇÑ µ¥ÀÌÅÍ·Î »õ·Î¿î ¸ðµ¨À» ±¸ÇÑ´Ù.
|
if (max_cost < cost) {
|
max_cost = cost;
|
|
compute_model_parameter (inliers, no_inliers, model);
|
}
|
}
|
|
delete [] samples;
|
delete [] inliers;
|
|
return max_cost;
|
}
|
|
bool CCornerCut::find_in_samples (sCoPoint *samples, int no_samples, sCoPoint *data)
|
{
|
for (int i=0; i<no_samples; ++i) {
|
if (samples[i].x == data->x && samples[i].y == data->y) {
|
return true;
|
}
|
}
|
return false;
|
}
|
|
void CCornerCut::get_samples (sCoPoint *samples, int no_samples, sCoPoint *data, int no_data)
|
{
|
// µ¥ÀÌÅÍ¿¡¼ Áߺ¹µÇÁö ¾Ê°Ô N°³ÀÇ ¹«ÀÛÀ§ ¼ÀÇÃÀ» äÃëÇÑ´Ù.
|
for (int i=0; i<no_samples; ) {
|
int j = rand()%no_data;
|
|
if (!find_in_samples(samples, i, &data[j])) {
|
samples[i] = data[j];
|
++i;
|
}
|
};
|
}
|
|
int CCornerCut::compute_model_parameter(sCoPoint samples[], int no_samples, sCoLine &model)
|
{
|
// PCA ¹æ½ÄÀ¸·Î Á÷¼± ¸ðµ¨ÀÇ ÆÄ¶ó¸ÞÅ͸¦ ¿¹ÃøÇÑ´Ù.
|
|
double sx = 0, sy = 0;
|
double sxx = 0, syy = 0;
|
double sxy = 0, sw = 0;
|
|
for(int i = 0; i<no_samples;++i)
|
{
|
double &x = samples[i].x;
|
double &y = samples[i].y;
|
|
sx += x;
|
sy += y;
|
sxx += x*x;
|
sxy += x*y;
|
syy += y*y;
|
sw += 1;
|
}
|
|
//variance;
|
double vxx = (sxx - sx*sx/sw)/sw;
|
double vxy = (sxy - sx*sy/sw)/sw;
|
double vyy = (syy - sy*sy/sw)/sw;
|
|
//principal axis
|
double theta = atan2(2*vxy, vxx - vyy)/2;
|
|
model.mx = cos(theta);
|
model.my = sin(theta);
|
|
//center of mass(xc, yc)
|
model.sx = sx/sw;
|
model.sy = sy/sw;
|
|
//Á÷¼±ÀÇ ¹æÁ¤½Ä: sin(theta)*(x - sx) = cos(theta)*(y - sy);
|
return 1;
|
}
|
|
double CCornerCut::compute_distance(sCoLine &line, sCoPoint &x)
|
{
|
// ÇÑ Á¡(x)·ÎºÎÅÍ Á÷¼±(line)¿¡ ³»¸° ¼ö¼±ÀÇ ±æÀÌ(distance)¸¦ °è»êÇÑ´Ù.
|
|
return fabs((x.x - line.sx)*line.my - (x.y - line.sy)*line.mx)/sqrt(line.mx*line.mx + line.my*line.my);
|
}
|
|
double CCornerCut::model_verification (sCoPoint *inliers, int *no_inliers, sCoLine &estimated_model, sCoPoint *data, int no_data, double distance_threshold)
|
{
|
*no_inliers = 0;
|
|
double cost = 0.;
|
|
for(int i=0; i<no_data; i++){
|
// Á÷¼±¿¡ ³»¸° ¼ö¼±ÀÇ ±æÀ̸¦ °è»êÇÑ´Ù.
|
double distance = compute_distance(estimated_model, data[i]);
|
|
// ¿¹ÃøµÈ ¸ðµ¨¿¡¼ À¯È¿ÇÑ µ¥ÀÌÅÍÀÎ °æ¿ì, À¯È¿ÇÑ µ¥ÀÌÅÍ ÁýÇÕ¿¡ ´õÇÑ´Ù.
|
if (distance < distance_threshold) {
|
cost += 1.;
|
|
inliers[*no_inliers] = data[i];
|
++(*no_inliers);
|
}
|
}
|
|
return cost;
|
}
|
|
// Bresenham's line algorithm
|
void CCornerCut::bresenham_Line(COwnerBuffer *pRes,CPoint posStart,CPoint posEnd,BYTE color)
|
{
|
if(posStart.x <= 0 || posStart.y <= 0 || posEnd.x <= 0 || posEnd.y <= 0)
|
return;
|
|
const bool steep = (abs(posEnd.y - posStart.y) > abs(posEnd.x - posStart.x));
|
|
if(steep)
|
{
|
swapLong(posStart.x, posStart.y);
|
swapLong(posEnd.x, posEnd.y);
|
}
|
|
if(posStart.x > posEnd.x)
|
{
|
swapLong(posStart.x, posEnd.x);
|
swapLong(posStart.y, posEnd.y);
|
}
|
|
const int dx = posEnd.x - posStart.x;
|
const int dy = abs(posEnd.y - posStart.y);
|
|
float error = (float)dx / 2.0f;
|
const int ystep = (posStart.y < posEnd.y) ? 1 : -1;
|
int y = (int)posStart.y;
|
|
const int maxX = (int)posEnd.x;
|
|
for(int x=(int)posStart.x; x<maxX; x++)
|
{
|
if(steep)
|
{
|
pRes->SetPixel(y,x, color);
|
}
|
else
|
{
|
pRes->SetPixel(x,y, color);
|
}
|
|
error -= dy;
|
if(error < 0)
|
{
|
y += ystep;
|
error += dx;
|
}
|
}
|
}
|