EdgeInspector_App/Process/InspectCamera.cpp
@@ -1,4 +1,4 @@
#include "StdAfx.h"
#include "StdAfx.h"
#include "InspectCamera.h"
#include "GlassRecipe.h"
#include "HardwareSettings.h"
@@ -15,14 +15,14 @@
#endif // USE_WEBSOCKET
#define BOUNDARY_GLASSSTARTWIDTH   160
#define BOUNDARYHORIZ_LEVELDIST      8   // 荐乞 版拌急阑 茫阑 锭狼 厚背芭府
#define BOUNDARYHORIZ_LEVELDIST      8   // 수평 경계선을 찾을 때의 비교거리
#define TIME_WAIT_GLASS_START      3000
#define align_4byte(in) ((in + 3)/4)*4
#define RAD_TO_DEGREE            (double)(180.0f / 3.1415926535f)
CInspectCamera::CInspectCamera(int iCam)
{
{
   m_iCamera = iCam;
   m_pThreadControl = new CThreadControl();
   m_pRecipe = NULL;
@@ -62,7 +62,7 @@
   ReleaseThread();
   ReleaseFullBuffer();
   if(m_pDefectControl != NULL)
   if (m_pDefectControl != NULL)
      delete m_pDefectControl;
   m_pDefectControl = NULL;
@@ -78,8 +78,8 @@
void CInspectCamera::ReleaseThread()
{
   m_bExitThread = TRUE;
   if(m_pThreadControl != NULL)
   m_bExitThread = TRUE;
   if (m_pThreadControl != NULL)
   {
      m_pThreadControl->ReleaseThreadControl();
      Sleep(100);
@@ -88,9 +88,9 @@
   }
}
int   CInspectCamera::InitInspect(int nThread,int maxDefect)
int   CInspectCamera::InitInspect(int nThread, int maxDefect)
{
   m_pThreadControl->InitThreadControl(nThread,this);
   m_pThreadControl->InitThreadControl(nThread, this);
   m_pDefectControl->InitDefectStorage(maxDefect);
@@ -113,7 +113,7 @@
   m_bExitThread = FALSE;
   CCameraSettings* pCamSetting = m_pHardparm->GetCameraSettings(m_iCamera, m_iScan);
   if(pCamSetting == NULL || m_pGlassData == NULL)
   if (pCamSetting == NULL || m_pGlassData == NULL)
   {
      g_pLog->DisplayMessage(_T("HW Setting Error.. or Glass Data Error.."));
      return FALSE;
@@ -125,12 +125,12 @@
   m_dPixelSizeX = pCamSetting->m_dConvResolution[m_pGlassData->GetStageNo()];
   m_dPixelSizeY = pCamSetting->m_dScanResolution[m_pGlassData->GetStageNo()];
   CSide_Data*   pSideData = m_pGlassData->GetSideData(pCamSetting->m_eDimension);
   CSide_Data* pSideData = m_pGlassData->GetSideData(pCamSetting->m_eDimension);
   pSideData->m_dPixelSizeX = m_dPixelSizeX;
   pSideData->m_dPixelSizeY = m_dPixelSizeY;
#if HALCON_VISION_KEY
   CBlSideData *pBlSideData = BlVision_GetVisionRecipe()->getSideData(pCamSetting->m_eDimension);
   CBlSideData* pBlSideData = BlVision_GetVisionRecipe()->getSideData(pCamSetting->m_eDimension);
   if (NULL != pBlSideData) {
      pBlSideData->m_mapSideLineInf.clear();
   }
@@ -145,12 +145,12 @@
BOOL CInspectCamera::ScanStartThread()
{
   if(m_pThreadControl == NULL)
      return FALSE;
   if (m_pThreadControl == NULL)
      return FALSE;
   int   nThread = m_pThreadControl->StartThreadControl();
   if(nThread <= 0)
   {
   if (nThread <= 0)
   {
      return FALSE;
   }
@@ -159,25 +159,25 @@
BOOL CInspectCamera::GetCheckFrame(stFrameIndex stFrame)
{
   CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,stFrame.nScanIdx);
   if(pCamera == NULL)
   CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(m_iCamera, stFrame.nScanIdx);
   if (pCamera == NULL)
      return FALSE;
   DimensionDir      emDim = pCamera->m_eDimension;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   int         nFrameHeight = pCamera->m_FrameSize.cy;
   int         nStartFrame = pSideData->m_nGlassStartLine/nFrameHeight;
   if(nStartFrame > stFrame.nFrameIdx)
   int         nFrameHeight = pCamera->m_FrameSize.cy;
   int         nStartFrame = pSideData->m_nGlassStartLine / nFrameHeight;
   if (nStartFrame > stFrame.nFrameIdx)
      return TRUE;
   return FALSE;
}
ERR_FIND_GLASSSTARTLINE CInspectCamera::IsGlassStartLine(int iThread,int &iScan)
ERR_FIND_GLASSSTARTLINE CInspectCamera::IsGlassStartLine(int iThread, int& iScan)
{
   iScan = m_iScan;
@@ -185,11 +185,11 @@
   stFrame.nScanIdx = m_iScan;
   if(m_bFindGlassStart[stFrame.nScanIdx] == TRUE)
   if (m_bFindGlassStart[stFrame.nScanIdx] == TRUE)
      return ERR_FINDGLASSSTART_SUCCESS;
   // 磊悼老锭 橇饭烙 荐甫 面盒洒 棱栏搁 巩力啊 救登绰芭 鞍促父... 橇饭烙 荐啊 何练窍搁 咯扁辑 公茄栏肺 吧覆.. 弊府绊 矫累急 茫疽栏搁 弊成 逞绢啊搁 登瘤 臼唱?
   if(m_pGrabber->GetGrabFrameCount() < 1)
   // 자동일때 프레임 수를 충분히 잡으면 문제가 안되는거 같다만... 프레임 수가 부족하면 여기서 무한으로 걸림.. 그리고 시작선 찾았으면 그냥 넘어가면 되지 않나?
   if (m_pGrabber->GetGrabFrameCount() < 1)
   {
      Sleep(0);
      return ERR_FINDGLASSSTART_FAIL;
@@ -204,63 +204,63 @@
      return ERR_FINDGLASSSTART_SUCCESS;
   */
   if(iThread != 0)
      return ERR_FINDGLASSSTART_FAIL;
   DimensionDir emDim = GetDimension(stFrame.nScanIdx);
   if (iThread != 0)
      return ERR_FINDGLASSSTART_FAIL;
   DimensionDir emDim = GetDimension(stFrame.nScanIdx);
   iScan = stFrame.nScanIdx;
   if(FindGlassStartLine(emDim,stFrame) == TRUE)
   if (FindGlassStartLine(emDim, stFrame) == TRUE)
   {
      g_pLog->DisplayMessage(_T("Find Start Line Success!"));
      ScanRegionSet(stFrame);
      ScanRegionSet(stFrame);
      m_bFindGlassStart[stFrame.nScanIdx] = TRUE;
      m_MsgJob.nState = 1;
      m_MsgJob.nDispLine = 0;
      m_MsgJob.nSide = (int)emDim;
      CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
      if(pSideData != NULL)
      if (pSideData != NULL)
         m_MsgJob.nDispLine = pSideData->m_nGlassStartLine;
      ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS,(WPARAM)&m_MsgJob, (int)emDim);
      ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)emDim);
      return ERR_FINDGLASSSTART_SUCCESS;
   }
   else
   {
   {
      return ERR_FINDGLASSSTART_FIND_FAIL;
   }
   return ERR_FINDGLASSSTART_FAIL;
}
BOOL CInspectCamera::OnThreadRun(int iThread, CInspectThread *pInspectThread)
BOOL CInspectCamera::OnThreadRun(int iThread, CInspectThread* pInspectThread)
{
   if(m_pRecipe == NULL)
      return FALSE;
   if(m_pHardparm == NULL)
   if (m_pRecipe == NULL)
      return FALSE;
   if(m_pGlassData == NULL)
   if (m_pHardparm == NULL)
      return FALSE;
   if(m_pGrabber == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   if (m_pGrabber == NULL)
      return FALSE;
   while(TRUE)
   while (TRUE)
   {
      Sleep(1);      // Sleep 1肺 吧绢拎具 茄促... 0栏肺 吧搁 八荤啊 救瞪嫐啊 乐澜.. 恐?
      Sleep(1);      // Sleep 1로 걸어줘야 한다... 0으로 걸면 검사가 안될‹š가 있음.. 왜?
      if(GetCheckExit() == TRUE)
      if (GetCheckExit() == TRUE)
      {
         g_pLog->DisplayMessage(_T("cam %d, Thread %d Thread Exit"),m_iCamera,iThread);
         g_pLog->DisplayMessage(_T("cam %d, Thread %d Thread Exit"), m_iCamera, iThread);
         break;
      }
      }
      // 1. 0锅 Thread肺 Start Line 茫扁
      // 1. 0번 Thread로 Start Line 찾기
      int iRetScan;
      switch(IsGlassStartLine(iThread,iRetScan))
      switch (IsGlassStartLine(iThread, iRetScan))
      {
      case ERR_FINDGLASSSTART_FAIL:
         continue;
@@ -269,19 +269,19 @@
         m_pGrabber->GrabScanStop();
         m_pGrabber->ClearGrabIdx();
         m_bExitThread = TRUE;
         g_pLog->DisplayMessage(_T("%s Process Find Glass StartLine Fail"),PANEL_SIDE[GetDimension(iRetScan)]);
         g_pLog->DisplayMessage(_T("%s Process Find Glass StartLine Fail"), PANEL_SIDE[GetDimension(iRetScan)]);
         m_MsgJob.nState = 1;
         m_MsgJob.nDispLine = 0;
         m_MsgJob.nSide = (int)GetDimension(m_iScan);
         ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS,(WPARAM)&m_MsgJob, (int)m_MsgJob.nSide);
         ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)m_MsgJob.nSide);
         continue;
         break;
      }
      // 2. Start Line阑 茫疽栏搁, 茄橇饭烙究 波郴辑 八荤 矫累
      }
      // 2. Start Line을 찾았으면, 한프레임씩 꺼내서 검사 시작
      stFrameIndex stFrame = m_pGrabber->GetGrabFrame();
      if(stFrame.nScanIdx < 0 || stFrame.nFrameIdx < 0)
      if (stFrame.nScanIdx < 0 || stFrame.nFrameIdx < 0)
         continue;
      DimensionDir emDim = GetDimension(stFrame.nScanIdx);
@@ -291,10 +291,10 @@
      m_pGlassData->GetSideData(emDim)->SetFrameProc(stFrame.nFrameIdx);
      // 3. Start Line Frame 焊促 捞傈牢瘤 眉农..
      if(CheckStartLineFrame(emDim,stFrame.nFrameIdx) == FALSE)
      // 3. Start Line Frame 보다 이전인지 체크..
      if (CheckStartLineFrame(emDim, stFrame.nFrameIdx) == FALSE)
      {
         g_pLog->DisplayMessage(_T("Check Start Line Frame.. %s : %d"),g_SideName[(int) emDim], stFrame.nFrameIdx);
         g_pLog->DisplayMessage(_T("Check Start Line Frame.. %s : %d"), g_SideName[(int)emDim], stFrame.nFrameIdx);
         continue;
      }
@@ -306,9 +306,9 @@
      SetFrameFinish(stFrame.nScanIdx, stFrame.nFrameIdx);
      BOOL bEnd = CheckThreadEnd(iThread,stFrame);
      if(stFrame.nFrameIdx % 5 == 0 && bEnd == FALSE && m_pGlassData->GetSideData(emDim)->m_bFindGlassEndLine == FALSE)
      BOOL bEnd = CheckThreadEnd(iThread, stFrame);
      if (stFrame.nFrameIdx % 5 == 0 && bEnd == FALSE && m_pGlassData->GetSideData(emDim)->m_bFindGlassEndLine == FALSE)
      {
         m_MsgJob.nState = 1;
         m_MsgJob.nDispLine = stFrame.nFrameIdx * m_nFrameHeight;
@@ -340,7 +340,7 @@
      }
   }
   g_pLog->DisplayMessage(_T("Camera %d-%d Thread End"),m_iCamera,iThread);
   g_pLog->DisplayMessage(_T("Camera %d-%d Thread End"), m_iCamera, iThread);
   return TRUE;
}
@@ -386,7 +386,7 @@
      pBlSideData->m_mBotMark.y = pSideData->m_ptBotMark_FindResult.y;
   }
   //添加此功能
   //警속늪묘콘
   pBlSideData->m_nStartLine = pSideData->m_nGlassStartLine;
   pBlSideData->m_nEndLine = pSideData->m_nGlassEndLine;
   pBlSideData->m_vDispVisionResult.clear();
@@ -400,12 +400,12 @@
   for (int i = 0; i < ngNum; i++) {
      NgInfo ng = ngArray[i];
      //if (ng.isRes)  continue;   //结果OK,继续
      //这里添加结果
      //if (ng.isRes)  continue;   //써벎OK,셨崎
      //侶쟁警속써벎
      if (5 == ng.ngType && (ng.result < ng.minValue || ng.result > ng.maxValue))
      {
         CDefect_Info defectInfo;
         defectInfo.m_iFrameIdx = stFrame.nFrameIdx; // stFrame.nFrameIdx;
         defectInfo.m_nCamID = m_iCamera;
@@ -418,72 +418,50 @@
         defectInfo.m_rtDefectPos_pxl = CRect(ng.xPosPxl, ng.yPosPxl, ng.xPosPxl + 50, ng.yPosPxl + 10);
         defectInfo.m_DefectLoc = DefectLoc_Corner_Chamfer;
         if (m_pDefectControl != NULL)
            m_pDefectControl->ExtractDefect_CorChamfer(eDim, m_iCamera, stFrame.nScanIdx, DefectLoc_Corner_Chamfer, defectInfo,  (int)(ng.result));
            m_pDefectControl->ExtractDefect_CorChamfer(eDim, m_iCamera, stFrame.nScanIdx, DefectLoc_Corner_Chamfer, defectInfo, (int)(ng.result));
      }
   }
#endif // HALCON_VISION_KEY
}
BOOL CInspectCamera::CheckThreadEnd(int iThread,stFrameIndex stFrame)
BOOL CInspectCamera::CheckThreadEnd(int iThread, stFrameIndex stFrame)
{
   int         iScan = stFrame.nScanIdx;
   CSingleLock   myLoc(&m_csThreadEnd);
   CSingleLock myLoc(&m_csThreadEnd);
   myLoc.Lock();
   // 捞固 场抄 Thread..
   if(m_iThreadEnd[iScan][iThread] == 1)
   {
   int        iScan = stFrame.nScanIdx;
   if (m_iThreadEnd[iScan][iThread] == 1) {
      myLoc.Unlock();
      return FALSE;
      return FALSE;
   }
   BOOL      bEnd = FALSE;
   if(CheckProcessEnd(iThread,stFrame) == TRUE)
   {
   BOOL bEnd = FALSE;
   if (CheckProcessEnd(iThread, stFrame) == TRUE) {
      m_iThreadEnd[iScan][iThread] = 1;
      bEnd = TRUE;
      myLoc.Unlock();
   }
   if(bEnd == TRUE)
   {
   if (bEnd == TRUE) {
      DimensionDir emDim = GetDimension(iScan);
      m_pGlassData->GetSideData(emDim)->m_bInspection_Complete = TRUE;
      g_pLog->DisplayMessage(_T("%s Thread %d Process End : Scan %d, Frame %d"),PANEL_SIDE[emDim],iThread,iScan,stFrame.nFrameIdx);
      if(GetThreadEndCount(iScan) == MAX_THREAD)
      {
      g_pLog->DisplayMessage(_T("%s Thread %d Process End : Scan %d, Frame %d"), PANEL_SIDE[emDim], iThread, iScan, stFrame.nFrameIdx);
      if (GetThreadEndCount(iScan) == MAX_THREAD) {
         myLoc.Lock();
         SaveFullImageCopy(iScan);
         myLoc.Unlock();
         g_pLog->DisplayMessage(_T("%s Scan Process All End"),PANEL_SIDE[emDim]);
         g_pLog->DisplayMessage(_T("%s Scan Process All End"), PANEL_SIDE[emDim]);
         FinallyVisionProc(emDim);
         if(m_pII2S != NULL)
            m_pII2S->II2S_InspectionEnd(m_iCamera,iScan);
         /*
         // Waiting All Frame Finish..
         DWORD dwTickCount = GetTickCount();
         while(GetTickCount() - dwTickCount < 5000)
         {
            if(CheckAllFrameFinish(iScan) == TRUE)
               break;
         if (m_pII2S != NULL) {
            m_pII2S->II2S_InspectionEnd(m_iCamera, iScan);
         }
         */
          //m_MsgJob.nState = 2;
          //m_MsgJob.nSide = (int)emDim;
         //m_MsgJob.nDispLine = stFrame.nFrameIdx * m_nFrameHeight;
          //::SendMessage(m_hWndViewScan, WM_POCESS_STATUS,(WPARAM)&m_MsgJob, (int)emDim);
      }
      }
   }
   myLoc.Unlock();
@@ -494,8 +472,8 @@
int   CInspectCamera::GetThreadEndCount(int iScan)
{
   int         nCount = 0;
   for(int i=0;i<MAX_THREAD;i++)
      if(m_iThreadEnd[iScan][i] == 1)
   for (int i = 0; i < MAX_THREAD; i++)
      if (m_iThreadEnd[iScan][i] == 1)
         nCount++;
   return nCount;
@@ -508,8 +486,9 @@
   m_nFrameFinishIdx[nCurrentScanIdx] = -1;
   for(int i=0; i<MAX_FRAM_COUNT; i++)
   for (int i = 0; i < MAX_FRAM_COUNT; i++) {
      m_bFrameFinish[nCurrentScanIdx][i] = FALSE;
   }
   cslocalLock.Unlock();
}
@@ -539,13 +518,19 @@
   CSingleLock cslocalLock(&m_csFrameFinishCheck);
   cslocalLock.Lock();
   if(m_nFrameFinishIdx[nCurrentScanIdx] == -1)
   if (m_nFrameFinishIdx[nCurrentScanIdx] == -1) {
      cslocalLock.Unlock();
      return FALSE;
   }
   for(int i=0; i<m_nFrameFinishIdx[nCurrentScanIdx]; i++)
      if(m_bFrameFinish[nCurrentScanIdx][i] == FALSE)
   for (int i = 0; i < m_nFrameFinishIdx[nCurrentScanIdx]; i++) {
      if (m_bFrameFinish[nCurrentScanIdx][i] == FALSE) {
         cslocalLock.Unlock();
         return FALSE;
      }
   }
   cslocalLock.Unlock();
   return TRUE;
}
@@ -574,44 +559,44 @@
   double dX_um = GetPixelToUm_X(ptEnd_pxl.x - ptStart_pxl.x);
   double dY_um = GetPixelToUm_Y(ptEnd_pxl.y - ptStart_pxl.y);
   return sqrt((dX_um*dX_um) + (dY_um*dY_um));
   return sqrt((dX_um * dX_um) + (dY_um * dY_um));
}
BOOL CInspectCamera::GetAlignRotate(DimensionDir emDim, CPoint ptSetTopMark, CPoint ptSetBotMark, CRect rtSetArea, CRect& bRotateArea)
{
   if(rtSetArea.IsRectEmpty() || rtSetArea.IsRectNull())
   if (rtSetArea.IsRectEmpty() || rtSetArea.IsRectNull())
      return FALSE;
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bTopMark_Find == FALSE || pSideData->m_bBotMark_Find == FALSE)
   if (pSideData->m_bTopMark_Find == FALSE || pSideData->m_bBotMark_Find == FALSE)
      return FALSE;
   CPoint ptSet_Area = rtSetArea.CenterPoint();
   double dSet_DiffX = (double) (ptSetBotMark.x - ptSetTopMark.x);
   double dSet_DiffY = (double) (ptSetBotMark.y - ptSetTopMark.y);
   double dset_T_Rad = (dSet_DiffY == 0.0) ? 0.0 : atan(dSet_DiffX/dSet_DiffY);
   double dSet_DiffX = (double)(ptSetBotMark.x - ptSetTopMark.x);
   double dSet_DiffY = (double)(ptSetBotMark.y - ptSetTopMark.y);
   double dset_T_Rad = (dSet_DiffY == 0.0) ? 0.0 : atan(dSet_DiffX / dSet_DiffY);
   CPoint ptFind_TopMark = pSideData->m_ptTopMark_FindResult;
   CPoint ptFind_BotMark = pSideData->m_ptBotMark_FindResult;
   double dFind_DiffX = (double) (ptFind_BotMark.x - ptFind_TopMark.x);
   double dFind_DiffY = (double) (ptFind_BotMark.y - ptFind_TopMark.y);
   double dFind_T_Rad = (dFind_DiffY == 0.0) ? 0.0 : atan(dFind_DiffX/dFind_DiffY);
   double dFind_DiffX = (double)(ptFind_BotMark.x - ptFind_TopMark.x);
   double dFind_DiffY = (double)(ptFind_BotMark.y - ptFind_TopMark.y);
   double dFind_T_Rad = (dFind_DiffY == 0.0) ? 0.0 : atan(dFind_DiffX / dFind_DiffY);
   double dDiff_T_Rad = dFind_T_Rad - dset_T_Rad;
   double dMarkToArea_X_pxl = ptSet_Area.x - ptSetTopMark.x;
   double dMarkToArea_Y_pxl = ptSet_Area.y - ptSetTopMark.y;
   double dMarkToArea_Distance_pxl = sqrt((dMarkToArea_X_pxl*dMarkToArea_X_pxl) + (dMarkToArea_Y_pxl*dMarkToArea_Y_pxl));
   double dMarkToArea_T_Rad = (dMarkToArea_Y_pxl == 0.0) ? 0.0 : atan(dMarkToArea_X_pxl/dMarkToArea_Y_pxl);
   double dMarkToArea_Distance_pxl = sqrt((dMarkToArea_X_pxl * dMarkToArea_X_pxl) + (dMarkToArea_Y_pxl * dMarkToArea_Y_pxl));
   double dMarkToArea_T_Rad = (dMarkToArea_Y_pxl == 0.0) ? 0.0 : atan(dMarkToArea_X_pxl / dMarkToArea_Y_pxl);
   double dRotateArea_T_Rad = dMarkToArea_T_Rad + dDiff_T_Rad;
@@ -620,25 +605,25 @@
   double dRotate_X_pxl = sin(dRotateArea_T_Rad) * dMarkToArea_Distance_pxl * dDirection;
   double dRotate_Y_pxl = cos(dRotateArea_T_Rad) * dMarkToArea_Distance_pxl * dDirection;
   bRotateArea.left = bRotateArea.right = (int) ptFind_TopMark.x + dRotate_X_pxl;
   bRotateArea.top = bRotateArea.bottom = (int) ptFind_TopMark.y + dRotate_Y_pxl;
   bRotateArea.left = bRotateArea.right = ptFind_TopMark.x + (LONG)dRotate_X_pxl;
   bRotateArea.top = bRotateArea.bottom = ptFind_TopMark.y + (LONG)dRotate_Y_pxl;
   bRotateArea.InflateRect(rtSetArea.Width()/2, rtSetArea.Height()/2);
   bRotateArea.InflateRect(rtSetArea.Width() / 2, rtSetArea.Height() / 2);
   return TRUE;
}
BOOL CInspectCamera::CopyRectImg(LPBYTE pOrg,LPBYTE pTgt,CSize szImg,CRect &rectIns)
BOOL CInspectCamera::CopyRectImg(LPBYTE pOrg, LPBYTE pTgt, CSize szImg, CRect& rectIns)
{
   if(pOrg == NULL || pTgt == NULL)
   if (pOrg == NULL || pTgt == NULL)
      return FALSE;
   int         v;
   int         dv = 0;
   for(v=rectIns.top;v<rectIns.bottom;v++,dv++)
   for (v = rectIns.top; v < rectIns.bottom; v++, dv++)
   {
      CopyMemory(pTgt+dv*rectIns.Width(),pOrg+v*szImg.cx+rectIns.left,rectIns.Width());
      CopyMemory(pTgt + dv * rectIns.Width(), pOrg + v * szImg.cx + rectIns.left, rectIns.Width());
   }
   return TRUE;
@@ -646,36 +631,36 @@
void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, COwnerBuffer* pBuffer, CString strFileName)
{
   if(m_pHardparm == NULL)
   if (m_pHardparm == NULL)
      return;
   if(m_pHardparm->m_bUse_SaveDebugImage == FALSE)
   if (m_pHardparm->m_bUse_SaveDebugImage == FALSE)
      return;
// #ifdef _DEBUG
   if(pBuffer == NULL)
   // #ifdef _DEBUG
   if (pBuffer == NULL)
      return;
   CString str;
   str.Format(_T("D:\\Inspection\\DebugFullImg\\%s_Side[%s]_Frame[%d].jpg"), strFileName, GetSideName(eDim), stFrame.nFrameIdx);
   g_pStatus->CheckDirectory(str);
   CBufferAttach saveImage(str);
   saveImage.AttachToFile(*pBuffer);
// #endif
   // #endif
}
void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, IplImage* pBuffer, CString strFileName)
{
   if(m_pHardparm == NULL)
   if (m_pHardparm == NULL)
      return;
   if(m_pHardparm->m_bUse_SaveDebugImage == FALSE)
   if (m_pHardparm->m_bUse_SaveDebugImage == FALSE)
      return;
// #ifdef _DEBUG
   if(pBuffer == NULL)
   // #ifdef _DEBUG
   if (pBuffer == NULL)
      return;
   CString str;
@@ -698,26 +683,28 @@
      g_pLog->DisplayMessage(_T("SaveDebugImage error..."));
   }
// #endif
   // #endif
}
void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, cv::Mat image, CString strFileName)
{
   if (m_pHardparm == NULL)
   if (m_pHardparm == NULL) {
      return;
   }
   if (m_pHardparm->m_bUse_SaveDebugImage == FALSE)
   if (m_pHardparm->m_bUse_SaveDebugImage == FALSE) {
      return;
   }
   // #ifdef _DEBUG
   if (image.empty() || image.data == NULL)
   if (image.empty() || image.data == NULL) {
      return;
   }
   CString str;
   str.Format(_T("D:\\Inspection\\DebugFullImg\\%s_Side[%s]_Frame[%d].jpg"), strFileName, GetSideName(eDim), stFrame.nFrameIdx);
   try
   {
   try {
      g_pStatus->CheckDirectory(str);
      USES_CONVERSION;
@@ -725,8 +712,7 @@
      std::string filePath(asciiStr);
      cv::imwrite(filePath, image);
   }
   catch (...)
   {
   catch (...) {
      g_pLog->DisplayMessage(_T("SaveDebugImage error..."));
   }
@@ -735,7 +721,7 @@
CString CInspectCamera::GetSideName(DimensionDir eDim)
{
   switch(eDim)
   switch (eDim)
   {
   case DIMENSION_A:      return _T("SideA_UP");
      break;
@@ -760,23 +746,24 @@
void CInspectCamera::SaveFullImageCopy(int iScan)
{
   // 4/17
   // 畴飘合 皋葛府啊 叠妨辑 促款登绰淀..
   // return;
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL) {
      return;
   if(m_pGrabber == NULL)
      return;
   }
   CSingleLock      cLock(&m_csSaveimage);
   if (m_pGrabber == NULL) {
      return;
   }
   CSingleLock   cLock(&m_csSaveimage);
   cLock.Lock();
   DimensionDir eDim = GetDimension(iScan);
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL) {
      cLock.Unlock();
      return;
   }
   int   nSetEnd = (pSideData->m_nGlassEndLine <= 0) ? pSideData->m_nPreGlassEndLine : pSideData->m_nGlassEndLine;
   int   nOffset = 1000;
@@ -786,73 +773,81 @@
   g_pLog->DisplayMessage(_T("%s Copy Full Image : nStartLine=%d, nEndLine=%d, nFullSize=%d"), PANEL_SIDE[eDim], nStartLine, nEndLine, nFullSize);
   if(nStartLine < 0)
   {
   if (nStartLine < 0) {
      nStartLine = 0;
   }
   if(nFullSize <= 0 || nEndLine < 0)
   if (nFullSize <= 0 || nEndLine < 0) {
      cLock.Unlock();
      return;
   }
   //if(nFullSize <= nStartLine)
   //   return;
   if (nFullSize <= nStartLine) {
      cLock.Unlock();
      return;
   }
   pINSPECTFULLIMAGE_BUFFER pImgBuf = GetFullImgBuffer(iScan);
   int   nFrameWidth,nFrameHeight;
   int   nFrameWidth, nFrameHeight;
   GetFrameSize(m_iCamera,iScan,nFrameWidth,nFrameHeight);
   GetFrameSize(m_iCamera, iScan, nFrameWidth, nFrameHeight);
   if(nFrameWidth <= 0 || nFrameHeight <= 0)
   if (nFrameWidth <= 0 || nFrameHeight <= 0) {
      cLock.Unlock();
      return;
   }
   if(nFullSize/nFrameHeight > m_pGrabber->GetFrameBuffer()->GetFrameCount())
      nFullSize = (m_pGrabber->GetFrameBuffer()->GetFrameCount()-1)*nFrameHeight;
   if (nFullSize / nFrameHeight > m_pGrabber->GetFrameBuffer()->GetFrameCount()) {
      nFullSize = (m_pGrabber->GetFrameBuffer()->GetFrameCount() - 1) * nFrameHeight;
   }
   if(nFullSize <= 100)
   if (nFullSize <= 100) {
      cLock.Unlock();
      return;
   }
   pImgBuf->iCamIdx = m_iCamera;
   pImgBuf->iScanIdx = iScan;
   pImgBuf->SetSize(CSize(nFrameWidth,nFullSize));
   pImgBuf->SetSize(CSize(nFrameWidth, nFullSize));
   g_pLog->DisplayMessage(_T("%s Copy Full Image : nFrameWidth=%d, nFrameHeight=%d"), PANEL_SIDE[eDim], nFrameWidth, nFullSize);
   g_pLog->DisplayMessage(_T("%s Full Image Memory Copy Start : Start[%d]-End[%d]"),PANEL_SIDE[eDim],nStartLine,nEndLine);
   g_pLog->DisplayMessage(_T("%s Full Image Memory Copy Start : Start[%d]-End[%d]"), PANEL_SIDE[eDim], nStartLine, nEndLine);
   LPBYTE lpHeader = m_pGrabber->GetFrameHeaderLine(iScan,nStartLine);
   if(lpHeader == NULL)
   {
      g_pLog->DisplayMessage(_T("%s Full Image Memory Copy fail : Start[%d]-End[%d]"),PANEL_SIDE[eDim],nStartLine,nEndLine);
   LPBYTE lpHeader = m_pGrabber->GetFrameHeaderLine(iScan, nStartLine);
   if (lpHeader == NULL) {
      cLock.Unlock();
      g_pLog->DisplayMessage(_T("%s Full Image Memory Copy fail : Start[%d]-End[%d]"), PANEL_SIDE[eDim], nStartLine, nEndLine);
      return;
   }
   CopyMemory(pImgBuf->pImage,lpHeader,sizeof(BYTE)*pImgBuf->szImage.cx*pImgBuf->szImage.cy);
   CopyMemory(pImgBuf->pImage, lpHeader, sizeof(BYTE) * pImgBuf->szImage.cx * pImgBuf->szImage.cy);
   cLock.Unlock();
   g_pLog->DisplayMessage(_T("%s Full Image Memory Copy complete : Start[%d]-End[%d]"),PANEL_SIDE[eDim],nStartLine,nEndLine);
   g_pLog->DisplayMessage(_T("%s Full Image Memory Copy complete : Start[%d]-End[%d]"), PANEL_SIDE[eDim], nStartLine, nEndLine);
}
BOOL CInspectCamera::CheckProcessEnd(int iThread, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   if(m_pGrabber == NULL)
      return FALSE;
   if (m_pGrabber == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(GetDimension(stFrame.nScanIdx));
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(g_pStatus->GetGrabFrameCount(stFrame.nScanIdx)-1 <= stFrame.nFrameIdx)
   if (g_pStatus->GetGrabFrameCount(stFrame.nScanIdx) - 1 <= stFrame.nFrameIdx)
      return TRUE;
    if(pSideData->m_nPreGlassEndFrame+MAX_THREAD <= stFrame.nFrameIdx)
       return TRUE;
   if (pSideData->m_nPreGlassEndFrame + MAX_THREAD <= stFrame.nFrameIdx)
      return TRUE;
   // Glass End Line阑 茫绰 Thread 鳖瘤 柳青 吝捞搁 促 场抄芭瘤..
   if(pSideData->m_bFindGlassEndLine == TRUE || pSideData->GetFrameProc(pSideData->m_nPreGlassEndFrame) == TRUE)
   // Glass End Line을 찾는 Thread 까지 진행 중이면 다 끝난거지..
   if (pSideData->m_bFindGlassEndLine == TRUE || pSideData->GetFrameProc(pSideData->m_nPreGlassEndFrame) == TRUE)
      return TRUE;
   return FALSE;
@@ -865,107 +860,107 @@
   SetGrabEnd(stFrame.nScanIdx);
}
BOOL CInspectCamera::CheckStartLineFrame(DimensionDir eDim,int iFrame)
BOOL CInspectCamera::CheckStartLineFrame(DimensionDir eDim, int iFrame)
{
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_nGlassStartFrame > iFrame)
   if (pSideData->m_nGlassStartFrame > iFrame)
      return FALSE;
   return TRUE;
}
int   CInspectCamera::GetLeftMargin(int iCam,int iScan)
int   CInspectCamera::GetLeftMargin(int iCam, int iScan)
{
   CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(iCam,iScan);
   if(pCamera == NULL)
      return 0;
   CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(iCam, iScan);
   if (pCamera == NULL)
      return 0;
   return pCamera->m_nMarginLeft;
}
void CInspectCamera::GetFrameSize(int iCam,int iScan,int &nFrameWidth,int &nFrameHeight)
void CInspectCamera::GetFrameSize(int iCam, int iScan, int& nFrameWidth, int& nFrameHeight)
{
   nFrameWidth = nFrameHeight = 0;
   CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(iCam,iScan);
   if(pCamera == NULL)
      return;
   CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(iCam, iScan);
   if (pCamera == NULL)
      return;
   nFrameWidth = pCamera->m_FrameSize.cx;
   nFrameHeight = pCamera->m_FrameSize.cy;
}
BOOL CInspectCamera::FindEndLine(int iThread,DimensionDir emDim,stFrameIndex stFrame)
BOOL CInspectCamera::FindEndLine(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_nPreGlassEndFrame != stFrame.nFrameIdx)
   if (pSideData->m_nPreGlassEndFrame != stFrame.nFrameIdx)
      return FALSE;
   m_MsgJob.nState = 1;
   m_MsgJob.nSide = (int)emDim;
   ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS,(WPARAM)&m_MsgJob, (int)emDim);
   ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)emDim);
#define BOUNDARY_GLASSSTARTWIDTH_ENDLINE   140
#define BOUNDARYHORIZ_LEVELDIST_ENDLINE      50   // 荐乞 版拌急阑 茫阑 锭狼 厚背芭府
#define BOUNDARYHORIZ_LEVELDIST_ENDLINE      50   // 수평 경계선을 찾을 때의 비교거리
   int         nFrameWidth      = m_nFrameWidth;
   int         nFrameHeight   = m_nFrameHeight;
   int         nThreshold      = m_pRecipe->m_SideParam[emDim].m_nFindStartEndLine_Threshold * BOUNDARY_GLASSSTARTWIDTH_ENDLINE;
   int         nFrameWidth = m_nFrameWidth;
   int         nFrameHeight = m_nFrameHeight;
   int         nThreshold = m_pRecipe->m_SideParam[emDim].m_nFindStartEndLine_Threshold * BOUNDARY_GLASSSTARTWIDTH_ENDLINE;
   int         nCountinueCount = 0;
   int         nHStart, nGab;
   BOOL      bContinue      = FALSE;
   int         nDivHor         = 0;
   int         iScan         = stFrame.nScanIdx;
   BOOL      bContinue = FALSE;
   int         nDivHor = 0;
   int         iScan = stFrame.nScanIdx;
   int         nSetHor = m_pRecipe->m_SideParam[(int) emDim].m_nFindStartEndLine_X_pxl;
   if(nSetHor < BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2) nSetHor = BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2;
   if(nSetHor > nFrameWidth-(BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2)) nSetHor = nFrameWidth-(BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2);
   int         nSetHor = m_pRecipe->m_SideParam[(int)emDim].m_nFindStartEndLine_X_pxl;
   g_pLog->DisplayMessage(_T( "%s End Edge Find position Frame[%d],Hor[%d]"),PANEL_SIDE[emDim],stFrame.nFrameIdx,nSetHor);
   if (nSetHor < BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2) nSetHor = BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2;
   if (nSetHor > nFrameWidth - (BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2)) nSetHor = nFrameWidth - (BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2);
   nHStart = nSetHor - BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2;
   g_pLog->DisplayMessage(_T("%s End Edge Find position Frame[%d],Hor[%d]"), PANEL_SIDE[emDim], stFrame.nFrameIdx, nSetHor);
   nHStart = nSetHor - BOUNDARY_GLASSSTARTWIDTH_ENDLINE / 2;
   const   int      nCalculateFrame = 3;
   int            nStartFrame = stFrame.nFrameIdx - 2;
   int            nVTop = nStartFrame*nFrameHeight;
   LPBYTE         lpHeader = m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx,nVTop);
   int            nVTop = nStartFrame * nFrameHeight;
   LPBYTE         lpHeader = m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, nVTop);
   CSISBuffer      pVertBuffer(lpHeader,nFrameWidth,nCalculateFrame*nFrameHeight);
   CSISBuffer      pVertBuffer(lpHeader, nFrameWidth, nCalculateFrame * nFrameHeight);
   if(lpHeader == NULL || pVertBuffer.IsValidBuffer() == FALSE)
   if (lpHeader == NULL || pVertBuffer.IsValidBuffer() == FALSE)
      return FALSE;
   int* pnSum = new int[nFrameHeight*nCalculateFrame + BOUNDARYHORIZ_LEVELDIST_ENDLINE];
   int* pnSum = new int[nFrameHeight * nCalculateFrame + BOUNDARYHORIZ_LEVELDIST_ENDLINE];
   ZeroMemory(pnSum, sizeof(int) * (nFrameHeight*nCalculateFrame + BOUNDARYHORIZ_LEVELDIST_ENDLINE));
   ZeroMemory(pnSum, sizeof(int) * (nFrameHeight * nCalculateFrame + BOUNDARYHORIZ_LEVELDIST_ENDLINE));
#ifdef _DEBUG
   CString str;
   str.Format(_T("D:\\InspectionData\\Debug\\Side_%d_EndLineSearch.bmp"),(int)emDim);
   str.Format(_T("D:\\InspectionData\\Debug\\Side_%d_EndLineSearch.bmp"), (int)emDim);
   CBufferAttach saveImage(str);
   saveImage.AttachToFile(pVertBuffer);
#endif
   for (int j = pVertBuffer.GetHeight()-1 ; j >= 0; j--)
   for (int j = pVertBuffer.GetHeight() - 1; j >= 0; j--)
   {
      for (int k = nHStart; k < nHStart+BOUNDARY_GLASSSTARTWIDTH_ENDLINE; k++)
      for (int k = nHStart; k < nHStart + BOUNDARY_GLASSSTARTWIDTH_ENDLINE; k++)
      {
         pnSum[j] += *pVertBuffer.GetDataAddress(k,j);
      }
         pnSum[j] += *pVertBuffer.GetDataAddress(k, j);
      }
      if (j <= (pVertBuffer.GetHeight()-1-BOUNDARYHORIZ_LEVELDIST_ENDLINE))
      if (j <= (pVertBuffer.GetHeight() - 1 - BOUNDARYHORIZ_LEVELDIST_ENDLINE))
      {
         if(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] == 0 || pnSum[j] == 0)   // 肋 给 等 捞固瘤..
         if (pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] == 0 || pnSum[j] == 0)   // 잘 못 된 이미지..
            continue;
         nGab = abs(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] - pnSum[j]);
         nGab = abs(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] - pnSum[j]);
         if (nGab > nThreshold)
            nCountinueCount++;
         else
@@ -973,13 +968,13 @@
         if (nCountinueCount >= 2)
         {
            // Glass狼 矫累瘤痢阑 茫酒辑 备炼眉俊 持绰促.
            pSideData->m_nGlassEndLine      = nStartFrame*nFrameHeight + j + 2;
            pSideData->m_nGlassEndFrame      = pSideData->m_nGlassEndLine/nFrameHeight;
            pSideData->m_bFindGlassEndLine   = TRUE;
            // Glass의 시작지점을 찾아서 구조체에 넣는다.
            pSideData->m_nGlassEndLine = nStartFrame * nFrameHeight + j + 2;
            pSideData->m_nGlassEndFrame = pSideData->m_nGlassEndLine / nFrameHeight;
            pSideData->m_bFindGlassEndLine = TRUE;
            // pSideData->m_nGlassEdgeXPos[1] = nSetHor;
            g_pLog->DisplayMessage(_T( "%s End Line Frame %d, Line %d"), PANEL_SIDE[emDim], pSideData->m_nGlassEndFrame, pSideData->m_nGlassEndLine);
            g_pLog->DisplayMessage(_T("%s End Line Frame %d, Line %d"), PANEL_SIDE[emDim], pSideData->m_nGlassEndFrame, pSideData->m_nGlassEndLine);
            /*
            // Log
@@ -988,11 +983,11 @@
               , PANEL_SIDE[emDim]
            , pEdgeInfo->nGlassEdgeXPos[1]
            , pEdgeInfo->nGlassEndLine
               , pEdgeInfo->nGlassEndLine / nFrameHeight);
               , pEdgeInfo->nGlassEndLine / nFrameHeight);
               */
            delete [] pnSum;
            delete[] pnSum;
            // SaveGlassLineImage(stFrame.nScanIdx,pSideData->m_nGlassEndLine,pSideData->m_nGlassEdgeXPos[1],emDim,_T("EndLine"));
            return TRUE;
@@ -1003,61 +998,61 @@
   pSideData->m_nGlassEndLine = pSideData->m_nPreGlassEndLine;
   pSideData->m_nGlassEndFrame = pSideData->m_nPreGlassEndFrame;
   pSideData->m_bFindGlassEndLine = TRUE;
   delete [] pnSum;
   delete[] pnSum;
   g_pLog->DisplayMessage(_T("%s EndLine Frame %d Fail"),PANEL_SIDE[emDim],stFrame.nFrameIdx);
   g_pLog->DisplayMessage(_T("%s EndLine Frame %d Fail"), PANEL_SIDE[emDim], stFrame.nFrameIdx);
   return FALSE;
}
BOOL CInspectCamera::FindSideLine(int iThread,DimensionDir emDim,stFrameIndex stFrame)
BOOL CInspectCamera::FindSideLine(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   CSide_Data*      pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if (pSideData == NULL)
   {
      g_pLog->DisplayMessage(_T("Side Line Find Fail - Glass Data or HW Setting Error"));
      return FALSE;
   }
   int nFindLine=-1;
   int nFindLine = -1;
   int nThres            = m_pRecipe->m_SideParam[(int)(emDim)].m_nSideLineThreshold;
   int nTopCornerSizeX_pxl = (int) GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeX_um);
   int nTopCornerSizeY_pxl = (int) GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeY_um);
   int nBotCornerSizeX_pxl = (int) GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeX_um);
   int nBotCornerSizeY_pxl = (int) GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeY_um);
   int nThres = m_pRecipe->m_SideParam[(int)(emDim)].m_nSideLineThreshold;
   int nTopCornerSizeX_pxl = (int)GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeX_um);
   int nTopCornerSizeY_pxl = (int)GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeY_um);
   int nBotCornerSizeX_pxl = (int)GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeX_um);
   int nBotCornerSizeY_pxl = (int)GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeY_um);
   // Make Region
   CSISEdgeFind   EdgeFind;
   const int      nSearchHeight   = 100;
   int            nFrameWidth      = m_nFrameWidth;
   int            nFrameHeight   = m_nFrameHeight;
   const int      nSearchHeight = 100;
   int            nFrameWidth = m_nFrameWidth;
   int            nFrameHeight = m_nFrameHeight;
   int nFrameYPos = stFrame.nFrameIdx * nFrameHeight;
   CRect rtROI = CRect(GetLeftMargin(m_iCamera,stFrame.nScanIdx),0,m_nFrameWidth-1,m_nFrameHeight);
   CRect rtROI = CRect(GetLeftMargin(m_iCamera, stFrame.nScanIdx), 0, m_nFrameWidth - 1, m_nFrameHeight);
   rtROI.OffsetRect(0, nFrameYPos);
   int nTopCorner_Bottom  = pSideData->m_nGlassStartLine + nTopCornerSizeY_pxl;
   int nBotCorner_Top      = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine - nBotCornerSizeY_pxl : pSideData->m_nPreGlassEndLine - nBotCornerSizeY_pxl;
   int nTopCorner_Bottom = pSideData->m_nGlassStartLine + nTopCornerSizeY_pxl;
   int nBotCorner_Top = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine - nBotCornerSizeY_pxl : pSideData->m_nPreGlassEndLine - nBotCornerSizeY_pxl;
   int nTopCorner_Bottom_Frame = nTopCorner_Bottom / nFrameHeight;
   int nBotCorner_Top_Frame = nBotCorner_Top / nFrameHeight;
   int nYPos_pxl = 0;
   if(nTopCorner_Bottom_Frame == stFrame.nFrameIdx)
   if (nTopCorner_Bottom_Frame == stFrame.nFrameIdx)
   {
      rtROI.top = (rtROI.top < nTopCorner_Bottom) ? nTopCorner_Bottom : rtROI.top;
      nYPos_pxl = rtROI.top;
      rtROI.OffsetRect(0, -nFrameYPos);
   }
   else if(nBotCorner_Top_Frame == stFrame.nFrameIdx)
   else if (nBotCorner_Top_Frame == stFrame.nFrameIdx)
   {
      rtROI.bottom = (nBotCorner_Top_Frame < rtROI.bottom) ? nBotCorner_Top : rtROI.bottom;
      // Frame gap..
      if(rtROI.Height() < m_nFrameHeight/3)
      if (rtROI.Height() < m_nFrameHeight / 3)
      {
         int nExtraArea = m_nFrameHeight - rtROI.Height();
         int nOffSetY = nFrameYPos - nExtraArea;
@@ -1078,36 +1073,36 @@
      rtROI.OffsetRect(0, -nFrameYPos);
   }
   if(nSearchHeight < rtROI.Height())
   if (nSearchHeight < rtROI.Height())
   {
      rtROI.top = rtROI.CenterPoint().y - nSearchHeight/2;
      rtROI.top = rtROI.CenterPoint().y - nSearchHeight / 2;
      rtROI.bottom = rtROI.top + nSearchHeight;
   }
   if(rtROI.left < 0)               rtROI.left = 0;
   if(rtROI.right >= m_nFrameWidth)   rtROI.right = m_nFrameWidth-1;
   if(rtROI.top < 0)               rtROI.top = 0;
   if(rtROI.bottom >= m_nFrameHeight)   rtROI.bottom = m_nFrameHeight-1;
   if (rtROI.left < 0)               rtROI.left = 0;
   if (rtROI.right >= m_nFrameWidth)   rtROI.right = m_nFrameWidth - 1;
   if (rtROI.top < 0)               rtROI.top = 0;
   if (rtROI.bottom >= m_nFrameHeight)   rtROI.bottom = m_nFrameHeight - 1;
   // Find Side Line
#define DEFECT_EDGE_AUTO_RATIO 0.3
#define DEFECT_EDGE_AUTO_PITCH 20
#define DEFECT_EDGE_CONTINUE 3   
   CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, nYPos_pxl),nFrameWidth,nFrameHeight);
   if(frameBuffer.IsValidBuffer() == FALSE)
   CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, nYPos_pxl), nFrameWidth, nFrameHeight);
   if (frameBuffer.IsValidBuffer() == FALSE)
      return nFindLine;
   EdgeFind.FindEdge_ToRightROI(&frameBuffer,nFindLine,DEFECT_EDGE_AUTO_PITCH,nThres,DEFECT_EDGE_AUTO_RATIO,0,rtROI);
   if(nFindLine > 0 && nFindLine < frameBuffer.GetWidth())
   EdgeFind.FindEdge_ToRightROI(&frameBuffer, nFindLine, DEFECT_EDGE_AUTO_PITCH, nThres, DEFECT_EDGE_AUTO_RATIO, 0, rtROI);
   if (nFindLine > 0 && nFindLine < frameBuffer.GetWidth())
   {
      m_iSideLine[stFrame.nScanIdx] = nFindLine;
      m_iSideLine[stFrame.nScanIdx] = nFindLine;
      pSideData->m_nSideLineFrame[stFrame.nFrameIdx] = nFindLine;
      pSideData->m_nSideLinePosY[stFrame.nFrameIdx] = rtROI.CenterPoint().y + nFrameYPos;
      // Side 茫绊, Chamfer 茫绰芭 眠啊 鞘夸...
      // Side 찾고, Chamfer 찾는거 추가 필요...
      pSideData->m_nSide_Chamfer_LineFrame[stFrame.nFrameIdx] = nFindLine + 0;
      g_pLog->DisplayMessage(_T("Find Side Line Frame[%d], Side[%d]"), stFrame.nFrameIdx, nFindLine);
@@ -1116,32 +1111,31 @@
   return TRUE;
}
BOOL CInspectCamera::FindSideLine_ExceptNotch(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindSideLine_ExceptNotch(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   CSide_Data*      pSideData = m_pGlassData->GetSideData(emDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   {
   if (pSideData == NULL) {
      g_pLog->DisplayMessage(_T("Side Line Find Fail - Glass Data or HW Setting Error"));
      return FALSE;
   }
   int nThres            = m_pRecipe->m_SideParam[(int)(emDim)].m_nSideLineThreshold;
   int nTopCornerSizeX_pxl = (int) GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeX_um);
   int nTopCornerSizeY_pxl = (int) GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeY_um);
   int nBotCornerSizeX_pxl = (int) GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeX_um);
   int nBotCornerSizeY_pxl = (int) GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeY_um);
   int nThres = m_pRecipe->m_SideParam[(int)(emDim)].m_nSideLineThreshold;
   int nTopCornerSizeX_pxl = (int)GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeX_um);
   int nTopCornerSizeY_pxl = (int)GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nTopCornerSizeY_um);
   int nBotCornerSizeX_pxl = (int)GetUmToPixel_X(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeX_um);
   int nBotCornerSizeY_pxl = (int)GetUmToPixel_Y(m_pRecipe->m_SideParam[(int)(emDim)].m_nBottomCornerSizeY_um);
   // Make Region
   CSISEdgeFind   EdgeFind;
   const int      nSearchHeight   = 50;
   int            nFrameWidth      = m_nFrameWidth;
   int            nFrameHeight   = m_nFrameHeight;
   const int      nSearchHeight = 50;
   int            nFrameWidth = m_nFrameWidth;
   int            nFrameHeight = m_nFrameHeight;
   int nFrameYPos = stFrame.nFrameIdx * nFrameHeight;
   int nTopCorner_Bottom  = pSideData->m_nGlassStartLine + nTopCornerSizeY_pxl;
   int nBotCorner_Top      = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine - nBotCornerSizeY_pxl : pSideData->m_nPreGlassEndLine - nBotCornerSizeY_pxl;
   int nTopCorner_Bottom = pSideData->m_nGlassStartLine + nTopCornerSizeY_pxl;
   int nBotCorner_Top = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine - nBotCornerSizeY_pxl : pSideData->m_nPreGlassEndLine - nBotCornerSizeY_pxl;
   int nTopCorner_Bottom_Frame = nTopCorner_Bottom / nFrameHeight;
   int nBotCorner_Top_Frame = nBotCorner_Top / nFrameHeight;
@@ -1150,19 +1144,20 @@
   CRect rtAllSide_pxl;
   rtAllSide_pxl.left = 0;
   rtAllSide_pxl.top = nTopCorner_Bottom;
   rtAllSide_pxl.right = nFrameWidth-1;
   rtAllSide_pxl.right = nFrameWidth - 1;
   rtAllSide_pxl.bottom = nBotCorner_Top;
   // 2. Make Frame Area
   CRect rtFrame_pxl = CRect(GetLeftMargin(m_iCamera,stFrame.nScanIdx),0,m_nFrameWidth-1,m_nFrameHeight);
   CRect rtFrame_pxl = CRect(GetLeftMargin(m_iCamera, stFrame.nScanIdx), 0, m_nFrameWidth - 1, m_nFrameHeight);
   rtFrame_pxl.OffsetRect(0, nFrameYPos);
   // 3. Make Find Side Line Area.
   CRect rtROI;
   rtROI.IntersectRect(rtFrame_pxl, rtAllSide_pxl);
   if(rtROI.IsRectEmpty() || rtROI.IsRectNull())
   if (rtROI.IsRectEmpty() || rtROI.IsRectNull()) {
      return FALSE;
   }
   // 4. Exception Notch Area...
   std::vector<CRect> vectorInspectAreaList_New;
@@ -1176,40 +1171,36 @@
   std::vector<CRect> vecInspectArea;
   for(int i=0; i<nNotchCount; i++)
   {
   for (int i = 0; i < nNotchCount; i++) {
      CRect rtNotchArea = pSideData->m_rtNotchArea_pxl[i];
      rtNotchArea.left = GetLeftMargin(m_iCamera,stFrame.nScanIdx);
      rtNotchArea.right = m_nFrameWidth-1;
      rtNotchArea.left = GetLeftMargin(m_iCamera, stFrame.nScanIdx);
      rtNotchArea.right = m_nFrameWidth - 1;
      vectorInspectAreaList_Old.resize(vectorInspectAreaList_New.size());
      std::copy(vectorInspectAreaList_New.begin(),  vectorInspectAreaList_New.end(), vectorInspectAreaList_Old.begin());
      std::copy(vectorInspectAreaList_New.begin(), vectorInspectAreaList_New.end(), vectorInspectAreaList_Old.begin());
      vectorInspectAreaList_New.clear();
      for(int j=0; j<vectorInspectAreaList_Old.size(); j++)
      {
      for (int j = 0; j < vectorInspectAreaList_Old.size(); j++) {
         CRect rtTemp = vectorInspectAreaList_Old[j];
         CRect rtNotchInterSectRect;
         rtNotchInterSectRect.IntersectRect(rtTemp,  rtNotchArea);
         rtNotchInterSectRect.IntersectRect(rtTemp, rtNotchArea);
         if(rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull())                        // 畴摹啊 救吧府绰 版快俊绰 促矫 持绢霖促..
         {
         if (rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) {
            vectorInspectAreaList_New.push_back(rtTemp);
            continue;
         }
         if(rtTemp.Height() == rtNotchInterSectRect.Height())                                       // Notch啊 康开狼 傈眉牢 版快
         if (rtTemp.Height() == rtNotchInterSectRect.Height()) {
            continue;
         }
         if(rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom)            // 1. Notch Frame 困俊 吧赴 版快
         {
         if (rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) {
            CRect rtNew = rtTemp;
            rtNew.top = rtNotchInterSectRect.bottom;
            vectorInspectAreaList_New.push_back(rtNew);
         }
         else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom)         // 2. Notch Frame 吝埃俊 吧赴 版快
         {
         else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) {
            CRect rtNewTop = rtTemp;
            rtNewTop.top = rtNotchInterSectRect.bottom;
            vectorInspectAreaList_New.push_back(rtNewTop);
@@ -1218,8 +1209,7 @@
            rtNewBot.bottom = rtNotchInterSectRect.top;
            vectorInspectAreaList_New.push_back(rtNewBot);
         }
         else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom)         // 3. Notch Frame 酒贰俊 吧赴 版快
         {
         else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) {
            CRect rtNew = rtTemp;
            rtNew.bottom = rtNotchInterSectRect.top;
            vectorInspectAreaList_New.push_back(rtNew);
@@ -1227,12 +1217,9 @@
      }
   }
   // 5. Side List..
   vecInspectArea.clear();
   for(int i=0; i<vectorInspectAreaList_New.size(); i++)
   {
   for (int i = 0; i < vectorInspectAreaList_New.size(); i++) {
      CRect rtInspectArea = vectorInspectAreaList_New[i];
      vecInspectArea.push_back(rtInspectArea);
   }
@@ -1241,25 +1228,24 @@
#define DEFECT_EDGE_AUTO_RATIO 0.3
#define DEFECT_EDGE_AUTO_PITCH 20
#define DEFECT_EDGE_CONTINUE 3
   int nFindSideLineSum = 0;
   int nFindSideLineCount = 0;
   int nFindSideLineCount = 0;
   int nFindSideChamferLineSum = 0;
   int nFindSideChamferLineCount = 0;
   int nChamferLineThres = m_pRecipe->m_SideParam[(int) emDim].m_nChamferLineThreshold;
   int nChamferLineThres = m_pRecipe->m_SideParam[(int)emDim].m_nChamferLineThreshold;
#if HALCON_VISION_KEY
   CBlSideData *pBlSideData = BlVision_GetVisionRecipe()->getSideData(emDim);
   CBlSideData* pBlSideData = BlVision_GetVisionRecipe()->getSideData(emDim);
#endif
   int stepSide = m_pGrabber->GetFrameBuffer()->GetFrameHeight();
   for (int i = 0; i < vecInspectArea.size(); i++) {
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, vecInspectArea[i].top), nFrameWidth, vecInspectArea[i].Height());
   for(int i=0; i<vecInspectArea.size(); i++)
   {
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, vecInspectArea[i].top),nFrameWidth,vecInspectArea[i].Height());
      if(frameBuffer.IsValidBuffer() == FALSE)
      if (frameBuffer.IsValidBuffer() == FALSE) {
         continue;
      }
#ifdef _DEBUG
      CString str;
@@ -1271,20 +1257,18 @@
      CRect rtFindROI = vecInspectArea[i];
      rtFindROI.OffsetRect(0, -rtFindROI.top);
      if(nSearchHeight < rtFindROI.Height())
      {
      if (nSearchHeight < rtFindROI.Height()) {
         CPoint ptCenter = rtFindROI.CenterPoint();
         rtFindROI.top = ptCenter.y - (nSearchHeight/2);
         rtFindROI.bottom = ptCenter.y + (nSearchHeight/2);
         rtFindROI.top = ptCenter.y - (nSearchHeight / 2);
         rtFindROI.bottom = ptCenter.y + (nSearchHeight / 2);
      }
      int         nSideLine = -1;
      EdgeFind.FindEdge_ToRightROI(&frameBuffer,nSideLine,DEFECT_EDGE_AUTO_PITCH,nThres,DEFECT_EDGE_AUTO_RATIO,0,rtFindROI);
      if(nSideLine != -1)
      {
      int   nSideLine = -1;
      EdgeFind.FindEdge_ToRightROI(&frameBuffer, nSideLine, DEFECT_EDGE_AUTO_PITCH, nThres, DEFECT_EDGE_AUTO_RATIO, 0, rtFindROI);
      if (nSideLine != -1) {
#if HALCON_VISION_KEY
         if (NULL != pBlSideData){
         if (NULL != pBlSideData) {
            SideLineInf inf;
            inf.left = 0;
            inf.top = vecInspectArea[i].top;
@@ -1295,7 +1279,7 @@
            int idx = (int)(vecInspectArea[i].top / stepSide);
            pBlSideData->m_mapSideLineInf[idx] = inf;
            //打印边界数据
            //댔丹긋썹鑒앴
            //Log_GetDebug()->TraceInfo("Find Side Line %d: %d, %d, (%d, %d, %d, %d), %d",
            //   idx,
            //   inf.nSideLine, inf.nThres,
@@ -1310,87 +1294,88 @@
         CChamferInspect chamferIns;
         double         dLine = -1;
         COwnerBuffer   ImgInsBin;
         chamferIns.Binarization(frameBuffer,ImgInsBin,nChamferLineThres);
         COwnerBuffer   ImgInsBin;
         chamferIns.Binarization(frameBuffer, ImgInsBin, nChamferLineThres);
         chamferIns.FindRightLine_Bin(ImgInsBin,nSideLine,dLine);
         if(dLine != -1)
         {
         chamferIns.FindRightLine_Bin(ImgInsBin, nSideLine, dLine);
         if (dLine != -1) {
            nFindSideChamferLineSum += (int)dLine;
            nFindSideChamferLineCount++;
         }
      }
   }
   if(nFindSideLineCount > 0)
   {
      int nAvgSideLine = (int) (nFindSideLineSum / nFindSideLineCount);   // Average..
   if (nFindSideLineCount > 0) {
      int nAvgSideLine = (int)(nFindSideLineSum / nFindSideLineCount);
      m_iSideLine[stFrame.nScanIdx] = nAvgSideLine;
      pSideData->m_nSideLineFrame[stFrame.nFrameIdx] = nAvgSideLine;
      pSideData->m_nSideLineFrame[stFrame.nFrameIdx] = nAvgSideLine;
      pSideData->m_nSideLinePosY[stFrame.nFrameIdx] = rtROI.CenterPoint().y + nFrameYPos;
   }
   if(nFindSideChamferLineCount > 0)
   {
      int nAvgChamferLine = (int) (nFindSideChamferLineSum / nFindSideChamferLineCount);   // Average..
      pSideData->m_nSide_Chamfer_LineFrame[stFrame.nFrameIdx] = nAvgChamferLine;            // Chamfer Line
   if (nFindSideChamferLineCount > 0) {
      int nAvgChamferLine = (int)(nFindSideChamferLineSum / nFindSideChamferLineCount);   // Average..
      pSideData->m_nSide_Chamfer_LineFrame[stFrame.nFrameIdx] = nAvgChamferLine;         // Chamfer Line
   }
   return TRUE;
}
BOOL CInspectCamera::FindTopCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindTopCorner(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   CSingleLock localLock(&m_csTopCorner);
   localLock.Lock();
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassStartLine == FALSE)
   if (pSideData == NULL || pSideParam == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   if(pSideData->m_bTopCorner_Find == TRUE)
   if (pSideData->m_bFindGlassStartLine == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   if (pSideData->m_bTopCorner_Find == TRUE) {
      localLock.Unlock();
      return TRUE;
   }
   /*
   BOOL bTopCornerUse = (BOOL) (m_pRecipe->m_SideParam[emDim].m_nTopCornerShape == 0) ? FALSE : TRUE;
   // Not Use Corner Inspection
   if(bTopCornerUse == FALSE)
   BOOL bTopCornerUse = (BOOL)(m_pRecipe->m_SideParam[emDim].m_nTopCornerShape == 0) ? FALSE : TRUE;
   if (bTopCornerUse == FALSE) {
      localLock.Unlock();
      return FALSE;
   */
   }
   double dCornerSizeY_Um   = (double) m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeY_um;
   int nCornerSizeY_Pixel   = (int) GetUmToPixel_Y(dCornerSizeY_Um);
   int nFrameHeight      = m_nFrameHeight;
   int nFindStartLine      = pSideData->m_nGlassStartLine;
   double dCornerSizeY_Um = (double)m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeY_um;
   int nCornerSizeY_Pixel = (int)GetUmToPixel_Y(dCornerSizeY_Um);
   int nFrameHeight = m_nFrameHeight;
   int nFindStartLine = pSideData->m_nGlassStartLine;
   int nTopCornerFrameIndex = (nFindStartLine + nCornerSizeY_Pixel) / nFrameHeight;
   if(stFrame.nFrameIdx < nTopCornerFrameIndex+1)
   if (stFrame.nFrameIdx < nTopCornerFrameIndex + 1) {
      localLock.Unlock();
      return FALSE;
   }
   int nSideLine = pSideData->m_nSideLineFrame[nTopCornerFrameIndex+1];
   int nSideLine = (int)pSideData->m_nSideLineFrame[nTopCornerFrameIndex + 1];
   if(nSideLine == -1)
   if (nSideLine == -1) {
      localLock.Unlock();
      return FALSE;
   }
   double dCornerSizeX_Um = (double) m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeX_um;
   int nCornerSizeX_Pixel = (int) GetUmToPixel_X(dCornerSizeX_Um);
   double dCornerSizeX_Um = (double)m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeX_um;
   int nCornerSizeX_Pixel = (int)GetUmToPixel_X(dCornerSizeX_Um);
   CRect rtTopCornerArea(0, 0, nCornerSizeX_Pixel, nCornerSizeY_Pixel);
   rtTopCornerArea.OffsetRect(nSideLine, nFindStartLine);
   pSideData->m_bTopCorner_Find = TRUE;
@@ -1399,11 +1384,15 @@
   int nTopCornerType = m_pRecipe->m_SideParam[emDim].m_nTopCornerShape;
   pSideData->m_nTopCornerShape = m_pRecipe->m_SideParam[emDim].m_nTopCornerShape;;
   if(pSideParam->m_bTopCornerFindDefect == FALSE)
   if (pSideParam->m_bTopCornerFindDefect == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   if(nTopCornerType == (int) 1)                     return FindTopCorner_CCut(iThread, emDim, stFrame);
   else if(nTopCornerType == (int) 2)                  return FindTopCorner_RCut(iThread, emDim, stFrame);
   localLock.Unlock();
   if (nTopCornerType == (int)1)                     return FindTopCorner_CCut(iThread, emDim, stFrame);
   else if (nTopCornerType == (int)2)                  return FindTopCorner_RCut(iThread, emDim, stFrame);
   else                                       return FindTopCorner_None(iThread, emDim, stFrame);
   return TRUE;
@@ -1411,21 +1400,21 @@
BOOL CInspectCamera::FindTopCorner_None(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == FALSE)
   if (pSideData == FALSE)
      return FALSE;
   CRect rtTopCornerArea = pSideData->m_rtTopCornerArea;
   rtTopCornerArea.right = rtTopCornerArea.left + ALIGN_4BYTE(rtTopCornerArea.Width());
   if(rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull())
   if (rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull())
      return FALSE;
   int nFrameWidth         = m_nFrameWidth;
   int nFrameWidth = m_nFrameWidth;
   // 1. Inspect ROI
   COwnerBuffer pBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height());
@@ -1439,7 +1428,7 @@
   int nMinSize = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Min_Size;
   int nDilation =  m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation;
   int nDilation = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation;
   // For Draw..
   pSideData->m_rtTopCornerArea_Offset = rtTopCornerArea;
@@ -1458,7 +1447,7 @@
      int nImageX = nInsStart;
      int nImageY = i;
      if (nImageX < 0 ||rtTopCornerArea.Width() <= nImageX || nImageY < 0 || rtTopCornerArea.Height() <= nImageY)
      if (nImageX < 0 || rtTopCornerArea.Width() <= nImageX || nImageY < 0 || rtTopCornerArea.Height() <= nImageY)
         continue;
      int nRange = (rtTopCornerArea.Width() <= nImageX + nInsRange) ? (rtTopCornerArea.Width() - 1 - nImageX) : nInsRange;
@@ -1504,23 +1493,23 @@
   return TRUE;
}
BOOL CInspectCamera::FindTopCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindTopCorner_CCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == FALSE)
   if (pSideData == FALSE)
      return FALSE;
   CRect rtTopCornerArea = pSideData->m_rtTopCornerArea;
   rtTopCornerArea.right = rtTopCornerArea.left + ALIGN_4BYTE(rtTopCornerArea.Width());
   if(rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull())
   if (rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull())
      return FALSE;
   int nFrameWidth         = m_nFrameWidth;
   int nFrameWidth = m_nFrameWidth;
   // 1. Inspect ROI
   COwnerBuffer pBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height());
@@ -1534,7 +1523,7 @@
   int nMinSize = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Min_Size;
   int nDilation =  m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation;
   int nDilation = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation;
   // For Draw..
   pSideData->m_rtTopCornerArea_Offset = rtTopCornerArea;
@@ -1554,18 +1543,18 @@
   for (int i = 0; i < rtTopCornerArea.Width(); i++)
   {
      int nX = rtTopCornerArea.Width() - 1 - i;
      int nY = (int) (((double)i * dScaleY) + nInsStart);
      int nY = (int)(((double)i * dScaleY) + nInsStart);
      if (nX < 0 ||rtTopCornerArea.Width() <= nX || nY < 0 || rtTopCornerArea.Height() <= nY)
      if (nX < 0 || rtTopCornerArea.Width() <= nX || nY < 0 || rtTopCornerArea.Height() <= nY)
         continue;
      int nRange = (rtTopCornerArea.Height() <= nY + nInsRange) ? (rtTopCornerArea.Height() - 1 - nY) : nInsRange;
      if(nRange == 0)
      if (nRange == 0)
         continue;
      for(int j=0; j<nRange; j++)
         pMaskBuffer.SetPixel(nX, nY+j, 255);
      for (int j = 0; j < nRange; j++)
         pMaskBuffer.SetPixel(nX, nY + j, 255);
      /*
      int nRange = (rtTopCornerArea.Width() <= nX + nInsRange) ? (rtTopCornerArea.Width() - 1 - nX) : nInsRange;
@@ -1615,23 +1604,23 @@
   return TRUE;
}
BOOL CInspectCamera::FindTopCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindTopCorner_RCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == FALSE)
   if (pSideData == FALSE)
      return FALSE;
   CRect rtTopCornerArea = pSideData->m_rtTopCornerArea;
   rtTopCornerArea.right = rtTopCornerArea.left + ALIGN_4BYTE(rtTopCornerArea.Width());
   if(rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull())
   if (rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull())
      return FALSE;
   int nFrameWidth         = m_nFrameWidth;
   int nFrameWidth = m_nFrameWidth;
   // 1. Inspect ROI
   COwnerBuffer pBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height());
@@ -1710,78 +1699,91 @@
   return TRUE;
}
BOOL CInspectCamera::FindTopAlignMark(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindTopAlignMark(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   CSingleLock localLock(&m_csThreadTopAlignMark);
   localLock.Lock();
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   CSide_Data*   pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if (pSideData == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   if(pSideData->m_bFindGlassStartLine == FALSE)
   if (pSideData->m_bFindGlassStartLine == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   if(pSideData->m_bTopMark_Find == TRUE)
   if (pSideData->m_bTopMark_Find == TRUE) {
      localLock.Unlock();
      return TRUE;
   }
    if(pSideData->m_bTopCorner_Find == FALSE)
       return FALSE;
   if (pSideData->m_bTopCorner_Find == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   BOOL bTopAlignMark = (BOOL) (m_pRecipe->m_SideParam[eDim].m_bTopMark_Use == 1) ? TRUE : FALSE;
   if(bTopAlignMark == FALSE)
   BOOL bTopAlignMark = (BOOL)(m_pRecipe->m_SideParam[eDim].m_bTopMark_Use == 1) ? TRUE : FALSE;
   if (bTopAlignMark == FALSE) {
      localLock.Unlock();
      return FindTopAlignMark_Virtual(iThread, eDim, stFrame);
   else
   {
      if(FindTopAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE)
   }
   else {
      if (FindTopAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) {
         localLock.Unlock();
         return FindTopAlignMark_Virtual(iThread, eDim, stFrame);
      else
      }
      else {
         localLock.Unlock();
         return TRUE;
      }
   }
}
BOOL CInspectCamera::FindTopAlignMark_Virtual(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindTopAlignMark_Virtual(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(eDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassStartLine == FALSE)
   if (pSideData->m_bFindGlassStartLine == FALSE)
      return FALSE;
   if(pSideData->m_bTopMark_Find == TRUE)
   if (pSideData->m_bTopMark_Find == TRUE)
      return TRUE;
    if(pSideData->m_bTopCorner_Find == FALSE)
       return FALSE;
   // 1. Make ROI
   int nFrameWidth         = m_nFrameWidth;
   int nFrameHeight      = m_nFrameHeight;
   int nStartLine               = pSideData->m_nGlassStartLine;
   double dEdgeToTopAlignMarkY_Um   = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeY_um;
   int nEdgeToTopAlignMarkY_Pixel  = (int) GetUmToPixel_Y(dEdgeToTopAlignMarkY_Um);
   int nTopAlignMarkY_Pixel      = nStartLine + nEdgeToTopAlignMarkY_Pixel;
   int nTopAlignMarkYPramIdx      = nTopAlignMarkY_Pixel / nFrameHeight;
   if((int) stFrame.nFrameIdx < nTopAlignMarkYPramIdx + 1)
   if (pSideData->m_bTopCorner_Find == FALSE)
      return FALSE;
   int nSideLine               = pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1];
   double nEdgeToTopAlignMarkX_Um   = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeX_um;
   int nEdgeToTopAlignMarkX_Pixel  = (int) GetUmToPixel_X(nEdgeToTopAlignMarkX_Um);
   int nTopAlignMarkX_Pixel      = nSideLine + nEdgeToTopAlignMarkX_Pixel;
   // 1. Make ROI
   int nFrameWidth = m_nFrameWidth;
   int nFrameHeight = m_nFrameHeight;
   int nStartLine = pSideData->m_nGlassStartLine;
   double dEdgeToTopAlignMarkY_Um = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeY_um;
   int nEdgeToTopAlignMarkY_Pixel = (int)GetUmToPixel_Y(dEdgeToTopAlignMarkY_Um);
   int nTopAlignMarkY_Pixel = nStartLine + nEdgeToTopAlignMarkY_Pixel;
   int nTopAlignMarkYPramIdx = nTopAlignMarkY_Pixel / nFrameHeight;
   if ((int)stFrame.nFrameIdx < nTopAlignMarkYPramIdx + 1)
      return FALSE;
   int nSideLine = (int)pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1];
   double nEdgeToTopAlignMarkX_Um = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeX_um;
   int nEdgeToTopAlignMarkX_Pixel = (int)GetUmToPixel_X(nEdgeToTopAlignMarkX_Um);
   int nTopAlignMarkX_Pixel = nSideLine + nEdgeToTopAlignMarkX_Pixel;
   CRect rtSearchArea = CRect(nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel, nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel);
   rtSearchArea.InflateRect(50, 50);
@@ -1792,67 +1794,67 @@
   return TRUE;
}
BOOL CInspectCamera::FindTopAlignMark_TempleteMatching(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindTopAlignMark_TempleteMatching(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(eDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassStartLine == FALSE)
   if (pSideData->m_bFindGlassStartLine == FALSE)
      return FALSE;
   if(pSideData->m_bTopMark_Find == TRUE)
   if (pSideData->m_bTopMark_Find == TRUE)
      return TRUE;
    if(pSideData->m_bTopCorner_Find == FALSE)
       return FALSE;
   if (pSideData->m_bTopCorner_Find == FALSE)
      return FALSE;
   // 1. Make ROI
   int nFrameWidth         = m_nFrameWidth;
   int nFrameHeight      = m_nFrameHeight;
   int nFrameWidth = m_nFrameWidth;
   int nFrameHeight = m_nFrameHeight;
   int nStartLine               = pSideData->m_nGlassStartLine;
   double dEdgeToTopAlignMarkY_Um   = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeY_um;
   int nEdgeToTopAlignMarkY_Pixel  = (int) GetUmToPixel_Y(dEdgeToTopAlignMarkY_Um);
   int nTopAlignMarkY_Pixel      = nStartLine + nEdgeToTopAlignMarkY_Pixel;
   int nTopAlignMarkYPramIdx      = nTopAlignMarkY_Pixel / nFrameHeight;
   int nStartLine = pSideData->m_nGlassStartLine;
   double dEdgeToTopAlignMarkY_Um = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeY_um;
   int nEdgeToTopAlignMarkY_Pixel = (int)GetUmToPixel_Y(dEdgeToTopAlignMarkY_Um);
   int nTopAlignMarkY_Pixel = nStartLine + nEdgeToTopAlignMarkY_Pixel;
   int nTopAlignMarkYPramIdx = nTopAlignMarkY_Pixel / nFrameHeight;
    if((int) stFrame.nFrameIdx < nTopAlignMarkYPramIdx + 1)
       return FALSE;
   if ((int)stFrame.nFrameIdx < nTopAlignMarkYPramIdx + 1)
      return FALSE;
   int nSideLine               = pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1];
   int nSideLine = (int)pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1];
   if(nSideLine <= 0)
   if (nSideLine <= 0)
   {
      CRect      rectSide = CRect(0,nTopAlignMarkY_Pixel,nFrameWidth-1,nTopAlignMarkY_Pixel);
      CRect      rectSide = CRect(0, nTopAlignMarkY_Pixel, nFrameWidth - 1, nTopAlignMarkY_Pixel);
      rectSide.InflateRect(0,30);
      rectSide.InflateRect(0, 30);
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rectSide.top),nFrameWidth,rectSide.Height());
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rectSide.top), nFrameWidth, rectSide.Height());
      if(frameBuffer.IsValidBuffer() == FALSE)
      if (frameBuffer.IsValidBuffer() == FALSE)
         return FALSE;
      rectSide.OffsetRect(0, -rectSide.top);
      int nThres            = m_pRecipe->m_SideParam[(int)(eDim)].m_nSideLineThreshold;
      int nThres = m_pRecipe->m_SideParam[(int)(eDim)].m_nSideLineThreshold;
      CSISEdgeFind   EdgeFind;
      EdgeFind.FindEdge_ToRightROI(&frameBuffer,nSideLine,DEFECT_EDGE_AUTO_PITCH,nThres,DEFECT_EDGE_AUTO_RATIO,0,rectSide);
      EdgeFind.FindEdge_ToRightROI(&frameBuffer, nSideLine, DEFECT_EDGE_AUTO_PITCH, nThres, DEFECT_EDGE_AUTO_RATIO, 0, rectSide);
   }
   if(nSideLine <= 0)
   if (nSideLine <= 0)
      return FALSE;
   double nEdgeToTopAlignMarkX_Um   = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeX_um;
   int nEdgeToTopAlignMarkX_Pixel  = (int) GetUmToPixel_X(nEdgeToTopAlignMarkX_Um);
   int nTopAlignMarkX_Pixel      = nSideLine + nEdgeToTopAlignMarkX_Pixel;
   double nEdgeToTopAlignMarkX_Um = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeX_um;
   int nEdgeToTopAlignMarkX_Pixel = (int)GetUmToPixel_X(nEdgeToTopAlignMarkX_Um);
   int nTopAlignMarkX_Pixel = nSideLine + nEdgeToTopAlignMarkX_Pixel;
   double dTarget_Rate = m_pRecipe->m_SideParam[(int) eDim].m_dTopMarkTemplateMatchingRate / 100.0;
   double dTarget_Rate = m_pRecipe->m_SideParam[(int)eDim].m_dTopMarkTemplateMatchingRate / 100.0;
   CvPoint ptMax_Point;
   double dMat_Max_Rate;
@@ -1921,75 +1923,80 @@
   // Make Mark Defect..
   CDefect_Info defectInfo;
   defectInfo.m_iFrameIdx         = stFrame.nFrameIdx;
   defectInfo.m_nCamID            = m_iCamera;
   defectInfo.m_nScanIdx         = stFrame.nScanIdx;
   defectInfo.m_nGlassStartLine   = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
   defectInfo.m_nSideIdx         = (int) eDim;
   defectInfo.m_ptDefectPos_pxl   = pSideData->m_rtTopMark_SearchArea.CenterPoint();
   defectInfo.m_rtDefectPos_pxl   = pSideData->m_rtTopMark_SearchArea;
   defectInfo.m_DefectLoc         = DefectLoc_Mark;
   defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
   defectInfo.m_nCamID = m_iCamera;
   defectInfo.m_nScanIdx = stFrame.nScanIdx;
   defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
   defectInfo.m_nSideIdx = (int)eDim;
   defectInfo.m_ptDefectPos_pxl = pSideData->m_rtTopMark_SearchArea.CenterPoint();
   defectInfo.m_rtDefectPos_pxl = pSideData->m_rtTopMark_SearchArea;
   defectInfo.m_DefectLoc = DefectLoc_Mark;
   m_pDefectControl->ExtractDefect_Mark(eDim, m_iCamera, stFrame.nScanIdx, defectInfo);
   return FALSE;
}
BOOL CInspectCamera::FindBotCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotCorner(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   CSingleLock localLock(&m_csBotCorner);
   localLock.Lock();
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   if (pSideData->m_bFindGlassStartLine == FALSE || pSideData->m_bFindGlassEndLine == FALSE)
   if (pSideData->m_bFindGlassStartLine == FALSE || pSideData->m_bFindGlassEndLine == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   if(pSideData->m_bBotCorner_Find == TRUE)
   if (pSideData->m_bBotCorner_Find == TRUE) {
      localLock.Unlock();
      return TRUE;
   }
   /*
   BOOL bBotCornerUse = (BOOL) (m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape == 0) ? FALSE : TRUE;
   if(bBotCornerUse == FALSE)
   BOOL bBotCornerUse = (BOOL)(m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape == 0) ? FALSE : TRUE;
   if (bBotCornerUse == FALSE) {
      localLock.Unlock();
      return FALSE;
   */
   }
   double dCornerSizeY_Um = (double) m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeY_um;
   int nCornerSizeY_Pixel = (int) GetUmToPixel_Y(dCornerSizeY_Um);
   int nFrameHeight      = m_nFrameHeight;
   int nFindBottomLine      = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dCornerSizeY_Um = (double)m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeY_um;
   int nCornerSizeY_Pixel = (int)GetUmToPixel_Y(dCornerSizeY_Um);
   int nFrameHeight = m_nFrameHeight;
   int nFindBottomLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   int nBottomCornerFrameIndex = (nFindBottomLine - nCornerSizeY_Pixel) / nFrameHeight;
   if((int) stFrame.nFrameIdx < nBottomCornerFrameIndex)
   if ((int)stFrame.nFrameIdx < nBottomCornerFrameIndex) {
      localLock.Unlock();
      return FALSE;
   }
   // 澜.. 内呈 Side 扼牢捞 捞傈 橇饭烙俊 乐栏搁 绢录瘤.. 茄搁俊 Thread 啊 咯矾俺 倒搁?... 困 橇饭烙狼 Thread 啊 酒流 Side 扼牢阑 给茫疽栏搁.. 绊刮 粱 秦焊磊..
   // 荤捞靛喊 Thread绰 窍唱父 倒绊 八荤 Thread甫 咯矾俺 倒府绰 备炼肺 官层具摆促
   int nSideLine = pSideData->m_nSideLineFrame[nBottomCornerFrameIndex];
   nSideLine = (nSideLine == -1) ? pSideData->m_nSideLineFrame[nBottomCornerFrameIndex] : nSideLine;
   // 음.. 코너 Side 라인이 이전 프레임에 있으면 어쩌지.. 한면에 Thread 가 여러개 돌면?... 위 프레임의 Thread 가 아직 Side 라인을 못찾았으면.. 고민 좀 해보자..
   // 사이드별 Thread는 하나만 돌고 검사 Thread를 여러개 돌리는 구조로 바꿔야겠다
   int nSideLine = (int)pSideData->m_nSideLineFrame[nBottomCornerFrameIndex];
   nSideLine = (nSideLine == -1) ? (int)pSideData->m_nSideLineFrame[nBottomCornerFrameIndex] : nSideLine;
   if(nSideLine == -1)
   if (nSideLine == -1) {
      localLock.Unlock();
      return FALSE;
   }
   double dCornerSizeX_Um = (double) m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeX_um;
   int nCornerSizeX_Pixel = (int) GetUmToPixel_X(dCornerSizeX_Um);
   double dCornerSizeX_Um = (double)m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeX_um;
   int nCornerSizeX_Pixel = (int)GetUmToPixel_X(dCornerSizeX_Um);
   CRect rtBottomCornerArea(0, 0, nCornerSizeX_Pixel, nCornerSizeY_Pixel);
   rtBottomCornerArea.OffsetRect(nSideLine, nFindBottomLine-nCornerSizeY_Pixel);
   rtBottomCornerArea.OffsetRect(nSideLine, nFindBottomLine - nCornerSizeY_Pixel);
   pSideData->m_bBotCorner_Find = TRUE;
   pSideData->m_rtBotCornerArea = rtBottomCornerArea;
@@ -1999,33 +2006,37 @@
   int nBottomCornerType = m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape;
   if(pSideParam->m_bBottomCornerFindDefect == FALSE)
   if (pSideParam->m_bBottomCornerFindDefect == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   if(nBottomCornerType == (int) 1)                  return FindBotCorner_CCut(iThread, emDim, stFrame);
   else if(nBottomCornerType == (int) 2)               return FindBotCorner_RCut(iThread, emDim, stFrame);
   localLock.Unlock();
   if (nBottomCornerType == (int)1)                  return FindBotCorner_CCut(iThread, emDim, stFrame);
   else if (nBottomCornerType == (int)2)               return FindBotCorner_RCut(iThread, emDim, stFrame);
   else                                       return FindBotCorner_None(iThread, emDim, stFrame);
   return TRUE;
}
BOOL CInspectCamera::FindBotCorner_None(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotCorner_None(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == FALSE)
   if (pSideData == FALSE)
      return FALSE;
   CRect rtBotCornerArea = pSideData->m_rtBotCornerArea;
   rtBotCornerArea.right = rtBotCornerArea.left + ALIGN_4BYTE(rtBotCornerArea.Width());
   if(rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull())
   if (rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull())
      return FALSE;
   int nFrameWidth         = m_nFrameWidth;
   int nFrameWidth = m_nFrameWidth;
   // 1. Inspect ROI
   COwnerBuffer pBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height());
@@ -2058,7 +2069,7 @@
      int nImageX = nInsStart;
      int nImageY = rtBotCornerArea.Height() - 1 - i;
      if (nImageX < 0 ||rtBotCornerArea.Width() <= nImageX || nImageY < 0 || rtBotCornerArea.Height() <= nImageY)
      if (nImageX < 0 || rtBotCornerArea.Width() <= nImageX || nImageY < 0 || rtBotCornerArea.Height() <= nImageY)
         continue;
      int nRange = (rtBotCornerArea.Width() <= nImageX + nInsRange) ? (rtBotCornerArea.Width() - 1 - nImageX) : nInsRange;
@@ -2105,23 +2116,23 @@
   return TRUE;
}
BOOL CInspectCamera::FindBotCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotCorner_CCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == FALSE)
   if (pSideData == FALSE)
      return FALSE;
   CRect rtBotCornerArea = pSideData->m_rtBotCornerArea;
   rtBotCornerArea.right = rtBotCornerArea.left + ALIGN_4BYTE(rtBotCornerArea.Width());
   if(rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull())
   if (rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull())
      return FALSE;
   int nFrameWidth         = m_nFrameWidth;
   int nFrameWidth = m_nFrameWidth;
   // 1. Inspect ROI
   COwnerBuffer pBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height());
@@ -2145,7 +2156,7 @@
   pSideData->m_rtBotCornerArea_Ins.bottom = pSideData->m_rtBotCornerArea_Offset.bottom - nInsRange;
   pSideData->m_rtBotCornerArea_Ins.top = pSideData->m_rtBotCornerArea_Offset.top - nInsRange;
   double dScaleY = (double) rtBotCornerArea.Height() / (double)rtBotCornerArea.Width();
   double dScaleY = (double)rtBotCornerArea.Height() / (double)rtBotCornerArea.Width();
   // 2. Make Masking..
   COwnerBuffer pMaskBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height());
@@ -2154,18 +2165,18 @@
   for (int i = 0; i < pMaskBuffer.GetWidth(); i++)
   {
      int nX = i;
      int nY = (int) ((double)i * dScaleY) - nInsStart;
      int nY = (int)((double)i * dScaleY) - nInsStart;
      if (nX < 0 || pMaskBuffer.GetWidth() <= nX || nY < 0 || pMaskBuffer.GetHeight() <= nY)
         continue;
      int nRange = (nY - nInsRange < 0) ? nY : nInsRange;
      if(nRange == 0)
      if (nRange == 0)
         continue;
      for(int j=0; j<nRange; j++)
         pMaskBuffer.SetPixel(nX, nY-j, 255);
      for (int j = 0; j < nRange; j++)
         pMaskBuffer.SetPixel(nX, nY - j, 255);
   }
   // 3. Processing
@@ -2206,23 +2217,23 @@
   return TRUE;
}
BOOL CInspectCamera::FindBotCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotCorner_RCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == FALSE)
   if (pSideData == FALSE)
      return FALSE;
   CRect rtBotCornerArea = pSideData->m_rtBotCornerArea;
   rtBotCornerArea.right = rtBotCornerArea.left + ALIGN_4BYTE(rtBotCornerArea.Width());
   if(rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull())
   if (rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull())
      return FALSE;
   int nFrameWidth         = m_nFrameWidth;
   int nFrameWidth = m_nFrameWidth;
   // 1. Inspect ROI
   COwnerBuffer pBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height());
@@ -2301,75 +2312,88 @@
   return TRUE;
}
BOOL CInspectCamera::FindBotAlignMark(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotAlignMark(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   CSingleLock localLock(&m_csThreadBotAlignMark);
   localLock.Lock();
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL) {
      localLock.Unlock();
      return FALSE;
   }
   CSide_Data*   pSideData = m_pGlassData->GetSideData(eDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL) {
      localLock.Unlock();
      return FALSE;
   }
    //if(pSideData->m_bBotCorner_Find == FALSE)
    //   return FALSE;
   if (pSideData->m_bBotCorner_Find == FALSE) {
      localLock.Unlock();
      return FALSE;
   }
   if(pSideData->m_bBotMark_Find == TRUE)
   if (pSideData->m_bBotMark_Find == TRUE) {
      localLock.Unlock();
      return TRUE;
   }
   BOOL bBotAlignMark = (BOOL) (m_pRecipe->m_SideParam[eDim].m_bBottomMark_Use == 1) ? TRUE : FALSE;
   BOOL bBotAlignMark = (BOOL)(m_pRecipe->m_SideParam[eDim].m_bBottomMark_Use == 1) ? TRUE : FALSE;
   if(bBotAlignMark == FALSE)
   if (bBotAlignMark == FALSE) {
      localLock.Unlock();
      return FindBotAlignMark_Virtual(iThread, eDim, stFrame);
   else
   {
      if(FindBotAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE)
   }
   else {
      if (FindBotAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) {
         localLock.Unlock();
         return FindBotAlignMark_Virtual(iThread, eDim, stFrame);
      else
      }
      else {
         localLock.Unlock();
         return TRUE;
      }
   }
}
BOOL CInspectCamera::FindBotAlignMark_Virtual(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotAlignMark_Virtual(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(eDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
    //if(pSideData->m_bBotCorner_Find == FALSE)
    //   return FALSE;
   //if(pSideData->m_bBotCorner_Find == FALSE)
   //   return FALSE;
   if(pSideData->m_bBotMark_Find == TRUE)
   if (pSideData->m_bBotMark_Find == TRUE)
      return TRUE;
   // 1. Make ROI
   int nFrameWidth         = m_nFrameWidth;
   int nFrameHeight      = m_nFrameHeight;
   int nFrameWidth = m_nFrameWidth;
   int nFrameHeight = m_nFrameHeight;
   int nEndLine                  = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dEdgeToBottomAlignMarkY_Um   = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeY_um;
   int nEdgeToBottomAlignMarkY_Pixel   = (int) GetUmToPixel_Y(dEdgeToBottomAlignMarkY_Um);
   int nBottomAlignMarkY_Pixel         = nEndLine - nEdgeToBottomAlignMarkY_Pixel;
   int nEndLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dEdgeToBottomAlignMarkY_Um = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeY_um;
   int nEdgeToBottomAlignMarkY_Pixel = (int)GetUmToPixel_Y(dEdgeToBottomAlignMarkY_Um);
   int nBottomAlignMarkY_Pixel = nEndLine - nEdgeToBottomAlignMarkY_Pixel;
   int nBottomCornerTopFrameIndex = nBottomAlignMarkY_Pixel / nFrameHeight; //pSideData->m_rtBotCornerArea.top / nFrameHeight;
   int nGlassEndLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   int nGlassEndLineFrame = nGlassEndLine / nFrameHeight;
   if((int) stFrame.nFrameIdx < nGlassEndLineFrame)
   if ((int)stFrame.nFrameIdx < nGlassEndLineFrame)
      return FALSE;
   int nSideLine               = pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex];
   double nEdgeToBotAlignMarkX_Um   = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeX_um;
   int nEdgeToBotAlignMarkX_Pixel  = (int) GetUmToPixel_X(nEdgeToBotAlignMarkX_Um);
   int nBottomAlignMarkX_Pixel      = nSideLine + nEdgeToBotAlignMarkX_Pixel;
   int nSideLine = (int)pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex];
   double nEdgeToBotAlignMarkX_Um = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeX_um;
   int nEdgeToBotAlignMarkX_Pixel = (int)GetUmToPixel_X(nEdgeToBotAlignMarkX_Um);
   int nBottomAlignMarkX_Pixel = nSideLine + nEdgeToBotAlignMarkX_Pixel;
   CRect rtSearchArea = CRect(nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel, nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel);
   rtSearchArea.InflateRect(50, 50);
@@ -2381,104 +2405,104 @@
   return TRUE;
}
BOOL CInspectCamera::FindBotAlignMark_TempleteMatching(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::FindBotAlignMark_TempleteMatching(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(eDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bBotMark_Find == TRUE)
   if (pSideData->m_bBotMark_Find == TRUE)
      return TRUE;
    //if(pSideData->m_bBotCorner_Find == FALSE)
    //   return FALSE;
   //if(pSideData->m_bBotCorner_Find == FALSE)
   //   return FALSE;
   // 1. Make ROI
   int nFrameWidth         = m_nFrameWidth;
   int nFrameHeight      = m_nFrameHeight;
   int nFrameWidth = m_nFrameWidth;
   int nFrameHeight = m_nFrameHeight;
   int nEndLine                  = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dEdgeToBottomAlignMarkY_Um   = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeY_um;
   int nEdgeToBottomAlignMarkY_Pixel   = (int) GetUmToPixel_Y(dEdgeToBottomAlignMarkY_Um);
   int nBottomAlignMarkY_Pixel         = nEndLine - nEdgeToBottomAlignMarkY_Pixel;
   int nEndLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dEdgeToBottomAlignMarkY_Um = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeY_um;
   int nEdgeToBottomAlignMarkY_Pixel = (int)GetUmToPixel_Y(dEdgeToBottomAlignMarkY_Um);
   int nBottomAlignMarkY_Pixel = nEndLine - nEdgeToBottomAlignMarkY_Pixel;
   int nBottomCornerTopFrameIndex = nBottomAlignMarkY_Pixel / nFrameHeight; // pSideData->m_rtBotCornerArea.top / nFrameHeight;
   int nGlassEndLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   int nGlassEndLineFrame = nGlassEndLine / nFrameHeight;
   if((int) stFrame.nFrameIdx < nGlassEndLineFrame)
   if ((int)stFrame.nFrameIdx < nGlassEndLineFrame)
      return FALSE;
   int nSideLine               = pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex];
   if(nSideLine <= 0)
   int nSideLine = (int)pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex];
   if (nSideLine <= 0)
   {
      CRect      rectSide = CRect(0,nBottomAlignMarkY_Pixel,nFrameWidth-1,nBottomAlignMarkY_Pixel);
      CRect      rectSide = CRect(0, nBottomAlignMarkY_Pixel, nFrameWidth - 1, nBottomAlignMarkY_Pixel);
      rectSide.InflateRect(0,30);
      rectSide.InflateRect(0, 30);
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rectSide.top),nFrameWidth,rectSide.Height());
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rectSide.top), nFrameWidth, rectSide.Height());
      if(frameBuffer.IsValidBuffer() == FALSE)
      if (frameBuffer.IsValidBuffer() == FALSE)
         return FALSE;
      rectSide.OffsetRect(0, -rectSide.top);
      int nThres            = m_pRecipe->m_SideParam[(int)(eDim)].m_nSideLineThreshold;
      int nThres = m_pRecipe->m_SideParam[(int)(eDim)].m_nSideLineThreshold;
      CSISEdgeFind   EdgeFind;
      EdgeFind.FindEdge_ToRightROI(&frameBuffer,nSideLine,DEFECT_EDGE_AUTO_PITCH,nThres,DEFECT_EDGE_AUTO_RATIO,0,rectSide);
      EdgeFind.FindEdge_ToRightROI(&frameBuffer, nSideLine, DEFECT_EDGE_AUTO_PITCH, nThres, DEFECT_EDGE_AUTO_RATIO, 0, rectSide);
   }
   if(nSideLine <= 0)
   if (nSideLine <= 0)
      return FALSE;
   double nEdgeToBotAlignMarkX_Um   = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeX_um;
   int nEdgeToBotAlignMarkX_Pixel  = (int) GetUmToPixel_X(nEdgeToBotAlignMarkX_Um);
   int nBottomAlignMarkX_Pixel      = nSideLine + nEdgeToBotAlignMarkX_Pixel;
   double nEdgeToBotAlignMarkX_Um = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeX_um;
   int nEdgeToBotAlignMarkX_Pixel = (int)GetUmToPixel_X(nEdgeToBotAlignMarkX_Um);
   int nBottomAlignMarkX_Pixel = nSideLine + nEdgeToBotAlignMarkX_Pixel;
   double dTarget_Rate = m_pRecipe->m_SideParam[(int) eDim].m_dBottomMarkTemplateMatchingRate / 100.0;
   double dTarget_Rate = m_pRecipe->m_SideParam[(int)eDim].m_dBottomMarkTemplateMatchingRate / 100.0;
   CvPoint ptMax_Point;
   double dMat_Max_Rate;
   double dMat_Min_Rate;
   for(int i=0 ; i<MAX_MARKER_COUNT ; i++)
   for (int i = 0; i < MAX_MARKER_COUNT; i++)
   {
USES_CONVERSION;
      USES_CONVERSION;
      char str_filename[256];
      sprintf_s(str_filename, "%s\\%s\\Side_%d_BotAlign_%d.bmp", W2A(RECIPE_ALIGN_PATH), W2A(m_pRecipe->GetRecipeName()), (int) eDim, i);
      sprintf_s(str_filename, "%s\\%s\\Side_%d_BotAlign_%d.bmp", W2A(RECIPE_ALIGN_PATH), W2A(m_pRecipe->GetRecipeName()), (int)eDim, i);
      IplImage* pTemplateImage = cvLoadImage(str_filename, CV_LOAD_IMAGE_GRAYSCALE);
      if(pTemplateImage == NULL)
      if (pTemplateImage == NULL)
         continue;
      CRect rtSearchArea = CRect(nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel, nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel);
      rtSearchArea.InflateRect(pTemplateImage->width * 2, pTemplateImage->height * 2);
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx,rtSearchArea.top), nFrameWidth, rtSearchArea.Height());
      CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtSearchArea.top), nFrameWidth, rtSearchArea.Height());
      if(!frameBuffer.IsValidBuffer())
      if (!frameBuffer.IsValidBuffer())
         continue;
      pSideData->m_rtBotMark_SearchArea = rtSearchArea;
      IplImage* scr = cvCreateImage(cvSize(rtSearchArea.Width(),rtSearchArea.Height()),8,1);
      IplImage* scr = cvCreateImage(cvSize(rtSearchArea.Width(), rtSearchArea.Height()), 8, 1);
      for(int i=0; i<rtSearchArea.Height(); i++)
      for (int i = 0; i < rtSearchArea.Height(); i++)
         memcpy(&scr->imageData[i * scr->widthStep], frameBuffer.GetDataAddress(rtSearchArea.left, i), rtSearchArea.Width());
      IplImage* ResultImage = cvCreateImage(cvSize(scr->width - pTemplateImage->width+1, scr->height - pTemplateImage->height+1 ),32,1);
      IplImage* ResultImage = cvCreateImage(cvSize(scr->width - pTemplateImage->width + 1, scr->height - pTemplateImage->height + 1), 32, 1);
      cvMatchTemplate(scr, pTemplateImage, ResultImage, CV_TM_CCOEFF_NORMED);
      cvMinMaxLoc(ResultImage, &dMat_Min_Rate, &dMat_Max_Rate, NULL, &ptMax_Point);
      ptMax_Point.x += pTemplateImage->width/2;
      ptMax_Point.y += pTemplateImage->height/2;
      ptMax_Point.x += pTemplateImage->width / 2;
      ptMax_Point.y += pTemplateImage->height / 2;
      int nTemplateW = pTemplateImage->width;
      int nTemplateH = pTemplateImage->height;
@@ -2486,41 +2510,41 @@
      cvReleaseImage(&pTemplateImage);
      cvReleaseImage(&scr);
      if(dMat_Max_Rate > dTarget_Rate)
      if (dMat_Max_Rate > dTarget_Rate)
      {
         pSideData->m_bBotMark_Find = TRUE;
         pSideData->m_rtBotMark_SearchArea = rtSearchArea;
         pSideData->m_ptBotMark_FindResult = CPoint(ptMax_Point.x, ptMax_Point.y);
         pSideData->m_ptBotMark_FindResult.Offset(rtSearchArea.left, rtSearchArea.top);
         pSideData->m_rtBotMark_FindResult = CRect(pSideData->m_ptBotMark_FindResult, pSideData->m_ptBotMark_FindResult);
         pSideData->m_rtBotMark_FindResult.InflateRect(nTemplateW/2, nTemplateH/2);
         pSideData->m_rtBotMark_FindResult.InflateRect(nTemplateW / 2, nTemplateH / 2);
         return TRUE;
      }
      }
   }
   // Make Mark Defect..
   CDefect_Info defectInfo;
   defectInfo.m_iFrameIdx         = stFrame.nFrameIdx;
   defectInfo.m_nCamID            = m_iCamera;
   defectInfo.m_nScanIdx         = stFrame.nScanIdx;
   defectInfo.m_nGlassStartLine   = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
   defectInfo.m_nSideIdx         = (int) eDim;
   defectInfo.m_ptDefectPos_pxl   = pSideData->m_rtBotMark_SearchArea.CenterPoint();
   defectInfo.m_rtDefectPos_pxl   = pSideData->m_rtBotMark_SearchArea;
   defectInfo.m_DefectLoc         = DefectLoc_Mark;
   defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
   defectInfo.m_nCamID = m_iCamera;
   defectInfo.m_nScanIdx = stFrame.nScanIdx;
   defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
   defectInfo.m_nSideIdx = (int)eDim;
   defectInfo.m_ptDefectPos_pxl = pSideData->m_rtBotMark_SearchArea.CenterPoint();
   defectInfo.m_rtDefectPos_pxl = pSideData->m_rtBotMark_SearchArea;
   defectInfo.m_DefectLoc = DefectLoc_Mark;
   m_pDefectControl->ExtractDefect_Mark(eDim, m_iCamera, stFrame.nScanIdx, defectInfo);
   return FALSE;
}
BOOL CInspectCamera::InspectDefect(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::InspectDefect(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   CRect rtInspectArea;
   int nCutLine = 0;
   if(MakeInspectRegion(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, rtInspectArea, nCutLine) == FALSE)
   if (MakeInspectRegion(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, rtInspectArea, nCutLine) == FALSE)
      return FALSE;
   // Inspect Area.
@@ -2528,9 +2552,9 @@
   std::vector<CDefect_Info> vecDefectCandidateList;
   for(int i=0; i<MAX_SIDE_INSPECT_TYPE; i++)
   for (int i = 0; i < MAX_SIDE_INSPECT_TYPE; i++)
   {
      InspectDefect_Process(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, rtInspectArea, nCutLine, (eSideInsType) i, &vecDefectCandidateList);
      InspectDefect_Process(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, rtInspectArea, nCutLine, (eSideInsType)i, &vecDefectCandidateList);
   }
   m_pDefectControl->ExtractDefect_Side(eDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList);
@@ -2538,20 +2562,20 @@
   return TRUE;
}
BOOL CInspectCamera::InspectDefect_Side(int iThread,DimensionDir eDim, stFrameIndex stFrame)
BOOL CInspectCamera::InspectDefect_Side(int iThread, DimensionDir eDim, stFrameIndex stFrame)
{
   std::vector<CRect> vecInspectAreaList;      // For Notch Region Divide..
   int nCutLine = 0;
   if(MakeInspectRegion(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, vecInspectAreaList, nCutLine) == FALSE)
   if (MakeInspectRegion(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, vecInspectAreaList, nCutLine) == FALSE)
      return FALSE;
   // Inspect Area.
   m_pGlassData->GetSideData(eDim)->m_nSideInspectAreaCount[stFrame.nFrameIdx] = vecInspectAreaList.size();
   for(int nRegionIdx=0; nRegionIdx<vecInspectAreaList.size(); nRegionIdx++)
   for (int nRegionIdx = 0; nRegionIdx < vecInspectAreaList.size(); nRegionIdx++)
   {
      if(MAX_SIDE_INSPECT_AREA_COUNT <= nRegionIdx)
      if (MAX_SIDE_INSPECT_AREA_COUNT <= nRegionIdx)
         continue;
      m_pGlassData->GetSideData(eDim)->m_rtInspectArea[stFrame.nFrameIdx] = vecInspectAreaList[nRegionIdx];
@@ -2560,9 +2584,9 @@
      std::vector<CDefect_Info> vecDefectCandidateList;
      for(int i=0; i<MAX_SIDE_INSPECT_TYPE; i++)
      for (int i = 0; i < MAX_SIDE_INSPECT_TYPE; i++)
      {
         InspectDefect_Process(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, vecInspectAreaList[nRegionIdx], nCutLine, (eSideInsType) i, &vecDefectCandidateList);
         InspectDefect_Process(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, vecInspectAreaList[nRegionIdx], nCutLine, (eSideInsType)i, &vecDefectCandidateList);
      }
      m_pDefectControl->ExtractDefect_Side(eDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList);
@@ -2571,64 +2595,64 @@
   return TRUE;
}
BOOL CInspectCamera::MakeInspectRegion(int iThread,DimensionDir eDim,int iScan,int iFrame, CRect& rtInspectArea, int& nCutLine)
BOOL CInspectCamera::MakeInspectRegion(int iThread, DimensionDir eDim, int iScan, int iFrame, CRect& rtInspectArea, int& nCutLine)
{
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_nSideLineFrame[iFrame] < 0)      // Side Line阑 给茫篮 版快..
   if (pSideData->m_nSideLineFrame[iFrame] < 0)      // Side Line을 못찾은 경우..
      return FALSE;
   // 1. Make Corner Area
   int nFindStartLine            = pSideData->m_nGlassStartLine;
   double dTopCornerSizeY_UM      = m_pRecipe->m_SideParam[eDim].m_nTopCornerSizeY_um;
   int nTopCornerYSizePixel      = (int) GetUmToPixel_Y(dTopCornerSizeY_UM);
   int nTopCornerEndLine         = nFindStartLine + nTopCornerYSizePixel;
   int nFindStartLine = pSideData->m_nGlassStartLine;
   double dTopCornerSizeY_UM = m_pRecipe->m_SideParam[eDim].m_nTopCornerSizeY_um;
   int nTopCornerYSizePixel = (int)GetUmToPixel_Y(dTopCornerSizeY_UM);
   int nTopCornerEndLine = nFindStartLine + nTopCornerYSizePixel;
   int nFindEndLine            = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dBottomCornerSizeY_UM   = m_pRecipe->m_SideParam[eDim].m_nBottomCornerSizeY_um;
   int nBottomCornerYSizePixel      = (int) GetUmToPixel_Y(dBottomCornerSizeY_UM);
   int nBottomCornerStartLine      = nFindEndLine - nBottomCornerYSizePixel;
   int nFindEndLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dBottomCornerSizeY_UM = m_pRecipe->m_SideParam[eDim].m_nBottomCornerSizeY_um;
   int nBottomCornerYSizePixel = (int)GetUmToPixel_Y(dBottomCornerSizeY_UM);
   int nBottomCornerStartLine = nFindEndLine - nBottomCornerYSizePixel;
   // 2. Max Inspect Area..
   CRect rtFrame;
   rtFrame.left               = pSideData->m_nSide_Chamfer_LineFrame[iFrame];
   rtFrame.top                  = iFrame * m_nFrameHeight;
   rtFrame.right               = rtFrame.left;
   rtFrame.bottom               = rtFrame.top + m_nFrameHeight;
   //rtFrame.top                  = rtFrame.top;   // 困肺 炼陛 歹 八荤秦辑 搬窃捞 钦媚瘤霸 秦焊磊..
   rtFrame.top                  = rtFrame.top - 100;   // 100 Pixel Frame 唱床柳 版快 巩力啊 登聪, 吝汗 八荤窍磊..
   rtFrame.left = (LONG)pSideData->m_nSide_Chamfer_LineFrame[iFrame];
   rtFrame.top = iFrame * m_nFrameHeight;
   rtFrame.right = rtFrame.left;
   rtFrame.bottom = rtFrame.top + m_nFrameHeight;
   int nMaxInspectRange         = 0;
   //rtFrame.top                  = rtFrame.top;   // 위로 조금 더 검사해서 결함이 합쳐지게 해보자..
   rtFrame.top = rtFrame.top - 100;   // 100 Pixel Frame 나눠진 경우 문제가 되니, 중복 검사하자..
   for(int i=0; i<MAX_SIDE_INSPECT_TYPE; i++)
   int nMaxInspectRange = 0;
   for (int i = 0; i < MAX_SIDE_INSPECT_TYPE; i++)
   {
      if(m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_bUseInspect == TRUE)
      if (m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_bUseInspect == TRUE)
      {
         int nSideLineOffset_pxl      = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_SideLine_Offset_um);
         int nInspect_Range_pxl      = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_Range_um);
         int nSideLineOffset_pxl = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_nInspect_SideLine_Offset_um);
         int nInspect_Range_pxl = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_nInspect_Range_um);
         int nInsRange            = abs(nSideLineOffset_pxl) + abs(nInspect_Range_pxl);
         nMaxInspectRange         = (nMaxInspectRange < nInsRange) ? nInsRange : nMaxInspectRange;
         int nInsRange = abs(nSideLineOffset_pxl) + abs(nInspect_Range_pxl);
         nMaxInspectRange = (nMaxInspectRange < nInsRange) ? nInsRange : nMaxInspectRange;
      }
   }
   rtFrame.InflateRect(nMaxInspectRange, 0);
   // 2. Make Roi, Exception Corner Area
   CRect rtGlassSideROI;
   rtGlassSideROI.left         = 0;
   rtGlassSideROI.top         = (nTopCornerEndLine < nFindStartLine) ? nFindStartLine : nTopCornerEndLine;
   rtGlassSideROI.right      = m_nFrameWidth;
   rtGlassSideROI.bottom      = nBottomCornerStartLine;
   rtGlassSideROI.left = 0;
   rtGlassSideROI.top = (nTopCornerEndLine < nFindStartLine) ? nFindStartLine : nTopCornerEndLine;
   rtGlassSideROI.right = m_nFrameWidth;
   rtGlassSideROI.bottom = nBottomCornerStartLine;
   nCutLine = rtFrame.CenterPoint().x;
   // 3. Return Inspect Area..
   rtInspectArea.IntersectRect(rtFrame, rtGlassSideROI);
   if(rtInspectArea.IsRectEmpty() || rtInspectArea.IsRectNull())
   if (rtInspectArea.IsRectEmpty() || rtInspectArea.IsRectNull())
      return FALSE;
   rtInspectArea.right = rtInspectArea.left + align_4byte(rtInspectArea.Width());
@@ -2636,57 +2660,57 @@
   return TRUE;
}
BOOL CInspectCamera::MakeInspectRegion(int iThread,DimensionDir eDim,int iScan,int iFrame, std::vector<CRect> & vecInspectArea, int& nCutLine)
BOOL CInspectCamera::MakeInspectRegion(int iThread, DimensionDir eDim, int iScan, int iFrame, std::vector<CRect>& vecInspectArea, int& nCutLine)
{
   CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_nSideLineFrame[iFrame] < 0)      // Side Line阑 给茫篮 版快..
   if (pSideData->m_nSideLineFrame[iFrame] < 0)      // Side Line을 못찾은 경우..
      return FALSE;
   // 1. Make Corner Area
   int nFindStartLine            = pSideData->m_nGlassStartLine;
   double dTopCornerSizeY_UM      = m_pRecipe->m_SideParam[eDim].m_nTopCornerSizeY_um;
   int nTopCornerYSizePixel      = (int) GetUmToPixel_Y(dTopCornerSizeY_UM);
   int nTopCornerEndLine         = nFindStartLine + nTopCornerYSizePixel;
   int nFindStartLine = pSideData->m_nGlassStartLine;
   double dTopCornerSizeY_UM = m_pRecipe->m_SideParam[eDim].m_nTopCornerSizeY_um;
   int nTopCornerYSizePixel = (int)GetUmToPixel_Y(dTopCornerSizeY_UM);
   int nTopCornerEndLine = nFindStartLine + nTopCornerYSizePixel;
   int nFindEndLine            = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dBottomCornerSizeY_UM   = m_pRecipe->m_SideParam[eDim].m_nBottomCornerSizeY_um;
   int nBottomCornerYSizePixel      = (int) GetUmToPixel_Y(dBottomCornerSizeY_UM);
   int nBottomCornerStartLine      = nFindEndLine - nBottomCornerYSizePixel;
   int nFindEndLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine;
   double dBottomCornerSizeY_UM = m_pRecipe->m_SideParam[eDim].m_nBottomCornerSizeY_um;
   int nBottomCornerYSizePixel = (int)GetUmToPixel_Y(dBottomCornerSizeY_UM);
   int nBottomCornerStartLine = nFindEndLine - nBottomCornerYSizePixel;
   // 2. Max Inspect Area..
   CRect rtFrame;
   rtFrame.left               = pSideData->m_nSide_Chamfer_LineFrame[iFrame];
   rtFrame.top                  = iFrame * m_nFrameHeight;
   rtFrame.right               = rtFrame.left;
   rtFrame.bottom               = rtFrame.top + m_nFrameHeight;
   rtFrame.left = (LONG)pSideData->m_nSide_Chamfer_LineFrame[iFrame];
   rtFrame.top = iFrame * m_nFrameHeight;
   rtFrame.right = rtFrame.left;
   rtFrame.bottom = rtFrame.top + m_nFrameHeight;
   //rtFrame.top                  = rtFrame.top;   // 困肺 炼陛 歹 八荤秦辑 搬窃捞 钦媚瘤霸 秦焊磊..
   rtFrame.top                  = rtFrame.top - 100;   // 100 Pixel Frame 唱床柳 版快 巩力啊 登聪, 吝汗 八荤窍磊..
   //rtFrame.top                  = rtFrame.top;   // 위로 조금 더 검사해서 결함이 합쳐지게 해보자..
   rtFrame.top = rtFrame.top - 100;   // 100 Pixel Frame 나눠진 경우 문제가 되니, 중복 검사하자..
   int nMaxInspectRange         = 0;
   int nMaxInspectRange = 0;
   for(int i=0; i<MAX_SIDE_INSPECT_TYPE; i++)
   for (int i = 0; i < MAX_SIDE_INSPECT_TYPE; i++)
   {
      if(m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_bUseInspect == TRUE)
      if (m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_bUseInspect == TRUE)
      {
         int nSideLineOffset_pxl      = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_SideLine_Offset_um);
         int nInspect_Range_pxl      = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_Range_um);
         int nSideLineOffset_pxl = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_nInspect_SideLine_Offset_um);
         int nInspect_Range_pxl = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_nInspect_Range_um);
         int nInsRange            = abs(nSideLineOffset_pxl) + abs(nInspect_Range_pxl);
         nMaxInspectRange         = (nMaxInspectRange < nInsRange) ? nInsRange : nMaxInspectRange;
         int nInsRange = abs(nSideLineOffset_pxl) + abs(nInspect_Range_pxl);
         nMaxInspectRange = (nMaxInspectRange < nInsRange) ? nInsRange : nMaxInspectRange;
      }
   }
   rtFrame.InflateRect(nMaxInspectRange, 0);
   // 2. Make Roi, Exception Corner Area
   CRect rtGlassSideROI;
   rtGlassSideROI.left         = 0;
   rtGlassSideROI.top         = (nTopCornerEndLine < nFindStartLine) ? nFindStartLine : nTopCornerEndLine;
   rtGlassSideROI.right      = m_nFrameWidth;
   rtGlassSideROI.bottom      = nBottomCornerStartLine;
   rtGlassSideROI.left = 0;
   rtGlassSideROI.top = (nTopCornerEndLine < nFindStartLine) ? nFindStartLine : nTopCornerEndLine;
   rtGlassSideROI.right = m_nFrameWidth;
   rtGlassSideROI.bottom = nBottomCornerStartLine;
   nCutLine = rtFrame.CenterPoint().x;
@@ -2694,7 +2718,7 @@
   CRect rtInspectArea;
   rtInspectArea.IntersectRect(rtFrame, rtGlassSideROI);
   if(rtInspectArea.IsRectEmpty() || rtInspectArea.IsRectNull())
   if (rtInspectArea.IsRectEmpty() || rtInspectArea.IsRectNull())
      return FALSE;
   // 4. Exception Notch Area...
@@ -2703,47 +2727,47 @@
   std::vector<CRect> vectorInspectAreaList_Old;
   vectorInspectAreaList_Old.clear();
   std::vector<CRect> vecExceptionNotchAreaList;
   int nNotchCount = m_pRecipe->m_SideParam[(int) eDim].m_nNotchCount;
   int nNotchCount = m_pRecipe->m_SideParam[(int)eDim].m_nNotchCount;
   for(int i=0; i<nNotchCount; i++)
   for (int i = 0; i < nNotchCount; i++)
   {
      int nDiff_StartLine = nFindStartLine - m_pRecipe->m_SideParam[(int) eDim].m_NotchPrm[i].m_nGlassStartLine_pxl;
      int nDiff_StartLine = nFindStartLine - m_pRecipe->m_SideParam[(int)eDim].m_NotchPrm[i].m_nGlassStartLine_pxl;
      CRect rtNotchArea = m_pRecipe->m_SideParam[(int) eDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
      CRect rtNotchArea = m_pRecipe->m_SideParam[(int)eDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
      rtNotchArea.OffsetRect(0, nDiff_StartLine);
      rtNotchArea.left = 0;
      rtNotchArea.right = m_nFrameWidth;
      vectorInspectAreaList_Old.resize(vectorInspectAreaList_New.size());
      std::copy(vectorInspectAreaList_New.begin(),  vectorInspectAreaList_New.end(), vectorInspectAreaList_Old.begin());
      std::copy(vectorInspectAreaList_New.begin(), vectorInspectAreaList_New.end(), vectorInspectAreaList_Old.begin());
      vectorInspectAreaList_New.clear();
      for(int j=0; j<vectorInspectAreaList_Old.size(); j++)
      for (int j = 0; j < vectorInspectAreaList_Old.size(); j++)
      {
         CRect rtTemp = vectorInspectAreaList_Old[j];
         CRect rtNotchInterSectRect;
         rtNotchInterSectRect.IntersectRect(rtTemp,  rtNotchArea);
         rtNotchInterSectRect.IntersectRect(rtTemp, rtNotchArea);
         if(rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull())      // 畴摹啊 救吧府绰 版快俊绰 促矫 持绢霖促..
         if (rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull())      // 노치가 안걸리는 경우에는 다시 넣어준다..
         {
            vectorInspectAreaList_New.push_back(rtTemp);
            continue;
         }
         if(rtTemp.Height() == rtNotchInterSectRect.Height())   // Notch啊 康开狼 傈眉牢 版快
         if (rtTemp.Height() == rtNotchInterSectRect.Height())   // Notch가 영역의 전체인 경우
            continue;
         if(rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom)            // 1. Notch Frame 困俊 吧赴 版快
         if (rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom)            // 1. Notch Frame 위에 걸린 경우
         {
            CRect rtNew = rtTemp;
            rtNew.top = rtNotchInterSectRect.bottom;
            vectorInspectAreaList_New.push_back(rtNew);
         }
         else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom)         // 2. Notch Frame 吝埃俊 吧赴 版快
         else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom)         // 2. Notch Frame 중간에 걸린 경우
         {
            CRect rtNewTop = rtTemp;
            rtNewTop.top = rtNotchInterSectRect.bottom;
@@ -2753,7 +2777,7 @@
            rtNewBot.bottom = rtNotchInterSectRect.top;
            vectorInspectAreaList_New.push_back(rtNewBot);
         }
         else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom)         // 3. Notch Frame 酒贰俊 吧赴 版快
         else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom)         // 3. Notch Frame 아래에 걸린 경우
         {
            CRect rtNew = rtTemp;
            rtNew.bottom = rtNotchInterSectRect.top;
@@ -2765,7 +2789,7 @@
   // 5. Make Return
   vecInspectArea.clear();
   for(int i=0; i<vectorInspectAreaList_New.size(); i++)
   for (int i = 0; i < vectorInspectAreaList_New.size(); i++)
   {
      CRect rtInspectArea = vectorInspectAreaList_New[i];
      rtInspectArea.right = rtInspectArea.left + align_4byte(rtInspectArea.Width());
@@ -2776,19 +2800,19 @@
   return TRUE;
}
BOOL CInspectCamera::InspectDefect_Process(int iThread,DimensionDir eDim,int iScan,int iFrame, CRect rtInspectArea, int nCutLine, eSideInsType emInsType, std::vector<CDefect_Info>* pDefectList)
BOOL CInspectCamera::InspectDefect_Process(int iThread, DimensionDir eDim, int iScan, int iFrame, CRect rtInspectArea, int nCutLine, eSideInsType emInsType, std::vector<CDefect_Info>* pDefectList)
{
   if (rtInspectArea.IsRectEmpty() == TRUE || m_pGlassData == NULL)
      return FALSE;
   int nSideLine = m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[iFrame];
   int nSideLine = (int)m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[iFrame];
   if (nSideLine < 0)
      return FALSE;
   DefectLocation defectLoc = DefectLoc_None;
   switch(emInsType)
   switch (emInsType)
   {
   case eSideInsType_Chip:         defectLoc = DefectLoc_Chip;
      break;
@@ -2810,42 +2834,42 @@
      return FALSE;
   }
   if(m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_bUseInspect == FALSE)
   if (m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_bUseInspect == FALSE)
      return TRUE;
   // 0. Parameter Initialize..
   CString strDefectType      = _T("Unknown");
   int nMethod               = 0;
   int nThreshold_Low         = 0;
   int nThreshold_High         = 0;
   int nPitch               = 0;
   int nPitch_Threshold      = 0;
   int nMinSize            = 0;
   int nMinSize_X            = 0;
   int nMinSize_Y            = 0;
   int nDilation            = 0;
   int nInsStart            = 0;
   int nInsRange            = 0;
   CString strDefectType = _T("Unknown");
   int nMethod = 0;
   int nThreshold_Low = 0;
   int nThreshold_High = 0;
   int nPitch = 0;
   int nPitch_Threshold = 0;
   int nMinSize = 0;
   int nMinSize_X = 0;
   int nMinSize_Y = 0;
   int nDilation = 0;
   int nInsStart = 0;
   int nInsRange = 0;
   BOOL bStartNearFilterUse   = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_bSide_Filter;
   int nStartNearFilterRange   = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nSide_Filter_um;
   BOOL bStartNearFilterUse = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_bSide_Filter;
   int nStartNearFilterRange = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nSide_Filter_um;
   nMethod                  = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nInspect_Method;
   nThreshold_Low            = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nMin_Threshold;
   nThreshold_High            = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nMax_Threshold;
   nPitch                  = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nDiff_Pitch;
   nPitch_Threshold         = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nDiff_Threshold;
   nMinSize               = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nMinSize_Filter_pxl;
   nMinSize_X               = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nMinSize_Filter_X_um);
   nMinSize_Y               = (int) GetUmToPixel_Y((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nMinSize_Filter_Y_um);
   nDilation               = m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nDefect_Size_Dilation;
   nMethod = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nInspect_Method;
   nThreshold_Low = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nMin_Threshold;
   nThreshold_High = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nMax_Threshold;
   nPitch = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nDiff_Pitch;
   nPitch_Threshold = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nDiff_Threshold;
   nMinSize = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nMinSize_Filter_pxl;
   nMinSize_X = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nMinSize_Filter_X_um);
   nMinSize_Y = (int)GetUmToPixel_Y((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nMinSize_Filter_Y_um);
   nDilation = m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nDefect_Size_Dilation;
   nInsStart               = (int) GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nInspect_SideLine_Offset_um);
   nInsRange               = (int) GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[(int) emInsType].m_nInspect_Range_um);
   nInsStart = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nInspect_SideLine_Offset_um);
   nInsRange = (int)GetUmToPixel_X((double)m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[(int)emInsType].m_nInspect_Range_um);
   //CRect rtProcessArea(rtInspectArea.CenterPoint().x + nInsStart, rtInspectArea.top, rtInspectArea.CenterPoint().x + nInsStart + nInsRange, rtInspectArea.bottom);
   CRect rtProcessArea(nCutLine + nInsStart, rtInspectArea.top, nCutLine + nInsStart + nInsRange, rtInspectArea.bottom);
   if (rtProcessArea.right < rtProcessArea.left)
   {
@@ -2859,20 +2883,20 @@
      return FALSE;
   CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(iScan, rtInspectArea.top), m_nFrameWidth, m_nFrameHeight);
   if(frameBuffer.IsValidBuffer() == FALSE)
   if (frameBuffer.IsValidBuffer() == FALSE)
      return FALSE;
   // Set Insert Area.. For UI..
   m_pGlassData->GetSideData(eDim)->m_rtInspectArea_InsType[(int) emInsType][iFrame] = rtProcessArea;
   m_pGlassData->GetSideData(eDim)->m_rtInspectArea_InsType[(int)emInsType][iFrame] = rtProcessArea;
   if(bStartNearFilterUse)
      m_pGlassData->GetSideData(eDim)->m_nSideFilterLine_InsType[(int) emInsType][iFrame] = (0 <= nStartNearFilterRange) ? rtProcessArea.left + nStartNearFilterRange : rtProcessArea.right + nStartNearFilterRange;
   if (bStartNearFilterUse)
      m_pGlassData->GetSideData(eDim)->m_nSideFilterLine_InsType[(int)emInsType][iFrame] = (0 <= nStartNearFilterRange) ? rtProcessArea.left + nStartNearFilterRange : rtProcessArea.right + nStartNearFilterRange;
   // 1. Inspect ROI
   COwnerBuffer pDefectProcessImage(rtProcessArea.Width(), rtProcessArea.Height());
   for (int i = 0; i < rtProcessArea.Height(); i++)
      memcpy(pDefectProcessImage.GetDataAddress(0,i), frameBuffer.GetDataAddress(rtProcessArea.left, i), rtProcessArea.Width());
      memcpy(pDefectProcessImage.GetDataAddress(0, i), frameBuffer.GetDataAddress(rtProcessArea.left, i), rtProcessArea.Width());
   // 2. Inspect Algorithm
   COwnerBuffer pBinImage;
@@ -2888,10 +2912,10 @@
   DefectProcess(eDim, iScan, iFrame, &pDefectProcessImage, &pBinImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, pDefectList);
   CString str;
   str.Format(_T("Defect\\InsArea_Ori_Frame%d_%d_%d_%d_%d"),iFrame, rtInspectArea.left, rtInspectArea.top, rtInspectArea.right, rtInspectArea.bottom);
   str.Format(_T("Defect\\InsArea_Ori_Frame%d_%d_%d_%d_%d"), iFrame, rtInspectArea.left, rtInspectArea.top, rtInspectArea.right, rtInspectArea.bottom);
   SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), &pDefectProcessImage, str);
   str.Format(_T("Defect\\InsArea_Bin_Frame%d_%d_%d_%d_%d"),iFrame, rtInspectArea.left, rtInspectArea.top, rtInspectArea.right, rtInspectArea.bottom);
   str.Format(_T("Defect\\InsArea_Bin_Frame%d_%d_%d_%d_%d"), iFrame, rtInspectArea.left, rtInspectArea.top, rtInspectArea.right, rtInspectArea.bottom);
   SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), &pBinImage, str);
   return TRUE;
@@ -2946,7 +2970,7 @@
            {
               if (compareResult.m128i_u8[k] != 0)
               {
                  pBinImage->SetPixel(j+k, i, 255); //[i * pBinImage->step1() + j + k] = (char)255;
                  pBinImage->SetPixel(j + k, i, 255); //[i * pBinImage->step1() + j + k] = (char)255;
               }
            }
         }
@@ -3041,7 +3065,7 @@
            {
               if (compareResult.m128i_u8[k] != 0)
               {
                  pBinImage->SetPixel(j+k, i, 255); // [i * pBinImage->step1() + j + k] = (char)255;
                  pBinImage->SetPixel(j + k, i, 255); // [i * pBinImage->step1() + j + k] = (char)255;
               }
            }
         }
@@ -3136,7 +3160,7 @@
            {
               if (compareResult.m128i_u8[k] != 0)
               {
                  pBinImage->SetPixel(j+k, i, 255); // [i * pBinImage->step1() + j + k] = (char)255;
                  pBinImage->SetPixel(j + k, i, 255); // [i * pBinImage->step1() + j + k] = (char)255;
               }
            }
         }
@@ -3226,19 +3250,19 @@
         }
         // 2. Threshold Suppress
         compare_Thres_Low      = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_min_epu8(imageSource, thresLow), thresLow), K_INV_ZERO);      // Greater Than
         compare_Thres_High      = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(imageSource, thresHigh), thresHigh), K_INV_ZERO);   // Less Than
         compare_Thres_Result   = _mm_or_si128(compare_Thres_Low, compare_Thres_High);
         compare_Thres_Low = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_min_epu8(imageSource, thresLow), thresLow), K_INV_ZERO);      // Greater Than
         compare_Thres_High = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(imageSource, thresHigh), thresHigh), K_INV_ZERO);   // Less Than
         compare_Thres_Result = _mm_or_si128(compare_Thres_Low, compare_Thres_High);
         // 3. Pitch Compare
         compare_Pitch_Up      = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Up));
         compare_Pitch_Down      = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Down));   // Less Than
         compare_Pitch_Up = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Up));
         compare_Pitch_Down = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Down));   // Less Than
         //compare_Pitch_Result   = _mm_min_epu8(compare_Pitch_Up, compare_Pitch_Down);
         compare_Pitch_Result   = _mm_max_epu8(compare_Pitch_Up, compare_Pitch_Down);
         compare_Pitch_Result   = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(compare_Pitch_Result, thresPitch), thresPitch), K_INV_ZERO);   // Less Than
         compare_Pitch_Result = _mm_max_epu8(compare_Pitch_Up, compare_Pitch_Down);
         compare_Pitch_Result = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(compare_Pitch_Result, thresPitch), thresPitch), K_INV_ZERO);   // Less Than
         // 4. And
         compare_Result         = _mm_and_si128(compare_Thres_Result, compare_Pitch_Result);
         compare_Result = _mm_and_si128(compare_Thres_Result, compare_Pitch_Result);
         int nProcCount = (pImageData->GetWidth() - (16 * nMul));
@@ -3250,7 +3274,7 @@
            {
               if (compare_Result.m128i_u8[k] != 0)
               {
                  pBinImage->SetPixel(j+k, i, 255); //[i * pBinImage->GetWidth() + j + k] = (char)255;
                  pBinImage->SetPixel(j + k, i, 255); //[i * pBinImage->GetWidth() + j + k] = (char)255;
               }
            }
         }
@@ -3340,19 +3364,19 @@
         }
         // 2. Threshold Suppress
         compare_Thres_Low      = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_min_epu8(imageSource, thresLow), thresLow), K_INV_ZERO);      // Greater Than
         compare_Thres_High      = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(imageSource, thresHigh), thresHigh), K_INV_ZERO);   // Less Than
         compare_Thres_Result   = _mm_or_si128(compare_Thres_Low, compare_Thres_High);
         compare_Thres_Low = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_min_epu8(imageSource, thresLow), thresLow), K_INV_ZERO);      // Greater Than
         compare_Thres_High = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(imageSource, thresHigh), thresHigh), K_INV_ZERO);   // Less Than
         compare_Thres_Result = _mm_or_si128(compare_Thres_Low, compare_Thres_High);
         // 3. Pitch Compare
         compare_Pitch_Up      = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Up));
         compare_Pitch_Down      = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Down));   // Less Than
         compare_Pitch_Up = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Up));
         compare_Pitch_Down = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Down));   // Less Than
         //compare_Pitch_Result   = _mm_min_epu8(compare_Pitch_Up, compare_Pitch_Down);
         compare_Pitch_Result   = _mm_max_epu8(compare_Pitch_Up, compare_Pitch_Down);
         compare_Pitch_Result   = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(compare_Pitch_Result, thresPitch), thresPitch), K_INV_ZERO);   // Less Than
         compare_Pitch_Result = _mm_max_epu8(compare_Pitch_Up, compare_Pitch_Down);
         compare_Pitch_Result = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(compare_Pitch_Result, thresPitch), thresPitch), K_INV_ZERO);   // Less Than
         // 4. And
         compare_Result         = _mm_and_si128(compare_Thres_Result, compare_Pitch_Result);
         compare_Result = _mm_and_si128(compare_Thres_Result, compare_Pitch_Result);
         int nProcCount = (pImageData->GetWidth() - (16 * nMul));
@@ -3364,7 +3388,7 @@
            {
               if (compare_Result.m128i_u8[k] != 0)
               {
                  pBinImage->SetPixel(j+k, i, 255); //[i * pBinImage->GetWidth() + j + k] = (char)255;
                  pBinImage->SetPixel(j + k, i, 255); //[i * pBinImage->GetWidth() + j + k] = (char)255;
               }
            }
         }
@@ -3384,9 +3408,9 @@
static int g_static_debug = 1;
BOOL CInspectCamera::DefectProcess(DimensionDir eDim,int iScan,int iFrame, COwnerBuffer* pImageData, COwnerBuffer* pBinImage, CRect rtROIPos, int nMinSize, int nMinSizeX, int nMinSizeY, int nDilation, BOOL bStartNearFilter, int nStartNearFilterRange, DefectLocation defectType, std::vector<CDefect_Info>* pDefectList)
BOOL CInspectCamera::DefectProcess(DimensionDir eDim, int iScan, int iFrame, COwnerBuffer* pImageData, COwnerBuffer* pBinImage, CRect rtROIPos, int nMinSize, int nMinSizeX, int nMinSizeY, int nDilation, BOOL bStartNearFilter, int nStartNearFilterRange, DefectLocation defectType, std::vector<CDefect_Info>* pDefectList)
{
   if(pDefectList == NULL)
   if (pDefectList == NULL)
      return FALSE;
   if (pImageData == NULL || pBinImage == NULL)
@@ -3400,8 +3424,8 @@
   cv::Mat pBinMat = cv::Mat::zeros(pBinImage->GetHeight(), pBinImage->GetWidth(), CV_8UC1);
   // OwnerBuffer 郴何肺 16硅荐 皋葛府 爱绊 乐绢辑 茄锅俊 墨乔 救蹬..
   for(int i=0; i<pBinImage->GetHeight(); i++)
   // OwnerBuffer 내부로 16배수 메모리 갖고 있어서 한번에 카피 안돼..
   for (int i = 0; i < pBinImage->GetHeight(); i++)
      CopyMemory(&pBinMat.data[pBinMat.step1() * i], pBinImage->GetDataAddress(0, i), pBinImage->GetWidth());
   /*
@@ -3416,17 +3440,17 @@
   //   cv::dilate(pBinMat, pBinMat, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3)), cv::Point(-1,-1), nDilation);
   CString strFileName;
   strFileName.Format(_T("Defect\\%s_Origin"), g_strDefectType[(int) defectType]);
   strFileName.Format(_T("Defect\\%s_Origin"), g_strDefectType[(int)defectType]);
   SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), pImageData, strFileName);
   strFileName.Format(_T("Defect\\%s_Bin"), g_strDefectType[(int) defectType]);
   strFileName.Format(_T("Defect\\%s_Bin"), g_strDefectType[(int)defectType]);
   SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), pBinImage, strFileName);
   cv::Mat matLabel, matStats, matCentrois;
   int numOfLables = cv::connectedComponentsWithStats(pBinMat, matLabel, matStats, matCentrois, 8);
   if(numOfLables <= 1)   // 硅版 窍唱父 乐澜..
   if (numOfLables <= 1)   // 배경 하나만 있음..
      return TRUE;
   std::vector<int> vecMin, vecMax, vecSum, vecPixelCount;
@@ -3449,9 +3473,9 @@
         int nPxlValue = (int)pImageData->GetPixel(j, i);
         if(nLabelIdx == 0)
         if (nLabelIdx == 0)
            continue;
         if(pBinImage->GetPixel(j, i) == 0 && nLabelIdx < MAX_DEFECT_COUNT_SIDE)
         if (pBinImage->GetPixel(j, i) == 0 && nLabelIdx < MAX_DEFECT_COUNT_SIDE)
            backgroundLables[nLabelIdx] = TRUE;
         if (nPxlValue < vecMin[nLabelIdx])
@@ -3466,7 +3490,7 @@
      }
   }
   int nDefectIdx = (int) pDefectList->size();
   int nDefectIdx = (int)pDefectList->size();
   for (int nIdx = 0; nIdx < numOfLables; nIdx++)
   {
@@ -3480,16 +3504,16 @@
      int width = matStats.at<int>(nIdx, cv::CC_STAT_WIDTH);
      int height = matStats.at<int>(nIdx, cv::CC_STAT_HEIGHT);
      int x = (int)matCentrois.at<double>(nIdx, 0); //吝缴谅钎
      int x = (int)matCentrois.at<double>(nIdx, 0); //중심좌표
      int y = (int)matCentrois.at<double>(nIdx, 1);
      if(MAX_DEFECT_COUNT_SIDE < nIdx)
      if (MAX_DEFECT_COUNT_SIDE < nIdx)
         continue;
      if(backgroundLables[nIdx] == TRUE)
      if (backgroundLables[nIdx] == TRUE)
         continue;
      if(nIdx == 0)
      if (nIdx == 0)
         continue;
      if ((0 < nStartNearFilterRange && left <= nStartNearFilterRange) || (nStartNearFilterRange < 0 && pBinImage->GetWidth() + nStartNearFilterRange <= left + width))
@@ -3498,10 +3522,10 @@
      if (vecPixelCount[nIdx] < nMinSize)
         bFiltering = TRUE;
      if(width < nMinSizeX)
      if (width < nMinSizeX)
         bFiltering = TRUE;
      if(height < nMinSizeY)
      if (height < nMinSizeY)
         bFiltering = TRUE;
      if (bStartNearFilter == TRUE && bStartNear == FALSE)
@@ -3519,27 +3543,27 @@
         CDefect_Info defectInfo;
         defectInfo.m_nIndex            = nDefectIdx++;
         defectInfo.m_iFrameIdx         = iFrame;
         defectInfo.m_nCamID            = m_iCamera;
         defectInfo.m_nScanIdx         = iScan;
         defectInfo.m_nGlassStartLine   = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
         defectInfo.m_nSideIdx         = (int) eDim;
         defectInfo.m_nIndex = nDefectIdx++;
         defectInfo.m_iFrameIdx = iFrame;
         defectInfo.m_nCamID = m_iCamera;
         defectInfo.m_nScanIdx = iScan;
         defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
         defectInfo.m_nSideIdx = (int)eDim;
         defectInfo.m_ptDefectPos_pxl   = rtDefectArea.CenterPoint();
         defectInfo.m_rtDefectPos_pxl   = rtDefectArea;
         defectInfo.m_ptDefectPos_pxl = rtDefectArea.CenterPoint();
         defectInfo.m_rtDefectPos_pxl = rtDefectArea;
         defectInfo.m_nMinSize         = nMinSize;
         defectInfo.m_nBlobDilation      = area;
         defectInfo.m_nMinSize = nMinSize;
         defectInfo.m_nBlobDilation = area;
         // Image Info
         defectInfo.m_nBlobCount         = vecPixelCount[nIdx];
         defectInfo.m_nGray_Max         = vecMax[nIdx];
         defectInfo.m_nGray_Min         = vecMin[nIdx];
         defectInfo.m_nGray_Sum         = vecSum[nIdx];
         defectInfo.m_dGray_Avg         = (double)(defectInfo.m_nGray_Sum) / (double)(defectInfo.m_nBlobCount);
         defectInfo.m_dRectArea_Ratio   = 100.0 * ((double) defectInfo.m_nBlobCount) / ((double) (rtDefectArea.Width() * rtDefectArea.Height()));
         defectInfo.m_DefectLoc         = defectType;
         defectInfo.m_nBlobCount = vecPixelCount[nIdx];
         defectInfo.m_nGray_Max = vecMax[nIdx];
         defectInfo.m_nGray_Min = vecMin[nIdx];
         defectInfo.m_nGray_Sum = vecSum[nIdx];
         defectInfo.m_dGray_Avg = (double)(defectInfo.m_nGray_Sum) / (double)(defectInfo.m_nBlobCount);
         defectInfo.m_dRectArea_Ratio = 100.0 * ((double)defectInfo.m_nBlobCount) / ((double)(rtDefectArea.Width() * rtDefectArea.Height()));
         defectInfo.m_DefectLoc = defectType;
         pDefectList->push_back(defectInfo);
      }
@@ -3548,9 +3572,9 @@
   return TRUE;
}
BOOL CInspectCamera::DefectProcess(DimensionDir eDim,int iScan,int iFrame, IplImage* pImageData, IplImage* pBinImage, CRect rtROIPos, int nMinSize, int nMinSizeX, int nMinSizeY, int nDilation, BOOL bStartNearFilter, int nStartNearFilterRange, DefectLocation defectType, std::vector<CDefect_Info>* pDefectList)
BOOL CInspectCamera::DefectProcess(DimensionDir eDim, int iScan, int iFrame, IplImage* pImageData, IplImage* pBinImage, CRect rtROIPos, int nMinSize, int nMinSizeX, int nMinSizeY, int nDilation, BOOL bStartNearFilter, int nStartNearFilterRange, DefectLocation defectType, std::vector<CDefect_Info>* pDefectList)
{
   if(pDefectList == NULL)
   if (pDefectList == NULL)
      return FALSE;
   if (pImageData == NULL || pBinImage == NULL)
@@ -3564,9 +3588,9 @@
   cv::Mat pBinMat = cv::Mat::zeros(pBinImage->height, pBinImage->width, CV_8UC1);
   // OwnerBuffer 郴何肺 16硅荐 皋葛府 爱绊 乐绢辑 茄锅俊 墨乔 救蹬..
   for(int i=0; i<pBinImage->height; i++)
      CopyMemory(&pBinMat.data[pBinMat.step1() * i], &pBinImage->imageData[pBinImage->widthStep*i], pBinImage->width);
   // OwnerBuffer 내부로 16배수 메모리 갖고 있어서 한번에 카피 안돼..
   for (int i = 0; i < pBinImage->height; i++)
      CopyMemory(&pBinMat.data[pBinMat.step1() * i], &pBinImage->imageData[pBinImage->widthStep * i], pBinImage->width);
   /*
   if(0 < nDilation)
@@ -3580,17 +3604,17 @@
   //   cv::dilate(pBinMat, pBinMat, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3)), cv::Point(-1,-1), nDilation);
   CString strFileName;
   strFileName.Format(_T("Defect\\%s_Origin"), g_strDefectType[(int) defectType]);
   strFileName.Format(_T("Defect\\%s_Origin"), g_strDefectType[(int)defectType]);
   SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), pImageData, strFileName);
   strFileName.Format(_T("Defect\\%s_Bin"), g_strDefectType[(int) defectType]);
   strFileName.Format(_T("Defect\\%s_Bin"), g_strDefectType[(int)defectType]);
   SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), pBinImage, strFileName);
   cv::Mat matLabel, matStats, matCentrois;
   int numOfLables = cv::connectedComponentsWithStats(pBinMat, matLabel, matStats, matCentrois, 8);
   if(numOfLables <= 1)   // 硅版 窍唱父 乐澜..
   if (numOfLables <= 1)   // 배경 하나만 있음..
      return TRUE;
   std::vector<int> vecMin, vecMax, vecSum, vecPixelCount;
@@ -3611,11 +3635,11 @@
      {
         int nLabelIdx = (int)label[j];
         int nPxlValue = (int)pImageData->imageData[i*pImageData->widthStep+j];
         int nPxlValue = (int)pImageData->imageData[i * pImageData->widthStep + j];
         if(nLabelIdx == 0)
         if (nLabelIdx == 0)
            continue;
         if(pBinImage->imageData[i*pImageData->widthStep+j] == 0 && nLabelIdx < MAX_DEFECT_COUNT_SIDE)
         if (pBinImage->imageData[i * pImageData->widthStep + j] == 0 && nLabelIdx < MAX_DEFECT_COUNT_SIDE)
            backgroundLables[nLabelIdx] = TRUE;
         if (nPxlValue < vecMin[nLabelIdx])
@@ -3630,7 +3654,7 @@
      }
   }
   int nDefectIdx = (int) pDefectList->size();
   int nDefectIdx = (int)pDefectList->size();
   for (int nIdx = 0; nIdx < numOfLables; nIdx++)
   {
@@ -3644,16 +3668,16 @@
      int width = matStats.at<int>(nIdx, cv::CC_STAT_WIDTH);
      int height = matStats.at<int>(nIdx, cv::CC_STAT_HEIGHT);
      int x = (int)matCentrois.at<double>(nIdx, 0); //吝缴谅钎
      int x = (int)matCentrois.at<double>(nIdx, 0); //중심좌표
      int y = (int)matCentrois.at<double>(nIdx, 1);
      if(MAX_DEFECT_COUNT_SIDE < nIdx)
      if (MAX_DEFECT_COUNT_SIDE < nIdx)
         continue;
      if(backgroundLables[nIdx] == TRUE)
      if (backgroundLables[nIdx] == TRUE)
         continue;
      if(nIdx == 0)
      if (nIdx == 0)
         continue;
      if ((0 < nStartNearFilterRange && left <= nStartNearFilterRange) || (nStartNearFilterRange < 0 && pBinImage->width + nStartNearFilterRange <= left + width))
@@ -3664,15 +3688,15 @@
      if (nMinSizeX != 0)
      {
      if(width < nMinSizeX)
         bFiltering = TRUE;
         if (width < nMinSizeX)
            bFiltering = TRUE;
      }
      if (nMinSizeY!= 0)
      if (nMinSizeY != 0)
      {
         if (height < nMinSizeY)
            bFiltering = TRUE;
      }
      if (bStartNearFilter == TRUE && bStartNear == FALSE)
         bFiltering = TRUE;
@@ -3689,27 +3713,27 @@
         CDefect_Info defectInfo;
         defectInfo.m_nIndex            = nDefectIdx++;
         defectInfo.m_iFrameIdx         = iFrame;
         defectInfo.m_nCamID            = m_iCamera;
         defectInfo.m_nScanIdx         = iScan;
         defectInfo.m_nGlassStartLine   = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
         defectInfo.m_nSideIdx         = (int) eDim;
         defectInfo.m_nIndex = nDefectIdx++;
         defectInfo.m_iFrameIdx = iFrame;
         defectInfo.m_nCamID = m_iCamera;
         defectInfo.m_nScanIdx = iScan;
         defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine;
         defectInfo.m_nSideIdx = (int)eDim;
         defectInfo.m_ptDefectPos_pxl   = rtDefectArea.CenterPoint();
         defectInfo.m_rtDefectPos_pxl   = rtDefectArea;
         defectInfo.m_ptDefectPos_pxl = rtDefectArea.CenterPoint();
         defectInfo.m_rtDefectPos_pxl = rtDefectArea;
         defectInfo.m_nMinSize         = nMinSize;
         defectInfo.m_nBlobDilation      = area;
         defectInfo.m_nMinSize = nMinSize;
         defectInfo.m_nBlobDilation = area;
         // Image Info
         defectInfo.m_nBlobCount         = vecPixelCount[nIdx];
         defectInfo.m_nGray_Max         = vecMax[nIdx];
         defectInfo.m_nGray_Min         = vecMin[nIdx];
         defectInfo.m_nGray_Sum         = vecSum[nIdx];
         defectInfo.m_dGray_Avg         = (double)(defectInfo.m_nGray_Sum) / (double)(defectInfo.m_nBlobCount);
         defectInfo.m_dRectArea_Ratio   = 100.0 * ((double) defectInfo.m_nBlobCount) / ((double) (rtDefectArea.Width() * rtDefectArea.Height()));
         defectInfo.m_DefectLoc         = defectType;
         defectInfo.m_nBlobCount = vecPixelCount[nIdx];
         defectInfo.m_nGray_Max = vecMax[nIdx];
         defectInfo.m_nGray_Min = vecMin[nIdx];
         defectInfo.m_nGray_Sum = vecSum[nIdx];
         defectInfo.m_dGray_Avg = (double)(defectInfo.m_nGray_Sum) / (double)(defectInfo.m_nBlobCount);
         defectInfo.m_dRectArea_Ratio = 100.0 * ((double)defectInfo.m_nBlobCount) / ((double)(rtDefectArea.Width() * rtDefectArea.Height()));
         defectInfo.m_DefectLoc = defectType;
         pDefectList->push_back(defectInfo);
      }
@@ -3718,59 +3742,59 @@
   return TRUE;
}
BOOL CInspectCamera::Notch_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Notch_Process(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassEndLine == FALSE)      // Notch Processing篮 End Line 茫篮 Frame捞..
   if (pSideData->m_bFindGlassEndLine == FALSE)      // Notch Processing은 End Line 찾은 Frame이..
      return FALSE;
   if(m_pRecipe == NULL)
   if (m_pRecipe == NULL)
      return FALSE;
   if(m_pDefectControl == NULL)
   if (m_pDefectControl == NULL)
      return FALSE;
   if(pSideData->m_bNotchInspection_Complete == TRUE)
   if (pSideData->m_bNotchInspection_Complete == TRUE)
      return TRUE;
   int nNotchCount = m_pRecipe->m_SideParam[(int) emDim].m_nNotchCount;
   int nNotchCount = m_pRecipe->m_SideParam[(int)emDim].m_nNotchCount;
   g_pLog->DisplayMessage(_T("Notch_Process %s : %d, count %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,nNotchCount);
   g_pLog->DisplayMessage(_T("Notch_Process %s : %d, count %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, nNotchCount);
   pSideData->m_nNotchCount = nNotchCount;
   for(int i=0; i<nNotchCount; i++)
   for (int i = 0; i < nNotchCount; i++)
   {
      if(m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_bNotch_Use == FALSE)
      if (m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[i].m_bNotch_Use == FALSE)
         continue;
      CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_ptTopMarkPos;
      CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_ptBotMarkPos;
      CRect rtSet_Area = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
      CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[i].m_ptTopMarkPos;
      CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[i].m_ptBotMarkPos;
      CRect rtSet_Area = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
      CRect rtRotateArea;
      CRect rtNotchAreaTemp;
      if(GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
      if (GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
         continue;
      g_pLog->DisplayMessage(_T("Notch_Process %s : %d, idx %d - %d,%d,%d,%d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i,rtRotateArea.left,rtRotateArea.top,rtRotateArea.right,rtRotateArea.bottom);
      g_pLog->DisplayMessage(_T("Notch_Process %s : %d, idx %d - %d,%d,%d,%d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i, rtRotateArea.left, rtRotateArea.top, rtRotateArea.right, rtRotateArea.bottom);
      pSideData->m_rtNotchArea_pxl[i] = rtRotateArea;
      //屏蔽Notch   区域上下位置
      //팁귁Notch   혐堵 龜쫍뿟?
      rtRotateArea.top += 15;
      rtRotateArea.bottom -= 15;
      IplImage* pOriginImage;
      IplImage* pEdgeImage;
      IplImage* pBinImage;
      pOriginImage = cvCreateImageHeader(cvSize(m_nFrameWidth, rtRotateArea.Height()),8,1);
      pOriginImage = cvCreateImageHeader(cvSize(m_nFrameWidth, rtRotateArea.Height()), 8, 1);
      cvSetData(pOriginImage, m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtRotateArea.top), IMAGE_WIDTH);
      pEdgeImage = cvCloneImage(pOriginImage);
      pBinImage = cvCloneImage(pOriginImage);
@@ -3802,7 +3826,7 @@
         defectInfo.m_nSideIdx = (int)emDim;
         defectInfo.m_ptDefectPos_pxl = rtRotateArea.CenterPoint();
         defectInfo.m_rtDefectPos_pxl = rtRotateArea;
         defectInfo.m_DefectLoc = DefectLoc_Notch_Crack;
         defectInfo.m_DefectLoc = DefectLoc_Notch_NoGrind;
         m_pDefectControl->ExtractDefect(emDim, m_iCamera, stFrame.nScanIdx, defectInfo);
         cvReleaseImageHeader(&pOriginImage);
@@ -3823,7 +3847,7 @@
      Notch_Process_FindCircle(emDim, stFrame, i);
      // 7. Notch Process End
      g_pLog->DisplayMessage(_T("7. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
      g_pLog->DisplayMessage(_T("7. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
      cvReleaseImageHeader(&pOriginImage);
      cvReleaseImage(&pEdgeImage);
      cvReleaseImage(&pBinImage);
@@ -3844,39 +3868,39 @@
      return;
   }
   // 中值滤波器大小,用于去噪,必须为奇数(若偶数会自动减1)
   // 櫓令쫀꺼포댕鬼,痰黨혼臀,극伎槨펜鑒(흼탉鑒삔菱땡숑1)
   const int nSmoothFilter = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
   // 磨边区域阈值,控制反二值化阈值,主要用于提取 Notch 边缘特征
   // 칠긋혐堵埴令,왠齡럽랗令뺏埴令,寮狼痰黨瓊혤 Notch 긋鍍景瀝
   const int nGrindThreshold = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold;
   // 玻璃区域阈值,控制正二值化阈值,用于提取玻璃主体区域
   // 깼젝혐堵埴令,왠齡攣랗令뺏埴令,痰黨瓊혤깼젝寮竟혐堵
   const int nGlassThreshold = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold;
   // 确保奇数滤波器大小
   // 횅괏펜鑒쫀꺼포댕鬼
   int nFilterSize = (nSmoothFilter % 2 == 0) ? (nSmoothFilter - 1) : nSmoothFilter;
   if (nFilterSize > 1) {
      // 中值滤波降噪
      // 櫓令쫀꺼슉臀
      cvSmooth(scr, img_Bin, CV_MEDIAN, nFilterSize);
   }
   // Edge图:反二值化阈值处理
   // Edge暠:럽랗令뺏埴令뇹잿
   cvThreshold(scr, img_Edge, nGrindThreshold, 255, CV_THRESH_BINARY_INV);
   CString strEdgeFileName;
   strEdgeFileName.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, img_Edge, strEdgeFileName);
   // Bin图:正常二值化
   // Bin暠:攣끽랗令뺏
   cvThreshold(scr, img_Bin, nGlassThreshold, 255, CV_THRESH_BINARY);
   CString strBinFileName;
   strBinFileName.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, img_Bin, strBinFileName);
}
void CInspectCamera::Notch_Process_Measure(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr,IplImage* img_Edge,IplImage* img_Bin, CRect rtROI)
void CInspectCamera::Notch_Process_Measure(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI)
{
   if(m_pRecipe == NULL)
   if (m_pRecipe == NULL)
      return;
   double dPixelSizeX = m_dPixelSizeX;
@@ -3886,8 +3910,8 @@
   IplImage* img_Find_MeasureLine;
   IplImage* img_Result = cvCloneImage(scr);
   double th = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nReferece_Line_Threshold;
   int nNotchCenterOffset = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nNotchCenter_Offset_pxl;
   double th = (double)m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nReferece_Line_Threshold;
   int nNotchCenterOffset = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nNotchCenter_Offset_pxl;
   cvThreshold(scr, img_Bin_MeasureLine, th, 255, CV_THRESH_BINARY);
@@ -3897,36 +3921,36 @@
   ptSeed.y = img_Bin_MeasureLine->height / 2;
   img_Find_MeasureLine = cvCloneImage(img_Bin_MeasureLine);
   // cvFloodFill(img_Find_MeasureLine, ptSeed, CV_RGB(255,255,255));      // 拱 锭巩俊 急捞 谗绢瘤绰 版快啊 乐绢辑 救茄促.
   // cvFloodFill(img_Find_MeasureLine, ptSeed, CV_RGB(255,255,255));      // 물 때문에 선이 끊어지는 경우가 있어서 안한다.
   // cvThreshold(img_Find_MeasureLine, img_Find_MeasureLine, 100, 255, CV_THRESH_BINARY);
   // 2. Find Curve Line
   double dStepAngle = 1.0;
   int nFindStep = (int) (360.0 / dStepAngle);
   int nSkipStep = 30;                                          // 贸澜 30档, 场 30档绰 胶诺茄促.
   int nFindStep = (int)(360.0 / dStepAngle);
   int nSkipStep = 30;                                          // 처음 30도, 끝 30도는 스킵한다.
   IplImage* img_Find_MeasureLine_Point = cvCloneImage(scr);
   std::vector<CPoint> vecPointList;
   for(int i=nSkipStep; i < nFindStep-nSkipStep; i++)
   for (int i = nSkipStep; i < nFindStep - nSkipStep; i++)
   {
      double dFindAngle = ((double) i) * dStepAngle;
      double dFindAngle = ((double)i) * dStepAngle;
      double dSearchRadius = 1800.0 + abs(nNotchCenterOffset);
      for(double dRadius = 0.0; dRadius < dSearchRadius; dRadius += 0.5)
      for (double dRadius = 0.0; dRadius < dSearchRadius; dRadius += 0.5)
      {
         int nX = (int) (ptSeed.x - (cos(ToRadian(dFindAngle)) * dRadius));
         int nY = (int) (ptSeed.y - (sin(ToRadian(dFindAngle)) * dRadius));
         int nX = (int)(ptSeed.x - (cos(ToRadian(dFindAngle)) * dRadius));
         int nY = (int)(ptSeed.y - (sin(ToRadian(dFindAngle)) * dRadius));
         if(nX < 0 ||img_Find_MeasureLine->width <= nX)
         if (nX < 0 || img_Find_MeasureLine->width <= nX)
            continue;
         if(nY < 0 ||img_Find_MeasureLine->height <= nY)
         if (nY < 0 || img_Find_MeasureLine->height <= nY)
            continue;
         if(img_Find_MeasureLine->imageData[nY * img_Find_MeasureLine->widthStep + nX] != 0)
         if (img_Find_MeasureLine->imageData[nY * img_Find_MeasureLine->widthStep + nX] != 0)
         {
            img_Find_MeasureLine_Point->imageData[nY * img_Find_MeasureLine_Point->widthStep + nX] = 255;
@@ -3939,9 +3963,9 @@
   }
   // 3. Meausre
   int nCount = vecPointList.size()-2;
   int nCount = vecPointList.size() - 2;
   if(nCount < MAX_SIDE_NOTCH_MEASURE_COUNT)   // 螟沥 器牢飘 俊矾
   if (nCount < MAX_SIDE_NOTCH_MEASURE_COUNT)   // 측정 포인트 에러
   {
      cvReleaseImage(&img_Bin_MeasureLine);
      cvReleaseImage(&img_Find_MeasureLine);
@@ -3950,18 +3974,18 @@
      return;
   }
   double dPointStep = (double) nCount / (MAX_SIDE_NOTCH_MEASURE_COUNT-1);      // 16 Point 螟沥..
   double dPointStep = (double)nCount / (MAX_SIDE_NOTCH_MEASURE_COUNT - 1);      // 16 Point 측정..
   for(int nMeasureIdx=0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
   for (int nMeasureIdx = 0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
   {
      int nPointIdx = nMeasureIdx * dPointStep;
      int nPointIdx = nMeasureIdx * (int)dPointStep;
      if(nPointIdx == 0)                     nPointIdx = 1;
      else if(vecPointList.size() <= nPointIdx)   nPointIdx = vecPointList.size() - 1;
      if (nPointIdx == 0)                     nPointIdx = 1;
      else if (vecPointList.size() <= nPointIdx)   nPointIdx = vecPointList.size() - 1;
      CPoint pt_Start      = vecPointList[nPointIdx-1];
      CPoint pt_End      = vecPointList[nPointIdx+1];
      CPoint pt_Measure   = vecPointList[nPointIdx];
      CPoint pt_Start = vecPointList[nPointIdx - 1];
      CPoint pt_End = vecPointList[nPointIdx + 1];
      CPoint pt_Measure = vecPointList[nPointIdx];
      m_pGlassData->GetSideData(emDim)->m_ptNotch_Reference[nNotchIdx][nMeasureIdx].x = pt_Measure.x; // + rtROI.left;
      m_pGlassData->GetSideData(emDim)->m_ptNotch_Reference[nNotchIdx][nMeasureIdx].y = pt_Measure.y + rtROI.top;
@@ -3971,12 +3995,12 @@
      double dAngle_Radian = ToRadian(-90.0);
      if(dDiff_X != 0.0)
         dAngle_Radian = atan(dDiff_y/dDiff_X);
      if (dDiff_X != 0.0)
         dAngle_Radian = atan(dDiff_y / dDiff_X);
      dAngle_Radian = ToRadian( 90.0 - abs(ToDegree(dAngle_Radian)) );
      dAngle_Radian = ToRadian(90.0 - abs(ToDegree(dAngle_Radian)));
      if(pt_End.x - pt_Start.x < 0.0)
      if (pt_End.x - pt_Start.x < 0.0)
         dAngle_Radian = dAngle_Radian * -1.0;
      double dSearchRadius = 100.0;
@@ -3989,19 +4013,19 @@
      BOOL bEdgeCheck = FALSE;
      for(double dRadius = 0.0; dRadius < dSearchRadius; dRadius += 0.2)
      for (double dRadius = 0.0; dRadius < dSearchRadius; dRadius += 0.2)
      {
         double dMeasureRadius = dSearchRadius - dRadius;
         int nX = pt_Measure.x - (cos(dAngle_Radian) * dMeasureRadius);
         int nY = pt_Measure.y + (sin(dAngle_Radian) * dMeasureRadius);
         int nX = (int)(pt_Measure.x - (cos(dAngle_Radian) * dMeasureRadius));
         int nY = (int)(pt_Measure.y + (sin(dAngle_Radian) * dMeasureRadius));
         img_Result->imageData[pt_Measure.y * img_Result->widthStep + pt_Measure.x] = 0;
         if(nX < 0 ||img_Edge->width <= nX)
         if (nX < 0 || img_Edge->width <= nX)
            continue;
         if(nY < 0 ||img_Edge->height <= nY)
         if (nY < 0 || img_Edge->height <= nY)
            continue;
         CPoint ptCheck = CPoint(nX, nY);
@@ -4011,41 +4035,41 @@
         BOOL bEdgeFind = FALSE;
         BOOL bBinEdgeFind = FALSE;
         for(int nCheckX = 0; nCheckX < 3; nCheckX++)
         for (int nCheckX = 0; nCheckX < 3; nCheckX++)
         {
            for(int nCheckY = 0; nCheckY < 3; nCheckY++)
            for (int nCheckY = 0; nCheckY < 3; nCheckY++)
            {
               int nFindX = nX - 1 + nCheckX;
               int nFindY = nY - 1 + nCheckY;
               if(nFindX < 0 ||img_Edge->width <= nFindX)
               if (nFindX < 0 || img_Edge->width <= nFindX)
                  continue;
               if(nFindY < 0 ||img_Edge->height <= nFindY)
               if (nFindY < 0 || img_Edge->height <= nFindY)
                  continue;
               if(img_Edge->imageData[nFindY * img_Edge->widthStep + nFindX] != 0)
               if (img_Edge->imageData[nFindY * img_Edge->widthStep + nFindX] != 0)
               {
                  bEdgeFind = TRUE;
                  //break;
               }
               if(img_Bin->imageData[nFindY * img_Bin->widthStep + nFindX] != 0)
               if (img_Bin->imageData[nFindY * img_Bin->widthStep + nFindX] != 0)
               {
                  bBinEdgeFind = TRUE;
                  //break;
               }
               if(bEdgeFind == TRUE && bBinEdgeFind == TRUE)
               if (bEdgeFind == TRUE && bBinEdgeFind == TRUE)
                  break;
            }
            if(bEdgeFind == TRUE && bBinEdgeFind == TRUE)
                  break;
            if (bEdgeFind == TRUE && bBinEdgeFind == TRUE)
               break;
         }
         if(bEdgeCheck == FALSE && (bEdgeFind == TRUE || bBinEdgeFind == TRUE))
         if (bEdgeCheck == FALSE && (bEdgeFind == TRUE || bBinEdgeFind == TRUE))
         {
            if(bFindEdge == FALSE && bEdgeFind == TRUE)
            if (bFindEdge == FALSE && bEdgeFind == TRUE)
            {
               img_Result->imageData[nY * img_Result->widthStep + nX] = 255;
               bFindEdge = TRUE;
@@ -4058,7 +4082,7 @@
            }
            //if(ptCheck != ptFindEdge && bFindEdge == TRUE && bFindChamfer == FALSE)
            if(ptCheck != ptFindEdge && bBinEdgeFind == TRUE && bFindChamfer == FALSE)
            if (ptCheck != ptFindEdge && bBinEdgeFind == TRUE && bFindChamfer == FALSE)
            {
               img_Result->imageData[nY * img_Result->widthStep + nX] = 200;
               bFindChamfer = TRUE;
@@ -4068,12 +4092,12 @@
               m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y = ptFindChamfer.y + rtROI.top;
            }
         }
         else if(bEdgeCheck == TRUE && bEdgeFind == FALSE)
         else if (bEdgeCheck == TRUE && bEdgeFind == FALSE)
         {
            bEdgeCheck = FALSE;
         }
         if(bFindEdge == TRUE && bFindChamfer == TRUE)
         if (bFindEdge == TRUE && bFindChamfer == TRUE)
            break;
      }
   }
@@ -4099,25 +4123,25 @@
   return;
}
bool CInspectCamera::Notch_Process_Calculate(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr,IplImage* img_Edge,IplImage* img_Bin, CRect rtROI)
bool CInspectCamera::Notch_Process_Calculate(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI)
{
   if(m_pRecipe == NULL || m_pGlassData == NULL)
   if (m_pRecipe == NULL || m_pGlassData == NULL)
      return FALSE;
   for(int nMeasureIdx=0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
   int NotchFlag = 0;
   for (int nMeasureIdx = 0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
   {
      CPoint ptRef_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Reference[nNotchIdx][nMeasureIdx];
      CPoint ptDim_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx];
      if (ptRef_pxl.x < 0 || ptRef_pxl.y < 0) {
   /*   if (ptRef_pxl.x < 0 || ptRef_pxl.y < 0) {
         g_pLog->DisplayMessage(_T("[ERROR] Invalid Ref Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptRef_pxl.x, ptRef_pxl.y);
         continue;
      }
      if (ptDim_pxl.x < 0 || ptDim_pxl.y < 0) {
         g_pLog->DisplayMessage(_T("[ERROR] Invalid Dim Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptDim_pxl.x, ptDim_pxl.y);
         continue;
      }
      }*/
      // Dimension
      double dX_dim_um = (double)(ptRef_pxl.x - ptDim_pxl.x) * m_dPixelSizeX;
@@ -4126,26 +4150,29 @@
      m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx] = dDimension;
      CPoint ptChamfer_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx];
      if (ptChamfer_pxl.x < 0 || ptChamfer_pxl.y < 0) {
   /*   if (ptChamfer_pxl.x < 0 || ptChamfer_pxl.y < 0) {
         g_pLog->DisplayMessage(_T("[ERROR] Invalid Chamfer Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptChamfer_pxl.x, ptChamfer_pxl.y);
         continue;
      }
      }*/
      double dX_Chamfer = (double)(ptChamfer_pxl.x - ptDim_pxl.x) * m_dPixelSizeX;
      double dY_Chamfer = (double)(ptChamfer_pxl.y - ptDim_pxl.y) * m_dPixelSizeY;
      double dChamfer = sqrtf((dX_Chamfer * dX_Chamfer) + (dY_Chamfer * dY_Chamfer));
      m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx] = dChamfer;
      if (dDimension > 2000.0 && dChamfer > 2000.0) {
      if (dDimension > 5000.0 && dChamfer > 5000.0) {
         g_pLog->DisplayMessage(_T("[ERROR] Abnormal Dimension & Chamfer too large at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Dimension: %.2f, Chamfer: %.2f"), nNotchIdx, nMeasureIdx, dDimension, dChamfer);
         continue;
         NotchFlag=1;
      }
   }
   if (NotchFlag == TRUE)
   {
      return FALSE;
   }else
   return TRUE;
}
void CInspectCamera::Notch_Process_Judge(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr,IplImage* img_Edge,IplImage* img_Bin, CRect rtROI)
void CInspectCamera::Notch_Process_Judge(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI)
{
   if (m_pRecipe == NULL || m_pGlassData == NULL) {
      g_pLog->DisplayMessage(_T("[ERROR] Recipe or Glass Data is NULL in Notch_Process_Judge"));
@@ -4158,15 +4185,15 @@
      return;
   }
   for(int nMeasureIdx=0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
   for (int nMeasureIdx = 0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++)
   {
      // Dimension
      if(m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_bNotch_Dimension_Use[nMeasureIdx] == TRUE)
      if (m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_bNotch_Dimension_Use[nMeasureIdx] == TRUE)
      {
         double dDimension_um = pSideData->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx];
         double dDimension_std_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_STD_mm[nMeasureIdx] * 1000.0;
         double dDimension_min_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_Diff_MIN_mm[nMeasureIdx] * 1000.0;
         double dDimension_max_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_Diff_MAX_mm[nMeasureIdx] * 1000.0;
         double dDimension_std_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_STD_mm[nMeasureIdx] * 1000.0;
         double dDimension_min_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_Diff_MIN_mm[nMeasureIdx] * 1000.0;
         double dDimension_max_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_Diff_MAX_mm[nMeasureIdx] * 1000.0;
         double dDimension_Diff_um = dDimension_std_um - dDimension_um;
         pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 1;
@@ -4175,48 +4202,48 @@
         pSideData->m_dNotch_Dimension_Edge_Judge_Min_um[nNotchIdx][nMeasureIdx] = dDimension_min_um;
         pSideData->m_dNotch_Dimension_Edge_Judge_Max_um[nNotchIdx][nMeasureIdx] = dDimension_max_um;
         if(dDimension_um > dDimension_std_um + dDimension_max_um)
         if (dDimension_um > dDimension_std_um + dDimension_max_um)
            pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 2;
         else if(dDimension_um < dDimension_std_um - dDimension_min_um)
         else if (dDimension_um < dDimension_std_um - dDimension_min_um)
            pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 3;
         if(pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] != 1)
         if (pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] != 1)
         {
            // Make 搬窃..
            // Make 결함..
            CRect rtDefectArea = CRect(pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x,
                                 pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y,
                                 pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x,
                                 pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y);
               pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y,
               pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x,
               pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y);
            rtDefectArea.InflateRect(10, 10);
            CDefect_Info defectInfo;
            defectInfo.m_iFrameIdx         = stFrame.nFrameIdx;
            defectInfo.m_nCamID            = m_iCamera;
            defectInfo.m_nScanIdx         = stFrame.nScanIdx;
            defectInfo.m_nGlassStartLine   = pSideData->m_nGlassStartLine;
            defectInfo.m_nSideIdx         = (int) emDim;
            defectInfo.m_ptDefectPos_pxl   = rtDefectArea.CenterPoint();
            defectInfo.m_rtDefectPos_pxl   = rtDefectArea;
            defectInfo.m_DefectLoc         = DefectLoc_Notch_Dimension;
            defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
            defectInfo.m_nCamID = m_iCamera;
            defectInfo.m_nScanIdx = stFrame.nScanIdx;
            defectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine;
            defectInfo.m_nSideIdx = (int)emDim;
            defectInfo.m_ptDefectPos_pxl = rtDefectArea.CenterPoint();
            defectInfo.m_rtDefectPos_pxl = rtDefectArea;
            defectInfo.m_DefectLoc = DefectLoc_Notch_Dimension;
            m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, defectInfo, dDimension_um, dDimension_Diff_um);
         }
      }
      // Chamfer
      if(m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_bNotch_Chamfer_Use[nMeasureIdx] == TRUE)
      if (m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_bNotch_Chamfer_Use[nMeasureIdx] == TRUE)
      {
         double dChamfer_um = pSideData->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx];
         double dChamfer_std_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_STD_mm[nMeasureIdx] * 1000.0;
         double dChamfer_min_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_Diff_MIN_mm[nMeasureIdx] * 1000.0;
         double dChamfer_max_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_Diff_MAX_mm[nMeasureIdx] * 1000.0;
         double dChamfer_std_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_STD_mm[nMeasureIdx] * 1000.0;
         double dChamfer_min_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_Diff_MIN_mm[nMeasureIdx] * 1000.0;
         double dChamfer_max_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_Diff_MAX_mm[nMeasureIdx] * 1000.0;
         double dChamfer_Diff_um = dChamfer_std_um - dChamfer_um;
         pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 1;
#if MINI_LED
         //选取测量研磨尺寸最大值
         //朞혤꿎좆桔칠넹당離댕令
         if (m_nChamferOffset_um < dChamfer_um) {
            m_nChamferOffset_um = dChamfer_um;
         }
@@ -4227,88 +4254,88 @@
         pSideData->m_dNotch_Chamfer_Edge_Judge_Min_um[nNotchIdx][nMeasureIdx] = dChamfer_min_um;
         pSideData->m_dNotch_Chamfer_Edge_Judge_Max_um[nNotchIdx][nMeasureIdx] = dChamfer_max_um;
         if(dChamfer_um > dChamfer_std_um + dChamfer_max_um)
         if (dChamfer_um > dChamfer_std_um + dChamfer_max_um)
            pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 2;
         else if(dChamfer_um < dChamfer_std_um - dChamfer_min_um)
         else if (dChamfer_um < dChamfer_std_um - dChamfer_min_um)
            pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 3;
         if(pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] != 1)
         if (pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] != 1)
         {
            // Make 搬窃..
            // Make 결함..
            CRect rtDefectArea = CRect(pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x,
                                 pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y,
                                 pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x,
                                 pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y);
               pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y,
               pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x,
               pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y);
            rtDefectArea.InflateRect(10, 10);
            CDefect_Info defectInfo;
            defectInfo.m_iFrameIdx         = stFrame.nFrameIdx;
            defectInfo.m_nCamID            = m_iCamera;
            defectInfo.m_nScanIdx         = stFrame.nScanIdx;
            defectInfo.m_nGlassStartLine   = pSideData->m_nGlassStartLine;
            defectInfo.m_nSideIdx         = (int) emDim;
            defectInfo.m_ptDefectPos_pxl   = rtDefectArea.CenterPoint();
            defectInfo.m_rtDefectPos_pxl   = rtDefectArea;
            defectInfo.m_DefectLoc         = DefectLoc_Notch_Chamfer;
            defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
            defectInfo.m_nCamID = m_iCamera;
            defectInfo.m_nScanIdx = stFrame.nScanIdx;
            defectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine;
            defectInfo.m_nSideIdx = (int)emDim;
            defectInfo.m_ptDefectPos_pxl = rtDefectArea.CenterPoint();
            defectInfo.m_rtDefectPos_pxl = rtDefectArea;
            defectInfo.m_DefectLoc = DefectLoc_Notch_Chamfer;
            m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, defectInfo, dChamfer_um, dChamfer_Diff_um);
         }
      }
      // Make Comment
      char strJudge[4][16] = {"None", "OK", "OV", "UN"};
      char strJudge[4][16] = { "None", "OK", "OV", "UN" };
      sprintf(pSideData->m_strNotchMeasure_Comment[nNotchIdx][nMeasureIdx], "NOTCH[%d]-POINT[%d]-DIM[%.1f/STD:%.1f][%s], CHAMFER[%.1f/STD:%.1f][%s]"
         , nNotchIdx+1, nMeasureIdx+1
         , nNotchIdx + 1, nMeasureIdx + 1
         , pSideData->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx]
         , pSideData->m_dNotch_Dimension_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx]
         , strJudge[pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx]]
         , pSideData->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx]
         , pSideData->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx]
         , strJudge[pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx]]);
            , strJudge[pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx]]
               , pSideData->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx]
               , pSideData->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx]
                  , strJudge[pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx]]);
   }
}
void CInspectCamera::Notch_Process_Defect(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr,IplImage* img_Edge,IplImage* img_Bin, CRect rtROI)
void CInspectCamera::Notch_Process_Defect(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return;
   if(scr == NULL)
   if (scr == NULL)
      return;
   CNOTCH_PARM* pNotchParam = &m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx];
   CNOTCH_PARM* pNotchParam = &m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx];
   if(pNotchParam->m_bNotch_Inspect_Defect_Use == FALSE)
   if (pNotchParam->m_bNotch_Inspect_Defect_Use == FALSE)
      return;
   CString strTemp;
   int nSide = (int) emDim;
   int nSide = (int)emDim;
   int nThreshold = pNotchParam->m_nNotch_Inspect_Defect_Threshold;
   int nOffset = pNotchParam->m_nNotch_Inspect_Defect_Offset;
#if MINI_NOTCH   //Defect检测开关, jiang
#if MINI_NOTCH   //Defect쇱꿎역밑, jiang
   int nEdgeThres = pNotchParam->m_nGrind_Threshold;
   int nNgType = pNotchParam->m_nNotch_Inspect_Defect_Judge_And;
   int xNgSize = pNotchParam->m_nNotch_Inspect_Defect_Judge_X_um;
   int yNgSize = pNotchParam->m_nNotch_Inspect_Defect_Judge_Y_um;
   Log_GetDebug()->TraceInfo("Norch Info: %d, (%d, %d, %d, %d), ROI(%d, %d, %d, %d), %d",
   Log_GetDebug()->TraceInfo("Norch Info: %d, (%d, %d, %d, %d), ROI(%d, %d, %d, %d), %d",
      nNotchIdx, nEdgeThres, nThreshold, nOffset, nNgType,
      rtROI.left, rtROI.top, rtROI.right, rtROI.bottom, __LINE__);
   //输出计算信息
   //渴놔셕炬斤口
   std::vector<Point2D> vNorchPoints;
   for (int nMeasureIdx = 0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++){
   for (int nMeasureIdx = 0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++) {
      CPoint ptChamfer_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx];
      Point2D point;
      point.x = ptChamfer_pxl.x;
      point.y = ptChamfer_pxl.y;
        vNorchPoints.push_back(point);
      vNorchPoints.push_back(point);
   }
   CRect defectResult[100];
   //nRet为缺陷数量,当前缺陷数 < 1时,表示为OK
   //nRet槨홧屈鑒좆,뎠품홧屈鑒 < 1珂,깊刻槨OK
   int nRet = BlVision_GetSoftVisionApp()->findNorchDefect(nSide, vNorchPoints, rtROI, nEdgeThres, nOffset, nThreshold, nNgType, xNgSize, yNgSize, defectResult);
   printf("Norch Defect Number:%d\n", nRet);
@@ -4336,8 +4363,14 @@
   m_nChamferOffset_um = 0;
#endif // MINI_LED
   // 렝岺법댕돔鈴봬珂샀코닸狂痙
   if (nOffset > 50) {
      g_pLog->DisplayMessage(_T("[WARN] Notch defect offset capped to 50 pixels, original: %d"), nOffset);
      nOffset = 50;
   }
   CRect rcIns = rtROI;
   rcIns.OffsetRect(-rcIns.left,-rcIns.top);
   rcIns.OffsetRect(-rcIns.left, -rcIns.top);
   IplImage* pProcImage = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);
   IplImage* pProcBinImage = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);
   IplImage* pProcessCanny = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);
@@ -4345,11 +4378,11 @@
   IplImage* pMaskImage = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);
   IplImage* pDilatedMaskImage = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);
   for(int i=0; i<rcIns.Height(); i++)
   for (int i = 0; i < rcIns.Height(); i++)
   {
      memcpy(pProcImage->imageData+(i*pProcImage->widthStep), scr->imageData+(rtROI.left + (i*scr->widthStep)), rcIns.Width());
      memcpy(pProcessCanny->imageData+(i*pProcessCanny->widthStep), img_Edge->imageData+(rtROI.left + (i*img_Edge->widthStep)), rcIns.Width());
      memcpy(pProcessBin->imageData+(i*pProcessBin->widthStep), img_Bin->imageData+(rtROI.left + (i*img_Bin->widthStep)), rcIns.Width());
      memcpy(pProcImage->imageData + (i * pProcImage->widthStep), scr->imageData + (rtROI.left + (i * scr->widthStep)), rcIns.Width());
      memcpy(pProcessCanny->imageData + (i * pProcessCanny->widthStep), img_Edge->imageData + (rtROI.left + (i * img_Edge->widthStep)), rcIns.Width());
      memcpy(pProcessBin->imageData + (i * pProcessBin->widthStep), img_Bin->imageData + (rtROI.left + (i * img_Bin->widthStep)), rcIns.Width());
   }
   strTemp.Format(_T("Notch\\Notch_%d_Defect_Edge"), nNotchIdx);
@@ -4363,43 +4396,44 @@
   strTemp.Format(_T("Notch\\Notch_%d_Defect_EdgeOrBin"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pMaskImage, strTemp);
   BOOL bFind;
   int    nFindX;
   for(int y=0;y<pMaskImage->height;y++)
   for (int y = 0; y < pMaskImage->height; y++)
   {
      bFind = FALSE;
      nFindX = 0;
      for(int x=0;x<pMaskImage->width;x++)
      for (int x = 0; x < pMaskImage->width; x++)
      {
         if(pMaskImage->imageData[y*pMaskImage->widthStep + x] != 0)
         if (pMaskImage->imageData[y * pMaskImage->widthStep + x] != 0)
         {
            bFind = TRUE;
            nFindX = x;
            break;
         }
         }
      }
      if(bFind == TRUE)
      if (bFind == TRUE)
      {
         memset(&pMaskImage->imageData[y*pMaskImage->widthStep], 255, nFindX);
         memset(&pMaskImage->imageData[y*pMaskImage->widthStep+nFindX], 0, pMaskImage->width - nFindX);
         memset(&pMaskImage->imageData[y * pMaskImage->widthStep], 255, nFindX);
         memset(&pMaskImage->imageData[y * pMaskImage->widthStep + nFindX], 0, pMaskImage->width - nFindX);
      }
   }
   strTemp.Format(_T("Notch\\Notch_%d_Defect_MaskPreImage"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pMaskImage, strTemp);
   if(0 < nOffset)
   if (0 < nOffset) {
      cvDilate(pMaskImage, pMaskImage, 0, nOffset);
   }
   strTemp.Format(_T("Notch\\Notch_%d_Defect_MaskDilateImage"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pMaskImage, strTemp);
   for(int i=0; i<pMaskImage->height; i++)
      for(int j=0; j<pMaskImage->width; j++)
         if(pMaskImage->imageData[i*pMaskImage->widthStep + j] != 0)
            pProcImage->imageData[i*pProcImage->widthStep+j] = (char) 255;
   for (int i = 0; i < pMaskImage->height; i++)
      for (int j = 0; j < pMaskImage->width; j++)
         if (pMaskImage->imageData[i * pMaskImage->widthStep + j] != 0)
            pProcImage->imageData[i * pProcImage->widthStep + j] = (char)255;
   strTemp.Format(_T("Notch\\Notch_%d_Defect_ProcImage"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pProcImage, strTemp);
@@ -4409,13 +4443,26 @@
   strTemp.Format(_T("Notch\\Notch_%d_Defect_ProcBinImage"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pProcBinImage, strTemp);
#if   MINI_LED == 0
   cvDilate(pMaskImage, pDilatedMaskImage, 0, pNotchParam->m_nNotch_Inspect_Defect_dilate);
   strTemp.Format(_T("Notch\\Notch_%d_Defect_pMaskImage2"), nNotchIdx);
#if   MINI_LED == 0
   // 掘齡툇郞늴鑒,렝岺법댕돔鈴봬珂샀코닸狂痙
   int nDilateCount = pNotchParam->m_nNotch_Inspect_Defect_dilate;
   nDilateCount = std::max(0, std::min(nDilateCount, 50));
   if (pNotchParam->m_nNotch_Inspect_Defect_dilate != nDilateCount) {
      g_pLog->DisplayMessage(_T("[WARN] Dilate count capped: Original=%d, Applied=%d"), pNotchParam->m_nNotch_Inspect_Defect_dilate, nDilateCount);
   }
   if (nDilateCount > 0) {
      cvDilate(pMaskImage, pDilatedMaskImage, 0, nDilateCount);
   }
   else {
      cvCopy(pMaskImage, pDilatedMaskImage);
   }
   strTemp.Format(_T("Notch\\Notch_%d_Defect_Mask_Dilated"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pDilatedMaskImage, strTemp);
   cvAnd(pDilatedMaskImage, pProcBinImage, pDilatedMaskImage);
   strTemp.Format(_T("Notch\\Notch_%d_Defect_pMaskImage3"), nNotchIdx);
   strTemp.Format(_T("Notch\\Notch_%d_Defect_Mask_And_Bin"), nNotchIdx);
   SaveDebugImage(emDim, stFrame, pDilatedMaskImage, strTemp);
#endif   
@@ -4423,9 +4470,9 @@
   int iScan = stFrame.nScanIdx;
   int iFrame = stFrame.nFrameIdx;
   CRect rtProcessArea = rtROI;
   int nMinSize_X = pNotchParam->m_nNotch_Inspect_Defect_Min_X_um / m_pGlassData->GetSideData(emDim)->m_dPixelSizeX;
   int nMinSize_Y = pNotchParam->m_nNotch_Inspect_Defect_Min_Y_um / m_pGlassData->GetSideData(emDim)->m_dPixelSizeY;
   int nMinSize_X = (pNotchParam->m_nNotch_Inspect_Defect_Min_X_um / (int)m_pGlassData->GetSideData(emDim)->m_dPixelSizeX);
   int nMinSize_Y = (pNotchParam->m_nNotch_Inspect_Defect_Min_Y_um / (int)m_pGlassData->GetSideData(emDim)->m_dPixelSizeY);
   int nMinSize = 0;
   int nDilation = 0;
@@ -4435,54 +4482,55 @@
   std::vector<CDefect_Info> vecDefectCandidateList;
#if   MINI_LED == 0   
      DefectProcess(emDim, iScan, iFrame, pProcImage, pDilatedMaskImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList);
   DefectProcess(emDim, iScan, iFrame, pProcImage, pDilatedMaskImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList);
#else
      DefectProcess(emDim, iScan, iFrame, pProcImage, pProcBinImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList);
   DefectProcess(emDim, iScan, iFrame, pProcImage, pProcBinImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList);
#endif   
   m_pDefectControl->ExtractDefect_Notch(emDim, m_iCamera, stFrame.nScanIdx, nNotchIdx, &vecDefectCandidateList);
   cvReleaseImage(&pDilatedMaskImage);
   cvReleaseImage(&pMaskImage);
   cvReleaseImage(&pProcImage);
   cvReleaseImage(&pProcBinImage);
   cvReleaseImage(&pProcessCanny);
   cvReleaseImage(&pProcessCanny);
   cvReleaseImage(&pProcessBin);
#endif
}
void CInspectCamera::Notch_Process_FindCircle(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return;
   if(pSideData->m_bFindGlassEndLine == FALSE)      // Notch Processing篮 End Line 茫篮 Frame捞..
   if (pSideData->m_bFindGlassEndLine == FALSE)      // Notch Processing은 End Line 찾은 Frame이..
      return;
   if(m_pRecipe == NULL)
   if (m_pRecipe == NULL)
      return;
   if(m_pDefectControl == NULL)
   if (m_pDefectControl == NULL)
      return;
   CNOTCH_PARM* pNotchParam = &m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx];
   CNOTCH_PARM* pNotchParam = &m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx];
   if(pNotchParam == NULL)
   if (pNotchParam == NULL)
      return;
   int nNotchCircleCount = pNotchParam->m_nNotch_Circle_Count;
   pSideData->m_nNotchCircleCount[nNotchIdx] = nNotchCircleCount;
   for(int nCircleIdx = 0; nCircleIdx < nNotchCircleCount; nCircleIdx++)
   for (int nCircleIdx = 0; nCircleIdx < nNotchCircleCount; nCircleIdx++)
   {
      BOOL bUse = pNotchParam->m_bNotch_Circle_Use[nCircleIdx];
      if(bUse == FALSE)
      if (bUse == FALSE)
         continue;
      // 1. Make ROI
@@ -4508,7 +4556,7 @@
      VectorDouble vectorR;
      // 2. Get Edge Line
      int nThreshold = m_pRecipe->m_SideParam[(int) emDim].m_nChamferLineThreshold;
      int nThreshold = m_pRecipe->m_SideParam[(int)emDim].m_nChamferLineThreshold;
      LPBYTE pFrameBuffer = m_pGrabber->GetFrameHeader(stFrame.nScanIdx, 0);
@@ -4545,13 +4593,13 @@
      SaveDebugImage(emDim, stFrame, pCannyEdgeImage, strTemp);
      // Find Edge
      for(int i=0; i<rtROI.Height(); i+=4)
      for (int i = 0; i < rtROI.Height(); i += 4)
      {
         for(int j=0; j<rtROI.Width(); j++)
         for (int j = 0; j < rtROI.Width(); j++)
         {
            BYTE nGray = pCannyEdgeImage->imageData[i * pCannyEdgeImage->widthStep + j];
            if(nGray != 0 )
            if (nGray != 0)
            {
               double dX_um = j * m_dPixelSizeX; // rtROI.left + j;
               double dY_um = i * m_dPixelSizeY; // rtROI.top + i;
@@ -4567,7 +4615,7 @@
      cvReleaseImage(&pCannyEdgeImage);
      // 3. Circle Fitting
      if(CCHDataFitting::CircleFitting(vectorX, vectorY, vectorR) == 1)
      if (CCHDataFitting::CircleFitting(vectorX, vectorY, vectorR) == 1)
      {
         double dCenterPos_X_um = vectorR[0];
         double dCenterPos_Y_um = vectorR[1];
@@ -4577,26 +4625,26 @@
         double dCenterPos_Y_pxl = rtROI.top + (dCenterPos_Y_um / m_dPixelSizeY);
         pSideData->m_nNotchCircle_Radius_Judge[nNotchIdx][nCircleIdx] = 1;
         pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].x = dCenterPos_X_pxl;
         pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].y = dCenterPos_Y_pxl;
         pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].x = (LONG)dCenterPos_X_pxl;
         pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].y = (LONG)dCenterPos_Y_pxl;
         pSideData->m_ptNotchCircle_Radius_Result_X_pxl[nNotchIdx][nCircleIdx] = dRadiuse_um / m_dPixelSizeX;
         pSideData->m_ptNotchCircle_Radius_Result_Y_pxl[nNotchIdx][nCircleIdx] = dRadiuse_um / m_dPixelSizeY;
         pSideData->m_ptNotchCircle_Radius_Result_um[nNotchIdx][nCircleIdx] = dRadiuse_um;
         // Judge..
         double dStd_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Circle_Spec_Radius_um[nCircleIdx];
         double dMin_um = abs(m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Circle_Spec_Radius_Min_um[nCircleIdx]) * -1.0;
         double dMax_um = abs(m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Circle_Spec_Radius_Max_um[nCircleIdx]);
         double dStd_um = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Circle_Spec_Radius_um[nCircleIdx];
         double dMin_um = abs(m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Circle_Spec_Radius_Min_um[nCircleIdx]) * -1.0;
         double dMax_um = abs(m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_dNotch_Circle_Spec_Radius_Max_um[nCircleIdx]);
         double dResult_um = dStd_um - dRadiuse_um;
         pSideData->m_ptNotchCircle_Radius_Judge_Std_um[nNotchIdx][nCircleIdx] =  dStd_um;
         pSideData->m_ptNotchCircle_Radius_Judge_Min_um[nNotchIdx][nCircleIdx] =  dMin_um;
         pSideData->m_ptNotchCircle_Radius_Judge_Max_um[nNotchIdx][nCircleIdx] =  dMax_um;
         pSideData->m_ptNotchCircle_Radius_Judge_Std_um[nNotchIdx][nCircleIdx] = dStd_um;
         pSideData->m_ptNotchCircle_Radius_Judge_Min_um[nNotchIdx][nCircleIdx] = dMin_um;
         pSideData->m_ptNotchCircle_Radius_Judge_Max_um[nNotchIdx][nCircleIdx] = dMax_um;
         pSideData->m_ptNotchCircle_Radius_Result_Diff_um[nNotchIdx][nCircleIdx] = dResult_um;
         if(dResult_um < dMin_um || dMax_um < dResult_um)
         if (dResult_um < dMin_um || dMax_um < dResult_um)
         {
            pSideData->m_nNotchCircle_Radius_Judge[nNotchIdx][nCircleIdx] = 2;   // NG
@@ -4606,14 +4654,14 @@
            measureDefect.m_nCamID = m_iCamera;
            measureDefect.m_nScanIdx = stFrame.nScanIdx;
            measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine;
            measureDefect.m_nSideIdx = (int) emDim;
            measureDefect.m_nSideIdx = (int)emDim;
            measureDefect.m_DefectLoc = DefectLoc_Notch_Circle_Radius;
            measureDefect.m_ptDefectPos_pxl = rtROI.CenterPoint(); // CPoint(nEndPointPosX, nEndPointPosY);
            measureDefect.m_rtDefectPos_pxl = CRect(rtROI.CenterPoint().x - 16, rtROI.CenterPoint().y - 16, rtROI.CenterPoint().x + 16, rtROI.CenterPoint().y + 16);
            m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, measureDefect, dRadiuse_um, dResult_um);
            sprintf(pSideData->m_strNotchCircle_Radius_Comment[nNotchIdx][nCircleIdx], "Rad. [NG] %.1f um / %.1f um", dRadiuse_um, dResult_um);
            sprintf(pSideData->m_strNotchCircle_Radius_Comment[nNotchIdx][nCircleIdx], "Rad. [NG] %.1f um / %.1f um", dRadiuse_um, dResult_um);
         }
         else
         {
@@ -4623,61 +4671,61 @@
   }
}
BOOL CInspectCamera::Measure(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   int   nEndFrame = pSideData->m_nGlassEndLine/m_nFrameHeight;
   int   nEndFrame = pSideData->m_nGlassEndLine / m_nFrameHeight;
    //if(nEndFrame != stFrame.nFrameIdx)
    //   return FALSE;
   //if(nEndFrame != stFrame.nFrameIdx)
   //   return FALSE;
   g_pLog->DisplayMessage(_T("Measure Start %s - %d"),g_SideName[(int) emDim],stFrame.nFrameIdx);
   g_pLog->DisplayMessage(_T("Measure Start %s - %d"), g_SideName[(int)emDim], stFrame.nFrameIdx);
   // Corner..
   Measure_TopCorner(iThread, emDim, stFrame);
   Measure_BotCorner(iThread, emDim, stFrame);
   if(pSideData->m_bFindGlassEndLine == FALSE)      // Side Line篮 End Line 茫篮 Frame 捞 螟沥 茄促..
   if (pSideData->m_bFindGlassEndLine == FALSE)      // Side Line은 End Line 찾은 Frame 이 측정 한다..
      return FALSE;
   g_pLog->DisplayMessage(_T("Side Measure Start %s - %d"),g_SideName[(int) emDim],stFrame.nFrameIdx);
   g_pLog->DisplayMessage(_T("Side Measure Start %s - %d"), g_SideName[(int)emDim], stFrame.nFrameIdx);
   // Side..
   Measure_Side(iThread, emDim, stFrame);
   g_pLog->DisplayMessage(_T("Side Measure End %s - %d"),g_SideName[(int) emDim],stFrame.nFrameIdx);
   g_pLog->DisplayMessage(_T("Side Measure End %s - %d"), g_SideName[(int)emDim], stFrame.nFrameIdx);
   return TRUE;
}
BOOL CInspectCamera::Measure_Side(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_Side(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL)
      return FALSE;
   if (pSideData->m_bTopMark_Find == FALSE || pSideData->m_bBotMark_Find == FALSE)
   {
      g_pLog->DisplayMessage(_T("Error : [%s] Top Align Mark or Bottom Align Mark Y is not detected.. [Fail to Measure Edge to Align Mark Line]"), g_SideName[(int) emDim]);
      g_pLog->DisplayMessage(_T("Error : [%s] Top Align Mark or Bottom Align Mark Y is not detected.. [Fail to Measure Edge to Align Mark Line]"), g_SideName[(int)emDim]);
      return FALSE;
   }
   ///////////////////////////////////////////////////////////////////////////////////////
#if HALCON_VISION_KEY
   //Set Info, 将MARK信息输入到SDK
   //Set Info, 쉥MARK斤口渴흙돕SDK
   CBlSideData* pBlSideData = BlVision_GetVisionRecipe()->getSideData(emDim); // ->m_bInspection_Complete = TRUE;
   pBlSideData->m_bInspection_Complete = TRUE;
   pBlSideData->m_dPixelSizeX = pSideData->m_dPixelSizeX;
@@ -4725,7 +4773,7 @@
   double distX = GetPixelToUm_X(ptTopAlignMark.x - ptBottomAlignMark.x);
   double distY = GetPixelToUm_Y(ptTopAlignMark.y - ptBottomAlignMark.y);
   double dTopAlignToBottomAlignDistance = sqrt((distX * distX) + (distY * distY));
   double dGlassTilt_Radian = 0.0;
   if (distX != 0.0)
      dGlassTilt_Radian = atan(distX / distY);
@@ -4734,22 +4782,22 @@
   for (int nMeasurePointIdx = 0; nMeasurePointIdx < nMeasureCount; nMeasurePointIdx++)
   {
      if(MAX_SIDE_DIMENSION_MEASURE_COUNT <= nMeasurePointIdx)
      if (MAX_SIDE_DIMENSION_MEASURE_COUNT <= nMeasurePointIdx)
         break;
      if(pSideData->m_bSideMeasureLine[nMeasurePointIdx] == TRUE)
      if (pSideData->m_bSideMeasureLine[nMeasurePointIdx] == TRUE)
         continue;
      double dMeasurePointPosX_um = sin(dGlassTilt_Radian) * pSideParam->m_nSideDimensionPos_TopMarkToDistance_um[nMeasurePointIdx];
      double dMeasurePointPosY_um = cos(dGlassTilt_Radian) * pSideParam->m_nSideDimensionPos_TopMarkToDistance_um[nMeasurePointIdx];
      int nMeasurePointPosX = ptTopAlignMark.x + (int) GetUmToPixel_X(dMeasurePointPosX_um);
      int nMeasurePointPosY = ptTopAlignMark.y + (int) GetUmToPixel_Y(dMeasurePointPosY_um);
      int nMeasurePointPosX = ptTopAlignMark.x + (int)GetUmToPixel_X(dMeasurePointPosX_um);
      int nMeasurePointPosY = ptTopAlignMark.y + (int)GetUmToPixel_Y(dMeasurePointPosY_um);
      double dEndPointPosX_um = cos(dGlassTilt_Radian) * nTopEdgeToMark_X_um * -1.0;
      double dEndPointPosY_um = sin(dGlassTilt_Radian) * nTopEdgeToMark_X_um;// * -1.0;
      int nEndPointPosX = nMeasurePointPosX + (int) GetUmToPixel_X(dEndPointPosX_um);
      int nEndPointPosY = nMeasurePointPosY + (int) GetUmToPixel_Y(dEndPointPosY_um);
      int nEndPointPosX = nMeasurePointPosX + (int)GetUmToPixel_X(dEndPointPosX_um);
      int nEndPointPosY = nMeasurePointPosY + (int)GetUmToPixel_Y(dEndPointPosY_um);
      int nFindRangeX = 100;
      int nFindRangeY = 20;
@@ -4757,40 +4805,40 @@
      CRect rtFindPos = CRect(nEndPointPosX, nEndPointPosY, nEndPointPosX, nEndPointPosY);
      rtFindPos.InflateRect(nFindRangeX, nFindRangeY);
      if(rtFindPos.left < 0)                        rtFindPos.left = 0;
      if(m_nFrameWidth <= rtFindPos.right)            rtFindPos.right = m_nFrameWidth-1;
      if(rtFindPos.top < pSideData->m_nGlassStartLine)   rtFindPos.top = pSideData->m_nGlassStartLine;
      if(pSideData->m_nGlassEndLine < rtFindPos.bottom)   rtFindPos.bottom = pSideData->m_nGlassEndLine;
      if (rtFindPos.left < 0)                        rtFindPos.left = 0;
      if (m_nFrameWidth <= rtFindPos.right)            rtFindPos.right = m_nFrameWidth - 1;
      if (rtFindPos.top < pSideData->m_nGlassStartLine)   rtFindPos.top = pSideData->m_nGlassStartLine;
      if (pSideData->m_nGlassEndLine < rtFindPos.bottom)   rtFindPos.bottom = pSideData->m_nGlassEndLine;
      if(rtFindPos.left >= rtFindPos.right)
      if (rtFindPos.left >= rtFindPos.right)
         continue;
      if(rtFindPos.top >= rtFindPos.bottom)
      if (rtFindPos.top >= rtFindPos.bottom)
         continue;
      if(rtFindPos.Width() <= 20 || rtFindPos.Height() <= 2)
         continue;
      if (rtFindPos.Width() <= 20 || rtFindPos.Height() <= 2)
         continue;
      LPBYTE pFrameBuffer = m_pGrabber->GetFrameHeader(stFrame.nScanIdx, 0);
      if(pFrameBuffer == NULL)
      if (pFrameBuffer == NULL)
         continue;
      COwnerBuffer pFindImage = COwnerBuffer(rtFindPos.Width(), rtFindPos.Height());
      for(int i=0; i<rtFindPos.Height(); i++)
      for (int i = 0; i < rtFindPos.Height(); i++)
         memcpy(pFindImage.GetDataAddress(0, i), pFrameBuffer + (m_nFrameWidth * (rtFindPos.top + i)) + rtFindPos.left, rtFindPos.Width());
       //{
       //   CString      str;
       //   str.Format(_T("D:\\Inspection\\DebugFullImg\\Side\\Org_%s_%02d.bmp"),g_SideName[(int) emDim],nMeasurePointIdx);
       //   CBufferAttach   attach(str);
       //   attach.AttachToFile(pFindImage);
       //}
      //{
      //   CString      str;
      //   str.Format(_T("D:\\Inspection\\DebugFullImg\\Side\\Org_%s_%02d.bmp"),g_SideName[(int) emDim],nMeasurePointIdx);
      //   CBufferAttach   attach(str);
      //   attach.AttachToFile(pFindImage);
      //}
      int nSideLineThres = m_pRecipe->m_SideParam[(int) emDim].m_nSideLineThreshold;
      int nChamferLineThres = m_pRecipe->m_SideParam[(int) emDim].m_nChamferLineThreshold;
      int nSideLineThres = m_pRecipe->m_SideParam[(int)emDim].m_nSideLineThreshold;
      int nChamferLineThres = m_pRecipe->m_SideParam[(int)emDim].m_nChamferLineThreshold;
      CRect rtFindROI = CRect(0,0,rtFindPos.Width()-1, rtFindPos.Height()-1);
      CRect rtFindROI = CRect(0, 0, rtFindPos.Width() - 1, rtFindPos.Height() - 1);
      int nFindEdgeLine = -1;
      int nFindChamferLine = -1;
@@ -4804,25 +4852,25 @@
      rtFindROI.left = nFindEdgeLine + 3;
      CChamferInspect      chamferIns;
      COwnerBuffer      ImgInsBin;
      chamferIns.Binarization(pFindImage,ImgInsBin,nChamferLineThres);
      COwnerBuffer      ImgInsBin;
      chamferIns.Binarization(pFindImage, ImgInsBin, nChamferLineThres);
       //{
       //   CString      str;
       //   str.Format(_T("D:\\Inspection\\DebugFullImg\\Side\\Bin_%s_%02d.bmp"),g_SideName[(int) emDim],nMeasurePointIdx);
       //   CBufferAttach   attach(str);
       //   attach.AttachToFile(ImgInsBin);
       //}
      //{
      //   CString      str;
      //   str.Format(_T("D:\\Inspection\\DebugFullImg\\Side\\Bin_%s_%02d.bmp"),g_SideName[(int) emDim],nMeasurePointIdx);
      //   CBufferAttach   attach(str);
      //   attach.AttachToFile(ImgInsBin);
      //}
      double         dLine = -1;
      chamferIns.FindRightLine_Bin(ImgInsBin,nFindEdgeLine,dLine);
      chamferIns.FindRightLine_Bin(ImgInsBin, nFindEdgeLine, dLine);
      nFindChamferLine = (int)dLine;
      //EdgeFind.FindEdge_ToRightROI(&pFindImage, nFindChamferLine, DEFECT_EDGE_AUTO_PITCH, nChamferLineThres, DEFECT_EDGE_AUTO_RATIO, 0, rtFindROI);
      int nSideLine = rtFindPos.left + nFindEdgeLine;
      int nChamferLine = rtFindPos.left + ((nFindChamferLine != -1 && pSideParam->m_bSideChamfer_Use[nMeasurePointIdx] == TRUE) ? nFindChamferLine : nFindEdgeLine);
      // Frame俊辑 措钎肺 茫篮吧肺 螟沥 搬苞肺 静霸 沁绰单.... 捞固瘤俊辑 促矫 茫档废 荐沥捞 鞘夸..且鳖??
      // Frame에서 대표로 찾은걸로 측정 결과로 쓰게 했는데.... 이미지에서 다시 찾도록 수정이 필요..할까??
      int nFrameIdx = (int)(nEndPointPosY / m_nFrameHeight);
      /*
      int nSideLine = pSideData->m_nSideLineFrame[nFrameIdx];
@@ -4843,15 +4891,15 @@
      pSideData->m_ptSideMeasure_ChamferLine[nMeasurePointIdx] = ptEnd_ChamferLine;         // Measure Chamfer Line..
      pSideData->m_dSideMeasrue_Chamfer_Result_mm[nMeasurePointIdx] = dDistance_ChamferLine_mm;
      pSideData->m_bSideMeasureLine[nMeasurePointIdx] = TRUE;
      // 烙矫肺 阜澜. SW 促款.
      // 임시로 막음. SW 다운.
      // continue;
      // Dimension
      double dTempValue = pSideParam->m_dSideDimensionSpec_mm_Std[nMeasurePointIdx];
      if(pSideParam->m_bSideDimension_Use[nMeasurePointIdx] == TRUE && dTempValue >= 0)
      if (pSideParam->m_bSideDimension_Use[nMeasurePointIdx] == TRUE && dTempValue >= 0)
      {
         double dStd_mm = pSideParam->m_dSideDimensionSpec_mm_Std[nMeasurePointIdx];
         double dMin_mm = (dStd_mm - abs(pSideParam->m_dSideDimensionSpec_mm_Min[nMeasurePointIdx]));
@@ -4859,7 +4907,7 @@
         double dResult_mm = dDistance_CutLine_mm;
         if(dResult_mm < dMin_mm || dMax_mm < dResult_mm)
         if (dResult_mm < dMin_mm || dMax_mm < dResult_mm)
         {
            pSideData->m_nSideMeasure_CutLine_Status[nMeasurePointIdx] = 2;   // NG
@@ -4885,23 +4933,23 @@
            measureDefect.m_nCamID = m_iCamera;
            measureDefect.m_nScanIdx = stFrame.nScanIdx;
            measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine;
            measureDefect.m_nSideIdx = (int) emDim;
            measureDefect.m_nSideIdx = (int)emDim;
            measureDefect.m_DefectLoc = DefectLoc_Measure_Dimension;
            measureDefect.m_ptDefectPos_pxl = ptEnd_CutLine; // CPoint(nEndPointPosX, nEndPointPosY);
            measureDefect.m_rtDefectPos_pxl = CRect(ptEnd_CutLine.x - 16, ptEnd_CutLine.y - 16, ptEnd_CutLine.x + 16, ptEnd_CutLine.y + 16);
            g_pLog->DisplayMessage(_T("Measure Glass Line NG Start %s-%d : %d,%d"),g_SideName[(int) emDim],nMeasurePointIdx,measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
            g_pLog->DisplayMessage(_T("Measure Glass Line NG Start %s-%d : %d,%d"), g_SideName[(int)emDim], nMeasurePointIdx, measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
            m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, measureDefect, dDistance_CutLine_mm, dResult_mm);
            g_pLog->DisplayMessage(_T("Measure Glass Line NG End %s-%d : %d,%d"),g_SideName[(int) emDim],nMeasurePointIdx,measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
            g_pLog->DisplayMessage(_T("Measure Glass Line NG End %s-%d : %d,%d"), g_SideName[(int)emDim], nMeasurePointIdx, measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
         }
         else
            pSideData->m_nSideMeasure_CutLine_Status[nMeasurePointIdx] = 1;   // OK
      }
      else if (pSideParam->m_bSideDimension_Use[nMeasurePointIdx] == TRUE && dTempValue < -0.01) {
#if HALCON_VISION_KEY
         //切割线的长度计算,  jiang, 09-27, 2024
         //학몇窟돨낀똑셕炬,  jiang, 09-27, 2024
         int nThres = pSideParam->m_nSideDimensionSpec_Thres[nMeasurePointIdx];
         int toLineDist = 1000 * pSideParam->m_dSideDimensionSpec_mm_Std[nMeasurePointIdx];
         int toTopY = pSideParam->m_nSideDimensionPos_TopMarkToDistance_um[nMeasurePointIdx];
@@ -4991,7 +5039,7 @@
      }
      // Chamfer
      if(pSideParam->m_bSideChamfer_Use[nMeasurePointIdx] == TRUE)
      if (pSideParam->m_bSideChamfer_Use[nMeasurePointIdx] == TRUE)
      {
         double dStd_mm = pSideParam->m_dSideChamfer_Spec_mm_Std[nMeasurePointIdx];
         double dMin_mm = (dStd_mm - abs(pSideParam->m_dSideChamfer_Spec_mm_Min[nMeasurePointIdx]));
@@ -4999,7 +5047,7 @@
         double dResult_mm = dDistance_ChamferLine_mm;
         if(dResult_mm < dMin_mm || dMax_mm < dResult_mm)
         if (dResult_mm < dMin_mm || dMax_mm < dResult_mm)
         {
            pSideData->m_nSideMeasure_ChamferLine_Status[nMeasurePointIdx] = 2;   // NG
@@ -5009,16 +5057,16 @@
            measureDefect.m_nCamID = m_iCamera;
            measureDefect.m_nScanIdx = stFrame.nScanIdx;
            measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine;
            measureDefect.m_nSideIdx = (int) emDim;
            measureDefect.m_nSideIdx = (int)emDim;
            measureDefect.m_DefectLoc = DefectLoc_Measure_Chamfer;
            measureDefect.m_ptDefectPos_pxl = CPoint(nEndPointPosX, nEndPointPosY);
            measureDefect.m_rtDefectPos_pxl = CRect(nEndPointPosX - 100, nEndPointPosY - 100, nEndPointPosX + 100, nEndPointPosY + 100);
            g_pLog->DisplayMessage(_T("Measure Glass NG Chamfer Start %s-%d : %d,%d"),g_SideName[(int) emDim],nMeasurePointIdx,measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
            g_pLog->DisplayMessage(_T("Measure Glass NG Chamfer Start %s-%d : %d,%d"), g_SideName[(int)emDim], nMeasurePointIdx, measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
            m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, measureDefect, dDistance_CutLine_mm, dResult_mm);
            g_pLog->DisplayMessage(_T("Measure Glass NG Chamfer End %s-%d : %d,%d"),g_SideName[(int) emDim],nMeasurePointIdx,measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
            g_pLog->DisplayMessage(_T("Measure Glass NG Chamfer End %s-%d : %d,%d"), g_SideName[(int)emDim], nMeasurePointIdx, measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
            /*
            // Make Defect
@@ -5043,24 +5091,24 @@
            pSideData->m_nSideMeasure_ChamferLine_Status[nMeasurePointIdx] = 1;   // OK
      }
      g_pLog->DisplayMessage(_T("Measure End %s-%d : %d,%d,%d,%d"),g_SideName[(int) emDim],nMeasurePointIdx,rtFindPos.left,rtFindPos.top,rtFindPos.right,rtFindPos.bottom);
      g_pLog->DisplayMessage(_T("Measure End %s-%d : %d,%d,%d,%d"), g_SideName[(int)emDim], nMeasurePointIdx, rtFindPos.left, rtFindPos.top, rtFindPos.right, rtFindPos.bottom);
   }
   return TRUE;
}
BOOL CInspectCamera::Measure_TopCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_TopCorner(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL)
      return FALSE;
   if(pSideParam->m_bTopCornerMeasureSize == FALSE)
   if (pSideParam->m_bTopCornerMeasureSize == FALSE)
      return FALSE;
   if (pSideData->m_bTopCorner_Find == FALSE)
@@ -5071,36 +5119,36 @@
   int nTopCornerType = pSideData->m_nTopCornerShape;
   if(nTopCornerType == (int) 1)                     return Measure_TopCorner_CCut(iThread, emDim, stFrame);
   else if(nTopCornerType == (int) 2)                  return Measure_TopCorner_RCut(iThread, emDim, stFrame);
   if (nTopCornerType == (int)1)                     return Measure_TopCorner_CCut(iThread, emDim, stFrame);
   else if (nTopCornerType == (int)2)                  return Measure_TopCorner_RCut(iThread, emDim, stFrame);
   else                                       pSideData->m_bTopCorner_Measure = TRUE;
   return TRUE;
}
BOOL CInspectCamera::Measure_TopCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_TopCorner_CCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL)
      return FALSE;
   CRect rtTopCornerArea = pSideData->m_rtTopCornerArea;
   rtTopCornerArea.InflateRect(50,50);
   rtTopCornerArea.InflateRect(50, 50);
   int      iCornerFrame = rtTopCornerArea.bottom/m_nFrameHeight;
   if(iCornerFrame > stFrame.nFrameIdx)
   int      iCornerFrame = rtTopCornerArea.bottom / m_nFrameHeight;
   if (iCornerFrame > stFrame.nFrameIdx)
      return FALSE;
   // Corner 八荤 父甸扁..
   if(FindCorner(iThread,emDim,stFrame,0,rtTopCornerArea) == TRUE)
   // Corner 검사 만들기..
   if (FindCorner(iThread, emDim, stFrame, 0, rtTopCornerArea) == TRUE)
   {
      double dXSizeStd_um = pSideParam->m_nTopCorner_Measure_Judge_Std_um_X;
      double dXSizeMin_um = pSideParam->m_nTopCorner_Measure_Judge_Min_um_X;
@@ -5110,29 +5158,29 @@
      double dYSizeMax_um = pSideParam->m_nTopCorner_Measure_Judge_Max_um_Y;
      int      nOpt = pSideParam->m_nTopCorner_Measure_Judge_OR_AND;
      if(nOpt == 0)
      if (nOpt == 0)
         return FALSE;
      double dResultWidth_um = pSideData->m_nTopCornerWidth;
      double dResultHeight_um = pSideData->m_nTopCornerHeight;
      pSideData->m_bTopCornerMeasureResult = TRUE;
      if(nOpt == 1)      // or
      if (nOpt == 1)      // or
      {
         if( (dResultWidth_um < dXSizeStd_um-dXSizeMin_um || dResultWidth_um > dXSizeStd_um+dXSizeMax_um) || (dResultHeight_um < dYSizeStd_um-dYSizeMin_um || dResultHeight_um > dYSizeStd_um+dYSizeMax_um))
         if ((dResultWidth_um < dXSizeStd_um - dXSizeMin_um || dResultWidth_um > dXSizeStd_um + dXSizeMax_um) || (dResultHeight_um < dYSizeStd_um - dYSizeMin_um || dResultHeight_um > dYSizeStd_um + dYSizeMax_um))
         {
            pSideData->m_bTopCornerMeasureResult = FALSE;   // NG            
         }
      }
      else            // and
      {
         if( (dResultWidth_um < dXSizeStd_um-dXSizeMin_um || dResultWidth_um > dXSizeStd_um+dXSizeMax_um) && (dResultHeight_um < dYSizeStd_um-dYSizeMin_um || dResultHeight_um > dYSizeStd_um+dYSizeMax_um))
         if ((dResultWidth_um < dXSizeStd_um - dXSizeMin_um || dResultWidth_um > dXSizeStd_um + dXSizeMax_um) && (dResultHeight_um < dYSizeStd_um - dYSizeMin_um || dResultHeight_um > dYSizeStd_um + dYSizeMax_um))
         {
            pSideData->m_bTopCornerMeasureResult = FALSE;   // NG            
         }
      }
      if(pSideData->m_bTopCornerMeasureResult == FALSE)
      if (pSideData->m_bTopCornerMeasureResult == FALSE)
      {
         // Make Defect            
         CDefect_Info measureDefect;
@@ -5141,47 +5189,47 @@
         measureDefect.m_nCamID = m_iCamera;
         measureDefect.m_nScanIdx = stFrame.nScanIdx;
         measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine;
         measureDefect.m_nSideIdx = (int) emDim;
         measureDefect.m_nSideIdx = (int)emDim;
         measureDefect.m_DefectLoc = DefectLoc_Measure_Corner;
         measureDefect.m_ptDefectPos_pxl = pSideData->m_rtTopCornerResult[1].CenterPoint();
         measureDefect.m_rtDefectPos_pxl = CRect(measureDefect.m_ptDefectPos_pxl.x - 16, measureDefect.m_ptDefectPos_pxl.y - 16, measureDefect.m_ptDefectPos_pxl.x + 16, measureDefect.m_ptDefectPos_pxl.y + 16);
         g_pLog->DisplayMessage(_T("Measure Top Corner NG Start %s : %d,%d"),g_SideName[(int) emDim],measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
         g_pLog->DisplayMessage(_T("Measure Top Corner NG Start %s : %d,%d"), g_SideName[(int)emDim], measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
         m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, measureDefect, dResultWidth_um, dResultHeight_um);
         g_pLog->DisplayMessage(_T("Measure Top Corner NG End %s : %d,%d"),g_SideName[(int) emDim],measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
         g_pLog->DisplayMessage(_T("Measure Top Corner NG End %s : %d,%d"), g_SideName[(int)emDim], measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
      }
   }
   return TRUE;
}
BOOL CInspectCamera::FindCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame,int nPos,CRect rtConnerRoi)
{
   g_pLog->DisplayMessage(_T("%s Corner pos %d, frame %d - %d,%d,%d,%d"),g_SideName[(int) emDim],nPos,stFrame.nFrameIdx,rtConnerRoi.left,rtConnerRoi.top,rtConnerRoi.right,rtConnerRoi.bottom);
BOOL CInspectCamera::FindCorner(int iThread, DimensionDir emDim, stFrameIndex stFrame, int nPos, CRect rtConnerRoi)
{
   g_pLog->DisplayMessage(_T("%s Corner pos %d, frame %d - %d,%d,%d,%d"), g_SideName[(int)emDim], nPos, stFrame.nFrameIdx, rtConnerRoi.left, rtConnerRoi.top, rtConnerRoi.right, rtConnerRoi.bottom);
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   // 1. Make ROI
   rtConnerRoi.left = (rtConnerRoi.left < 0) ? 0 : rtConnerRoi.left;
   rtConnerRoi.top = (rtConnerRoi.top < 0) ? 0 : rtConnerRoi.top;
   rtConnerRoi.right = (rtConnerRoi.right >= m_nFrameWidth) ? m_nFrameWidth-1 : rtConnerRoi.right;
   rtConnerRoi.right = (rtConnerRoi.right >= m_nFrameWidth) ? m_nFrameWidth - 1 : rtConnerRoi.right;
   // 2. Get Image Buffer
   BYTE* pBuffer               = m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtConnerRoi.top);
   IplImage* pConnerOriginImage   = cvCreateImage(cvSize(rtConnerRoi.Width(), rtConnerRoi.Height()), 8, 1);
   BYTE* pBuffer = m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtConnerRoi.top);
   IplImage* pConnerOriginImage = cvCreateImage(cvSize(rtConnerRoi.Width(), rtConnerRoi.Height()), 8, 1);
   IplImage* pConnerEdgeImage;
   IplImage* pConnerEdgeOutLineImage      = cvCreateImage(cvSize(rtConnerRoi.Width(), rtConnerRoi.Height()), 8, 1);
   IplImage* pConnerEdgeOutLineImage = cvCreateImage(cvSize(rtConnerRoi.Width(), rtConnerRoi.Height()), 8, 1);
   if(pBuffer == NULL)
   if (pBuffer == NULL)
      return FALSE;
   for(int i=0; i<rtConnerRoi.Height(); i++)
      memcpy(pConnerOriginImage->imageData+(i*pConnerOriginImage->widthStep), (char*) &pBuffer[rtConnerRoi.left + (i*m_nFrameWidth)], rtConnerRoi.Width());
   for (int i = 0; i < rtConnerRoi.Height(); i++)
      memcpy(pConnerOriginImage->imageData + (i * pConnerOriginImage->widthStep), (char*)&pBuffer[rtConnerRoi.left + (i * m_nFrameWidth)], rtConnerRoi.Width());
   pConnerEdgeImage = cvCloneImage(pConnerOriginImage);
@@ -5194,14 +5242,14 @@
   BOOL bFind = FALSE;
   int    nContinueCount = 5;
   UINT nTarget      = 0;
   UINT nCompare      = 0;
   int    nDiff         = 0;
   UINT nTarget = 0;
   UINT nCompare = 0;
   int    nDiff = 0;
   int nEdgeFilter;
   double dCornerEdgeTh1;
   if(nPos == 0)
   if (nPos == 0)
   {
      nEdgeFilter = pSideParam->m_nTopCornerEdgeFilterSize;
      dCornerEdgeTh1 = pSideParam->m_nTopCornerEdgeThreshold;
@@ -5212,46 +5260,46 @@
      dCornerEdgeTh1 = pSideParam->m_nBottomCornerEdgeThreshold;
   }
   if(nEdgeFilter % 2 == 0)
   if (nEdgeFilter % 2 == 0)
      nEdgeFilter = nEdgeFilter - 1;
   if(1 < nEdgeFilter)
   if (1 < nEdgeFilter)
      cvSmooth(pConnerEdgeImage, pConnerEdgeImage, CV_MEDIAN, nEdgeFilter);
   dCornerEdgeTh1 *= 10.;
   dCornerEdgeTh1 *= 10.;
   double dCornerEdgeTh2 = 40.0;
   int sigma=5;
   int sigma = 5;
   cvCanny(pConnerEdgeImage, pConnerEdgeImage, dCornerEdgeTh1, dCornerEdgeTh2, sigma);
   // Side
   for(int i=0; i<pConnerEdgeImage->height; i++)
   for (int i = 0; i < pConnerEdgeImage->height; i++)
   {
      for(int j=0; j<pConnerEdgeImage->width; j++)
      for (int j = 0; j < pConnerEdgeImage->width; j++)
      {
         nTarget = (UINT) pConnerEdgeImage->imageData[pConnerOriginImage->widthStep*i + j];
         nTarget = (UINT)pConnerEdgeImage->imageData[pConnerOriginImage->widthStep * i + j];
         if(nTarget != 0)
         if (nTarget != 0)
         {
            pConnerEdgeOutLineImage->imageData[pConnerOriginImage->widthStep*i + j] = 255;
            pConnerEdgeOutLineImage->imageData[pConnerOriginImage->widthStep * i + j] = 255;
            break;
         }
      }
   }
   // Top, Bottom
   if(nPos == 0)
   if (nPos == 0)
   {
      for(int i=0; i<pConnerEdgeImage->width; i++)
      for (int i = 0; i < pConnerEdgeImage->width; i++)
      {
         for(int j=0; j<pConnerEdgeImage->height; j++)
         for (int j = 0; j < pConnerEdgeImage->height; j++)
         {
            nTarget = (UINT) pConnerEdgeImage->imageData[pConnerOriginImage->widthStep*j + i];
            nTarget = (UINT)pConnerEdgeImage->imageData[pConnerOriginImage->widthStep * j + i];
            if(nTarget != 0)
            if (nTarget != 0)
            {
               pConnerEdgeOutLineImage->imageData[pConnerEdgeOutLineImage->widthStep*j + i] = 255;
               pConnerEdgeOutLineImage->imageData[pConnerEdgeOutLineImage->widthStep * j + i] = 255;
               break;
            }
         }
@@ -5259,15 +5307,15 @@
   }
   else
   {
      for(int i=0; i<pConnerEdgeImage->width; i++)
      for (int i = 0; i < pConnerEdgeImage->width; i++)
      {
         for(int j=0; j<pConnerEdgeImage->height; j++)
         for (int j = 0; j < pConnerEdgeImage->height; j++)
         {
            nTarget = (UINT) pConnerEdgeImage->imageData[pConnerOriginImage->widthStep*(pConnerOriginImage->height- 1 -j) + i];
            nTarget = (UINT)pConnerEdgeImage->imageData[pConnerOriginImage->widthStep * (pConnerOriginImage->height - 1 - j) + i];
            if(nTarget != 0)
            if (nTarget != 0)
            {
               pConnerEdgeOutLineImage->imageData[pConnerEdgeOutLineImage->widthStep*(pConnerEdgeOutLineImage->height- 1 -j) + i] = 255;
               pConnerEdgeOutLineImage->imageData[pConnerEdgeOutLineImage->widthStep * (pConnerEdgeOutLineImage->height - 1 - j) + i] = 255;
               break;
            }
         }
@@ -5279,7 +5327,7 @@
   strTemp.Format(_T("Corner\\ConnerProcess_OutLine_%d.jpg"), nPos);
   SaveDebugImage(emDim, stFrame, pConnerEdgeOutLineImage, strTemp);
   // 4. OutLine Projection Data
   std::vector<int> vecProjectionX;
@@ -5290,13 +5338,13 @@
   int nValue;
   for(int i=0; i<rtConnerRoi.Height(); i++)
   for (int i = 0; i < rtConnerRoi.Height(); i++)
   {
      for(int j=0; j<rtConnerRoi.Width(); j++)
      for (int j = 0; j < rtConnerRoi.Width(); j++)
      {
         nValue = (int) pConnerEdgeOutLineImage->imageData[j+(i*pConnerEdgeOutLineImage->widthStep)];
         nValue = (int)pConnerEdgeOutLineImage->imageData[j + (i * pConnerEdgeOutLineImage->widthStep)];
         if(pConnerEdgeOutLineImage->imageData[i*pConnerEdgeOutLineImage->widthStep + j] != 0)
         if (pConnerEdgeOutLineImage->imageData[i * pConnerEdgeOutLineImage->widthStep + j] != 0)
         {
            vecProjectionX[j]++;
            vecProjectionY[i]++;
@@ -5307,12 +5355,12 @@
   // 5. Find Edge
   CPoint ptConner[3];
   int nMaxCount   = -1;
   int nMaxIdx      = 0;
   int nMaxCount = -1;
   int nMaxIdx = 0;
   for(int i=0; i<rtConnerRoi.Width(); i++)
   for (int i = 0; i < rtConnerRoi.Width(); i++)
   {
      if(nMaxCount < vecProjectionX[i])
      if (nMaxCount < vecProjectionX[i])
      {
         nMaxIdx = i;
         nMaxCount = vecProjectionX[i];
@@ -5320,14 +5368,14 @@
   }
   ptConner[0].x = ptConner[1].x = ptConner[2].x = nMaxIdx;
   if(nPos == 0)
   if (nPos == 0)
   {
      nMaxCount   = -1;
      nMaxIdx      = 0;
      nMaxCount = -1;
      nMaxIdx = 0;
      for(int i=0; i<rtConnerRoi.Height(); i++)
      for (int i = 0; i < rtConnerRoi.Height(); i++)
      {
         if(nMaxCount < vecProjectionY[i])
         if (nMaxCount < vecProjectionY[i])
         {
            nMaxIdx = i;
            nMaxCount = vecProjectionY[i];
@@ -5338,12 +5386,12 @@
   }
   else
   {
      nMaxCount   = -1;
      nMaxIdx      = 0;
      nMaxCount = -1;
      nMaxIdx = 0;
      for(int i=rtConnerRoi.Height()-1; 0 <= i; i--)
      for (int i = rtConnerRoi.Height() - 1; 0 <= i; i--)
      {
         if(nMaxCount < vecProjectionY[i])
         if (nMaxCount < vecProjectionY[i])
         {
            nMaxIdx = i;
            nMaxCount = vecProjectionY[i];
@@ -5353,41 +5401,41 @@
      ptConner[0].y = ptConner[1].y = ptConner[2].y = nMaxIdx;
   }
   double dCornerSizeY_Um   = (double)pSideParam->m_nTopCornerSizeY_um;
   int nCornerSizeY_Pixel   = (int) GetUmToPixel_Y(dCornerSizeY_Um);
   double dCornerSizeX_Um = (double) pSideParam->m_nTopCornerSizeX_um;
   int nCornerSizeX_Pixel = (int) GetUmToPixel_X(dCornerSizeX_Um);
   double dCornerSizeY_Um = (double)pSideParam->m_nTopCornerSizeY_um;
   int nCornerSizeY_Pixel = (int)GetUmToPixel_Y(dCornerSizeY_Um);
   double dCornerSizeX_Um = (double)pSideParam->m_nTopCornerSizeX_um;
   int nCornerSizeX_Pixel = (int)GetUmToPixel_X(dCornerSizeX_Um);
   // 6. Find Conner Cut : 
   if(nCornerSizeX_Pixel != 0 && nCornerSizeY_Pixel != 0)
   if (nCornerSizeX_Pixel != 0 && nCornerSizeY_Pixel != 0)
   {
      BOOL    bFind = FALSE;
      double    dAddDistance = 0.0;
      int nSearchRange = 8;
      int nSearchRangeX = (int) ((double)nCornerSizeX_Pixel * 0.10);   // 10%俊辑 茫澜..
      int nSearchRangeY = (int) ((double)nCornerSizeY_Pixel * 0.10);   // 10%俊辑 茫澜..
      int nSearchRangeX = (int)((double)nCornerSizeX_Pixel * 0.10);   // 10%에서 찾음..
      int nSearchRangeY = (int)((double)nCornerSizeY_Pixel * 0.10);   // 10%에서 찾음..
      nSearchRangeX = nSearchRangeY = 10;
      for(int i=ptConner[0].x ; i<pConnerEdgeOutLineImage->width; i++)
      for (int i = ptConner[0].x; i < pConnerEdgeOutLineImage->width; i++)
      {
         if(i < 0 || i >= pConnerEdgeOutLineImage->width)
         if (i < 0 || i >= pConnerEdgeOutLineImage->width)
            continue;
         if(nPos == 0)
         if (nPos == 0)
         {
            //for(int j=0; j<nSearchRangeX; j++)
            for(int j=-nSearchRangeX;j<nSearchRangeX;j++)
            for (int j = -nSearchRangeX; j < nSearchRangeX; j++)
            {
               if((ptConner[0].y)+j < 0 || (ptConner[0].y)+j >= pConnerEdgeOutLineImage->height)
               if ((ptConner[0].y) + j < 0 || (ptConner[0].y) + j >= pConnerEdgeOutLineImage->height)
                  continue;
               if(pConnerEdgeOutLineImage->imageData[i+(((ptConner[0].y)+j) * pConnerEdgeOutLineImage->widthStep)] != 0)
               if (pConnerEdgeOutLineImage->imageData[i + (((ptConner[0].y) + j) * pConnerEdgeOutLineImage->widthStep)] != 0)
               {
                  dAddDistance = (((double)j)*m_dPixelSizeY)/m_dPixelSizeX;
                  ptConner[1].x = i + (int) dAddDistance;
                  dAddDistance = (((double)j) * m_dPixelSizeY) / m_dPixelSizeX;
                  ptConner[1].x = i + (int)dAddDistance;
                  bFind = TRUE;
                  break;
               }
@@ -5396,131 +5444,131 @@
         else
         {
            //for(int j=0; j<nSearchRangeX; j++)
            for(int j=-nSearchRangeX;j<nSearchRangeX;j++)
            for (int j = -nSearchRangeX; j < nSearchRangeX; j++)
            {
               if((ptConner[0].y)-j < 0 || (ptConner[0].y)-j >= pConnerEdgeOutLineImage->height)
               if ((ptConner[0].y) - j < 0 || (ptConner[0].y) - j >= pConnerEdgeOutLineImage->height)
                  continue;
               if(pConnerEdgeOutLineImage->imageData[i+(((ptConner[0].y)-j) * pConnerEdgeOutLineImage->widthStep)] != 0)
               if (pConnerEdgeOutLineImage->imageData[i + (((ptConner[0].y) - j) * pConnerEdgeOutLineImage->widthStep)] != 0)
               {
                  dAddDistance = (((double)j)*m_dPixelSizeY)/m_dPixelSizeX;
                  ptConner[1].x = i + (int) dAddDistance;
                  dAddDistance = (((double)j) * m_dPixelSizeY) / m_dPixelSizeX;
                  ptConner[1].x = i + (int)dAddDistance;
                  bFind = TRUE;
                  break;
               }
            }
         }
         }
         if(bFind)
         if (bFind)
            break;
      }
      bFind = FALSE;
      if(nPos == 0)
      if (nPos == 0)
      {
         for(int i=ptConner[0].y ; i<pConnerEdgeOutLineImage->height; i++)
         for (int i = ptConner[0].y; i < pConnerEdgeOutLineImage->height; i++)
         {
            if(i < 0 || i >= pConnerEdgeOutLineImage->height)
            if (i < 0 || i >= pConnerEdgeOutLineImage->height)
               continue;
            //for(int j=0; j<nSearchRangeY; j++)
            for(int j=-nSearchRangeY;j<nSearchRangeY;j++)
            for (int j = -nSearchRangeY; j < nSearchRangeY; j++)
            {
               if(ptConner[0].x+j < 0 || ptConner[0].x+j >= pConnerEdgeOutLineImage->widthStep)
               if (ptConner[0].x + j < 0 || ptConner[0].x + j >= pConnerEdgeOutLineImage->widthStep)
                  continue;
               if(pConnerEdgeOutLineImage->imageData[ptConner[0].x+j+(i * pConnerEdgeOutLineImage->widthStep)] != 0)
               if (pConnerEdgeOutLineImage->imageData[ptConner[0].x + j + (i * pConnerEdgeOutLineImage->widthStep)] != 0)
               {
                  dAddDistance = (((double)j)*m_dPixelSizeX)/m_dPixelSizeY;
                  ptConner[2].y = i + (int) dAddDistance;
                  dAddDistance = (((double)j) * m_dPixelSizeX) / m_dPixelSizeY;
                  ptConner[2].y = i + (int)dAddDistance;
                  bFind = TRUE;
                  break;
               }
            }
            if(bFind)
            if (bFind)
               break;
         }
      }
      else
      {
         for(int i=ptConner[0].y ; 0 <= i; i--)
         for (int i = ptConner[0].y; 0 <= i; i--)
         {
            if(i < 0 || i >= pConnerEdgeOutLineImage->height)
            if (i < 0 || i >= pConnerEdgeOutLineImage->height)
               continue;
            //for(int j=0; j<nSearchRangeY; j++)
            for(int j=-nSearchRangeY;j<nSearchRangeY;j++)
            for (int j = -nSearchRangeY; j < nSearchRangeY; j++)
            {
               if(ptConner[0].x+j < 0 || ptConner[0].x+j >= pConnerEdgeOutLineImage->widthStep)
               if (ptConner[0].x + j < 0 || ptConner[0].x + j >= pConnerEdgeOutLineImage->widthStep)
                  continue;
               if(pConnerEdgeOutLineImage->imageData[ptConner[0].x+j+(i * pConnerEdgeOutLineImage->widthStep)] != 0)
               if (pConnerEdgeOutLineImage->imageData[ptConner[0].x + j + (i * pConnerEdgeOutLineImage->widthStep)] != 0)
               {
                  dAddDistance = (((double)j)*m_dPixelSizeX)/m_dPixelSizeY;
                  ptConner[2].y = i - (int) dAddDistance;
                  dAddDistance = (((double)j) * m_dPixelSizeX) / m_dPixelSizeY;
                  ptConner[2].y = i - (int)dAddDistance;
                  bFind = TRUE;
                  break;
               }
            }
            if(bFind)
            if (bFind)
               break;
         }
      }
   }
   if(nPos == 0)
   {
      pSideData->m_rtTopCornerResult[0].left      = rtConnerRoi.left;
      pSideData->m_rtTopCornerResult[0].top      = rtConnerRoi.top;
      pSideData->m_rtTopCornerResult[0].right      = rtConnerRoi.right;
      pSideData->m_rtTopCornerResult[0].bottom       = rtConnerRoi.bottom;
   }
      if(nPos == 0)
   if (nPos == 0)
   {
      pSideData->m_rtTopCornerResult[0].left = rtConnerRoi.left;
      pSideData->m_rtTopCornerResult[0].top = rtConnerRoi.top;
      pSideData->m_rtTopCornerResult[0].right = rtConnerRoi.right;
      pSideData->m_rtTopCornerResult[0].bottom = rtConnerRoi.bottom;
      if (nPos == 0)
      {
         pSideData->m_rtTopCornerResult[1].left      = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].top      = ptConner[0].y + rtConnerRoi.top;
         pSideData->m_rtTopCornerResult[1].right      = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].bottom       = ptConner[2].y + rtConnerRoi.top;
         pSideData->m_rtTopCornerResult[1].left = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].top = ptConner[0].y + rtConnerRoi.top;
         pSideData->m_rtTopCornerResult[1].right = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].bottom = ptConner[2].y + rtConnerRoi.top;
      }
      else
      {
         pSideData->m_rtTopCornerResult[1].left      = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].top      = ptConner[2].y + rtConnerRoi.top;
         pSideData->m_rtTopCornerResult[1].right      = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].bottom       = ptConner[0].y + rtConnerRoi.top;
      }
         pSideData->m_rtTopCornerResult[1].left = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].top = ptConner[2].y + rtConnerRoi.top;
         pSideData->m_rtTopCornerResult[1].right = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtTopCornerResult[1].bottom = ptConner[0].y + rtConnerRoi.top;
      }
      pSideData->m_nTopCornerWidth = (int)(abs(pSideData->m_rtTopCornerResult[1].right  - pSideData->m_rtTopCornerResult[1].left) * m_dPixelSizeX);
      pSideData->m_nTopCornerHeight = (int)(abs(pSideData->m_rtTopCornerResult[1].bottom  - pSideData->m_rtTopCornerResult[1].top) * m_dPixelSizeY);
      pSideData->m_nTopCornerWidth = (int)(abs(pSideData->m_rtTopCornerResult[1].right - pSideData->m_rtTopCornerResult[1].left) * m_dPixelSizeX);
      pSideData->m_nTopCornerHeight = (int)(abs(pSideData->m_rtTopCornerResult[1].bottom - pSideData->m_rtTopCornerResult[1].top) * m_dPixelSizeY);
      pSideData->m_bTopCorner_Measure = TRUE;
   }
   else
   {
      pSideData->m_rtBottomCornerResult[0].left      = rtConnerRoi.left;
      pSideData->m_rtBottomCornerResult[0].top      = rtConnerRoi.top;
      pSideData->m_rtBottomCornerResult[0].right      = rtConnerRoi.right;
      pSideData->m_rtBottomCornerResult[0].bottom       = rtConnerRoi.bottom;
      pSideData->m_rtBottomCornerResult[0].left = rtConnerRoi.left;
      pSideData->m_rtBottomCornerResult[0].top = rtConnerRoi.top;
      pSideData->m_rtBottomCornerResult[0].right = rtConnerRoi.right;
      pSideData->m_rtBottomCornerResult[0].bottom = rtConnerRoi.bottom;
      if(nPos == 0)
      if (nPos == 0)
      {
         pSideData->m_rtBottomCornerResult[1].left      = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].top      = ptConner[0].y + rtConnerRoi.top;
         pSideData->m_rtBottomCornerResult[1].right      = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].bottom       = ptConner[2].y + rtConnerRoi.top;
         pSideData->m_rtBottomCornerResult[1].left = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].top = ptConner[0].y + rtConnerRoi.top;
         pSideData->m_rtBottomCornerResult[1].right = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].bottom = ptConner[2].y + rtConnerRoi.top;
      }
      else
      {
         pSideData->m_rtBottomCornerResult[1].left      = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].top      = ptConner[2].y + rtConnerRoi.top;
         pSideData->m_rtBottomCornerResult[1].right      = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].bottom       = ptConner[0].y + rtConnerRoi.top;
      }
         pSideData->m_rtBottomCornerResult[1].left = ptConner[0].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].top = ptConner[2].y + rtConnerRoi.top;
         pSideData->m_rtBottomCornerResult[1].right = ptConner[1].x + rtConnerRoi.left;
         pSideData->m_rtBottomCornerResult[1].bottom = ptConner[0].y + rtConnerRoi.top;
      }
      pSideData->m_nBottomCornerWidth = (int)(abs(pSideData->m_rtBottomCornerResult[1].right  - pSideData->m_rtBottomCornerResult[1].left) * m_dPixelSizeX);
      pSideData->m_nBottomCornerHeight = (int)(abs(pSideData->m_rtBottomCornerResult[1].bottom  - pSideData->m_rtBottomCornerResult[1].top) * m_dPixelSizeY);
      pSideData->m_nBottomCornerWidth = (int)(abs(pSideData->m_rtBottomCornerResult[1].right - pSideData->m_rtBottomCornerResult[1].left) * m_dPixelSizeX);
      pSideData->m_nBottomCornerHeight = (int)(abs(pSideData->m_rtBottomCornerResult[1].bottom - pSideData->m_rtBottomCornerResult[1].top) * m_dPixelSizeY);
      pSideData->m_bBotCorner_Measure = TRUE;
   }
@@ -5529,41 +5577,41 @@
   cvReleaseImage(&pConnerEdgeOutLineImage);
   vecProjectionX.clear();
   vecProjectionY.clear();
   vecProjectionY.clear();
   g_pLog->DisplayMessage(_T("%s Corner pos %d End, frame %d - %d,%d,%d,%d"),g_SideName[(int) emDim],nPos,stFrame.nFrameIdx,rtConnerRoi.left,rtConnerRoi.top,rtConnerRoi.right,rtConnerRoi.bottom);
   g_pLog->DisplayMessage(_T("%s Corner pos %d End, frame %d - %d,%d,%d,%d"), g_SideName[(int)emDim], nPos, stFrame.nFrameIdx, rtConnerRoi.left, rtConnerRoi.top, rtConnerRoi.right, rtConnerRoi.bottom);
   return TRUE;
}
BOOL CInspectCamera::Measure_TopCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_TopCorner_RCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL)
      return FALSE;
   // R Corner 螟沥
   // R Corner 측정
   return TRUE;
}
BOOL CInspectCamera::Measure_BotCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_BotCorner(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL)
      return FALSE;
   if(pSideParam->m_bBottomCornerMeasureSize == FALSE)
   if (pSideParam->m_bBottomCornerMeasureSize == FALSE)
      return FALSE;
   if (pSideData->m_bBotCorner_Find == FALSE)
@@ -5574,35 +5622,35 @@
   int nBotCornerType = pSideData->m_nBotCornerShape;
   if(nBotCornerType == (int) 1)                     return Measure_BotCorner_CCut(iThread, emDim, stFrame);
   else if(nBotCornerType == (int) 2)                  return Measure_BotCorner_RCut(iThread, emDim, stFrame);
   if (nBotCornerType == (int)1)                     return Measure_BotCorner_CCut(iThread, emDim, stFrame);
   else if (nBotCornerType == (int)2)                  return Measure_BotCorner_RCut(iThread, emDim, stFrame);
   else                                       pSideData->m_bBotCorner_Measure = TRUE;
   return TRUE;
}
BOOL CInspectCamera::Measure_BotCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_BotCorner_CCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim];
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim];
   if(pSideData == NULL || pSideParam == NULL)
   if (pSideData == NULL || pSideParam == NULL)
      return FALSE;
   CRect rtBottomCornerArea = pSideData->m_rtBotCornerArea;
   rtBottomCornerArea.InflateRect(50,50);
   rtBottomCornerArea.InflateRect(50, 50);
   int      iCornerFrame = rtBottomCornerArea.bottom/m_nFrameHeight;
   int      iCornerFrame = rtBottomCornerArea.bottom / m_nFrameHeight;
   if(iCornerFrame > stFrame.nFrameIdx)
   if (iCornerFrame > stFrame.nFrameIdx)
      return FALSE;
   // Corner 八荤 父甸扁..
   if(FindCorner(iThread,emDim,stFrame,1,rtBottomCornerArea) == TRUE)
   // Corner 검사 만들기..
   if (FindCorner(iThread, emDim, stFrame, 1, rtBottomCornerArea) == TRUE)
   {
      double dXSizeStd_um = pSideParam->m_nBottomCorner_Measure_Judge_Std_um_X;
      double dXSizeMin_um = pSideParam->m_nBottomCorner_Measure_Judge_Min_um_X;
@@ -5612,29 +5660,29 @@
      double dYSizeMax_um = pSideParam->m_nBottomCorner_Measure_Judge_Max_um_Y;
      int      nOpt = pSideParam->m_nBottomCorner_Measure_Judge_OR_AND;
      if(nOpt == 0)
      if (nOpt == 0)
         return FALSE;
      double dResultWidth_um = pSideData->m_nBottomCornerWidth;
      double dResultHeight_um = pSideData->m_nBottomCornerHeight;
      pSideData->m_bBottomMeasureResult = TRUE;
      if(nOpt == 1)      // or
      if (nOpt == 1)      // or
      {
         if( (dResultWidth_um < dXSizeStd_um-dXSizeMin_um || dResultWidth_um > dXSizeStd_um+dXSizeMax_um) || (dResultHeight_um < dYSizeStd_um-dYSizeMin_um || dResultHeight_um > dYSizeStd_um+dYSizeMax_um))
         if ((dResultWidth_um < dXSizeStd_um - dXSizeMin_um || dResultWidth_um > dXSizeStd_um + dXSizeMax_um) || (dResultHeight_um < dYSizeStd_um - dYSizeMin_um || dResultHeight_um > dYSizeStd_um + dYSizeMax_um))
         {
            pSideData->m_bBottomMeasureResult = FALSE;   // NG            
         }
      }
      else            // and
      {
         if( (dResultWidth_um < dXSizeStd_um-dXSizeMin_um || dResultWidth_um > dXSizeStd_um+dXSizeMax_um) && (dResultHeight_um < dYSizeStd_um-dYSizeMin_um || dResultHeight_um > dYSizeStd_um+dYSizeMax_um))
         if ((dResultWidth_um < dXSizeStd_um - dXSizeMin_um || dResultWidth_um > dXSizeStd_um + dXSizeMax_um) && (dResultHeight_um < dYSizeStd_um - dYSizeMin_um || dResultHeight_um > dYSizeStd_um + dYSizeMax_um))
         {
            pSideData->m_bBottomMeasureResult = FALSE;   // NG            
         }
      }
      if(pSideData->m_bBottomMeasureResult == FALSE)
      if (pSideData->m_bBottomMeasureResult == FALSE)
      {
         // Make Defect            
         CDefect_Info measureDefect;
@@ -5643,65 +5691,65 @@
         measureDefect.m_nCamID = m_iCamera;
         measureDefect.m_nScanIdx = stFrame.nScanIdx;
         measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine;
         measureDefect.m_nSideIdx = (int) emDim;
         measureDefect.m_nSideIdx = (int)emDim;
         measureDefect.m_DefectLoc = DefectLoc_Measure_Corner;
         measureDefect.m_ptDefectPos_pxl = pSideData->m_rtTopCornerResult[1].CenterPoint();
         measureDefect.m_rtDefectPos_pxl = CRect(measureDefect.m_ptDefectPos_pxl.x - 16, measureDefect.m_ptDefectPos_pxl.y - 16, measureDefect.m_ptDefectPos_pxl.x + 16, measureDefect.m_ptDefectPos_pxl.y + 16);
         g_pLog->DisplayMessage(_T("Measure Bottom Corner NG Start %s : %d,%d"),g_SideName[(int) emDim],measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
         g_pLog->DisplayMessage(_T("Measure Bottom Corner NG Start %s : %d,%d"), g_SideName[(int)emDim], measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
         m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, measureDefect, dResultWidth_um, dResultHeight_um);
         g_pLog->DisplayMessage(_T("Measure Bottom Corner NG End %s : %d,%d"),g_SideName[(int) emDim],measureDefect.m_ptDefectPos_pxl.x,measureDefect.m_ptDefectPos_pxl.y);
         g_pLog->DisplayMessage(_T("Measure Bottom Corner NG End %s : %d,%d"), g_SideName[(int)emDim], measureDefect.m_ptDefectPos_pxl.x, measureDefect.m_ptDefectPos_pxl.y);
      }
   }
   return TRUE;
}
BOOL CInspectCamera::Measure_BotCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::Measure_BotCorner_RCut(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   return TRUE;
}
BOOL CInspectCamera::UserDefect_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::UserDefect_Process(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassEndLine == FALSE)      // User Defect Processing篮 End Line 茫篮 Frame捞..
   if (pSideData->m_bFindGlassEndLine == FALSE)      // User Defect Processing은 End Line 찾은 Frame이..
      return FALSE;
   if(m_pRecipe == NULL)
   if (m_pRecipe == NULL)
      return FALSE;
   if(m_pDefectControl == NULL)
   if (m_pDefectControl == NULL)
      return FALSE;
   std::vector<CDefect_Info> vecDefectCandidateList;
   int nUserDefectAreaCount = m_pRecipe->m_SideParam[(int) emDim].m_nUserDefectAreaCount;
   int nUserDefectAreaCount = m_pRecipe->m_SideParam[(int)emDim].m_nUserDefectAreaCount;
   pSideData->m_nUserDefectAreaCount = nUserDefectAreaCount;
   for(int i=0; i<nUserDefectAreaCount; i++)
   for (int i = 0; i < nUserDefectAreaCount; i++)
   {
      if(m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_bUseInspect == 0)
      if (m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[i].m_bUseInspect == 0)
         continue;
      CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_ptTopMarkPos;
      CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_ptBotMarkPos;
      CRect rtSet_Area = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_rtUserDefectArea;
      CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[i].m_ptTopMarkPos;
      CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[i].m_ptBotMarkPos;
      CRect rtSet_Area = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[i].m_rtUserDefectArea;
      CRect rtRotateArea;
      if(GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
      if (GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
         continue;
      pSideData->m_rtUserDefectArea_pxl[i] = rtRotateArea;
@@ -5714,47 +5762,47 @@
   return TRUE;
}
BOOL CInspectCamera::InspectDefect_UserDefectProcess(int iThread,DimensionDir emDim, stFrameIndex stFrame, int nUserDefectIdx, CRect rtUserDefectArea, std::vector<CDefect_Info>* pDefectList)
BOOL CInspectCamera::InspectDefect_UserDefectProcess(int iThread, DimensionDir emDim, stFrameIndex stFrame, int nUserDefectIdx, CRect rtUserDefectArea, std::vector<CDefect_Info>* pDefectList)
{
   if (rtUserDefectArea.IsRectEmpty() == TRUE || m_pGlassData == NULL)
      return FALSE;
   DefectLocation defectLoc = DefectLoc_UserDefect;
   if(m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_bUseInspect == FALSE)
   if (m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_bUseInspect == FALSE)
      return TRUE;
   // 0. Parameter Initialize..
   CString strDefectType      = _T("Unknown");
   int nMethod               = 0;
   int nThreshold_Low         = 0;
   int nThreshold_High         = 0;
   int nPitch               = 0;
   int nPitch_Threshold      = 0;
   int nMinSize            = 0;
   int   nJudge_Size_Min_X_um   = 0;
   int   nJudge_Size_Min_Y_um   = 0;
   int   nJudge_Size_Min_OR_AND  = 0;   // 0 : No Use, 1 : OR, 2 : AND
   CString strDefectType = _T("Unknown");
   int nMethod = 0;
   int nThreshold_Low = 0;
   int nThreshold_High = 0;
   int nPitch = 0;
   int nPitch_Threshold = 0;
   int nMinSize = 0;
   int   nJudge_Size_Min_X_um = 0;
   int   nJudge_Size_Min_Y_um = 0;
   int   nJudge_Size_Min_OR_AND = 0;   // 0 : No Use, 1 : OR, 2 : AND
   nMethod                  = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nInspect_Method;
   nThreshold_Low            = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nMin_Threshold;
   nThreshold_High            = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nMax_Threshold;
   nPitch                  = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nDiff_Pitch;
   nPitch_Threshold         = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nDiff_Threshold;
   nMinSize               = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nMinSize_Filter_pxl;
   nJudge_Size_Min_X_um      = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nJudge_Size_Min_X_um;
   nJudge_Size_Min_Y_um      = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nJudge_Size_Min_Y_um;
   nJudge_Size_Min_OR_AND      = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_nJudge_Size_Min_OR_AND;
   nMethod = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nInspect_Method;
   nThreshold_Low = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nMin_Threshold;
   nThreshold_High = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nMax_Threshold;
   nPitch = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nDiff_Pitch;
   nPitch_Threshold = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nDiff_Threshold;
   nMinSize = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nMinSize_Filter_pxl;
   nJudge_Size_Min_X_um = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nJudge_Size_Min_X_um;
   nJudge_Size_Min_Y_um = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nJudge_Size_Min_Y_um;
   nJudge_Size_Min_OR_AND = m_pRecipe->m_SideParam[(int)emDim].m_UserDefectPrm[nUserDefectIdx].m_nJudge_Size_Min_OR_AND;
   CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtUserDefectArea.top), m_nFrameWidth, m_nFrameHeight);
   if(frameBuffer.IsValidBuffer() == FALSE)
   if (frameBuffer.IsValidBuffer() == FALSE)
      return FALSE;
   // 1. Inspect ROI
   COwnerBuffer pDefectProcessImage(rtUserDefectArea.Width(), rtUserDefectArea.Height());
   for (int i = 0; i < rtUserDefectArea.Height(); i++)
      memcpy(pDefectProcessImage.GetDataAddress(0,i), frameBuffer.GetDataAddress(rtUserDefectArea.left, i), rtUserDefectArea.Width());
      memcpy(pDefectProcessImage.GetDataAddress(0, i), frameBuffer.GetDataAddress(rtUserDefectArea.left, i), rtUserDefectArea.Width());
   // 2. Inspect Algorithm
   COwnerBuffer pBinImage;
@@ -5783,52 +5831,52 @@
   return TRUE;
}
BOOL CInspectCamera::ExceptionArea_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame)
BOOL CInspectCamera::ExceptionArea_Process(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return FALSE;
   CSide_Data*   pSideData = m_pGlassData->GetSideData(emDim);
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassEndLine == FALSE)      // Exception Area Processing篮 End Line 茫篮 Frame捞..
   if (pSideData->m_bFindGlassEndLine == FALSE)      // Exception Area Processing은 End Line 찾은 Frame이..
      return FALSE;
   if(m_pRecipe == NULL)
   if (m_pRecipe == NULL)
      return FALSE;
   if(m_pDefectControl == NULL)
   if (m_pDefectControl == NULL)
      return FALSE;
   int nExceptionCount = m_pRecipe->m_SideParam[(int) emDim].m_nExptionCount;
   int nExceptionCount = m_pRecipe->m_SideParam[(int)emDim].m_nExptionCount;
   pSideData->m_nExceptionAreaCount = nExceptionCount;
   for(int i=0; i<nExceptionCount; i++)
   for (int i = 0; i < nExceptionCount; i++)
   {
      if(m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_nFilterType == 0)
      if (m_pRecipe->m_SideParam[(int)emDim].m_ExpAreaPrm[i].m_nFilterType == 0)
         continue;
      CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_ptTopMarkPos;
      CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_ptBotMarkPos;
      CRect rtSet_Area = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_rtExceptionArea;
      CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int)emDim].m_ExpAreaPrm[i].m_ptTopMarkPos;
      CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int)emDim].m_ExpAreaPrm[i].m_ptBotMarkPos;
      CRect rtSet_Area = m_pRecipe->m_SideParam[(int)emDim].m_ExpAreaPrm[i].m_rtExceptionArea;
      CRect rtRotateArea;
      if(GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
      if (GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE)
         continue;
      pSideData->m_rtExceptionArea_pxl[i] = rtRotateArea;
      int nDefectCount = m_pDefectControl->GetDefectCount();
      for(int nDefectIdx=0; nDefectIdx<nDefectCount; nDefectIdx++)
      for (int nDefectIdx = 0; nDefectIdx < nDefectCount; nDefectIdx++)
      {
         CDefect* pDefect = m_pDefectControl->GetDefect(nDefectIdx);
         if(pDefect == NULL)
         if (pDefect == NULL)
            continue;
         CRect rtDefectArea = pDefect->m_DefectInfo.m_rtDefectPos_pxl;
@@ -5836,20 +5884,20 @@
         CRect rtIntersect;
         rtIntersect.IntersectRect(rtRotateArea, rtDefectArea);
         if(rtIntersect == rtDefectArea)
         if (rtIntersect == rtDefectArea)
            pDefect->m_nExceptionArea = 2;
         else if(0 < rtIntersect.Width() || 0 < rtIntersect.Height())
         else if (0 < rtIntersect.Width() || 0 < rtIntersect.Height())
            pDefect->m_nExceptionArea = 1;
         else
            continue;
         int nFilterType = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_nFilterType;
         int nFilterType = m_pRecipe->m_SideParam[(int)emDim].m_ExpAreaPrm[i].m_nFilterType;
         if(nFilterType == 0)
         if (nFilterType == 0)
            continue;
         else if(nFilterType == 1 && (pDefect->m_nExceptionArea == 1 || pDefect->m_nExceptionArea == 2))
         else if (nFilterType == 1 && (pDefect->m_nExceptionArea == 1 || pDefect->m_nExceptionArea == 2))
            pDefect->m_DefectInfo.m_DefectLoc = DefectLoc_Exception;
         else if(nFilterType == 2 && pDefect->m_nExceptionArea == 2)
         else if (nFilterType == 2 && pDefect->m_nExceptionArea == 2)
            pDefect->m_DefectInfo.m_DefectLoc = DefectLoc_Exception;
      }
   }
@@ -5857,55 +5905,55 @@
   return TRUE;
}
void CInspectCamera::SaveGlassLineImage(int iScan,int nLine,int nXPos,DimensionDir emDim,CString strName)
void CInspectCamera::SaveGlassLineImage(int iScan, int nLine, int nXPos, DimensionDir emDim, CString strName)
{
   int         nImgWidth = 100;
   int         nImgHeight = 200;
   CvRect         saveRect = cvRect(nXPos-nImgWidth,0,nImgWidth*2,nImgHeight*2);
   int         nImgHeight = 200;
   int         iStartV = nLine-nImgHeight;
   CvRect         saveRect = cvRect(nXPos - nImgWidth, 0, nImgWidth * 2, nImgHeight * 2);
   if(iStartV < 0)
   int         iStartV = nLine - nImgHeight;
   if (iStartV < 0)
      iStartV = 0;
   LPBYTE   pImg = m_pGrabber->GetFrameHeaderLine(iScan,iStartV);
   if(pImg == NULL)
   LPBYTE   pImg = m_pGrabber->GetFrameHeaderLine(iScan, iStartV);
   if (pImg == NULL)
      return;
   IplImage *IpImg = cvCreateImage(cvSize(saveRect.width,saveRect.height),8,1);
   IplImage* IpImg = cvCreateImage(cvSize(saveRect.width, saveRect.height), 8, 1);
   cvZero(IpImg);
   int         nFrameWidth,nFrameHeight;
   int         nFrameWidth, nFrameHeight;
   GetFrameSize(m_iCamera,iScan,nFrameWidth,nFrameHeight);
   GetFrameSize(m_iCamera, iScan, nFrameWidth, nFrameHeight);
   for(int i=0; i< saveRect.height; i++)
   {
      memcpy(&IpImg->imageData[IpImg->widthStep*i], pImg+saveRect.x, sizeof(BYTE)*IpImg->width);
   for (int i = 0; i < saveRect.height; i++)
   {
      memcpy(&IpImg->imageData[IpImg->widthStep * i], pImg + saveRect.x, sizeof(BYTE) * IpImg->width);
      pImg += nFrameWidth;
   }
   CString         strFile;
   strFile.Format(_T("%s\\IMG_MARK\\%s\\%s\\%s\\%s_%s.jpg"),PATH_INSPECTION_DATA,g_pBase->m_strLoadingDay,g_pBase->m_strHPanelID,g_pBase->m_strLoadingTime,PANEL_SIDE[emDim],strName);
   strFile.Format(_T("%s\\IMG_MARK\\%s\\%s\\%s\\%s_%s.jpg"), PATH_INSPECTION_DATA, g_pBase->m_strLoadingDay, g_pBase->m_strHPanelID, g_pBase->m_strLoadingTime, PANEL_SIDE[emDim], strName);
   g_pStatus->CheckDirectory(strFile);
   cv::Point startPoint(0,saveRect.height/2);
   cv::Point endPoint(saveRect.width,saveRect.height/2);
   cv::Point startPoint(0, saveRect.height / 2);
   cv::Point endPoint(saveRect.width, saveRect.height / 2);
   cvLine(IpImg, startPoint, endPoint, cvScalar(255, 0, 0), 1);
   USES_CONVERSION;
   char str_filename[1024];
   sprintf_s(str_filename, "%s", W2A(strFile));
   cvSaveImage(str_filename,IpImg);
   cvSaveImage(str_filename, IpImg);
   cvReleaseImage(&IpImg);
}
BOOL CInspectCamera::OnThreadEnd(int iThread, CInspectThread *pInspectThread)
BOOL CInspectCamera::OnThreadEnd(int iThread, CInspectThread* pInspectThread)
{
   return TRUE;
}
@@ -5916,79 +5964,79 @@
}
void CInspectCamera::ReleaseFullBuffer()
{
{
   int   i;
   for(i=0;i<MAX_SCAN_COUNT;i++)
   for (i = 0; i < MAX_SCAN_COUNT; i++)
   {
      m_FullImgBuffer[i].Reset();
   }
   }
}
void CInspectCamera::SetSimulation(BOOL bSimulation)
{
   m_bSimulation = bSimulation;
   if(m_pGlassData == NULL)
   if (m_pGlassData == NULL)
      return;
   m_pGlassData->SetSimulation(bSimulation);
}
void CInspectCamera::SetParameter(CGlassRecipe *pRecipe,CHardwareSettings *pHW)
void CInspectCamera::SetParameter(CGlassRecipe* pRecipe, CHardwareSettings* pHW)
{
   g_pLog->DisplayMessage(_T("SetParameter Cam[%d] start"),m_iCamera);
   g_pLog->DisplayMessage(_T("SetParameter Cam[%d] start"), m_iCamera);
   m_bExitThread = TRUE;
   ZeroMemory(m_iThreadEnd,sizeof(m_iThreadEnd));
   ZeroMemory(m_bFindGlassStart,sizeof(m_bFindGlassStart));
   ZeroMemory(m_iSideLine,sizeof(m_iSideLine));
   ZeroMemory(m_iThreadEnd, sizeof(m_iThreadEnd));
   ZeroMemory(m_bFindGlassStart, sizeof(m_bFindGlassStart));
   ZeroMemory(m_iSideLine, sizeof(m_iSideLine));
   m_pRecipe = pRecipe;
   m_pHardparm = pHW;
   if(m_pGrabber != NULL)
   if (m_pGrabber != NULL)
   {
      m_pGrabber->ClearGrabIdx();
      //m_pGrabber->ClearBuffer();
   }
   if(m_pDefectControl != NULL)
   }
   if (m_pDefectControl != NULL)
   {
      m_pDefectControl->SetHWRecipe(pHW);
      m_pDefectControl->ResetDefectControl();
   }
   g_pLog->DisplayMessage(_T("SetParameter Cam[%d] end"),m_iCamera);
   g_pLog->DisplayMessage(_T("SetParameter Cam[%d] end"), m_iCamera);
}
void CInspectCamera::SetGlassData(CGlass_Data *pGlassData)
void CInspectCamera::SetGlassData(CGlass_Data* pGlassData)
{
   m_pGlassData = pGlassData;
   if(m_pGrabber != NULL)
   if (m_pGrabber != NULL)
   {
      for(int i=0;i<MAX_DIMENSION_COUNT;i++)
      for (int i = 0; i < MAX_DIMENSION_COUNT; i++)
      {
         CSide_Data* pSideData = m_pGlassData->GetSideData((DimensionDir)i);
         if(pSideData == NULL)
         if (pSideData == NULL)
            continue;
         pSideData->m_nPreGlassEndFrame = m_pGrabber->GetFrameBuffer()->GetFrameCount()-1;
         pSideData->m_nPreGlassEndFrame = m_pGrabber->GetFrameBuffer()->GetFrameCount() - 1;
      }
   }
}
void CInspectCamera::SetGrabber(CGrabberControl *pGrabber)
void CInspectCamera::SetGrabber(CGrabberControl* pGrabber)
{
   m_pGrabber = pGrabber;
   if(m_pDefectControl != NULL)
   if (m_pDefectControl != NULL)
      m_pDefectControl->SetGrabber(pGrabber);
}
DimensionDir CInspectCamera::GetDimension(int iScan)
{
   CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,iScan);
   if(pCamera == NULL)
   CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(m_iCamera, iScan);
   if (pCamera == NULL)
      return DIMENSION_NONE;
   return pCamera->m_eDimension;
@@ -5998,9 +6046,9 @@
{
   g_pLog->DisplayMessage(_T("Set Grab End"));
   CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,iScan);
   if(pCamera == NULL)
   CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(m_iCamera, iScan);
   if (pCamera == NULL)
   {
      g_pLog->DisplayMessage(_T("Camera Setting NULL"));
      return;
@@ -6008,83 +6056,83 @@
   DimensionDir      emDim = pCamera->m_eDimension;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return;
   int      nStageNo = g_pBase->m_nStageNo;
   if(nStageNo < 0 || nStageNo > 1)
   if (nStageNo < 0 || nStageNo > 1)
      nStageNo = 0;
   int   nGlassSize = (int) (((double) m_pRecipe->m_SideParam[(int) emDim].m_nSidePanelSize_um) / pCamera->m_dScanResolution[nStageNo]);
   int   nGlassSize = (int)(((double)m_pRecipe->m_SideParam[(int)emDim].m_nSidePanelSize_um) / pCamera->m_dScanResolution[nStageNo]);
   pSideData->m_nPreGlassEndLine = pSideData->m_nGlassStartLine + nGlassSize;
   pSideData->m_nPreGlassEndFrame = pSideData->m_nPreGlassEndLine/pCamera->m_FrameSize.cy;
   pSideData->m_nPreGlassEndFrame = pSideData->m_nPreGlassEndLine / pCamera->m_FrameSize.cy;
   g_pStatus->SetGrabFrametoScan(iScan,pSideData->m_nPreGlassEndFrame+5);
   g_pStatus->SetGrabFrametoScan(iScan, pSideData->m_nPreGlassEndFrame + 5);
   g_pLog->DisplayMessage(_T("%s Scan %d : Set Grab EndFrame - GlassEnd %d, Frame %d, GrabBuf %d"),PANEL_SIDE[emDim],iScan,pSideData->m_nPreGlassEndLine,pSideData->m_nPreGlassEndFrame,pSideData->m_nPreGlassEndFrame+5);
   g_pLog->DisplayMessage(_T("%s Scan %d : Set Grab EndFrame - GlassEnd %d, Frame %d, GrabBuf %d"), PANEL_SIDE[emDim], iScan, pSideData->m_nPreGlassEndLine, pSideData->m_nPreGlassEndFrame, pSideData->m_nPreGlassEndFrame + 5);
}
BOOL CInspectCamera::FindGlassStartLine(DimensionDir emDim,stFrameIndex stFrame)
{
BOOL CInspectCamera::FindGlassStartLine(DimensionDir emDim, stFrameIndex stFrame)
{
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,stFrame.nScanIdx);
   if(pCamera == NULL)
   CCameraSettings* pCamera = m_pHardparm->GetCameraSettings(m_iCamera, stFrame.nScanIdx);
   if (pCamera == NULL)
      return FALSE;
   int         nFrame = m_pGrabber->GetFrameBuffer()->GetFrameCount()/2;
   int         nFrame = m_pGrabber->GetFrameBuffer()->GetFrameCount() / 2;
   int         nFrameWidth = pCamera->m_FrameSize.cx;
   int         nFrameHeight = pCamera->m_FrameSize.cy;
   int         nSkipFrame = 0; // EI... // (m_bSimulation == FALSE) ? 1 : 0; //pGlsInfo->m_nFindGlassStartOffset[emDim] / nFrameHeight;
   int         nSetHor = m_pRecipe->m_SideParam[(int) emDim].m_nFindStartEndLine_X_pxl;
   int         nSetHor = m_pRecipe->m_SideParam[(int)emDim].m_nFindStartEndLine_X_pxl;
   if(nSetHor < BOUNDARY_GLASSSTARTWIDTH / 2) nSetHor = BOUNDARY_GLASSSTARTWIDTH / 2;
   if(nSetHor > nFrameWidth-(BOUNDARY_GLASSSTARTWIDTH / 2)) nSetHor = nFrameWidth-(BOUNDARY_GLASSSTARTWIDTH / 2);
   if (nSetHor < BOUNDARY_GLASSSTARTWIDTH / 2) nSetHor = BOUNDARY_GLASSSTARTWIDTH / 2;
   if (nSetHor > nFrameWidth - (BOUNDARY_GLASSSTARTWIDTH / 2)) nSetHor = nFrameWidth - (BOUNDARY_GLASSSTARTWIDTH / 2);
   // pSideData->nGlassEdgeXPos[0] = nSetHor;   
   int         j, k, nGab;
   int         nThreshold = m_pRecipe->m_SideParam[emDim].m_nFindStartEndLine_Threshold * BOUNDARY_GLASSSTARTWIDTH;
   int         *pnSum = new int[nFrameHeight + BOUNDARYHORIZ_LEVELDIST];
   int* pnSum = new int[nFrameHeight + BOUNDARYHORIZ_LEVELDIST];
   LPBYTE      lpHeader;
   int         nCountinueCount = 0;
   int         nRet,nHStart;
   int         nRet, nHStart;
   DWORD      dwT1 = GetTickCount();
   g_pLog->DisplayMessage(_T("%s Find Glass Start Start : Scan %d "),PANEL_SIDE[emDim],stFrame.nScanIdx);
   g_pLog->DisplayMessage(_T("%s Find Glass Start Start : Scan %d "), PANEL_SIDE[emDim], stFrame.nScanIdx);
   for(int iFrame=0;iFrame<nFrame;iFrame++)
   for (int iFrame = 0; iFrame < nFrame; iFrame++)
   {
      while (TRUE)
      {
         nRet = m_pGrabber->IsAcqFrame(iFrame);
         if (nRet < 2)      // 酒流 救嘛躯栏骨肺 措扁.
         if (nRet < 2)      // 아직 안찍혔으므로 대기.
         {
            if (GetTickCount() - dwT1 > TIME_WAIT_GLASS_START)
            {
               g_pLog->DisplayMessage(_T("%s Find Glass Start : no image(Grab Time Out),%d sec"),PANEL_SIDE[emDim],TIME_WAIT_GLASS_START/1000);
               delete [] pnSum;
               g_pLog->DisplayMessage(_T("%s Find Glass Start : no image(Grab Time Out),%d sec"), PANEL_SIDE[emDim], TIME_WAIT_GLASS_START / 1000);
               delete[] pnSum;
               return FALSE;
            }
            Sleep(1);
         }
         }
         else
            break;
      }
      if (nSkipFrame > iFrame)
         continue;
         continue;
      lpHeader = m_pGrabber->GetFrameHeader(stFrame.nScanIdx,iFrame);
      if(lpHeader == NULL)
      lpHeader = m_pGrabber->GetFrameHeader(stFrame.nScanIdx, iFrame);
      if (lpHeader == NULL)
      {
         g_pLog->DisplayMessage(_T("%s Find Glass Start : no image(Image is Null)"),PANEL_SIDE[emDim]);
         delete [] pnSum;
         g_pLog->DisplayMessage(_T("%s Find Glass Start : no image(Image is Null)"), PANEL_SIDE[emDim]);
         delete[] pnSum;
         return FALSE;
      }
@@ -6098,40 +6146,40 @@
      {
         for (k = nHStart; k < nHStart + BOUNDARY_GLASSSTARTWIDTH; k++)
         {
            // Grab牢 版快 滚欺狼 版拌俊辑 1024扼牢阑 逞绢哎 版快 促澜 滚欺甫 啊廉客具 茄促.
            // Grab인 경우 버퍼의 경계에서 1024라인을 넘어갈 경우 다음 버퍼를 가져와야 한다.
            if (j == nFrameHeight && nLine != 0 && bChangeBuffer == FALSE)
            {
            {
               DWORD dwTick = GetTickCount();
               while (TRUE)
               {
                  if(GetTickCount()-dwTick > TIME_WAIT_GLASS_START/2)
                  {
                     g_pLog->DisplayMessage(_T("%s No Image"),PANEL_SIDE[emDim]);
                     delete [] pnSum;
               {
                  if (GetTickCount() - dwTick > TIME_WAIT_GLASS_START / 2)
                  {
                     g_pLog->DisplayMessage(_T("%s No Image"), PANEL_SIDE[emDim]);
                     delete[] pnSum;
                     return FALSE;
                  }
                  if(m_pGrabber->IsAcqFrame(iFrame + 1) > 1)
                  if (m_pGrabber->IsAcqFrame(iFrame + 1) > 1)
                  {
                     lpHeader = m_pGrabber->GetFrameHeader(stFrame.nScanIdx,iFrame + 1);
                     if(lpHeader != NULL)
                     lpHeader = m_pGrabber->GetFrameHeader(stFrame.nScanIdx, iFrame + 1);
                     if (lpHeader != NULL)
                     {
                        bChangeBuffer = TRUE;
                        //g_pLog->DisplayMessage(_T("%s Change Buffer %d, %d, %d"),PANEL_SIDE[pRecipe->GetDimension()], j, i, g_pBase->m_pMemFrameNo[GetCameraID()]);
                        break;
                     }
                  }
               }
                     }
                  }
               }
               nLine = 0;
            }
            pnSum[j] += *(lpHeader + nLine * nFrameWidth + k);
         }
         nLine++;
         nLine++;
         if (j >= BOUNDARYHORIZ_LEVELDIST)
         {
            nGab = abs(pnSum[j - BOUNDARYHORIZ_LEVELDIST] - pnSum[j]);
            nGab = abs(pnSum[j - BOUNDARYHORIZ_LEVELDIST] - pnSum[j]);
            if (nGab > nThreshold)
               nCountinueCount++;
            else
@@ -6139,27 +6187,27 @@
            if (nCountinueCount >= 2)
            {
               g_pLog->DisplayMessage(_T("%s Start Line Frame %d, Line %d, Gab %d, Thres %d"), PANEL_SIDE[emDim],iFrame, j, nGab, nThreshold);
               // Glass狼 矫累瘤痢阑 茫酒辑 备炼眉俊 持绰促.
               g_pLog->DisplayMessage(_T("%s Start Line Frame %d, Line %d, Gab %d, Thres %d"), PANEL_SIDE[emDim], iFrame, j, nGab, nThreshold);
               // Glass의 시작지점을 찾아서 구조체에 넣는다.
               pSideData->m_nGlassStartLine = iFrame * nFrameHeight + j - 2;
               pSideData->m_nGlassStartFrame = pSideData->m_nGlassStartLine/nFrameHeight;
               pSideData->m_nGlassStartFrame = pSideData->m_nGlassStartLine / nFrameHeight;
               pSideData->m_bFindGlassStartLine = TRUE;
               // Log
               g_pLog->DisplayMessage(_T(""));
               g_pLog->DisplayMessage(_T("%s Glass StartLine :: Pixel %ld nFrameNo=%d")
                  , PANEL_SIDE[emDim]
               , pSideData->m_nGlassStartLine
                  , pSideData->m_nGlassStartLine / nFrameHeight);
                  , pSideData->m_nGlassStartLine
                     , pSideData->m_nGlassStartLine / nFrameHeight);
               delete [] pnSum;
               delete[] pnSum;
               // 22.07.24
               // SaveGlassLineImage(stFrame.nScanIdx,pSideData->m_nGlassStartLine,nSetHor,emDim,_T("StartLine"));
               MakeNotchArea(emDim);
               // Make Judge Line
               pSideData->m_nCenterJudgeArea_Start = pSideData->m_nGlassStartLine + m_pRecipe->m_SideParam[(int) emDim].m_nCenterJudgeArea_StartLine_To_Start_pxl;
               pSideData->m_nCenterJudgeArea_End = pSideData->m_nGlassStartLine + m_pRecipe->m_SideParam[(int) emDim].m_nCenterJudgeArea_StartLine_To_End_pxl;
               pSideData->m_nCenterJudgeArea_Start = pSideData->m_nGlassStartLine + m_pRecipe->m_SideParam[(int)emDim].m_nCenterJudgeArea_StartLine_To_Start_pxl;
               pSideData->m_nCenterJudgeArea_End = pSideData->m_nGlassStartLine + m_pRecipe->m_SideParam[(int)emDim].m_nCenterJudgeArea_StartLine_To_End_pxl;
               return TRUE;
            }
@@ -6167,37 +6215,37 @@
      }
   }
   delete [] pnSum;
   delete[] pnSum;
   return FALSE;
}
BOOL CInspectCamera::MakeNotchArea(DimensionDir emDim)
{
   if(m_pGlassData == NULL || m_pRecipe == NULL)
   if (m_pGlassData == NULL || m_pRecipe == NULL)
      return FALSE;
   CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
   if(pSideData == NULL)
   if (pSideData == NULL)
      return FALSE;
   if(pSideData->m_bFindGlassStartLine == FALSE)
   if (pSideData->m_bFindGlassStartLine == FALSE)
      return FALSE;
   int nNotchCount = m_pRecipe->m_SideParam[(int) emDim].m_nNotchCount;
   int nNotchCount = m_pRecipe->m_SideParam[(int)emDim].m_nNotchCount;
   pSideData->m_nNotchCount = nNotchCount;
   g_pLog->DisplayMessage(_T("Make Notch Area - Side[%s] Notch Count[%d]"), g_SideName[(int) emDim], nNotchCount);
   g_pLog->DisplayMessage(_T("Make Notch Area - Side[%s] Notch Count[%d]"), g_SideName[(int)emDim], nNotchCount);
   for(int i=0; i<nNotchCount; i++)
   for (int i = 0; i < nNotchCount; i++)
   {
      if(MAX_SIDE_NOTCH_COUNT <= i)
      if (MAX_SIDE_NOTCH_COUNT <= i)
         break;
      int nStartLine_Offset = pSideData->m_nGlassStartLine - m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_nGlassStartLine_pxl;
      int nStartLine_Offset = pSideData->m_nGlassStartLine - m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[i].m_nGlassStartLine_pxl;
      pSideData->m_rtNotchArea_pxl[i] = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
      pSideData->m_rtNotchArea_pxl[i] = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
      pSideData->m_rtNotchArea_pxl[i].OffsetRect(0, nStartLine_Offset);
   }
@@ -6205,13 +6253,19 @@
   return TRUE;
}
BOOL CInspectCamera::ProcessFrame(int iThread,DimensionDir emDim,stFrameIndex stFrame)
BOOL CInspectCamera::ProcessFrame(int iThread, DimensionDir emDim, stFrameIndex stFrame)
{
   try {
      // 1. Find End Line.. (Corner甫 力寇茄 Side扼牢阑 茫扁 困秦 End Line何磐 茫绰促)
      // 1. Find End Line.. (Corner를 제외한 Side라인을 찾기 위해 End Line부터 찾는다)
      FindEndLine(iThread, emDim, stFrame);
      // 2. Find Side Line.. (秦寸 橇饭烙俊辑 Corner/Notch 甫 力寇茄 Side 扼牢 茫扁)
      bool bIsRipSide = (emDim == DIMENSION_A_RIP || emDim == DIMENSION_B_RIP || emDim == DIMENSION_C_RIP || emDim == DIMENSION_D_RIP);
      if (bIsRipSide) {
         CRIP_THICKNESS_PARM& rip = m_pRecipe->m_SideParam[emDim].m_RipThk;
         return TRUE;
      }
      // 2. Find Side Line.. (해당 프레임에서 Corner/Notch 를 제외한 Side 라인 찾기)
#if USE_AI_DETECT
      FindSideLine(iThread, emDim, stFrame);
#else
@@ -6259,15 +6313,15 @@
int   CInspectCamera::GetDefectCount()
{
   if(m_pDefectControl == NULL)
   if (m_pDefectControl == NULL)
      return 0;
   return m_pDefectControl->GetDefectCount();
}
CDefect *CInspectCamera::GetDefect(int iDefect)
CDefect* CInspectCamera::GetDefect(int iDefect)
{
   if(m_pDefectControl == NULL)
   if (m_pDefectControl == NULL)
      return NULL;
   return m_pDefectControl->GetDefect(iDefect);
@@ -6320,7 +6374,7 @@
   if (m_wsClients != nullptr)
   {
      m_wsClients->set_message_handler([this](const std::string& msg) {
         // JSON 格式
         // JSON 목駕
         if (!msg.empty() && msg.size() > 3) {
            try {
               nlohmann::json json_data = nlohmann::json::parse(msg);
@@ -6328,7 +6382,7 @@
               DimensionDir emDim = (DimensionDir)(json_data.value("nLineType", 0) - 1);
               WSReceiveData wsReceiveData;
               // 解析 JSON 数据并填充 wsReceiveData
               // 썩驕 JSON 鑒앴깻輕념 wsReceiveData
               wsReceiveData.nRecipe = json_data.value("Reciepe", 0);
               wsReceiveData.nLineType = json_data.value("nLineType", 0);
               wsReceiveData.nIndex = json_data.value("nIndex", 0);
@@ -6336,19 +6390,19 @@
               wsReceiveData.nFrameIdx = json_data.value("nFrameIdx", 0);
               wsReceiveData.strSN = json_data.value("SN", "");
               wsReceiveData.dTimeStamp = json_data.value("TimeStamp", 0.0);
               wsReceiveData.nGNum = json_data.value("NGnum", 0);  // NG 数量
               wsReceiveData.nGNum = json_data.value("NGnum", 0);  // NG 鑒좆
               // 格式化并显示基本信息
               // 목駕뺏깻鞫刻샘굶斤口
               CString strText;
               strText.Format(_T("Reciepe: %d, LineType: %d, Index: %d, SN: %s, NGNum: %d, TimeStamp: %f\n"),
                  wsReceiveData.nRecipe, wsReceiveData.nLineType, wsReceiveData.nIndex, wsReceiveData.strSN.c_str(), wsReceiveData.nGNum, wsReceiveData.dTimeStamp);
               if (wsReceiveData.nLineType > 0
                  && wsReceiveData.nLineType < 9
               if (wsReceiveData.nLineType > 0
                  && wsReceiveData.nLineType < 9
                  && wsReceiveData.nGNum != 0
                  && g_pBase->m_strHPanelID.Compare(CString(wsReceiveData.strSN.c_str())) == 0)
               {
                  // 遍历并填充 ngPosArray
                  // 깁저깻輕념 ngPosArray
                  auto ngPosArray = json_data["NGPosArray"];
                  for (auto& ngPos : ngPosArray) {
                     WSReceiveData::NGPosition ngPosition;
@@ -6382,15 +6436,15 @@
               g_pLog->DisplayMessage(strText);
            }
            catch (const nlohmann::json::parse_error& e) {
               // 处理 JSON 解析错误
               // 뇹잿 JSON 썩驕댄轎
               std::cerr << "JSON parse error: " << e.what() << std::endl;
            }
         }
         else {
            // 处理空消息
            // 뇹잿왕句口
            std::cerr << "Empty message" << std::endl;
         }
      });
         });
   }
}
@@ -6427,18 +6481,18 @@
   std::string jsonMetadata = CreateJsonWSSendData(wsData);
   // 预先分配内存,减少动态扩容
   // 渡邱롸토코닸,숑 帽檄윈휭
   std::vector<char> message;
   message.reserve(jsonMetadata.size() + width * height);
   // 插入 JSON 数据和图像数据
   // 꿨흙 JSON 鑒앴뵨暠獗鑒앴
   message.insert(message.end(), jsonMetadata.begin(), jsonMetadata.end());
   message.insert(message.end(), data, data + width * height);
   // 使用 std::move 传递 message,避免拷贝
   // 賈痰 std::move 눈뒵 message,긁출옙굔
   bool isSucceed = m_wsClients->send_binary_to_idle_client_with_retry(std::move(message), 1000, 50);
   if (!isSucceed)
   {
   {
      CDefect_Info defectInfo;
      CRect rtDefectPos_pxl(left, top, left + width, top + height);
      defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
@@ -6562,7 +6616,7 @@
      for (int i = 0; i < rtProcessArea.Height(); i++)
         memcpy(pDefectProcessImage.GetDataAddress(0, i), frameBuffer.GetDataAddress(rtProcessArea.left, i), rtProcessArea.Width());
      // 发送从临时缓冲区中获取的数据
      // 랙箇닖줄珂뻠녑혐櫓삿혤돨鑒앴
      int state = (stFrame.nFrameIdx == 0) ? 1 : (pDefectProcessImage.GetHeight() < IMAGE_HEIGHT ? 2 : 3);
      SendImageDataOverWebSocket(eDim, stFrame, stFrame.nFrameIdx, pDefectProcessImage.GetDataAddress(0, 0), state, nCutLine, vecInspectAreaList[nRegionIdx].top, pDefectProcessImage.GetWidth(), pDefectProcessImage.GetHeight());
@@ -6577,7 +6631,7 @@
#if USE_AI_DETECT
void CInspectCamera::SetUseAIDetect(bool bUseAIDetect)
{
{
   m_bUseAIDetect = bUseAIDetect;
}
@@ -6655,7 +6709,7 @@
         rtProcessArea.bottom += nHeightOff;
      }
      // 保证图像高度为4的倍数
      // 괏聯暠獗멕똑槨4돨굡鑒
      nHeightOff = rtProcessArea.Height() % 4;
      if (nHeightOff != 0)
      {
@@ -6683,7 +6737,7 @@
      myLoc.Lock();
      long long dStartTime = GetCurrentTimestamp();
      // 发送从临时缓冲区中获取的数据
      // 랙箇닖줄珂뻠녑혐櫓삿혤돨鑒앴
      std::vector<AiDetectResult> results;
      if (m_pAiDetectEx->detect(frame, results, m_strChannel)) {
         for (auto& result : results) {