#include "StdAfx.h"
|
#include "EdgeTriangle.h"
|
#include "CHImageControls/CHImageProcess.h"
|
#include "FormulaParser.h"
|
#include "CHCommonClasses/ProcessTimer.h"
|
#include "CHImageControls/CHDataFitting.h"
|
#include <numeric>
|
#include <math.h>
|
#include <tmmintrin.h>
|
#include <smmintrin.h>
|
|
#include "OpenCV/cxcore.h"
|
|
|
|
using namespace CHImageControls;
|
|
static BYTE pDeleteArray[512] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
|
inline bool CompareMaxSize(CPixelRegion& a, CPixelRegion& b)
|
{
|
return (a.GetMaxSize() > b.GetMaxSize());
|
}
|
|
inline bool CompareMinSize(CPixelRegion& a, CPixelRegion& b)
|
{
|
return (a.GetMinSize() > b.GetMinSize());
|
}
|
|
int Round( double value )
|
{
|
#if (defined _MSC_VER && defined _M_X64) || (defined __GNUC__ && defined __x86_64__ && defined __SSE2__ && !defined __APPLE__)
|
__m128d t = _mm_set_sd( value );
|
return _mm_cvtsd_si32(t);
|
#elif defined _MSC_VER && defined _M_IX86
|
int t;
|
__asm
|
{
|
fld value;
|
fistp t;
|
}
|
return t;
|
#elif defined _MSC_VER && defined _M_ARM && defined HAVE_TEGRA_OPTIMIZATION
|
TEGRA_ROUND(value);
|
#elif defined CV_ICC || defined __GNUC__
|
# ifdef HAVE_TEGRA_OPTIMIZATION
|
TEGRA_ROUND(value);
|
# else
|
return (int)lrint(value);
|
# endif
|
#else
|
double intpart, fractpart;
|
fractpart = modf(value, &intpart);
|
if ((fabs(fractpart) != 0.5) || ((((int)intpart) % 2) != 0))
|
return (int)(value + (value >= 0 ? 0.5 : -0.5));
|
else
|
return (int)intpart;
|
#endif
|
}
|
|
double CEdgeTriangle::AbsSum(double init, double x)
|
{
|
x = (x>0) ? x: -x;
|
return init + x;
|
}
|
|
double CEdgeTriangle::Sum(double init, double x)
|
{
|
return init + x;
|
}
|
|
double CEdgeTriangle::Square(double init, double x)
|
{
|
return init + x*x;
|
}
|
|
double CEdgeTriangle::Cubic(double init, double x)
|
{
|
return init + x*x*x;
|
}
|
|
double CEdgeTriangle::ForthPower(double init, double x)
|
{
|
return init + x*x*x*x;
|
}
|
|
void CEdgeTriangle::GetMinLocation(float *pImage, int nWidth, int nHeight, int nStep, int& nPosX, int& nPosY, double& dValue)
|
{
|
float fValue = 9999.9f;
|
|
float *pSubX, *pSubY;
|
pSubY = pImage;
|
for(int i=0; i<nHeight; i++)
|
{
|
pSubX = pSubY;
|
for(int j=0; j<nWidth; j++)
|
{
|
if (fValue > *pSubX)
|
{
|
nPosX = j;
|
nPosY = i;
|
fValue = *pSubX;
|
}
|
pSubX++;
|
}
|
pSubY += nStep;
|
}
|
|
dValue = fValue;
|
}
|
|
void CEdgeTriangle::GetMaxLocation(float *pImage, int nWidth, int nHeight, int nStep, int& nPosX, int& nPosY, double& dValue)
|
{
|
float fValue = -9999.9f;
|
|
float *pSubX, *pSubY;
|
pSubY = pImage;
|
for(int i=0; i<nHeight; i++)
|
{
|
pSubX = pSubY;
|
for(int j=0; j<nWidth; j++)
|
{
|
if (fValue < *pSubX)
|
{
|
nPosX = j;
|
nPosY = i;
|
fValue = *pSubX;
|
}
|
pSubX++;
|
}
|
pSubY += nStep;
|
}
|
|
dValue = fValue;
|
}
|
|
|
CEdgeTriangle::CEdgeTriangle(void)
|
{
|
Reset();
|
}
|
|
CEdgeTriangle::~CEdgeTriangle(void)
|
{
|
Reset();
|
}
|
|
BOOL CEdgeTriangle::ImageSobelEdge(CCHImageData* pSrcImage, CCHImageData* pDstImage)
|
{
|
if (pSrcImage==NULL || pDstImage==NULL) return FALSE;
|
|
BYTE *pSrcPtr = (BYTE*)pSrcImage->GetImageBuffer();
|
short *pDstPtr = (short*)pDstImage->GetImageBuffer();
|
|
int nWidth = pSrcImage->GetWidth();
|
int nHeight = pSrcImage->GetHeight();
|
int nSrcStep = pSrcImage->GetWidthStep();
|
int nDstStep = pDstImage->GetWidthStep() / sizeof(short);
|
|
__m128i zeroData = _mm_setzero_si128();
|
__m128i currentData = _mm_setzero_si128();
|
__m128i sobelData = _mm_set1_epi16(2);
|
__m128i lowUnpack = _mm_setzero_si128(); // low unpack
|
__m128i highUnpack = _mm_setzero_si128(); // high unpack
|
__m128i multiData = _mm_setzero_si128();
|
__m128i TopKernel = _mm_setzero_si128();
|
__m128i BottomKernel = _mm_setzero_si128();
|
__m128i tempData = _mm_setzero_si128();
|
|
static int nShiftOne, nShiftTwo;
|
|
BYTE *pSrcImageX;
|
short *pDstImageX;
|
|
int nY0X2 = 2;
|
int nY1X0 = nWidth;
|
int nY1X2 = nWidth + 2;
|
int nY2X0 = 2*nWidth;
|
int nY2X2 = 2*nWidth + 2;
|
|
int nRight = nWidth - 1;
|
|
for (int y=0; y<nHeight-2; y++)
|
{
|
pSrcImageX = pSrcPtr + (y*nSrcStep);
|
pDstImageX = pDstPtr + ((y+1)*nDstStep) + 1;
|
|
for (int x=0; x<nWidth-7; x+=8)
|
{
|
// [1] vertical kernel
|
|
// get pixel data (y+2,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0));
|
tempData = _mm_unpacklo_epi8(currentData, zeroData); // low (Y2X0)
|
highUnpack = _mm_unpackhi_epi8(currentData, zeroData); // high
|
|
nShiftOne = _mm_extract_epi16(highUnpack, 0);
|
nShiftTwo = _mm_extract_epi16(highUnpack, 1);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(tempData, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftOne, 7);
|
|
// mul * 2
|
multiData = _mm_mullo_epi16(highUnpack, sobelData);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(highUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftTwo, 7);
|
|
BottomKernel = _mm_add_epi16(tempData, multiData);
|
BottomKernel = _mm_add_epi16(BottomKernel, highUnpack); // bottom kernel value
|
|
// get pixel data (y,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX));
|
lowUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low (Y0X0)
|
highUnpack = _mm_unpackhi_epi8(currentData, zeroData); // high
|
|
nShiftOne = _mm_extract_epi16(highUnpack, 0);
|
nShiftTwo = _mm_extract_epi16(highUnpack, 1);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(lowUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftOne, 7);
|
|
// mul * 2
|
multiData = _mm_mullo_epi16(highUnpack, sobelData);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(highUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftTwo, 7);
|
|
TopKernel = _mm_add_epi16(lowUnpack, multiData);
|
TopKernel = _mm_add_epi16(TopKernel, highUnpack); // top kernel value
|
|
TopKernel = _mm_sub_epi16(TopKernel, BottomKernel); // top = top - bottom
|
|
// lowUnpack, TopKernel, sobelData, currentData,
|
|
// lowUnpack (Y0X0)
|
// [1] Horizontal kernel
|
// get pixel data (y+1,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low (Y1X0)
|
highUnpack = _mm_mullo_epi16(highUnpack, sobelData); // mul * 2
|
lowUnpack = _mm_add_epi16(lowUnpack, highUnpack); // add result
|
|
// get pixel data (y+2,x) tempData (Y2X0)
|
lowUnpack = _mm_add_epi16(lowUnpack, tempData); // add result
|
|
|
// get pixel data (y,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY0X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low (Y0X2)
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
// get pixel data (y+1,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low (Y1X2)
|
highUnpack = _mm_mullo_epi16(highUnpack, sobelData); // mul * 2
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
// get pixel data (y+2,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low (Y2X2)
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
TopKernel = _mm_add_epi16(TopKernel, lowUnpack); // add horizontal + vertical
|
|
TopKernel = _mm_srai_epi16(TopKernel, 1); // shift right 1 <div>
|
|
_mm_storeu_si128( (__m128i*)(pDstImageX), TopKernel);
|
|
pSrcImageX += 8;
|
pDstImageX += 8;
|
}
|
// error
|
*(pDstPtr + (y*nDstStep)) = 0;
|
*(pDstPtr + (y*nDstStep) + nRight) = 0;
|
}
|
|
// error
|
*(pDstPtr + ((nHeight-1)*nDstStep)) = 0;
|
*(pDstPtr + ((nHeight-2)*nDstStep)) = 0;
|
*(pDstPtr + ((nHeight-1)*nDstStep)+ nRight) = 0;
|
*(pDstPtr + ((nHeight-2)*nDstStep)+ nRight) = 0;
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::SetImageSource(CCHImageData* imageSource)
|
{
|
if (imageSource==NULL) return FALSE;
|
|
if (!imageSource->GetImageExist()) return FALSE;
|
|
return m_imageSource.CopyImageFrom(imageSource);
|
}
|
|
BOOL CEdgeTriangle::SetImageModel(CCHImageData* imageModel)
|
{
|
if (imageModel==NULL) return FALSE;
|
|
if (!imageModel->GetImageExist()) return FALSE;
|
|
return m_imageModel.CopyImageFrom(imageModel);
|
}
|
|
BOOL CEdgeTriangle::SetRecipeTriangle(const CRecipeTriangle& recipeTriangle)
|
{
|
if (recipeTriangle.GetRecipeModelCount()<1)
|
{
|
return FALSE;
|
}
|
|
if (recipeTriangle.GetRecipeMarkerCount()<1)
|
{
|
return FALSE;
|
}
|
|
if (recipeTriangle.GetRecipeFormulaCount()<1)
|
{
|
return FALSE;
|
}
|
|
m_recipeTriangle = recipeTriangle;
|
|
return FALSE;
|
}
|
|
int CEdgeTriangle::ModelProcess(CCHImageData *imageModel, CCHImageData *imageSource)
|
{
|
m_resultTriangle.ResetResultModel();
|
|
if (imageModel==NULL || !imageModel->GetImageExist())
|
{
|
return ImageFailModel;
|
}
|
|
if (imageSource==NULL || !imageSource->GetImageExist())
|
{
|
return ImageFailSource;
|
}
|
|
UINT nModelCount = 0;
|
if ((nModelCount=m_recipeTriangle.GetRecipeModelCount())<1)
|
{
|
return RecipeFailModel;
|
}
|
|
// find process
|
CResultModel resultModel;
|
CRecipeModel *pRecipeModel = NULL;
|
CCHImageData bandModel, bandSource;
|
|
for (UINT i=0; i<nModelCount; i++)
|
{
|
resultModel.Reset();
|
pRecipeModel = m_recipeTriangle.GetRecipeModel(i);
|
|
if (pRecipeModel!=NULL)
|
{
|
if (imageModel->GetBandImage(pRecipeModel->m_nTypeBand, &bandModel))
|
{
|
if (imageSource->GetBandImage(pRecipeModel->m_nTypeBand, &bandSource))
|
{
|
switch(pRecipeModel->m_nTypeMethod)
|
{
|
case ModelMethod_Full:
|
resultModel.m_nResultCode = MatchFull(&bandSource, &bandModel, pRecipeModel, resultModel);
|
break;
|
|
case ModelMethod_Level:
|
resultModel.m_nResultCode = MatchLevel(&bandSource, &bandModel, pRecipeModel, resultModel);
|
break;
|
|
default:
|
resultModel.m_nResultCode = RecipeFailModel;
|
break;
|
}
|
}
|
else
|
{
|
resultModel.m_nResultCode = ImageFailBandSource;
|
}
|
}
|
else
|
{
|
resultModel.m_nResultCode = ImageFailBandModel;
|
}
|
}
|
else
|
{
|
resultModel.m_nResultCode = RecipeFailModel;
|
}
|
|
m_resultTriangle.AddResultModel(resultModel);
|
}
|
|
return ProcessSuccess;
|
}
|
|
BOOL CEdgeTriangle::MatchImage(CCHImageData *pSource, CCHImageData *pModel, CRect* pRect, double dScore, int& nPosX, int& nPosY, double& dResult)
|
{
|
if (pRect==NULL)
|
{
|
if (!CCHImageProcess::ImageMatching(pSource, pModel, nPosX, nPosY, dResult))
|
{
|
return FALSE;
|
}
|
}
|
else
|
{
|
if (!CCHImageProcess::ImageMatching(pSource, pModel, *pRect, nPosX, nPosY, dResult))
|
{
|
return FALSE;
|
}
|
}
|
|
if (dResult < dScore) return FALSE;
|
|
if (pRect)
|
{
|
nPosX = pRect->left + nPosX + int(double(pModel->GetWidth()) / 2.0 + 0.5);
|
nPosY = pRect->top + nPosY + int(double(pModel->GetHeight()) / 2.0 + 0.5);
|
}
|
else
|
{
|
nPosX = nPosX + int(double(pModel->GetWidth()) / 2.0 + 0.5);
|
nPosY = nPosY + int(double(pModel->GetHeight()) / 2.0 + 0.5);
|
}
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::MatchImage(CCHImageData *pSource, CCHImageData *pModel, CRect* pRect, double dScore, double& dPosX, double& dPosY, double& dResult)
|
{
|
if (pRect==NULL)
|
{
|
if (!CCHImageProcess::ImageMatching(pSource, pModel, dPosX, dPosY, dResult))
|
{
|
return FALSE;
|
}
|
}
|
else
|
{
|
if (!CCHImageProcess::ImageMatching(pSource, pModel, *pRect, dPosX, dPosY, dResult))
|
{
|
return FALSE;
|
}
|
}
|
|
if (dResult < dScore) return FALSE;
|
|
double dHalfWidth = double(pModel->GetWidth()) / 2.0;
|
double dHalfHeight = double(pModel->GetHeight()) / 2.0;
|
|
// result
|
if (pRect)
|
{
|
dPosX += double(pRect->left) + double(pModel->GetWidth()) / 2.0;
|
dPosY += double(pRect->top) + double(pModel->GetHeight()) / 2.0;
|
}
|
else
|
{
|
dPosX += double(pModel->GetWidth()) / 2.0;
|
dPosY += double(pModel->GetHeight()) / 2.0;
|
}
|
|
return TRUE;
|
}
|
|
int CEdgeTriangle::MatchFull(CCHImageData *pSource, CCHImageData *pModel, const CRecipeModel *pRecipeModel, CResultModel& resultModel)
|
{
|
resultModel.Reset();
|
|
if (!MatchImage(pSource, pModel, NULL, pRecipeModel->m_dScoreThres, resultModel.m_dCenterX, resultModel.m_dCenterY, resultModel.m_dResultScore))
|
{
|
return ProcessFailModel;
|
}
|
|
// full match
|
double dHalfWidth = double(pModel->GetWidth()) / 2.0;
|
double dHalfHeight = double(pModel->GetHeight()) / 2.0;
|
|
resultModel.m_nFindLeft = Round(resultModel.m_dCenterX - dHalfWidth);
|
resultModel.m_nFindTop = Round(resultModel.m_dCenterY - dHalfHeight);
|
resultModel.m_nFindRight = resultModel.m_nFindLeft + pModel->GetWidth();
|
resultModel.m_nFindBottom = resultModel.m_nFindTop + pModel->GetHeight();
|
|
return ProcessSuccess;
|
}
|
|
|
int CEdgeTriangle::MatchLevel(CCHImageData *pSource, CCHImageData *pModel, const CRecipeModel *pRecipeModel, CResultModel& resultModel)
|
{
|
resultModel.Reset();
|
|
if (pRecipeModel->m_nLevelFirst < pRecipeModel->m_nLevelLast) return ProcessFailModel;
|
|
CCHImageData resizeSource, resizeModel, resultImage;
|
CCHImageData* pProcessSource = NULL;
|
CCHImageData* pProcessModel = NULL;
|
|
CRect rtRect;
|
double dResult;
|
int nLevel, nScale, nPosX, nPosY;
|
|
nLevel = pRecipeModel->m_nLevelFirst;
|
|
do
|
{
|
nPosX = nPosY = 0;
|
pProcessSource = pProcessModel = NULL;
|
|
if (nLevel==1)
|
{
|
pProcessSource = pSource;
|
pProcessModel = pModel;
|
}
|
else
|
{
|
switch(nLevel)
|
{
|
case 2:
|
if (ImageResizeHalf(pModel, &resizeModel)!=1) return ProcessFailModel;
|
if (ImageResizeHalf(pSource, &resizeSource)!=1) return ProcessFailModel;
|
break;
|
case 3:
|
if (ImageResizeQuarter(pModel, &resizeModel)!=1) return ProcessFailModel;
|
if (ImageResizeQuarter(pSource, &resizeSource)!=1) return ProcessFailModel;
|
break;
|
case 4:
|
if (ImageResizeOneEighth(pModel, &resizeModel)!=1) return ProcessFailModel;
|
if (ImageResizeOneEighth(pSource, &resizeSource)!=1) return ProcessFailModel;
|
break;
|
default:
|
return ProcessFailModel;
|
}
|
|
pProcessSource = &resizeSource;
|
pProcessModel = &resizeModel;
|
|
} // end if
|
|
// last & first level
|
if (nLevel==pRecipeModel->m_nLevelLast && nLevel==pRecipeModel->m_nLevelFirst)
|
{
|
if (!MatchImage(pProcessSource, pProcessModel, NULL, pRecipeModel->m_dScoreThres, resultModel.m_dCenterX, resultModel.m_dCenterY, resultModel.m_dResultScore))
|
{
|
return ProcessFailModel;
|
}
|
|
double dHalfWidth = double(pProcessModel->GetWidth()) / 2.0;
|
double dHalfHeight = double(pProcessModel->GetHeight()) / 2.0;
|
|
nScale = 1;
|
nScale = nScale << (nLevel-1);
|
|
resultModel.m_dCenterX *= double(nScale);
|
resultModel.m_dCenterY *= double(nScale);
|
|
resultModel.m_nFindLeft = Round(resultModel.m_dCenterX - (dHalfWidth*double(nScale)));
|
resultModel.m_nFindTop = Round(resultModel.m_dCenterY - (dHalfHeight*double(nScale)));
|
resultModel.m_nFindRight = resultModel.m_nFindLeft + (pProcessModel->GetWidth()*nScale);
|
resultModel.m_nFindBottom = resultModel.m_nFindTop + (pProcessModel->GetHeight()*nScale);
|
|
break; // break while
|
}
|
|
// last level
|
if (nLevel==pRecipeModel->m_nLevelLast)
|
{
|
if (!MatchImage(pProcessSource, pProcessModel, &rtRect, pRecipeModel->m_dScoreThres, resultModel.m_dCenterX, resultModel.m_dCenterY, resultModel.m_dResultScore))
|
{
|
return ProcessFailModel;
|
}
|
|
double dHalfWidth = double(pProcessModel->GetWidth()) / 2.0;
|
double dHalfHeight = double(pProcessModel->GetHeight()) / 2.0;
|
|
nScale = 1;
|
nScale = nScale << (nLevel-1);
|
|
resultModel.m_dCenterX *= double(nScale);
|
resultModel.m_dCenterY *= double(nScale);
|
|
resultModel.m_nFindLeft = Round(resultModel.m_dCenterX - (dHalfWidth*double(nScale)));
|
resultModel.m_nFindTop = Round(resultModel.m_dCenterY - (dHalfHeight*double(nScale)));
|
resultModel.m_nFindRight = resultModel.m_nFindLeft + (pProcessModel->GetWidth()*nScale);
|
resultModel.m_nFindBottom = resultModel.m_nFindTop + (pProcessModel->GetHeight()*nScale);
|
|
break; // break while
|
}
|
|
// first level
|
if (nLevel==pRecipeModel->m_nLevelFirst)
|
{
|
if (!MatchImage(pProcessSource, pProcessModel, NULL, pRecipeModel->m_dScoreThres, nPosX, nPosY, dResult))
|
{
|
return ProcessFailModel;
|
}
|
|
// check stop score
|
nScale = 1;
|
if (dResult > pRecipeModel->m_dScoreStop)
|
{
|
nScale = nScale << (nLevel-pRecipeModel->m_nLevelLast);
|
nLevel = pRecipeModel->m_nLevelLast;
|
}
|
else
|
{
|
nScale = 2;
|
nLevel--;
|
}
|
|
// set next level search range
|
nPosX *= nScale;
|
nPosY *= nScale;
|
|
int nHalfWidth = (pProcessModel->GetWidth() * nScale) / 2;
|
int nHalfHeight = (pProcessModel->GetWidth() * nScale) / 2;
|
|
rtRect.left = nPosX - nHalfWidth - pRecipeModel->m_nLevelRange;
|
rtRect.top = nPosY - nHalfHeight - pRecipeModel->m_nLevelRange;
|
rtRect.right = nPosX + nHalfWidth + pRecipeModel->m_nLevelRange;
|
rtRect.bottom = nPosY + nHalfHeight + pRecipeModel->m_nLevelRange;
|
|
continue; // continue while
|
}
|
|
// middle level
|
if (!MatchImage(pProcessSource, pProcessModel, &rtRect, pRecipeModel->m_dScoreThres, nPosX, nPosY, dResult))
|
{
|
return ProcessFailModel;
|
}
|
|
// check stop score
|
nScale = 1;
|
if (dResult > pRecipeModel->m_dScoreStop)
|
{
|
nScale = nScale << (nLevel-pRecipeModel->m_nLevelLast);
|
nLevel = pRecipeModel->m_nLevelLast;
|
}
|
else
|
{
|
nScale = 2;
|
nLevel--;
|
}
|
|
// set next level search range
|
nPosX *= nScale;
|
nPosY *= nScale;
|
|
int nHalfWidth = (pProcessModel->GetWidth() * nScale) / 2;
|
int nHalfHeight = (pProcessModel->GetWidth() * nScale) / 2;
|
|
rtRect.left = nPosX - nHalfWidth - pRecipeModel->m_nLevelRange;
|
rtRect.top = nPosY - nHalfHeight - pRecipeModel->m_nLevelRange;
|
rtRect.right = nPosX + nHalfWidth + pRecipeModel->m_nLevelRange;
|
rtRect.bottom = nPosY + nHalfHeight + pRecipeModel->m_nLevelRange;
|
|
} while(nLevel>=pRecipeModel->m_nLevelLast);
|
|
return ProcessSuccess;
|
}
|
|
|
int CEdgeTriangle::MarkerProcess(CCHImageData *imageSource)
|
{
|
m_resultTriangle.ResetResultMarker();
|
|
if (imageSource==NULL || !imageSource->GetImageExist())
|
{
|
return ImageFailSource;
|
}
|
|
UINT nMarkerCount = 0;
|
if ((nMarkerCount=m_recipeTriangle.GetRecipeMarkerCount())<1)
|
{
|
return RecipeFailMarker;
|
}
|
|
// measure process
|
int nResultCode = ProcessSuccess;
|
|
CResultMarker resultMarker;
|
CRecipeMarker *pRecipeMarker = NULL;
|
CCHImageData bandSource;
|
for (UINT i=0; i<nMarkerCount; i++)
|
{
|
resultMarker.Reset();
|
pRecipeMarker = m_recipeTriangle.GetRecipeMarker(i);
|
|
if (pRecipeMarker!=NULL)
|
{
|
resultMarker.m_nResultCode = MeasureImage(imageSource, pRecipeMarker, resultMarker);
|
}
|
else
|
{
|
nResultCode = RecipeFailMarker;
|
resultMarker.m_nResultCode = RecipeFailMarker;
|
}
|
|
if (resultMarker.m_nResultCode!=ProcessSuccess)
|
{
|
nResultCode = ProcessFailMarker;
|
}
|
|
m_resultTriangle.AddResultMarker(resultMarker);
|
}
|
|
return nResultCode;
|
}
|
|
/*
|
|
BOOL CEdgeTriangle::GetEdgeLeftPosition(int nEdgeType, int nSearchType, int nStartPos, double& dPosition)
|
{
|
if (m_vectorEdgeResult.size()<1) return FALSE;
|
|
BOOL bReturn = FALSE;
|
UINT nWidth = (UINT)m_vectorImageData.size();
|
double dValue = -9999.0;
|
int nIndex = -1;
|
|
UINT i = 0;
|
switch(nSearchType)
|
{
|
case EdgeSearch_Out2In:
|
dPosition = 9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition < dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_In2Out:
|
dPosition = -9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > (nWidth/2)) continue;
|
|
if (m_vectorEdgeResult[i].dPosition > dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_MinMax:
|
dValue = 0.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
|
if ( fabs(dValue) < fabs(m_vectorEdgeResult[i].dStrength))
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
default:
|
return FALSE;
|
}
|
|
if (nIndex!=-1)
|
m_vectorEdgeResult[nIndex].nEdgeType = EdgeResult_Left;
|
|
return bReturn;
|
}
|
|
BOOL CEdgeTriangle::GetEdgeRightPosition(int nEdgeType, int nSearchType, int nStartPos, double& dPosition)
|
{
|
if (m_vectorEdgeResult.size()<1) return FALSE;
|
|
BOOL bReturn = FALSE;
|
UINT nWidth = (UINT)m_vectorImageData.size();
|
double dValue = -9999.0;
|
int nIndex = -1;
|
|
UINT i = 0;
|
switch(nSearchType)
|
{
|
case EdgeSearch_Out2In:
|
dPosition = -9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition > dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_In2Out:
|
dPosition = 9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition < dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_MinMax:
|
dValue = 0;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
|
if ( fabs(dValue) < fabs(m_vectorEdgeResult[i].dStrength))
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
default:
|
return FALSE;
|
}
|
|
if (nIndex!=-1)
|
m_vectorEdgeResult[nIndex].nEdgeType = EdgeResult_Right;
|
|
return bReturn;
|
}
|
|
*/
|
|
BOOL CEdgeTriangle::GetEdgeLeftPosition(int nEdgeType, int nSearchType, int nStartPos, int nEndPos, double& dPosition)
|
{
|
if (m_vectorEdgeResult.size()<1) return FALSE;
|
|
BOOL bReturn = FALSE;
|
UINT nWidth = (UINT)m_vectorImageData.size();
|
double dValue = -9999.0;
|
int nIndex = -1;
|
|
UINT i = 0;
|
switch(nSearchType)
|
{
|
case EdgeSearch_Out2In:
|
dPosition = 9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > nEndPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition < dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_In2Out:
|
dPosition = -9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > nEndPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition > dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_MinMax:
|
dValue = 0.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > nEndPos) continue;
|
|
if ( fabs(dValue) < fabs(m_vectorEdgeResult[i].dStrength))
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
default:
|
return FALSE;
|
}
|
|
if (nIndex!=-1)
|
m_vectorEdgeResult[nIndex].nEdgeType = EdgeResult_Left;
|
|
return bReturn;
|
}
|
|
BOOL CEdgeTriangle::GetEdgeRightPosition(int nEdgeType, int nSearchType, int nStartPos, int nEndPos, double& dPosition)
|
{
|
if (m_vectorEdgeResult.size()<1) return FALSE;
|
|
BOOL bReturn = FALSE;
|
UINT nWidth = (UINT)m_vectorImageData.size();
|
double dValue = -9999.0;
|
int nIndex = -1;
|
|
UINT i = 0;
|
switch(nSearchType)
|
{
|
case EdgeSearch_Out2In:
|
dPosition = -9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > nEndPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition > dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_In2Out:
|
dPosition = 9999.;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > nEndPos) continue;
|
|
if (m_vectorEdgeResult[i].dPosition < dPosition)
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
case EdgeSearch_MinMax:
|
dValue = 0;
|
for (i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if (m_vectorEdgeResult[i].nSignal != nEdgeType) continue;
|
if (m_vectorEdgeResult[i].dPosition < nStartPos) continue;
|
if (m_vectorEdgeResult[i].dPosition > nEndPos) continue;
|
|
if ( fabs(dValue) < fabs(m_vectorEdgeResult[i].dStrength))
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dPosition = m_vectorEdgeResult[i].dPosition;
|
bReturn = TRUE;
|
nIndex = i;
|
}
|
}
|
break;
|
|
default:
|
return FALSE;
|
}
|
|
if (nIndex!=-1)
|
m_vectorEdgeResult[nIndex].nEdgeType = EdgeResult_Right;
|
|
return bReturn;
|
}
|
|
|
BOOL CEdgeTriangle::GetImageData(CCHImageData* pSubImage, VectorDouble& vectorImageData)
|
{
|
if (pSubImage==NULL || !pSubImage->GetImageExist() || pSubImage->GetChannels()>1) return FALSE;
|
|
int nWidth = pSubImage->GetWidth();
|
int nHeight = pSubImage->GetHeight();
|
int nStep = pSubImage->GetWidthStep();
|
BYTE *pImage = (BYTE*)pSubImage->GetImageBuffer();
|
|
// edge dir
|
if (pSubImage->GetWidth()>pSubImage->GetHeight())
|
{
|
return CalculateImageValue(EdgeDirection_Vert, pImage, nWidth, nHeight, nStep, vectorImageData);
|
}
|
|
return CalculateImageValue(EdgeDirection_Horiz, pImage, nWidth, nHeight, nStep, vectorImageData);
|
}
|
|
BOOL CEdgeTriangle::GetEdgeData(CCHImageData* pSubImage, VectorDouble& vectorEdgeData, int nKernelSize, double dKernelSigma)
|
{
|
VectorDouble vectorImageData;
|
if (!GetImageData(pSubImage, vectorImageData))
|
{
|
return FALSE;
|
}
|
return CalculateEdgeValue(vectorImageData, vectorEdgeData, nKernelSize, dKernelSigma);
|
}
|
|
BOOL CEdgeTriangle::GetEdgeData(int& nBandType, CCHImageData* pSubImage, VectorDouble& vectorEdgeData, int nKernelSize, double dKernelSigma)
|
{
|
if (nBandType==BandTypeColor)
|
{
|
CCHImageData bandImage;
|
|
double dSum = 0.0, dTmpSum;
|
VectorDouble vectorBandData;
|
VectorDouble vectorBandEdgeData;
|
|
for (int i=0; i<BandTypeColor; i++)
|
{
|
vectorBandData.clear();
|
vectorBandEdgeData.clear();
|
|
if (!pSubImage->GetBandImage(i, &bandImage)) continue;
|
|
if (!GetImageData(&bandImage, vectorBandData)) continue;
|
|
if (!CalculateEdgeValue(vectorBandData, vectorBandEdgeData, nKernelSize, dKernelSigma)) continue;
|
|
dTmpSum = std::accumulate(vectorBandEdgeData.begin(), vectorBandEdgeData.end(), 0.0, Sum);
|
if (dSum > dTmpSum) continue;
|
|
dSum = dTmpSum;
|
nBandType = i;
|
vectorEdgeData = vectorBandEdgeData;
|
}
|
|
if (nBandType==BandTypeColor) return FALSE;
|
|
return TRUE;
|
}
|
|
VectorDouble vectorImageData;
|
if (!GetImageData(pSubImage, vectorImageData))
|
{
|
return FALSE;
|
}
|
|
return CalculateEdgeValue(vectorImageData, vectorEdgeData, nKernelSize, dKernelSigma);
|
}
|
|
|
int CEdgeTriangle::MeasureImage(CCHImageData *imageSource, const CRecipeMarker* pRecipeMarker, CResultMarker& resultMarker)
|
{
|
// sub image
|
int nRet = ProcessFailMarker;
|
CCHImageData rectImage;
|
|
int nWidth = pRecipeMarker->m_nROIWidth + (4 - (pRecipeMarker->m_nROIWidth%4));
|
|
if (!imageSource->GetBandImage(pRecipeMarker->m_nTypeBand,
|
pRecipeMarker->m_nROILeft, pRecipeMarker->m_nROITop, nWidth, pRecipeMarker->m_nROIHeight,
|
&rectImage))
|
{
|
return ImageFailSub;
|
}
|
|
// measure type
|
resultMarker.m_nMeasureType = pRecipeMarker->m_nMeasureType;
|
|
switch(pRecipeMarker->m_nMeasureType)
|
{
|
case Measure_Line:
|
nRet = Process_MeasureLine(rectImage, pRecipeMarker, resultMarker);
|
break;
|
case Measure_Circle:
|
nRet = Process_MeasureCircle(rectImage, pRecipeMarker, resultMarker);
|
break;
|
case Measure_Ellipse:
|
nRet = Process_MeasureEllipse(rectImage, pRecipeMarker, resultMarker);
|
break;
|
default:
|
return ProcessFailMarker;
|
}
|
|
return nRet;
|
}
|
|
int CEdgeTriangle::Process_MeasureLine(CCHImageData& imageData, const CRecipeMarker* pRecipeMarker, CResultMarker& resultMarker)
|
{
|
// result clear
|
m_vectorImageData.clear();
|
m_vectorEdgeType.clear();
|
m_vectorEdgeData.clear();
|
m_vectorEdgeResult.clear();
|
|
// pre-process
|
switch(pRecipeMarker->m_nTypePreProcess)
|
{
|
case PreProc_None:
|
{
|
CalculateImageValue(
|
pRecipeMarker->m_nEdgeDirection,
|
(BYTE*)imageData.GetImageBuffer(),
|
imageData.GetWidth(),
|
imageData.GetHeight(),
|
imageData.GetWidthStep()/sizeof(BYTE),
|
m_vectorImageData);
|
|
CalculateEdgeValue(
|
m_vectorImageData,
|
m_vectorEdgeData,
|
m_vectorEdgeType,
|
pRecipeMarker->m_dEdgePosiThres,
|
pRecipeMarker->m_dEdgeNegaThres,
|
pRecipeMarker->m_nEdgeKernelSize,
|
pRecipeMarker->m_dEdgeKernelSigma);
|
|
break;
|
}
|
|
case PreProc_Sobel:
|
{
|
CCHImageData edgeImage(imageData.GetWidth(), imageData.GetHeight(), IPL_DEPTH_16S, 1);
|
if (!ImageSobelEdge(&imageData, &edgeImage))
|
{
|
return PreProcessFail;
|
}
|
|
CalculateEdgeValue(
|
pRecipeMarker->m_nEdgeDirection,
|
(short*)edgeImage.GetImageBuffer(),
|
edgeImage.GetWidth(),
|
edgeImage.GetHeight(),
|
edgeImage.GetWidthStep()/sizeof(short),
|
m_vectorEdgeData,
|
m_vectorEdgeType,
|
pRecipeMarker->m_dEdgePosiThres,
|
pRecipeMarker->m_dEdgeNegaThres);
|
|
break;
|
}
|
|
default:
|
return ProcessFailMarker;
|
}
|
|
// FILE *fp = NULL;
|
// _tfopen_s(&fp, _T("d:\\result.csv"), _T("w"));
|
// for (int i=0; i<(int)m_vectorImageData.size(); i++)
|
// {
|
// _ftprintf_s(fp, _T("%d, %lf, %lf\n"), i, m_vectorImageData[i], m_vectorEdgeData[i]);
|
// }
|
// fclose(fp);
|
|
|
// calculate edge position
|
CalculateEdgePosition(pRecipeMarker->m_nTypeSubPixel, pRecipeMarker->m_dEdgePosiThres, pRecipeMarker->m_dEdgeNegaThres, pRecipeMarker->m_nIteration);
|
|
double dLeftPos = 9999.0;
|
double dRightPos = -9999.0;
|
|
if(pRecipeMarker->m_nEdgeSearchType==EdgeSearch_MinMax)
|
{
|
int nIdx = -1;
|
double dValue = 0;
|
|
//left
|
for(int i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if(m_vectorEdgeResult[i].nSignal != pRecipeMarker->m_nEdgeLeft) continue;
|
if(fabs(dValue) < fabs(m_vectorEdgeResult[i].dStrength))
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dLeftPos = m_vectorEdgeResult[i].dPosition;
|
nIdx = i;
|
}
|
}
|
if(dLeftPos == 9999.0) return EdgeFailLeft;
|
m_vectorEdgeResult[nIdx].nEdgeType = EdgeResult_Left;
|
|
dValue = 0;
|
//Right
|
for(int i=0; i<m_vectorEdgeResult.size(); i++)
|
{
|
if(m_vectorEdgeResult[i].nSignal != pRecipeMarker->m_nEdgeRight) continue;
|
if(fabs(dValue) < fabs(m_vectorEdgeResult[i].dStrength))
|
{
|
dValue = m_vectorEdgeResult[i].dStrength;
|
dRightPos = m_vectorEdgeResult[i].dPosition;
|
nIdx = i;
|
}
|
}
|
if(dRightPos == -9999.0) return EdgeFailRight;
|
m_vectorEdgeResult[nIdx].nEdgeType = EdgeResult_Right;
|
}
|
else
|
{
|
// get left position
|
if (!GetEdgeLeftPosition(pRecipeMarker->m_nEdgeLeft, pRecipeMarker->m_nEdgeSearchType, 0, int(m_vectorEdgeData.size()/2), dLeftPos))
|
{
|
return EdgeFailLeft;
|
}
|
|
// get right position
|
if (!GetEdgeRightPosition(pRecipeMarker->m_nEdgeRight, pRecipeMarker->m_nEdgeSearchType, int(m_vectorEdgeData.size()/2), int(m_vectorEdgeData.size()), dRightPos))
|
{
|
return EdgeFailRight;
|
}
|
}
|
|
// set marker result
|
switch (pRecipeMarker->m_nEdgeDirection)
|
{
|
case EdgeDirection_Vert:
|
resultMarker.m_nEdgeDirection = EdgeDirection_Vert;
|
resultMarker.m_dLength = dRightPos - dLeftPos;
|
|
resultMarker.m_dFirstX = double(pRecipeMarker->m_nROILeft) + dLeftPos;
|
resultMarker.m_dSecondX = double(pRecipeMarker->m_nROILeft) + dRightPos;
|
resultMarker.m_dCenterX = double(pRecipeMarker->m_nROILeft) + dLeftPos + (resultMarker.m_dLength)/2.0;
|
|
resultMarker.m_dFirstY = double(pRecipeMarker->m_nROITop) + (double(pRecipeMarker->m_nROIHeight)/2.0);
|
resultMarker.m_dSecondY = double(pRecipeMarker->m_nROITop) + (double(pRecipeMarker->m_nROIHeight)/2.0);
|
resultMarker.m_dCenterY = double(pRecipeMarker->m_nROITop) + (double(pRecipeMarker->m_nROIHeight)/2.0);
|
break;
|
|
case EdgeDirection_Horiz:
|
resultMarker.m_nEdgeDirection = EdgeDirection_Horiz;
|
resultMarker.m_dLength = dRightPos - dLeftPos;
|
|
resultMarker.m_dFirstY = double(pRecipeMarker->m_nROITop) + dLeftPos;
|
resultMarker.m_dSecondY = double(pRecipeMarker->m_nROITop) + dRightPos;
|
resultMarker.m_dCenterY = double(pRecipeMarker->m_nROITop) + dLeftPos + (resultMarker.m_dLength)/2.0;
|
|
resultMarker.m_dFirstX = double(pRecipeMarker->m_nROILeft) + (double(pRecipeMarker->m_nROIWidth)/2.0);
|
resultMarker.m_dSecondX = double(pRecipeMarker->m_nROILeft) + (double(pRecipeMarker->m_nROIWidth)/2.0);
|
resultMarker.m_dCenterX = double(pRecipeMarker->m_nROILeft) + (double(pRecipeMarker->m_nROIWidth)/2.0);
|
break;
|
}
|
|
return ProcessSuccess;
|
}
|
|
int CEdgeTriangle::Process_MeasureCircle(CCHImageData& imageData, const CRecipeMarker* pRecipeMarker, CResultMarker& resultMarker)
|
{
|
int nWidth = imageData.GetWidth();
|
int nHeight = imageData.GetHeight();
|
|
CCHImageData edgeImage;
|
edgeImage.CreateImage(nWidth, nHeight);
|
edgeImage.ClearImage(0);
|
|
BYTE* pSrcImage = (BYTE*)imageData.GetImageBuffer();
|
BYTE *pEdgeImage = (BYTE*)edgeImage.GetImageBuffer();
|
|
// step 1: sobel edge
|
if (!ImageSobelEdge(pSrcImage, pEdgeImage, nWidth, nHeight))
|
{
|
return CircleCoefficientFail;
|
}
|
// edgeImage.SaveImage(_T("d:\\edge.bmp"));
|
|
// step 2: threshold
|
if (!ImageThresholding(pEdgeImage, nWidth, nHeight, pRecipeMarker->m_nCircleThreshold))
|
{
|
return CircleCoefficientFail;
|
}
|
// edgeImage.SaveImage(_T("d:\\thres.bmp"));
|
|
// step 3: closing
|
CCHImageData closeImage;
|
closeImage.CreateImage(nWidth, nHeight);
|
BYTE *pCloseImage = (BYTE*)closeImage.GetImageBuffer();
|
ImageDilate(pEdgeImage, pCloseImage, nWidth, nHeight);
|
ImageErode(pCloseImage, pEdgeImage, nWidth, nHeight);
|
// edgeImage.SaveImage(_T("d:\\close.bmp"));
|
|
// step 4: thinning
|
if (!ImageThinning(pEdgeImage, nWidth, nHeight))
|
{
|
return CircleCoefficientFail;
|
}
|
// edgeImage.SaveImage(_T("d:\\thin.bmp"));
|
|
// step 5: blob analysis
|
VectorPixelRegion vectorPixelRegion;
|
if (!ImageBlobAnalysis(pEdgeImage, nWidth, nHeight, vectorPixelRegion, pRecipeMarker->m_nCircleBlobMargin))
|
{
|
return CircleCoefficientFail;
|
}
|
|
VectorDouble vectorX, vectorY, vectorResult;
|
for (VectorPointIt it=vectorPixelRegion[0].vectorPoint.begin(); it!=vectorPixelRegion[0].vectorPoint.end(); it++)
|
{
|
vectorX.push_back(it->x);
|
vectorY.push_back(it->y);
|
}
|
|
if (CCHDataFitting::CircleFitting(vectorX, vectorY, vectorResult)<1)
|
{
|
return CircleCoefficientFail;
|
}
|
|
resultMarker.m_dCenterX = pRecipeMarker->m_nROILeft + vectorResult[0];
|
resultMarker.m_dCenterY = pRecipeMarker->m_nROITop + vectorResult[1];
|
resultMarker.m_dLength = vectorResult[2];
|
|
return TRUE;
|
}
|
|
int CEdgeTriangle::Process_MeasureEllipse(CCHImageData& imageData, const CRecipeMarker* pRecipeMarker, CResultMarker& resultMarker)
|
{
|
int nWidth = imageData.GetWidth();
|
int nHeight = imageData.GetHeight();
|
|
CCHImageData edgeImage;
|
edgeImage.CreateImage(nWidth, nHeight);
|
edgeImage.ClearImage(0);
|
|
BYTE* pSrcImage = (BYTE*)imageData.GetImageBuffer();
|
BYTE *pEdgeImage = (BYTE*)edgeImage.GetImageBuffer();
|
|
// step 1: sobel edge
|
if (!ImageSobelEdge(pSrcImage, pEdgeImage, nWidth, nHeight))
|
{
|
return CircleCoefficientFail;
|
}
|
// edgeImage.SaveImage(_T("d:\\edge.bmp"));
|
|
// step 2: threshold
|
if (!ImageThresholding(pEdgeImage, nWidth, nHeight, pRecipeMarker->m_nCircleThreshold))
|
{
|
return CircleCoefficientFail;
|
}
|
// edgeImage.SaveImage(_T("d:\\thres.bmp"));
|
|
// step 3: closing
|
CCHImageData closeImage;
|
closeImage.CreateImage(nWidth, nHeight);
|
BYTE *pCloseImage = (BYTE*)closeImage.GetImageBuffer();
|
ImageDilate(pEdgeImage, pCloseImage, nWidth, nHeight);
|
ImageErode(pCloseImage, pEdgeImage, nWidth, nHeight);
|
// edgeImage.SaveImage(_T("d:\\close.bmp"));
|
|
// step 4: thinning
|
if (!ImageThinning(pEdgeImage, nWidth, nHeight))
|
{
|
return CircleCoefficientFail;
|
}
|
// edgeImage.SaveImage(_T("d:\\thin.bmp"));
|
|
// step 5: blob analysis
|
VectorPixelRegion vectorPixelRegion;
|
if (!ImageBlobAnalysis(pEdgeImage, nWidth, nHeight, vectorPixelRegion, pRecipeMarker->m_nCircleBlobMargin))
|
{
|
return CircleCoefficientFail;
|
}
|
|
VectorDouble vectorX, vectorY, vectorResult;
|
for (VectorPointIt it=vectorPixelRegion[0].vectorPoint.begin(); it!=vectorPixelRegion[0].vectorPoint.end(); it++)
|
{
|
vectorX.push_back(it->x);
|
vectorY.push_back(it->y);
|
}
|
|
// step 6: ellipse fitting
|
if (CCHDataFitting::EllipseFitting(vectorX, vectorY, vectorResult)<1)
|
{
|
return CircleCoefficientFail;
|
}
|
|
resultMarker.m_dCenterX = pRecipeMarker->m_nROILeft + vectorResult[0]; // center x
|
resultMarker.m_dCenterY = pRecipeMarker->m_nROITop + vectorResult[1]; // center y
|
resultMarker.m_dFirstY = resultMarker.m_dFirstX = vectorResult[2]; // length width
|
resultMarker.m_dSecondY = resultMarker.m_dSecondX = vectorResult[3]; // length height
|
resultMarker.m_dLength = vectorResult[4]; // angle
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateImageValue(int nDirection, BYTE *pImage, int nWidth, int nHeight, int nStep, VectorDouble& vectorImageData)
|
{
|
vectorImageData.clear();
|
|
if (pImage==NULL) return FALSE;
|
|
double dValue = 0.0;
|
|
switch (nDirection)
|
{
|
case EdgeDirection_Vert:
|
for (int j=0; j<nWidth; j++)
|
{
|
dValue = 0.0;
|
for (int i=0; i<nHeight; i++)
|
{
|
dValue += pImage[(i*nStep)+j];
|
}
|
dValue /= double(nHeight);
|
vectorImageData.push_back(dValue);
|
}
|
break;
|
|
case EdgeDirection_Horiz:
|
for (int i=0; i<nHeight; i++)
|
{
|
dValue = 0.0;
|
for (int j=0; j<nWidth; j++)
|
{
|
dValue += UCHAR(pImage[(i*nStep)+j]);
|
}
|
dValue /= double(nWidth);
|
vectorImageData.push_back(dValue);
|
}
|
break;
|
}
|
|
return TRUE;
|
}
|
|
|
BOOL CEdgeTriangle::CalculateEdgeValue(int nDirection, short *pImage, int nWidth, int nHeight, int nStep, VectorDouble& vectorEdgeData, VectorInteger& vectorEdgeType, double dPositiveThres, double dNegativeThres)
|
{
|
vectorEdgeData.clear();
|
vectorEdgeType.clear();
|
|
if (pImage==NULL) return FALSE;
|
|
double dValue = 0.0;
|
int nType = EdgeSignal_None;
|
|
switch (nDirection)
|
{
|
case EdgeDirection_Vert:
|
for (int j=0; j<nWidth; j++)
|
{
|
dValue = 0.0;
|
nType = EdgeSignal_None;
|
|
for (int i=0; i<nHeight; i++)
|
{
|
dValue += pImage[(i*nStep)+j];
|
}
|
dValue /= double(nHeight);
|
|
if (dValue >= dPositiveThres)
|
{
|
nType = EdgeSignal_Positive;
|
}
|
else if (dValue <= dNegativeThres )
|
{
|
nType = EdgeSignal_Negative;
|
}
|
|
vectorEdgeType.push_back(nType);
|
vectorEdgeData.push_back(dValue);
|
}
|
break;
|
|
case EdgeDirection_Horiz:
|
for (int i=0; i<nHeight; i++)
|
{
|
dValue = 0.0;
|
nType = EdgeSignal_None;
|
|
for (int j=0; j<nWidth; j++)
|
{
|
dValue += UCHAR(pImage[(i*nStep)+j]);
|
}
|
dValue /= double(nWidth);
|
|
if (dValue >= dPositiveThres)
|
{
|
nType = EdgeSignal_Positive;
|
}
|
else if (dValue <= dNegativeThres )
|
{
|
nType = EdgeSignal_Negative;
|
}
|
|
vectorEdgeData.push_back(dValue);
|
vectorEdgeType.push_back(nType);
|
}
|
break;
|
}
|
|
return TRUE;
|
}
|
|
//2014-02-28
|
/*
|
BOOL CEdgeTriangle::CalculateEdgeValue(const VectorDouble& vectorImageData, VectorDouble& vectorEdgeData, int nKernelSize, double dKernelSigma)
|
{
|
vectorEdgeData.clear();
|
|
double dLeft = 0.0;
|
double dRight = 0.0;
|
double dValue = 0.0;
|
|
// half gaussian
|
VectorDouble kernelTemp;
|
double dDiv = sqrt(2.0*CV_PI)*dKernelSigma;
|
for (int i=0; i<10; i++)
|
{
|
dValue = (i + 0.5) * (i + 0.5);
|
dValue = exp( -1.0 * ( dValue / (2.0*(dKernelSigma*dKernelSigma)) ) ) / dDiv;
|
if (dValue<0.0001) break;
|
kernelTemp.push_back(dValue);
|
}
|
|
// full gaussian
|
int nPitchSize = (int)kernelTemp.size();
|
VectorDouble kernelGaussian;
|
for (int i=nPitchSize-1; i>=0; i--)
|
{
|
kernelGaussian.push_back(kernelTemp[i]);
|
}
|
for (int i=0; i<nPitchSize; i++)
|
{
|
kernelGaussian.push_back(kernelTemp[i]);
|
}
|
|
nKernelSize = nPitchSize * 2;
|
|
if (vectorImageData.size()<nKernelSize) return FALSE;
|
|
// push first pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
}
|
|
// push center pitch
|
for (int i=0; i<vectorImageData.size()-(nKernelSize); i++)
|
{
|
dLeft = dRight = 0.0;
|
for (int j=0; j<nPitchSize; j++)
|
{
|
dLeft += vectorImageData[i+j] * kernelGaussian[j];
|
dRight += vectorImageData[i+j+nPitchSize] * kernelGaussian[j+nPitchSize];
|
}
|
dValue = dRight - dLeft;
|
vectorEdgeData.push_back(dValue);
|
}
|
|
// push last pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
}
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateEdgeValue(const VectorDouble& vectorImageData, VectorDouble& vectorEdgeData, VectorInteger& vectorEdgeType, double dPositiveThres, double dNegativeThres, int nKernelSize, double dKernelSigma)
|
{
|
vectorEdgeData.clear();
|
vectorEdgeType.clear();
|
|
int nType = EdgeSignal_None;
|
double dLeft = 0.0;
|
double dRight = 0.0;
|
double dValue = 0.0;
|
|
// half gaussian
|
VectorDouble kernelTemp;
|
double dDiv = sqrt(2.0*CV_PI)*dKernelSigma;
|
for (int i=0; i<10; i++)
|
{
|
dValue = (i + 0.5) * (i + 0.5);
|
dValue = exp( -1.0 * ( dValue / (2.0*(dKernelSigma*dKernelSigma)) ) ) / dDiv;
|
if (dValue<0.0001) break;
|
kernelTemp.push_back(dValue);
|
}
|
|
// full gaussian
|
int nPitchSize = (int)kernelTemp.size();
|
VectorDouble kernelGaussian;
|
for (int i=nPitchSize-1; i>=0; i--)
|
{
|
kernelGaussian.push_back(kernelTemp[i]);
|
}
|
for (int i=0; i<nPitchSize; i++)
|
{
|
kernelGaussian.push_back(kernelTemp[i]);
|
}
|
|
nKernelSize = nPitchSize * 2;
|
|
if (vectorImageData.size()<nKernelSize) return FALSE;
|
|
// push first pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
vectorEdgeType.push_back(EdgeSignal_None);
|
}
|
|
// push center pitch
|
for (int i=0; i<vectorImageData.size()-(nKernelSize); i++)
|
{
|
dLeft = dRight = 0.0;
|
nType = EdgeSignal_None;
|
|
for (int j=0; j<nPitchSize; j++)
|
{
|
dLeft += vectorImageData[i+j] * kernelGaussian[j];
|
dRight += vectorImageData[i+j+nPitchSize] * kernelGaussian[j+nPitchSize];
|
}
|
|
dValue = dRight - dLeft;
|
if (dValue >= dPositiveThres)
|
{
|
nType = EdgeSignal_Positive;
|
}
|
else if (dValue <= dNegativeThres )
|
{
|
nType = EdgeSignal_Negative;
|
}
|
|
vectorEdgeData.push_back(dValue);
|
vectorEdgeType.push_back(nType);
|
}
|
|
// push last pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
vectorEdgeType.push_back(EdgeSignal_None);
|
}
|
|
return TRUE;
|
}
|
*/
|
|
BOOL CEdgeTriangle::CalculateEdgeValue(const VectorDouble& vectorImageData, VectorDouble& vectorEdgeData, int nKernelSize, double dKernelSigma)
|
{
|
vectorEdgeData.clear();
|
double dValue = 0.0;
|
|
// half gaussian
|
VectorDouble kernelTemp;
|
double dDiv = sqrt(2.0*CV_PI)*dKernelSigma;
|
for (int i=0; i<20; i++)
|
{
|
dValue = (i) * (i);
|
dValue = exp( -1.0 * ( dValue / (2.0*(dKernelSigma*dKernelSigma)) ) ) / dDiv;
|
if (dValue<0.00001) break;
|
kernelTemp.push_back(dValue);
|
}
|
|
// full gaussian
|
int nPitchSize = (int)kernelTemp.size();
|
VectorDouble kernelData;
|
for (int i=nPitchSize-1; i>=0; i--)
|
{
|
kernelData.push_back(-kernelTemp[i]);
|
}
|
kernelData.push_back(0.0);
|
|
for (int i=0; i<nPitchSize; i++)
|
{
|
kernelData.push_back(kernelTemp[i]);
|
}
|
|
nKernelSize = nPitchSize * 2;
|
|
if (vectorImageData.size()<nKernelSize) return FALSE;
|
|
// push first pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
}
|
|
// push center pitch
|
for (int i=0; i<vectorImageData.size()-(nKernelSize); i++)
|
{
|
dValue = 0.0;
|
for (int j=0; j<(int)kernelData.size(); j++)
|
{
|
dValue += vectorImageData[i+j] * kernelData[j];
|
}
|
vectorEdgeData.push_back(dValue);
|
}
|
|
// push last pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
}
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateEdgeValue(const VectorDouble& vectorImageData, VectorDouble& vectorEdgeData, VectorInteger& vectorEdgeType, double dPositiveThres, double dNegativeThres, int nKernelSize, double dKernelSigma)
|
{
|
vectorEdgeData.clear();
|
vectorEdgeType.clear();
|
int nType = EdgeSignal_None;
|
double dValue = 0.0;
|
|
// half gaussian
|
VectorDouble kernelTemp;
|
double dDiv = sqrt(2.0*CV_PI)*dKernelSigma;
|
for (int i=0; i<20; i++)
|
{
|
dValue = (i) * (i);
|
dValue = exp( -1.0 * ( dValue / (2.0*(dKernelSigma*dKernelSigma)) ) ) / dDiv;
|
if (dValue<0.00001) break;
|
kernelTemp.push_back(dValue);
|
}
|
|
// full gaussian
|
int nPitchSize = (int)kernelTemp.size();
|
VectorDouble kernelData;
|
for (int i=nPitchSize-1; i>=0; i--)
|
{
|
kernelData.push_back(-kernelTemp[i]);
|
}
|
kernelData.push_back(0.0);
|
|
for (int i=0; i<nPitchSize; i++)
|
{
|
kernelData.push_back(kernelTemp[i]);
|
}
|
nKernelSize = nPitchSize * 2;
|
|
if (vectorImageData.size()<nKernelSize) return FALSE;
|
|
// push first pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
vectorEdgeType.push_back(EdgeSignal_None);
|
}
|
|
// push center pitch
|
for (int i=0; i<vectorImageData.size()-(nKernelSize); i++)
|
{
|
dValue = 0.0;
|
nType = EdgeSignal_None;
|
for (int j=0; j<(int)kernelData.size(); j++)
|
{
|
dValue += vectorImageData[i+j] * kernelData[j];
|
}
|
|
if (dValue >= dPositiveThres)
|
{
|
nType = EdgeSignal_Positive;
|
}
|
else if (dValue <= dNegativeThres )
|
{
|
nType = EdgeSignal_Negative;
|
}
|
|
vectorEdgeData.push_back(dValue);
|
vectorEdgeType.push_back(nType);
|
}
|
|
// push last pitch
|
for (int i=0; i<nPitchSize; i++)
|
{
|
vectorEdgeData.push_back(0.0);
|
vectorEdgeType.push_back(EdgeSignal_None);
|
}
|
|
return TRUE;
|
}
|
|
void CEdgeTriangle::CalculateEdgePosition(int nSubPixelType, double dPosiThres, double dNegaThres, int nIteration)
|
{
|
m_vectorEdgeResult.clear();
|
|
int nEdgeIndex = 0;
|
int nEdgePosition = 0;
|
int nEdgeType = EdgeSignal_None;
|
double dEdgeValue = 0.0;
|
double dEdgeThres = 0.0;
|
|
if (nSubPixelType==SubPixel_Linear)
|
{
|
for (UINT i=1; i<m_vectorEdgeType.size()-1; i++)
|
{
|
if (m_vectorEdgeType[i-1] == m_vectorEdgeType[i]) continue;
|
|
switch(m_vectorEdgeType[i])
|
{
|
case EdgeSignal_None:
|
nEdgePosition = i-1;
|
nEdgeType = m_vectorEdgeType[nEdgePosition];
|
dEdgeThres = (m_vectorEdgeType[nEdgePosition]==EdgeSignal_Positive) ? dPosiThres: dNegaThres;
|
dEdgeValue = m_vectorEdgeData[nEdgePosition];
|
break;
|
case EdgeSignal_Negative:
|
nEdgePosition = i;
|
nEdgeType = EdgeSignal_Negative;
|
dEdgeThres = dNegaThres;
|
dEdgeValue = m_vectorEdgeData[i];
|
break;
|
case EdgeSignal_Positive:
|
nEdgePosition = i;
|
nEdgeType = EdgeSignal_Positive;
|
dEdgeThres = dPosiThres;
|
dEdgeValue = m_vectorEdgeData[i];
|
break;
|
} // end switch
|
|
if (nEdgeType==EdgeSignal_None) continue;
|
|
CEdgeResult edgeResult(nEdgeIndex, nEdgeType, nEdgePosition, dEdgeValue);
|
|
if (CalculateInterpolateLinear(edgeResult, dEdgeThres))
|
{
|
m_vectorEdgeResult.push_back(edgeResult);
|
nEdgeIndex++;
|
}
|
|
} // end for
|
}
|
else
|
{
|
|
for (UINT i=1; i<m_vectorEdgeType.size()-1; i++)
|
{
|
nEdgeType = EdgeSignal_None;
|
|
switch(m_vectorEdgeType[i])
|
{
|
case EdgeSignal_Positive:
|
{
|
nEdgeType = EdgeSignal_Positive;
|
nEdgePosition = i;
|
dEdgeValue = m_vectorEdgeData[i];
|
|
for (UINT j=i+1; m_vectorEdgeType.size()-1; j++)
|
{
|
if (m_vectorEdgeType[j] != EdgeSignal_Positive) break;
|
|
if (dEdgeValue < m_vectorEdgeData[j])
|
{
|
nEdgePosition = j;
|
dEdgeValue = m_vectorEdgeData[j];
|
}
|
i = j;
|
}
|
}
|
break;
|
|
case EdgeSignal_Negative:
|
{
|
nEdgeType = EdgeSignal_Negative;
|
nEdgePosition = i;
|
dEdgeValue = m_vectorEdgeData[i];
|
|
for (UINT j=i+1; m_vectorEdgeType.size()-1; j++)
|
{
|
if (m_vectorEdgeType[j] != EdgeSignal_Negative) break;
|
|
if (dEdgeValue > m_vectorEdgeData[j])
|
{
|
nEdgePosition = j;
|
dEdgeValue = m_vectorEdgeData[j];
|
}
|
i = j;
|
}
|
|
}
|
break;
|
} // end switch
|
|
if (nEdgeType==EdgeSignal_None) continue;
|
|
CEdgeResult edgeResult(nEdgeIndex, nEdgeType, nEdgePosition, dEdgeValue);
|
|
switch(nSubPixelType)
|
{
|
case SubPixel_Quadratic:
|
if (CalculateInterpolateQuadratic(edgeResult))
|
{
|
m_vectorEdgeResult.push_back(edgeResult);
|
nEdgeIndex++;
|
}
|
break;
|
|
case SubPixel_Gaussian:
|
if (CalculateInterpolateGaussian(edgeResult, nEdgeType))
|
{
|
m_vectorEdgeResult.push_back(edgeResult);
|
nEdgeIndex++;
|
}
|
break;
|
|
case SubPixel_Quadratic_Regress:
|
if (CalculateInterpolateQuadraticRegression(edgeResult))
|
{
|
m_vectorEdgeResult.push_back(edgeResult);
|
nEdgeIndex++;
|
}
|
break;
|
|
case SubPixel_Gaussian_Regress:
|
if (CalculateInterpolateGaussianRegression(edgeResult, nEdgeType))
|
{
|
m_vectorEdgeResult.push_back(edgeResult);
|
nEdgeIndex++;
|
}
|
break;
|
|
} // end switch
|
|
} // end for
|
}
|
|
}
|
|
BOOL CEdgeTriangle::CalculateInterpolateLinear(CEdgeResult& edgeResult, double dEdgeThreshold)
|
{
|
UINT i = 0;
|
|
int nPosition = edgeResult.nEdgePosition-1;
|
double dPositionValue = m_vectorEdgeData[edgeResult.nEdgePosition-1];
|
double dValue = m_vectorEdgeData[edgeResult.nEdgePosition];
|
|
VectorDouble vectorX; // x point
|
vectorX.push_back(double(edgeResult.nEdgePosition-1));
|
vectorX.push_back(double(edgeResult.nEdgePosition));
|
|
VectorDouble vectorY; // y point
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nEdgePosition-1]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nEdgePosition]);
|
|
|
VectorDouble vectorResult;
|
if (CCHDataFitting::PolynomialFitting(vectorX, vectorY, vectorResult, 1)<1)
|
{
|
return FALSE;
|
}
|
|
edgeResult.dPosition = (dEdgeThreshold-vectorResult[0]) / vectorResult[1];
|
edgeResult.dStrength = dEdgeThreshold;
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateInterpolateQuadratic(CEdgeResult& edgeResult)
|
{
|
if (m_vectorEdgeData.size()<1) return FALSE;
|
|
UINT i = 0;
|
|
for (i=edgeResult.nEdgePosition-1; i>0; i--)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nLeftPosition = i;
|
}
|
|
for (i=edgeResult.nEdgePosition+1; i<m_vectorEdgeType.size(); i++)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nRightPosition = i;
|
}
|
|
// coef
|
if (edgeResult.nLeftPosition==edgeResult.nEdgePosition)
|
edgeResult.nLeftPosition = edgeResult.nEdgePosition - 1;
|
|
if (edgeResult.nRightPosition==edgeResult.nEdgePosition)
|
edgeResult.nRightPosition = edgeResult.nEdgePosition + 1;
|
|
edgeResult.nLeftPosition = edgeResult.nEdgePosition - 1;
|
edgeResult.nRightPosition = edgeResult.nEdgePosition + 1;
|
|
// set 3 point
|
VectorDouble vectorX; // x point
|
// vectorX.push_back(double(edgeResult.nLeftPosition));
|
// vectorX.push_back(double(edgeResult.nEdgePosition));
|
// vectorX.push_back(double(edgeResult.nRightPosition));
|
vectorX.push_back(0.0);
|
vectorX.push_back(1.0);
|
vectorX.push_back(2.0);
|
|
VectorDouble vectorY; // y point
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nLeftPosition]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nEdgePosition]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nRightPosition]);
|
|
VectorDouble vectorResult;
|
if (CCHDataFitting::PolynomialFitting(vectorX, vectorY, vectorResult, 2)<1)
|
{
|
return FALSE;
|
}
|
|
edgeResult.dPosition = edgeResult.nLeftPosition + (-1.0 * vectorResult[1]) / (2.0 * vectorResult[2]);
|
edgeResult.dStrength = -1.0 * ( ( (vectorResult[1]*vectorResult[1]) - (4.0 * vectorResult[2] * vectorResult[0]) ) / (4.0 * vectorResult[2]) );
|
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateInterpolateGaussian(CEdgeResult& edgeResult, int nEdgeType)
|
{
|
if (m_vectorEdgeData.size()<1) return FALSE;
|
|
UINT i = 0;
|
|
for (i=edgeResult.nEdgePosition-1; i>0; i--)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nLeftPosition = i;
|
}
|
|
for (i=edgeResult.nEdgePosition+1; i<m_vectorEdgeType.size(); i++)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nRightPosition = i;
|
}
|
|
// coef
|
if (edgeResult.nLeftPosition==edgeResult.nEdgePosition)
|
edgeResult.nLeftPosition = edgeResult.nEdgePosition - 1;
|
|
if (edgeResult.nRightPosition==edgeResult.nEdgePosition)
|
edgeResult.nRightPosition = edgeResult.nEdgePosition + 1;
|
|
edgeResult.nLeftPosition = edgeResult.nEdgePosition - 1;
|
edgeResult.nRightPosition = edgeResult.nEdgePosition + 1;
|
|
// set 3 point
|
VectorDouble vectorX; // x point
|
// vectorX.push_back(double(edgeResult.nLeftPosition));
|
// vectorX.push_back(double(edgeResult.nEdgePosition));
|
// vectorX.push_back(double(edgeResult.nRightPosition));
|
vectorX.push_back(0.0);
|
vectorX.push_back(1.0);
|
vectorX.push_back(2.0);
|
|
|
VectorDouble vectorY; // y point
|
if (nEdgeType==EdgeSignal_Negative)
|
{
|
vectorY.push_back(-m_vectorEdgeData[edgeResult.nLeftPosition]);
|
vectorY.push_back(-m_vectorEdgeData[edgeResult.nEdgePosition]);
|
vectorY.push_back(-m_vectorEdgeData[edgeResult.nRightPosition]);
|
}
|
else
|
{
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nLeftPosition]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nEdgePosition]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nRightPosition]);
|
}
|
|
VectorDouble vectorResult;
|
if (CCHDataFitting::GaussianFitting(vectorX, vectorY, vectorResult)<1)
|
{
|
return FALSE;
|
}
|
|
edgeResult.dPosition = edgeResult.nLeftPosition + vectorResult[1];
|
edgeResult.dStrength = (nEdgeType==EdgeSignal_Negative) ? -vectorResult[0]: vectorResult[0];
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateInterpolateQuadraticRegression(CEdgeResult& edgeResult)
|
{
|
if (m_vectorEdgeData.size()<1) return FALSE;
|
|
UINT i = 0;
|
|
for (i=edgeResult.nEdgePosition-1; i>0; i--)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nLeftPosition = i;
|
}
|
|
for (i=edgeResult.nEdgePosition+1; i<m_vectorEdgeType.size(); i++)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nRightPosition = i;
|
}
|
|
if ((edgeResult.nRightPosition-edgeResult.nLeftPosition)<2) return FALSE;
|
|
int nIndex = 0;
|
VectorDouble vectorX, vectorY;
|
for (i=(UINT)edgeResult.nLeftPosition; i<(UINT)edgeResult.nRightPosition+1; i++)
|
{
|
vectorX.push_back(nIndex++);
|
vectorY.push_back(m_vectorEdgeData[i]);
|
}
|
|
VectorDouble vectorResult;
|
if (CCHDataFitting::PolynomialFitting(vectorX, vectorY, vectorResult, 2)<1)
|
{
|
return FALSE;
|
}
|
|
|
edgeResult.dPosition = edgeResult.nLeftPosition + (-1.0 * vectorResult[1]) / (2.0 * vectorResult[2]);
|
edgeResult.dStrength = -1.0 * ( ( (vectorResult[1]*vectorResult[1]) - (4.0 * vectorResult[2] * vectorResult[0]) ) / (4.0 * vectorResult[2]) );
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateInterpolateGaussianRegression(CEdgeResult& edgeResult, int nEdgeType)
|
{
|
if (m_vectorEdgeData.size()<1) return FALSE;
|
|
UINT i = 0;
|
|
for (i=edgeResult.nEdgePosition-1; i>0; i--)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nLeftPosition = i;
|
}
|
|
for (i=edgeResult.nEdgePosition+1; i<m_vectorEdgeType.size(); i++)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nRightPosition = i;
|
}
|
|
if ((edgeResult.nRightPosition-edgeResult.nLeftPosition)<2) return FALSE;
|
|
int nIndex = 0;
|
VectorDouble vectorX, vectorY;
|
for (i=(UINT)edgeResult.nLeftPosition; i<(UINT)edgeResult.nRightPosition+1; i++)
|
{
|
vectorX.push_back(nIndex++);
|
|
if (nEdgeType==EdgeSignal_Negative)
|
vectorY.push_back(-m_vectorEdgeData[i]);
|
else
|
vectorY.push_back(m_vectorEdgeData[i]);
|
}
|
|
VectorDouble vectorResult;
|
if (CCHDataFitting::GaussianFitting(vectorX, vectorY, vectorResult)<1)
|
{
|
return FALSE;
|
}
|
|
int nMaxPos = edgeResult.nEdgePosition - edgeResult.nLeftPosition;
|
|
if (vectorResult[1] < nMaxPos-1.0 || vectorResult[1] > nMaxPos+1.0)
|
{
|
vectorX.clear();
|
vectorX.push_back(0.0);
|
vectorX.push_back(1.0);
|
vectorX.push_back(2.0);
|
|
vectorY.clear();
|
edgeResult.nLeftPosition = edgeResult.nEdgePosition - 1;
|
edgeResult.nRightPosition = edgeResult.nEdgePosition + 1;
|
if (nEdgeType==EdgeSignal_Negative)
|
{
|
vectorY.push_back(-m_vectorEdgeData[edgeResult.nLeftPosition]);
|
vectorY.push_back(-m_vectorEdgeData[edgeResult.nEdgePosition]);
|
vectorY.push_back(-m_vectorEdgeData[edgeResult.nRightPosition]);
|
}
|
else
|
{
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nLeftPosition]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nEdgePosition]);
|
vectorY.push_back(m_vectorEdgeData[edgeResult.nRightPosition]);
|
}
|
|
vectorResult.clear();
|
if (CCHDataFitting::GaussianFitting(vectorX, vectorY, vectorResult)<1)
|
{
|
return FALSE;
|
}
|
}
|
|
edgeResult.dPosition = edgeResult.nLeftPosition + vectorResult[1];
|
edgeResult.dStrength = (nEdgeType==EdgeSignal_Negative) ? -vectorResult[0]: vectorResult[0];
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::CalculateInterpolateGaussianRegressionReweight(CEdgeResult& edgeResult, int nEdgeType, int nIteration)
|
{
|
if (m_vectorEdgeData.size()<1) return FALSE;
|
|
UINT i = 0;
|
|
for (i=edgeResult.nEdgePosition-1; i>0; i--)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nLeftPosition = i;
|
}
|
|
for (i=edgeResult.nEdgePosition+1; i<m_vectorEdgeType.size(); i++)
|
{
|
if (m_vectorEdgeType[i]!=edgeResult.nSignal) break;
|
edgeResult.nRightPosition = i;
|
}
|
|
if ((edgeResult.nRightPosition-edgeResult.nLeftPosition)<2) return FALSE;
|
|
VectorDouble vectorX, vectorY;
|
for (i=(UINT)edgeResult.nLeftPosition; i<(UINT)edgeResult.nRightPosition+1; i++)
|
{
|
vectorX.push_back(double(i));
|
|
if (nEdgeType==EdgeSignal_Negative)
|
vectorY.push_back(-m_vectorEdgeData[i]);
|
else
|
vectorY.push_back(m_vectorEdgeData[i]);
|
}
|
|
VectorDouble vectorResult;
|
nIteration = CCHDataFitting::IRLS_GaussianFitting(vectorX, vectorY, vectorResult, nIteration, 3.0);
|
|
if (nIteration<1) return FALSE;
|
|
edgeResult.dPosition = vectorResult[1];
|
edgeResult.dStrength = (nEdgeType==EdgeSignal_Negative) ? -vectorResult[0]: vectorResult[0];
|
|
return TRUE;
|
}
|
|
|
int CEdgeTriangle::ModelMarkerProcess(CCHImageData *imageModel, CCHImageData *imageSource)
|
{
|
int nResultCode = ModelProcess(imageModel, imageSource);
|
|
if (nResultCode!=ProcessSuccess)
|
{
|
return nResultCode;
|
}
|
|
const CResultModel *pResultModel = m_resultTriangle.GetResultModel(0);
|
if (pResultModel==NULL)
|
{
|
return ProcessFailModel;
|
}
|
|
if (pResultModel->m_nResultCode!=ProcessSuccess)
|
{
|
return ResultFailModel;
|
}
|
|
CCHImageData subImage;
|
CRect rtRect(pResultModel->m_nFindLeft, pResultModel->m_nFindTop, pResultModel->m_nFindRight, pResultModel->m_nFindBottom);
|
if (!imageSource->GetSubImage(rtRect, &subImage))
|
{
|
return ImageFailSub;
|
}
|
|
return MarkerProcess(&subImage);
|
}
|
|
int CEdgeTriangle::MarkerFormulaProcess(CCHImageData *imageSource)
|
{
|
m_resultTriangle.ResetResultMarker();
|
|
int nResultCode = MarkerProcess(imageSource);
|
|
if (nResultCode!=ProcessSuccess)
|
{
|
return nResultCode;
|
}
|
|
return FormulaProcess();
|
}
|
|
BOOL CEdgeTriangle::CheckFormulationString(const CString& strFormulation, CString& strResultFormulation, CRecipeTriangle* pRecipeTriangle)
|
{
|
if (pRecipeTriangle==NULL) return FALSE;
|
|
strResultFormulation = _T("");
|
|
int s_idx = 0;
|
int nIndex = 0;
|
int nMarkerIndex = 0;
|
CString cMarkerType = _T("");
|
CString strItem = _T("");
|
|
CRecipeMarker *pRecipeMarker = NULL;
|
|
for (int i=0; i<strFormulation.GetLength(); i++)
|
{
|
TCHAR ch = strFormulation.GetAt(i);
|
|
if (ch==_T('['))
|
{
|
nIndex = strFormulation.Find(_T(']'), i+1);
|
|
if (nIndex>i)
|
{
|
strItem = strFormulation.Mid(i, (nIndex-i+1));
|
|
int s_idx = strItem.Find(_T('%'), 0);
|
if (s_idx<1) return FALSE;
|
|
int e_idx = strItem.Find(_T('_'), s_idx+1);
|
if (e_idx<1) return FALSE;
|
|
// get marker index & result
|
CString strIndex = strItem.Mid(s_idx+1, e_idx-s_idx-1);
|
nMarkerIndex = ::_ttoi(strIndex) - 1;
|
|
pRecipeMarker = pRecipeTriangle->GetRecipeMarker(nMarkerIndex);
|
if (pRecipeMarker==NULL) return FALSE;
|
|
// get marker type & result
|
cMarkerType = strItem.GetAt(e_idx+1);
|
|
#ifdef X
|
switch(cMarkerType)
|
{
|
case _T('F'):
|
strItem.Format(_T("%d_First"), nMarkerIndex);
|
break;
|
case _T('S'):
|
strItem.Format(_T("%d_Second"), nMarkerIndex);
|
break;
|
case _T('C'):
|
strItem.Format(_T("%d_Center"), nMarkerIndex);
|
break;
|
case _T('L'):
|
strItem.Format(_T("%d_Length"), nMarkerIndex);
|
break;
|
default:
|
return FALSE;
|
}
|
#else
|
|
if (cMarkerType == "F") { strItem.Format(_T("%d_First"), nMarkerIndex); }
|
if (cMarkerType == "S") { strItem.Format(_T("%d_Second"), nMarkerIndex); }
|
if (cMarkerType == "C") { strItem.Format(_T("%d_Center"), nMarkerIndex); }
|
if (cMarkerType == "L") { strItem.Format(_T("%d_Length"), nMarkerIndex); }
|
#endif
|
|
strResultFormulation += strItem;
|
i = nIndex;
|
}
|
else
|
{
|
return FALSE;
|
}
|
|
continue;
|
} // end if
|
|
strResultFormulation += ch;
|
}
|
|
return TRUE;
|
}
|
|
BOOL CEdgeTriangle::GetResultFormulation(const CString& strFormulation, CString& strResultFormulation)
|
{
|
strResultFormulation = _T("");
|
|
int s_idx = 0;
|
int nIndex = 0;
|
int nMarkerIndex = 0;
|
CString cMarkerType = _T("");
|
CString strItem = _T("");
|
|
const CResultMarker *pResultMarker = NULL;
|
|
for (int i=0; i<strFormulation.GetLength(); i++)
|
{
|
TCHAR ch = strFormulation.GetAt(i);
|
|
if (ch==_T('['))
|
{
|
nIndex = strFormulation.Find(_T(']'), i+1);
|
|
if (nIndex>i)
|
{
|
strItem = strFormulation.Mid(i, (nIndex-i+1));
|
|
int s_idx = strItem.Find(_T('%'), 0);
|
if (s_idx<1) return FALSE;
|
|
int e_idx = strItem.Find(_T('_'), s_idx+1);
|
if (e_idx<1) return FALSE;
|
|
// get marker index & result
|
CString strIndex = strItem.Mid(s_idx+1, e_idx-s_idx-1);
|
nMarkerIndex = ::_ttoi(strIndex) - 1;
|
|
|
pResultMarker = m_resultTriangle.GetResultMarker((UINT)nMarkerIndex);
|
if (pResultMarker==NULL) return FALSE;
|
|
// get marker type & result
|
cMarkerType = strItem.GetAt(e_idx+1);
|
|
if (pResultMarker->m_nEdgeDirection==EdgeDirection_Vert)
|
{
|
#ifdef X
|
switch(cMarkerType)
|
{
|
case _T('F'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dFirstX);
|
break;
|
case _T('S'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dSecondX);
|
break;
|
case _T('C'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dCenterX);
|
break;
|
case _T('L'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dLength);
|
break;
|
default:
|
return FALSE;
|
}
|
#else
|
if (cMarkerType == "F") { strItem.Format(_T("%lf"), pResultMarker->m_dFirstX); }
|
if (cMarkerType == "S") { strItem.Format(_T("%lf"), pResultMarker->m_dSecondX); }
|
if (cMarkerType == "C") { strItem.Format(_T("%lf"), pResultMarker->m_dCenterX); }
|
if (cMarkerType == "L") { strItem.Format(_T("%lf"), pResultMarker->m_dLength); }
|
#endif
|
}
|
else
|
{
|
#ifdef X
|
switch(cMarkerType)
|
{
|
case _T('F'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dFirstY);
|
break;
|
case _T('S'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dSecondY);
|
break;
|
case _T('C'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dCenterY);
|
break;
|
case _T('L'):
|
strItem.Format(_T("%lf"), pResultMarker->m_dLength);
|
break;
|
default:
|
return FALSE;
|
}
|
#else
|
if (cMarkerType == "F") { strItem.Format(_T("%lf"), pResultMarker->m_dFirstY); }
|
if (cMarkerType == "S") { strItem.Format(_T("%lf"), pResultMarker->m_dSecondY); }
|
if (cMarkerType == "C") { strItem.Format(_T("%lf"), pResultMarker->m_dCenterY); }
|
if (cMarkerType == "L") { strItem.Format(_T("%lf"), pResultMarker->m_dLength); }
|
#endif
|
}
|
|
strResultFormulation += strItem;
|
i = nIndex;
|
}
|
else
|
{
|
return FALSE;
|
}
|
|
continue;
|
} // end if
|
|
strResultFormulation += ch;
|
}
|
|
return TRUE;
|
}
|
|
int CEdgeTriangle::FormulaProcess()
|
{
|
m_resultTriangle.ResetResultFormula();
|
|
if (m_resultTriangle.GetResultMarkerCount()<1)
|
{
|
return ResultFailMarker;
|
}
|
|
UINT nFormulaCount = 0;
|
if ((nFormulaCount=m_recipeTriangle.GetRecipeFormulaCount())<1)
|
{
|
return RecipeFailFormula;
|
}
|
|
CString strResultFormulation = _T("");
|
CEvaluator evaluator;
|
CRecipeFormula *pRecipeFormula = NULL;
|
CResultFormula resultFormula;
|
for (UINT i=0; i<nFormulaCount; i++)
|
{
|
resultFormula.Reset();
|
pRecipeFormula = m_recipeTriangle.GetRecipeFormula(i);
|
|
if (pRecipeFormula!=NULL)
|
{
|
resultFormula.m_strResultName = pRecipeFormula->m_strResultName;
|
|
// get result formula string
|
if (!GetResultFormulation(pRecipeFormula->m_strFormulation, strResultFormulation))
|
{
|
resultFormula.m_nResultCode = ProcessFailFormula;
|
}
|
else if(evaluator.Interpret(strResultFormulation)) // interpret formula
|
{
|
resultFormula.m_nResultCode = ProcessFailFormula;
|
}
|
else if (evaluator.Evaluate(resultFormula.m_dResultValue)) // calculate formula
|
{
|
resultFormula.m_nResultCode = ProcessFailFormula;
|
}
|
else
|
{
|
resultFormula.m_nResultCode = ProcessSuccess;
|
}
|
}
|
else
|
{
|
resultFormula.m_nResultCode = RecipeFailFormula;
|
}
|
|
m_resultTriangle.AddResultFormula(resultFormula);
|
}
|
|
return ProcessSuccess;
|
}
|
|
int CEdgeTriangle::TriangleProcess(CCHImageData *imageModel, CCHImageData *imageSource)
|
{
|
int nResultCode = ModelMarkerProcess(imageModel, imageSource);
|
|
if (nResultCode!=ProcessSuccess)
|
{
|
return nResultCode;
|
}
|
|
nResultCode = FormulaProcess();
|
|
if (nResultCode!=ProcessSuccess)
|
{
|
return nResultCode;
|
}
|
|
return ProcessSuccess;
|
}
|
|
int CEdgeTriangle::ProcessModel()
|
{
|
return ModelProcess(&m_imageModel, &m_imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModel(CCHImageData* imageSource, const CRecipeModel& recipeModel)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.AddRecipeModel(recipeModel);
|
|
return ModelProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModel(CCHImageData* imageSource, const VectorRecipeModel& vectorRecipeModel)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.SetRecipeModel(vectorRecipeModel);
|
|
return ModelProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModel(CCHImageData* imageModel, CCHImageData* imageSource, const CRecipeModel& recipeModel)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.AddRecipeModel(recipeModel);
|
|
return ModelProcess(imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModel(CCHImageData* imageModel, CCHImageData* imageSource, const VectorRecipeModel& vectorRecipeModel)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.SetRecipeModel(vectorRecipeModel);
|
|
return ModelProcess(imageModel, imageSource);
|
}
|
|
|
int CEdgeTriangle::ProcessMarker()
|
{
|
return MarkerProcess(&m_imageModel);
|
}
|
|
int CEdgeTriangle::ProcessMarker(CCHImageData* imageSource, const CRecipeMarker& recipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.AddRecipeMarker(recipeMarker);
|
|
return MarkerProcess(imageSource);
|
}
|
|
int CEdgeTriangle::ProcessMarker(CCHImageData* imageSource, const VectorRecipeMarker& vectorRecipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.SetRecipeMarker(vectorRecipeMarker);
|
|
return MarkerProcess(imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker()
|
{
|
return ModelMarkerProcess(&m_imageModel, &m_imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker(CCHImageData* imageSource, const CRecipeModel& recipeModel, const CRecipeMarker& recipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.AddRecipeModel(recipeModel);
|
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.AddRecipeMarker(recipeMarker);
|
|
return ModelMarkerProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker(CCHImageData* imageSource, const CRecipeModel& recipeModel, const VectorRecipeMarker& vectorRecipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.AddRecipeModel(recipeModel);
|
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.SetRecipeMarker(vectorRecipeMarker);
|
|
return ModelMarkerProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker(CCHImageData* imageSource, const VectorRecipeModel& vectorRecipeModel, const VectorRecipeMarker& vectorRecipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.SetRecipeModel(vectorRecipeModel);
|
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.SetRecipeMarker(vectorRecipeMarker);
|
|
return ModelMarkerProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker(CCHImageData* imageModel, CCHImageData* imageSource, const CRecipeModel& recipeModel, const CRecipeMarker& recipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.AddRecipeModel(recipeModel);
|
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.AddRecipeMarker(recipeMarker);
|
|
return ModelMarkerProcess(imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker(CCHImageData* imageModel, CCHImageData* imageSource, const CRecipeModel& recipeModel, const VectorRecipeMarker& vectorRecipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.AddRecipeModel(recipeModel);
|
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.SetRecipeMarker(vectorRecipeMarker);
|
|
return ModelMarkerProcess(imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessModelMarker(CCHImageData* imageModel, CCHImageData* imageSource, const VectorRecipeModel& vectorRecipeModel, const VectorRecipeMarker& vectorRecipeMarker)
|
{
|
m_recipeTriangle.ResetRecipeModel();
|
m_recipeTriangle.SetRecipeModel(vectorRecipeModel);
|
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.SetRecipeMarker(vectorRecipeMarker);
|
|
return ModelMarkerProcess(imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessMarkerFormula()
|
{
|
return MarkerFormulaProcess(&m_imageModel);
|
}
|
|
int CEdgeTriangle::ProcessMarkerFormula(CCHImageData* imageSource, const CRecipeMarker& recipeMarker, const CRecipeFormula& recipeFormula)
|
{
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.AddRecipeMarker(recipeMarker);
|
|
m_recipeTriangle.ResetRecipeFormula();
|
m_recipeTriangle.AddRecipeFormula(recipeFormula);
|
|
return MarkerFormulaProcess(imageSource);
|
}
|
|
int CEdgeTriangle::ProcessMarkerFormula(CCHImageData* imageSource, const VectorRecipeMarker& vectorRecipeMarker, const VectorRecipeFormula& vectorRecipeFormula)
|
{
|
m_recipeTriangle.ResetRecipeMarker();
|
m_recipeTriangle.SetRecipeMarker(vectorRecipeMarker);
|
|
m_recipeTriangle.ResetRecipeFormula();
|
m_recipeTriangle.SetRecipeFormula(vectorRecipeFormula);
|
|
return MarkerFormulaProcess(imageSource);
|
}
|
|
int CEdgeTriangle::ProcessTriangle()
|
{
|
return TriangleProcess(&m_imageModel, &m_imageSource);
|
}
|
|
int CEdgeTriangle::ProcessTriangle(CCHImageData* imageSource)
|
{
|
return TriangleProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessTriangle(CCHImageData* imageSource, const CRecipeTriangle& recipeTriangle)
|
{
|
m_recipeTriangle = recipeTriangle;
|
|
return TriangleProcess(&m_imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ProcessTriangle(CCHImageData* imageModel, CCHImageData* imageSource, const CRecipeTriangle& recipeTriangle)
|
{
|
m_recipeTriangle = recipeTriangle;
|
|
return TriangleProcess(imageModel, imageSource);
|
}
|
|
int CEdgeTriangle::ImageResizeHalf(CCHImageData* pSource, CCHImageData* pResult)
|
{
|
if (pSource==NULL || pResult==NULL) return 0;
|
|
if (!pSource->GetImageExist()) return 0;
|
|
if (pSource->GetChannels()!=1) return 0;
|
|
const int nScale = 2;
|
int nWidth = pSource->GetWidth() / nScale;
|
int nHeight = pSource->GetHeight() / nScale;
|
|
if (!pResult->CreateImage(nWidth, nHeight)) return 0;
|
|
const int nSrcWidthStep = pSource->GetWidthStep() * nScale;
|
const int nResWidthStep = pResult->GetWidthStep();
|
|
BYTE *pSrcBuf, *pResBuf, *pSrcImg, *pResImg;
|
pSrcBuf = (BYTE*)pSource->GetImageBuffer();
|
pResBuf = (BYTE*)pResult->GetImageBuffer();
|
|
unsigned long long mask[2] = {0x00FF00FF00FF00FF, 0x00FF00FF00FF00FF};
|
__m128i MaskData = _mm_loadu_si128((const __m128i*)mask);
|
__m128i CurrentData;
|
|
for (int i=0; i<nHeight; i++)
|
{
|
pSrcImg = pSrcBuf;
|
pResImg = pResBuf;
|
|
int j=0;
|
for (j=0; j<nWidth-8; j+=8)
|
{
|
CurrentData = _mm_loadu_si128((const __m128i*)(pSrcImg));
|
CurrentData = _mm_and_si128(CurrentData, MaskData);
|
CurrentData = _mm_packus_epi16(CurrentData, CurrentData);
|
|
_mm_storel_epi64((__m128i*)pResImg, CurrentData);
|
|
pSrcImg += 16;
|
pResImg += 8;
|
}
|
|
for (; j<nWidth; j++)
|
{
|
*pResImg = *pSrcImg;
|
pSrcImg += nScale;
|
pResImg++;
|
}
|
|
pSrcBuf += nSrcWidthStep;
|
pResBuf += nResWidthStep;
|
|
}
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageResizeQuarter(CCHImageData* pSource, CCHImageData* pResult)
|
{
|
if (pSource==NULL || pResult==NULL) return 0;
|
|
if (!pSource->GetImageExist()) return 0;
|
|
if (pSource->GetChannels()!=1) return 0;
|
|
const int nScale = 4;
|
int nWidth = pSource->GetWidth() / nScale;
|
int nHeight = pSource->GetHeight() / nScale;
|
|
if (!pResult->CreateImage(nWidth, nHeight)) return 0;
|
|
const int nSrcWidthStep = pSource->GetWidthStep() * nScale;
|
const int nResWidthStep = pResult->GetWidthStep();
|
|
BYTE *pSrcBuf, *pResBuf, *pSrcImg, *pResImg;
|
pSrcBuf = (BYTE*)pSource->GetImageBuffer();
|
pResBuf = (BYTE*)pResult->GetImageBuffer();
|
|
unsigned long long mask[2] = {0x000000FF000000FF, 0x000000FF000000FF};
|
__m128i MaskData = _mm_loadu_si128((const __m128i*)mask);
|
__m128i CurrentData1;
|
__m128i CurrentData2;
|
|
for (int i=0; i<nHeight; i++)
|
{
|
pSrcImg = pSrcBuf;
|
pResImg = pResBuf;
|
|
int j;
|
for (j=0; j<nWidth-8; j+=8)
|
{
|
CurrentData1 = _mm_loadu_si128((const __m128i*)(pSrcImg));
|
CurrentData2 = _mm_loadu_si128((const __m128i*)(pSrcImg+16));
|
|
CurrentData1 = _mm_and_si128(CurrentData1, MaskData);
|
CurrentData2 = _mm_and_si128(CurrentData2, MaskData);
|
|
CurrentData1 = _mm_packus_epi16(CurrentData1, CurrentData2);
|
CurrentData1 = _mm_packus_epi16(CurrentData1, CurrentData1);
|
|
_mm_storel_epi64((__m128i*)pResImg, CurrentData1);
|
|
pSrcImg += 32;
|
pResImg += 8;
|
}
|
|
for (; j<nWidth; j++)
|
{
|
*pResImg = *pSrcImg;
|
pSrcImg += nScale;
|
pResImg++;
|
}
|
|
pSrcBuf += nSrcWidthStep;
|
pResBuf += nResWidthStep;
|
}
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageResizeOneEighth(CCHImageData* pSource, CCHImageData* pResult)
|
{
|
if (pSource==NULL || pResult==NULL) return 0;
|
|
if (!pSource->GetImageExist()) return 0;
|
|
if (pSource->GetChannels()!=1) return 0;
|
|
const int nScale = 8;
|
int nWidth = pSource->GetWidth() / nScale;
|
int nHeight = pSource->GetHeight() / nScale;
|
|
if (!pResult->CreateImage(nWidth, nHeight)) return 0;
|
|
const int nSrcWidthStep = pSource->GetWidthStep() * nScale;
|
const int nResWidthStep = pResult->GetWidthStep();
|
|
BYTE *pSrcBuf, *pResBuf, *pSrcImg, *pResImg;
|
pSrcBuf = (BYTE*)pSource->GetImageBuffer();
|
pResBuf = (BYTE*)pResult->GetImageBuffer();
|
|
unsigned long long mask[2] = {0x00000000000000FF, 0x00000000000000FF};
|
__m128i MaskData = _mm_loadu_si128((const __m128i*)mask);
|
__m128i CurrentData1;
|
__m128i CurrentData2;
|
__m128i CurrentData3;
|
__m128i CurrentData4;
|
|
for (int i=0; i<nHeight; i++)
|
{
|
pSrcImg = pSrcBuf;
|
pResImg = pResBuf;
|
|
int j;
|
for (j=0; j<nWidth-8; j+=8)
|
{
|
CurrentData1 = _mm_loadu_si128((const __m128i*)(pSrcImg));
|
CurrentData2 = _mm_loadu_si128((const __m128i*)(pSrcImg+16));
|
CurrentData3 = _mm_loadu_si128((const __m128i*)(pSrcImg+32));
|
CurrentData4 = _mm_loadu_si128((const __m128i*)(pSrcImg+48));
|
|
CurrentData1 = _mm_and_si128(CurrentData1, MaskData);
|
CurrentData2 = _mm_and_si128(CurrentData2, MaskData);
|
CurrentData3 = _mm_and_si128(CurrentData3, MaskData);
|
CurrentData4 = _mm_and_si128(CurrentData4, MaskData);
|
|
CurrentData1 = _mm_packus_epi16(CurrentData1, CurrentData2);
|
CurrentData3 = _mm_packus_epi16(CurrentData3, CurrentData4);
|
|
CurrentData1 = _mm_packus_epi16(CurrentData1, CurrentData3);
|
|
CurrentData1 = _mm_packus_epi16(CurrentData1, CurrentData1);
|
|
_mm_storel_epi64((__m128i*)pResImg, CurrentData1);
|
|
pSrcImg += 64;
|
pResImg += 8;
|
}
|
|
for (; j<nWidth; j++)
|
{
|
*pResImg = *pSrcImg;
|
pSrcImg += nScale;
|
pResImg++;
|
}
|
|
pSrcBuf += nSrcWidthStep;
|
pResBuf += nResWidthStep;
|
}
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageAverage(BYTE* pSrcImage, BYTE *pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage==NULL || pDstImage==NULL) return 0;
|
|
__m128i zeroData = _mm_setzero_si128();
|
__m128i currentData = _mm_setzero_si128();
|
__m128i totalData = _mm_setzero_si128();
|
__m128i divData = _mm_set1_epi16(65536/9);
|
__m128i k1 = _mm_setzero_si128();
|
__m128i k2 = _mm_setzero_si128();
|
__m128i k3 = _mm_setzero_si128();
|
__m128i k4 = _mm_setzero_si128();
|
|
static int nShiftOne, nShiftTwo;
|
|
register BYTE *pSrcImageX, *pDstImageX;
|
|
int nY1X0 = nWidth;
|
int nY2X0 = 2*nWidth;
|
|
for (int y=0; y<nHeight-2; y++)
|
{
|
pSrcImageX = pSrcImage + (y*nWidth);
|
pDstImageX = pDstImage + ((y+1)*nWidth) + 1;
|
|
for (int x=0; x<nWidth; x+=8)
|
{
|
// get pixel data (y,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX));
|
k1 = _mm_unpacklo_epi8(currentData, zeroData); // low
|
k2 = _mm_unpackhi_epi8(currentData, zeroData); // high
|
nShiftOne = _mm_extract_epi16(k2, 0);
|
nShiftTwo = _mm_extract_epi16(k2, 1);
|
k3 = _mm_srli_si128(k1, 2);
|
k3 = _mm_insert_epi16(k3, nShiftOne, 7);
|
k4 = _mm_srli_si128(k3, 2);
|
k4 = _mm_insert_epi16(k4, nShiftTwo, 7);
|
|
totalData = _mm_add_epi16(k1, k3); // k1 + k3
|
totalData = _mm_add_epi16(totalData, k4); // k4
|
|
// get pixel data (y+1,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0));
|
k1 = _mm_unpacklo_epi8(currentData, zeroData); // low
|
k2 = _mm_unpackhi_epi8(currentData, zeroData); // high
|
nShiftOne = _mm_extract_epi16(k2, 0);
|
nShiftTwo = _mm_extract_epi16(k2, 1);
|
k3 = _mm_srli_si128(k1, 2);
|
k3 = _mm_insert_epi16(k3, nShiftOne, 7);
|
k4 = _mm_srli_si128(k3, 2);
|
k4 = _mm_insert_epi16(k4, nShiftTwo, 7);
|
|
totalData = _mm_add_epi16(totalData, k1); // k1
|
totalData = _mm_add_epi16(totalData, k3); // k3
|
totalData = _mm_add_epi16(totalData, k4); // k4
|
|
// get pixel data (y+2,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0));
|
k1 = _mm_unpacklo_epi8(currentData, zeroData); // low
|
k2 = _mm_unpackhi_epi8(currentData, zeroData); // high
|
nShiftOne = _mm_extract_epi16(k2, 0);
|
nShiftTwo = _mm_extract_epi16(k2, 1);
|
k3 = _mm_srli_si128(k1, 2);
|
k3 = _mm_insert_epi16(k3, nShiftOne, 7);
|
k4 = _mm_srli_si128(k3, 2);
|
k4 = _mm_insert_epi16(k4, nShiftTwo, 7);
|
|
totalData = _mm_add_epi16(totalData, k1); // k1
|
totalData = _mm_add_epi16(totalData, k3); // k3
|
totalData = _mm_add_epi16(totalData, k4); // k4
|
|
totalData = _mm_srai_epi16(totalData, 3);
|
|
totalData = _mm_packus_epi16(totalData, totalData); // last result
|
|
_mm_storel_epi64( (__m128i*)(pDstImageX), totalData);
|
|
pSrcImageX += 8;
|
pDstImageX += 8;
|
}
|
|
}
|
|
memcpy(pDstImage, pSrcImage, nWidth);
|
memcpy(pDstImage+((nHeight-1)*nWidth), pSrcImage+((nHeight-1)*nWidth), nWidth);
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageErode(BYTE* pSrcImage, BYTE *pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage==NULL || pDstImage==NULL) return 0;
|
|
__m128i p1 = _mm_setzero_si128();
|
__m128i p2 = _mm_setzero_si128();
|
__m128i p3 = _mm_setzero_si128();
|
__m128i p4 = _mm_setzero_si128();
|
__m128i s = _mm_setzero_si128();
|
__m128i t = _mm_setzero_si128();
|
__m128i u = _mm_setzero_si128();
|
__m128i v = _mm_setzero_si128();
|
|
|
register BYTE *pSrcImageX, *pDstImageX;
|
register int nShiftOne, nShiftTwo;
|
register int nY1X0 = nWidth;
|
register int nY2X0 = 2*nWidth;
|
|
register int nLast = (nWidth % 16) ? 6: 2;
|
|
int nSrcIdx = 0;
|
int nDstIdx = 0;
|
|
for (int y=0; y<nHeight-2; y++)
|
{
|
pSrcImageX = pSrcImage + (y*nWidth);
|
pDstImageX = pDstImage + ((y+1)*nWidth) + 1;
|
|
nSrcIdx = (y*nWidth);
|
nDstIdx = ((y+1)*nWidth) + 1;
|
|
*(pDstImageX-1) = 0;
|
|
for (int x=0; x<nWidth; x+=16)
|
{
|
// get pixel data (y,x), (y,x+16)
|
p1 = _mm_loadu_si128((__m128i*)(pSrcImageX));
|
p2 = _mm_loadu_si128((__m128i*)(pSrcImageX+16));
|
|
nShiftOne = _mm_extract_epi8(p2, 0);
|
nShiftTwo = _mm_extract_epi8(p2, 1);
|
|
p3 = _mm_srli_si128(p1, 1);
|
p3 = _mm_insert_epi8(p3, nShiftOne, 15);
|
p4 = _mm_srli_si128(p3, 1);
|
p4 = _mm_insert_epi8(p4, nShiftTwo, 15);
|
|
// first line and
|
s = _mm_and_si128(p1, p3); // p1 & p3
|
s = _mm_and_si128(s, p4); // p1 & p3 & p4
|
|
// get pixel data (y+1,x), (y+1,x+16)
|
p1 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0));
|
p2 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0+16));
|
|
nShiftOne = _mm_extract_epi8(p2, 0);
|
nShiftTwo = _mm_extract_epi8(p2, 1);
|
|
p3 = _mm_srli_si128(p1, 1);
|
p3 = _mm_insert_epi8(p3, nShiftOne, 15);
|
p4 = _mm_srli_si128(p3, 1);
|
p4 = _mm_insert_epi8(p4, nShiftTwo, 15);
|
|
// second line and
|
t = _mm_and_si128(p1, p3); // p1 & p3
|
t = _mm_and_si128(t, p4); // p1 & p3 & p4
|
|
// get pixel data (y+2,x), (y+2,x+16)
|
p1 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0));
|
p2 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0+16));
|
|
nShiftOne = _mm_extract_epi8(p2, 0);
|
nShiftTwo = _mm_extract_epi8(p2, 1);
|
|
p3 = _mm_srli_si128(p1, 1);
|
p3 = _mm_insert_epi8(p3, nShiftOne, 15);
|
p4 = _mm_srli_si128(p3, 1);
|
p4 = _mm_insert_epi8(p4, nShiftTwo, 15);
|
|
// second line and
|
u = _mm_and_si128(p1, p3); // p1 & p3
|
u = _mm_and_si128(u, p4); // p1 & p3 & p4
|
|
// last result
|
v = _mm_and_si128(s, t); // s & t
|
v = _mm_and_si128(v, u); // s & t & u
|
|
_mm_storeu_si128( (__m128i*)(pDstImageX), v);
|
|
pSrcImageX += 16;
|
pDstImageX += 16;
|
|
nSrcIdx += 16;
|
nDstIdx += 16;
|
}
|
|
*(pDstImageX-nLast) = 0;
|
|
}
|
|
memset(pDstImage, 0, nWidth);
|
memset(pDstImage+((nHeight-1)*nWidth), 0, nWidth);
|
|
return 1;
|
|
}
|
|
int CEdgeTriangle::ImageOR(BYTE* pSrcImage1, BYTE *pSrcImage2, BYTE* pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage1==NULL || pSrcImage2==NULL || pDstImage==NULL) return 0;
|
|
register BYTE *pSrcBuffer1 = pSrcImage1;
|
register BYTE *pSrcBuffer2 = pSrcImage2;
|
register BYTE *pDstBuffer = pDstImage;
|
|
__m128i v0, v1, r;
|
|
register int i;
|
register int nTotalSize = nWidth*nHeight;
|
|
for(i=0; i<=nTotalSize-16; i+=16 )
|
{
|
v0 = _mm_loadu_si128( (const __m128i*)(pSrcBuffer1) );
|
v1 = _mm_loadu_si128( (const __m128i*)(pSrcBuffer2) );
|
|
r = _mm_or_si128(v0, v1);
|
|
_mm_storeu_si128( (__m128i*)(pDstBuffer), r );
|
pSrcBuffer1 += 16;
|
pSrcBuffer2 += 16;
|
pDstBuffer += 16;
|
}
|
|
for( ; i <=nTotalSize-8; i+=8 )
|
{
|
v0 = _mm_loadl_epi64( (const __m128i*)(pSrcBuffer1) );
|
v1 = _mm_loadl_epi64( (const __m128i*)(pSrcBuffer2) );
|
|
r = _mm_or_si128(v0, v1);
|
|
_mm_storel_epi64( (__m128i*)(pDstBuffer), r );
|
pSrcBuffer1 += 8;
|
pSrcBuffer2 += 8;
|
pDstBuffer += 8;
|
}
|
|
for ( ; i<nTotalSize; i++)
|
{
|
*(pDstBuffer++) = (*pSrcBuffer1++)|(*pSrcBuffer2++);
|
}
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageAND(BYTE* pSrcImage1, BYTE *pSrcImage2, BYTE* pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage1==NULL || pSrcImage2==NULL || pDstImage==NULL) return 0;
|
|
register BYTE *pSrcBuffer1 = pSrcImage1;
|
register BYTE *pSrcBuffer2 = pSrcImage2;
|
register BYTE *pDstBuffer = pDstImage;
|
|
__m128i v0, v1, r;
|
|
register int i;
|
register int nTotalSize = nWidth*nHeight;
|
|
for(i=0; i<=nTotalSize-16; i+=16 )
|
{
|
v0 = _mm_loadu_si128( (const __m128i*)(pSrcBuffer1) );
|
v1 = _mm_loadu_si128( (const __m128i*)(pSrcBuffer2) );
|
|
r = _mm_and_si128(v0, v1);
|
|
_mm_storeu_si128( (__m128i*)(pDstBuffer), r );
|
pSrcBuffer1 += 16;
|
pSrcBuffer2 += 16;
|
pDstBuffer += 16;
|
}
|
|
for( ; i <=nTotalSize-8; i+=8 )
|
{
|
v0 = _mm_loadl_epi64( (const __m128i*)(pSrcBuffer1) );
|
v1 = _mm_loadl_epi64( (const __m128i*)(pSrcBuffer2) );
|
|
r = _mm_and_si128(v0, v1);
|
|
_mm_storel_epi64( (__m128i*)(pDstBuffer), r );
|
pSrcBuffer1 += 8;
|
pSrcBuffer2 += 8;
|
pDstBuffer += 8;
|
}
|
|
for ( ; i<nTotalSize; i++)
|
{
|
*(pDstBuffer++) = (*pSrcBuffer1++)&(*pSrcBuffer2++);
|
}
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageExclusiveOR(BYTE* pSrcImage1, BYTE *pSrcImage2, BYTE* pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage1==NULL || pSrcImage2==NULL || pDstImage==NULL) return 0;
|
|
register BYTE *pSrcBuffer1 = pSrcImage1;
|
register BYTE *pSrcBuffer2 = pSrcImage2;
|
register BYTE *pDstBuffer = pDstImage;
|
|
__m128i v0, v1, r;
|
|
register int i;
|
register int nTotalSize = nWidth*nHeight;
|
|
for(i=0; i<=nTotalSize-16; i+=16 )
|
{
|
v0 = _mm_loadu_si128( (const __m128i*)(pSrcBuffer1) );
|
v1 = _mm_loadu_si128( (const __m128i*)(pSrcBuffer2) );
|
|
r = _mm_xor_si128(v0, v1);
|
|
_mm_storeu_si128( (__m128i*)(pDstBuffer), r );
|
pSrcBuffer1 += 16;
|
pSrcBuffer2 += 16;
|
pDstBuffer += 16;
|
}
|
|
for( ; i <=nTotalSize-8; i+=8 )
|
{
|
v0 = _mm_loadl_epi64( (const __m128i*)(pSrcBuffer1) );
|
v1 = _mm_loadl_epi64( (const __m128i*)(pSrcBuffer2) );
|
|
r = _mm_xor_si128(v0, v1);
|
|
_mm_storel_epi64( (__m128i*)(pDstBuffer), r );
|
pSrcBuffer1 += 8;
|
pSrcBuffer2 += 8;
|
pDstBuffer += 8;
|
}
|
|
for ( ; i<nTotalSize; i++)
|
{
|
*(pDstBuffer++) = (*pSrcBuffer1++)^(*pSrcBuffer2++);
|
}
|
|
return 1;
|
}
|
|
|
int CEdgeTriangle::ImageDilate(BYTE* pSrcImage, BYTE *pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage==NULL || pDstImage==NULL) return 0;
|
|
__m128i p1 = _mm_setzero_si128();
|
__m128i p2 = _mm_setzero_si128();
|
__m128i p3 = _mm_setzero_si128();
|
__m128i p4 = _mm_setzero_si128();
|
__m128i s = _mm_setzero_si128();
|
__m128i t = _mm_setzero_si128();
|
__m128i u = _mm_setzero_si128();
|
__m128i v = _mm_setzero_si128();
|
|
register BYTE *pSrcImageX, *pDstImageX;
|
register int nShiftOne, nShiftTwo;
|
register int nY1X0 = nWidth;
|
register int nY2X0 = 2*nWidth;
|
|
register int nLast = (nWidth % 16) ? 6: 2;
|
|
for (int y=0; y<nHeight-2; y++)
|
{
|
pSrcImageX = pSrcImage + (y*nWidth);
|
pDstImageX = pDstImage + ((y+1)*nWidth) + 1;
|
|
*(pDstImageX-1) = 0;
|
|
for (int x=0; x<nWidth; x+=16)
|
{
|
// get pixel data (y,x), (y,x+16)
|
p1 = _mm_loadu_si128((__m128i*)(pSrcImageX));
|
p2 = _mm_loadu_si128((__m128i*)(pSrcImageX+16));
|
|
nShiftOne = _mm_extract_epi8(p2, 0);
|
nShiftTwo = _mm_extract_epi8(p2, 1);
|
|
p3 = _mm_srli_si128(p1, 1);
|
p3 = _mm_insert_epi8(p3, nShiftOne, 15);
|
p4 = _mm_srli_si128(p3, 1);
|
p4 = _mm_insert_epi8(p4, nShiftTwo, 15);
|
|
// first line and
|
s = _mm_or_si128(p1, p3); // p1 & p3
|
s = _mm_or_si128(s, p4); // p1 & p3 & p4
|
|
// get pixel data (y+1,x), (y+1,x+16)
|
p1 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0));
|
p2 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0+16));
|
|
nShiftOne = _mm_extract_epi8(p2, 0);
|
nShiftTwo = _mm_extract_epi8(p2, 1);
|
|
p3 = _mm_srli_si128(p1, 1);
|
p3 = _mm_insert_epi8(p3, nShiftOne, 15);
|
p4 = _mm_srli_si128(p3, 1);
|
p4 = _mm_insert_epi8(p4, nShiftTwo, 15);
|
|
// second line and
|
t = _mm_or_si128(p1, p3); // p1 & p3
|
t = _mm_or_si128(t, p4); // p1 & p3 & p4
|
|
// get pixel data (y+2,x), (y+2,x+16)
|
p1 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0));
|
p2 = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0+16));
|
|
nShiftOne = _mm_extract_epi8(p2, 0);
|
nShiftTwo = _mm_extract_epi8(p2, 1);
|
|
p3 = _mm_srli_si128(p1, 1);
|
p3 = _mm_insert_epi8(p3, nShiftOne, 15);
|
p4 = _mm_srli_si128(p3, 1);
|
p4 = _mm_insert_epi8(p4, nShiftTwo, 15);
|
|
// second line and
|
u = _mm_or_si128(p1, p3); // p1 & p3
|
u = _mm_or_si128(u, p4); // p1 & p3 & p4
|
|
// last result
|
v = _mm_or_si128(s, t); // s & t
|
v = _mm_or_si128(v, u); // s & t & u
|
|
_mm_storeu_si128( (__m128i*)(pDstImageX), v);
|
|
pSrcImageX += 16;
|
pDstImageX += 16;
|
}
|
}
|
|
memset(pDstImage, 0, nWidth);
|
memset(pDstImage+((nHeight-1)*nWidth), 0, nWidth);
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageSobelEdge(BYTE* pSrcImage, BYTE *pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage==NULL || pDstImage==NULL) return 0;
|
|
__m128i zeroData = _mm_setzero_si128();
|
__m128i currentData = _mm_setzero_si128();
|
__m128i sobelData = _mm_set1_epi16(2);
|
__m128i lowUnpack = _mm_setzero_si128(); // low unpack
|
__m128i highUnpack = _mm_setzero_si128(); // high unpack
|
__m128i multiData = _mm_setzero_si128();
|
__m128i TopKernel = _mm_setzero_si128();
|
__m128i BottomKernel = _mm_setzero_si128();
|
__m128i tempData = _mm_setzero_si128();
|
|
register BYTE *pSrcImageX, *pDstImageX;
|
register int nShiftOne, nShiftTwo;
|
register int nY0X2 = 2;
|
register int nY1X0 = nWidth;
|
register int nY1X2 = nWidth + 2;
|
register int nY2X0 = 2*nWidth;
|
register int nY2X2 = 2*nWidth + 2;
|
register int nLast = (nWidth % 8) ? 6: 2;
|
|
for (int y=0; y<nHeight-2; y++)
|
{
|
pSrcImageX = pSrcImage + (y*nWidth);
|
pDstImageX = pDstImage + ((y+1)*nWidth) + 1;
|
|
*(pDstImageX-1) = 0;
|
|
for (int x=0; x<nWidth; x+=8)
|
{
|
// [1] vertical kernel
|
|
// get pixel data (y+2,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0));
|
tempData = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_unpackhi_epi8(currentData, zeroData); // high
|
|
nShiftOne = _mm_extract_epi16(highUnpack, 0);
|
nShiftTwo = _mm_extract_epi16(highUnpack, 1);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(tempData, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftOne, 7);
|
|
// mul * 2
|
multiData = _mm_mullo_epi16(highUnpack, sobelData);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(highUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftTwo, 7);
|
|
BottomKernel = _mm_add_epi16(tempData, multiData);
|
BottomKernel = _mm_add_epi16(BottomKernel, highUnpack); // top kernel value
|
|
// get pixel data (y,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX));
|
lowUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_unpackhi_epi8(currentData, zeroData); // high
|
|
nShiftOne = _mm_extract_epi16(highUnpack, 0);
|
nShiftTwo = _mm_extract_epi16(highUnpack, 1);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(lowUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftOne, 7);
|
|
// mul * 2
|
multiData = _mm_mullo_epi16(highUnpack, sobelData);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(highUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftTwo, 7);
|
|
TopKernel = _mm_add_epi16(lowUnpack, multiData);
|
TopKernel = _mm_add_epi16(TopKernel, highUnpack); // top kernel value
|
|
TopKernel = _mm_sub_epi16(TopKernel, BottomKernel); // top + bottom
|
TopKernel = _mm_abs_epi16(TopKernel); // horizontal result
|
|
// lowUnpack, TopKernel, sobelData, currentData,
|
|
// [1] Horizontal kernel
|
// get pixel data (y+1,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_mullo_epi16(highUnpack, sobelData); // mul * 2
|
lowUnpack = _mm_add_epi16(lowUnpack, highUnpack); // add result
|
|
// get pixel data (y+2,x)
|
// currentData = _mm_loadu_si128((__m128i*)(pSrcImage+((y+2)*nWidth)+x));
|
// highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
lowUnpack = _mm_add_epi16(lowUnpack, tempData); // add result
|
|
// get pixel data (y,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY0X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
// get pixel data (y+1,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_mullo_epi16(highUnpack, sobelData); // mul * 2
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
// get pixel data (y+2,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
lowUnpack = _mm_abs_epi16(lowUnpack); // abs result
|
TopKernel = _mm_add_epi16(TopKernel, lowUnpack); // add horizontal + vertical
|
|
TopKernel = _mm_srai_epi16(TopKernel, 1); // shift right 1 <add>
|
|
TopKernel = _mm_packus_epi16(TopKernel, TopKernel); // last result
|
|
_mm_storel_epi64( (__m128i*)(pDstImageX), TopKernel);
|
|
pSrcImageX += 8;
|
pDstImageX += 8;
|
}
|
|
*(pDstImageX-nLast) = 0;
|
}
|
|
memset(pDstImage, 0, nWidth);
|
memset(pDstImage+((nHeight-1)*nWidth), 0, nWidth);
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageThresholding(BYTE* pImage, int nWidth, int nHeight, int nThresValue)
|
{
|
if (pImage==NULL) return 0;
|
|
register BYTE *pBuffer = pImage;
|
|
__m128i _x80 = _mm_set1_epi8('\x80');
|
__m128i ThresData = _mm_set1_epi8(uchar(nThresValue)^0x80);
|
__m128i v0, v1;
|
|
register int i;
|
register int nTotalSize = nWidth*nHeight;
|
|
for(i=0; i<=nTotalSize-32; i+=32 )
|
{
|
v0 = _mm_loadu_si128( (const __m128i*)(pBuffer) );
|
v1 = _mm_loadu_si128( (const __m128i*)(pBuffer+16) );
|
v0 = _mm_cmpgt_epi8( _mm_xor_si128(v0, _x80), ThresData );
|
v1 = _mm_cmpgt_epi8( _mm_xor_si128(v1, _x80), ThresData );
|
_mm_storeu_si128( (__m128i*)(pBuffer), v0 );
|
_mm_storeu_si128( (__m128i*)(pBuffer+16), v1 );
|
pBuffer+=32;
|
}
|
|
for( ; i <=nTotalSize-8; i+=8 )
|
{
|
v0 = _mm_loadl_epi64( (const __m128i*)(pBuffer) );
|
v0 = _mm_cmpgt_epi8( _mm_xor_si128(v0, _x80), ThresData );
|
_mm_storel_epi64( (__m128i*)(pBuffer), v0 );
|
pBuffer+=8;
|
}
|
|
for (; i<nTotalSize; i++)
|
{
|
*(pBuffer++) = (*pBuffer>nThresValue) ? 255: 0;
|
}
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageThinning(BYTE* pImage, int nWidth, int nHeight)
|
{
|
if (pImage==NULL) return 0;
|
|
// Rosenfeld _parallel thinning algorithm from Graphics Gems with some modifications;
|
// running calculation of weight number;
|
|
static int pMasks[]={0x80, 0x02, 0x20, 0x08} ;
|
BYTE *pKernel = new BYTE[nWidth];
|
|
pKernel[nWidth-1] = 0; // Used for lower-right pixel
|
|
int nCount = 1;
|
int nPassCount = 0;
|
register BYTE *pSubX, *pSubY;
|
|
while (nCount) // Scan image while deletions
|
{
|
nCount = 0;
|
nPassCount++;
|
|
for (int i=0 ; i<4 ; i++)
|
{
|
int m = pMasks[i];
|
|
// set image pointer
|
pSubX = pSubY = pImage+nWidth+1;
|
|
// Build initial previous scan buffer.
|
int p = (*(pSubX++)!=0);
|
|
pKernel[0] = p;
|
|
for (int x=1; x<nWidth-1; x++)
|
{
|
p = ((p<<1)&0x06) | (*(pSubX++)!=0);
|
pKernel[x] = p ;
|
}
|
|
// Scan image for pixel deletion candidates.
|
|
pSubY += nWidth;
|
|
for (int y=1; y<nHeight-1; y++)
|
{
|
int q = pKernel[0];
|
|
p = ((q<<3)&0x48) | (*pSubY!=0);
|
pKernel[0] = p;
|
pSubX = (pSubY+1);
|
|
for (int x=1 ; x<nWidth-1; x++)
|
{
|
q = pKernel[x];
|
p = ((p<<1)&0x1B6) | ((q<<3)&0x48) | (*(pSubX++)!=0);
|
|
//0x1B6=110110110=2^8 + 2^7 +2^5 + 2^4 + 2^2 + 2^1;
|
//0x48=1001000=2^6 + 2^3
|
|
pKernel[x] = p;
|
|
if (((p&m) == 0) && pDeleteArray[p] )
|
{
|
nCount++;
|
*(pImage+(y*nWidth)+x) = 0;
|
}
|
}
|
|
pSubY += nWidth;
|
}
|
}
|
}
|
|
delete[] pKernel;
|
|
return 1;
|
}
|
|
int CEdgeTriangle::ImageBlobAnalysis(BYTE *pImage, int nWidth, int nHeight, VectorPixelRegion& vectorRegion, int nBlobMargin)
|
{
|
if (pImage==NULL) return 0;
|
|
int nSizeThres = 8;
|
int i, j, y, x;
|
|
for (i=0; i<nHeight; i++)
|
{
|
*(pImage+(i*nWidth)) = 0;
|
*(pImage+(i*nWidth)+(nWidth-1)) = 0;
|
}
|
|
for (j=0; j<nWidth; j++)
|
{
|
*(pImage+j) = 0;
|
*(pImage+((nHeight-1)*nWidth)+j) = 0;
|
}
|
|
size_t nSize;
|
VectorPoint vectorPixel;
|
CPixelRegion pixelRegion;
|
register BYTE *pSrcImgY = pImage + (1*nWidth) + 1;
|
register BYTE *pSrcImgX, *pSubX, *pSubY;
|
|
for (i=1; i<nHeight-1; i++)
|
{
|
pSrcImgX = pSrcImgY;
|
for (j=1; j<nWidth-1; j++)
|
{
|
if (*pSrcImgX > 200)
|
{
|
*pSrcImgX = 128;
|
vectorPixel.push_back(CPoint(j, i));
|
|
// new pixel region
|
pixelRegion.Reset();
|
|
while ((nSize=vectorPixel.size())>0)
|
{
|
x = vectorPixel[nSize-1].x;
|
y = vectorPixel[nSize-1].y;
|
|
// delete end point
|
vectorPixel.pop_back();
|
|
// add point to new region
|
pixelRegion.vectorPoint.push_back(CPoint(x, y));
|
|
// get current point
|
pSubY = pImage + ((y-1)*nWidth) + (x-1);
|
|
for (int sy=-1; sy<2; sy++)
|
{
|
pSubX = pSubY;
|
for (int sx=-1; sx<2; sx++)
|
{
|
if (*pSubX > 200)
|
{
|
*pSubX = 128;
|
vectorPixel.push_back(CPoint(x+sx, y+sy));
|
}
|
pSubX++;
|
}
|
pSubY += nWidth;
|
}
|
|
if (pixelRegion.nLeft>x) pixelRegion.nLeft = x;
|
if (pixelRegion.nRight<x) pixelRegion.nRight = x;
|
if (pixelRegion.nTop>y) pixelRegion.nTop = y;
|
if (pixelRegion.nBottom<y) pixelRegion.nBottom = y;
|
}
|
|
vectorPixel.clear();
|
|
// check size
|
if (pixelRegion.vectorPoint.size()<nSizeThres) continue;
|
|
vectorRegion.push_back(pixelRegion);
|
} // end if
|
pSrcImgX++;
|
} //end for j
|
pSrcImgY += nWidth;
|
}// end for i
|
|
if (vectorRegion.size()==0) return 0;
|
|
// sort blob max size
|
std::sort(vectorRegion.begin(), vectorRegion.end(), CompareMaxSize);
|
|
return 1;
|
}
|