#include "StdAfx.h" #include "EdgeTriangle.h" #include "CHImageControls/CHImageProcess.h" #include "FormulaParser.h" #include "CHCommonClasses/ProcessTimer.h" #include "CHImageControls/CHDataFitting.h" #include #include #include #include #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 *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; iGetImageBuffer(); 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 _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; iGetBandImage(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 (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 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 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 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 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 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 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 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; iGetBandImage(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; im_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; im_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= 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= 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=0; i--) { kernelGaussian.push_back(kernelTemp[i]); } for (int i=0; i= 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=0; i--) { kernelData.push_back(-kernelTemp[i]); } kernelData.push_back(0.0); for (int i=0; i=0; i--) { kernelData.push_back(-kernelTemp[i]); } kernelData.push_back(0.0); for (int i=0; i= 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 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; i0; i--) { if (m_vectorEdgeType[i]!=edgeResult.nSignal) break; edgeResult.nLeftPosition = i; } for (i=edgeResult.nEdgePosition+1; i0; i--) { if (m_vectorEdgeType[i]!=edgeResult.nSignal) break; edgeResult.nLeftPosition = i; } for (i=edgeResult.nEdgePosition+1; i0; i--) { if (m_vectorEdgeType[i]!=edgeResult.nSignal) break; edgeResult.nLeftPosition = i; } for (i=edgeResult.nEdgePosition+1; i 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; im_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; ii) { 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; ii) { 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; im_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; iGetImageExist()) 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; iGetImageExist()) 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 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 (; inThresValue) ? 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 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.nRighty) pixelRegion.nTop = y; if (pixelRegion.nBottom