#include "StdAfx.h" #include "InspectCamera.h" #include "GlassRecipe.h" #include "HardwareSettings.h" #include "MulticamControl.h" #include "RadientControl.h" #include "Glass_Data.h" #include "SISBuffer.h" #include "SISEdgeFind.h" #include "../Fitting/CHDataFitting.h" #include "ChamferInspect.h" #if USE_WEBSOCKET #include #endif // USE_WEBSOCKET #define BOUNDARY_GLASSSTARTWIDTH 160 #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; m_pHardparm = NULL; m_pGrabber = NULL; m_pGlassData = NULL; m_pII2S = NULL; m_bExitThread = FALSE; m_hWndViewScan = NULL; m_pDefectControl = new CDefectControl(); m_dPixelSizeX = 7.0; m_dPixelSizeY = 7.0; m_nFrameWidth = IMAGE_WIDTH; m_nFrameHeight = IMAGE_HEIGHT; m_bSimulation = FALSE; m_nChamferOffset_um = 0; #if HALCON_VISION_KEY for (int i = 0; i < 8; i++) { m_fInspectLastTime[i] = MININT; } #endif // HALCON_VISION_KEY #if USE_AI_DETECT g_pLog->DisplayMessage(_T("AI Server start. Cam[%d]"), iCam); int nPort = 8080 + iCam; m_pAiDetectEx = new AiDetectEx("127.0.0.1", nPort); m_bUseAIDetect = m_pAiDetectEx->startServer(); m_strChannel = m_pAiDetectEx->generateChannel(); g_pLog->DisplayMessage(_T("AI Server end. Cam[%d] Port[%d] ret[%d]"), iCam, nPort, m_bUseAIDetect); #endif // USE_AI_DETECT } CInspectCamera::~CInspectCamera(void) { ReleaseThread(); ReleaseFullBuffer(); if(m_pDefectControl != NULL) delete m_pDefectControl; m_pDefectControl = NULL; #if USE_AI_DETECT if (m_bUseAIDetect && m_pAiDetectEx != nullptr) { m_pAiDetectEx->stopServer(); m_pAiDetectEx->releaseChannel(m_strChannel); delete m_pAiDetectEx; } #endif // USE_AI_DETECT } void CInspectCamera::ReleaseThread() { m_bExitThread = TRUE; if(m_pThreadControl != NULL) { m_pThreadControl->ReleaseThreadControl(); Sleep(100); delete m_pThreadControl; m_pThreadControl = NULL; } } int CInspectCamera::InitInspect(int nThread,int maxDefect) { m_pThreadControl->InitThreadControl(nThread,this); m_pDefectControl->InitDefectStorage(maxDefect); return 1; } int CInspectCamera::ReInitThread(int nThread) { m_pThreadControl->ReleaseThreadControl(); Sleep(100); m_pThreadControl->InitThreadControl(nThread, this); return 1; } BOOL CInspectCamera::ScanStart(int iScan) { m_iScan = iScan; m_iSideLine[iScan] = 0; m_bExitThread = FALSE; CCameraSettings* pCamSetting = m_pHardparm->GetCameraSettings(m_iCamera, m_iScan); if(pCamSetting == NULL || m_pGlassData == NULL) { g_pLog->DisplayMessage(_T("HW Setting Error.. or Glass Data Error..")); return FALSE; } // Resolution m_nFrameWidth = pCamSetting->m_FrameSize.cx; m_nFrameHeight = pCamSetting->m_FrameSize.cy; 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); pSideData->m_dPixelSizeX = m_dPixelSizeX; pSideData->m_dPixelSizeY = m_dPixelSizeY; #if HALCON_VISION_KEY CBlSideData *pBlSideData = BlVision_GetVisionRecipe()->getSideData(pCamSetting->m_eDimension); if (NULL != pBlSideData) { pBlSideData->m_mapSideLineInf.clear(); } #endif // HALCON_VISION_KEY ResetFrameFinish(iScan); ScanStartThread(); return TRUE; } BOOL CInspectCamera::ScanStartThread() { if(m_pThreadControl == NULL) return FALSE; int nThread = m_pThreadControl->StartThreadControl(); if(nThread <= 0) { return FALSE; } return TRUE; } BOOL CInspectCamera::GetCheckFrame(stFrameIndex stFrame) { 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) return FALSE; 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) { iScan = m_iScan; stFrameIndex stFrame; stFrame.nScanIdx = m_iScan; if(m_bFindGlassStart[stFrame.nScanIdx] == TRUE) return ERR_FINDGLASSSTART_SUCCESS; // ÀÚµ¿À϶§ ÇÁ·¹ÀÓ ¼ö¸¦ ÃæºÐÈ÷ ÀâÀ¸¸é ¹®Á¦°¡ ¾ÈµÇ´Â°Å °°´Ù¸¸... ÇÁ·¹ÀÓ ¼ö°¡ ºÎÁ·ÇÏ¸é ¿©±â¼­ ¹«ÇÑÀ¸·Î °É¸².. ±×¸®°í ½ÃÀÛ¼± ã¾ÒÀ¸¸é ±×³É ³Ñ¾î°¡¸é µÇÁö ¾Ê³ª? if(m_pGrabber->GetGrabFrameCount() < 1) { Sleep(0); return ERR_FINDGLASSSTART_FAIL; } /* stFrameIndex stFrame; stFrame.nScanIdx = m_iScan; if(m_bFindGlassStart[stFrame.nScanIdx] == TRUE) return ERR_FINDGLASSSTART_SUCCESS; */ if(iThread != 0) return ERR_FINDGLASSSTART_FAIL; DimensionDir emDim = GetDimension(stFrame.nScanIdx); iScan = stFrame.nScanIdx; if(FindGlassStartLine(emDim,stFrame) == TRUE) { g_pLog->DisplayMessage(_T("Find Start Line Success!")); 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) m_MsgJob.nDispLine = pSideData->m_nGlassStartLine; ::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) { if(m_pRecipe == NULL) return FALSE; if(m_pHardparm == NULL) return FALSE; if(m_pGlassData == NULL) return FALSE; if(m_pGrabber == NULL) return FALSE; while(TRUE) { Sleep(1); // Sleep 1·Î °É¾îÁà¾ß ÇÑ´Ù... 0À¸·Î °É¸é °Ë»ç°¡ ¾ÈµÉ‹š°¡ ÀÖÀ½.. ¿Ö? if(GetCheckExit() == TRUE) { g_pLog->DisplayMessage(_T("cam %d, Thread %d Thread Exit"),m_iCamera,iThread); break; } // 1. 0¹ø Thread·Î Start Line ã±â int iRetScan; switch(IsGlassStartLine(iThread,iRetScan)) { case ERR_FINDGLASSSTART_FAIL: continue; break; case ERR_FINDGLASSSTART_FIND_FAIL: m_pGrabber->GrabScanStop(); m_pGrabber->ClearGrabIdx(); m_bExitThread = TRUE; 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); continue; break; } // 2. Start LineÀ» ã¾ÒÀ¸¸é, ÇÑÇÁ·¹ÀÓ¾¿ ²¨³»¼­ °Ë»ç ½ÃÀÛ stFrameIndex stFrame = m_pGrabber->GetGrabFrame(); if(stFrame.nScanIdx < 0 || stFrame.nFrameIdx < 0) continue; DimensionDir emDim = GetDimension(stFrame.nScanIdx); // printf("%s : %d : frame =============\r\n", g_cSideName[(int) emDim], stFrame.nFrameIdx); // g_pLog->DisplayMessage(_T("%s : %d : frame ============="),g_SideName[(int) emDim], stFrame.nFrameIdx); m_pGlassData->GetSideData(emDim)->SetFrameProc(stFrame.nFrameIdx); // 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); continue; } // 4. Process.. ProcessFrame(iThread, emDim, stFrame); // 5. End Check.. SetFrameFinishEndFrame(stFrame.nScanIdx, stFrame.nFrameIdx); SetFrameFinish(stFrame.nScanIdx, stFrame.nFrameIdx); 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; m_MsgJob.nSide = (int)emDim; int nSetEnd = (m_pGlassData->GetSideData(emDim)->m_nGlassEndLine <= 0) ? m_pGlassData->GetSideData(emDim)->m_nPreGlassEndLine : m_pGlassData->GetSideData(emDim)->m_nGlassEndLine; if (m_MsgJob.nDispLine < nSetEnd) { ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)emDim); } } if (bEnd && m_pGlassData->GetSideData(emDim)->m_bFindGlassEndLine) { m_MsgJob.nState = 1; m_MsgJob.nDispLine = stFrame.nFrameIdx * m_nFrameHeight; m_MsgJob.nSide = (int)emDim; int nSetEnd = (m_pGlassData->GetSideData(emDim)->m_nGlassEndLine <= 0) ? m_pGlassData->GetSideData(emDim)->m_nPreGlassEndLine : m_pGlassData->GetSideData(emDim)->m_nGlassEndLine; int nOffset = nSetEnd - m_MsgJob.nDispLine; if (nOffset >= 0 && nOffset < m_nFrameHeight) { ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)emDim); m_MsgJob.nDispLine = nSetEnd - m_nFrameHeight + 100; ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS, (WPARAM)&m_MsgJob, (int)emDim); } } } g_pLog->DisplayMessage(_T("Camera %d-%d Thread End"),m_iCamera,iThread); return TRUE; } void CInspectCamera::FinallyVisionProc(DimensionDir eDim) { /* code */ #if HALCON_VISION_KEY CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); BOOL isFindSuccess = pSideData->m_bBotMark_Find && pSideData->m_bTopMark_Find; if (!isFindSuccess) return; double lastTime = GetTickCount(); int idx = (int)(eDim); double dTime = fabs(lastTime - m_fInspectLastTime[idx]); if (dTime < 3000) return; m_fInspectLastTime[idx] = lastTime; CBlSideData* pBlSideData = BlVision_GetVisionRecipe()->getSideData(eDim); // ->m_bInspection_Complete = TRUE; //Set Info pBlSideData->m_bInspection_Complete = TRUE; pBlSideData->m_dPixelSizeX = pSideData->m_dPixelSizeX; pBlSideData->m_dPixelSizeY = pSideData->m_dPixelSizeY; pBlSideData->m_bTopMark_Find = FALSE; pBlSideData->m_bBotMark_Find = FALSE; pBlSideData->m_mTopMark.x = 0; pBlSideData->m_mTopMark.y = 0; pBlSideData->m_mBotMark.x = 0; pBlSideData->m_mBotMark.y = 0; pBlSideData->m_nStartLine = 0; pBlSideData->m_nEndLine = 0; //Set MarkPos if (pSideData->m_bTopMark_Find) { pBlSideData->m_bTopMark_Find = pSideData->m_bTopMark_Find; pBlSideData->m_mTopMark.x = pSideData->m_ptTopMark_FindResult.x; pBlSideData->m_mTopMark.y = pSideData->m_ptTopMark_FindResult.y; } if (pSideData->m_bBotMark_Find) { pBlSideData->m_bBotMark_Find = pSideData->m_bBotMark_Find; pBlSideData->m_mBotMark.x = pSideData->m_ptBotMark_FindResult.x; 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(); CString test_data_kdist; stFrameIndex stFrame = m_pGrabber->GetGrabFrame(); NgInfo ngArray[NG_INF_TOTAL]; int ngNum = BlVision_GetSoftVisionApp()->Execute((int)(eDim), ngArray); if (ngNum < 1) return; for (int i = 0; i < ngNum; i++) { NgInfo ng = ngArray[i]; //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; defectInfo.m_nScanIdx = stFrame.nScanIdx; defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(eDim)->m_nGlassStartLine; defectInfo.m_nSideIdx = (int)eDim; defectInfo.m_ptDefectPos_pxl.x = ng.xPosPxl; defectInfo.m_ptDefectPos_pxl.y = ng.yPosPxl; defectInfo.m_dGray_Avg = ng.result; 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)); } } #endif // HALCON_VISION_KEY } BOOL CInspectCamera::CheckThreadEnd(int iThread,stFrameIndex stFrame) { int iScan = stFrame.nScanIdx; CSingleLock myLoc(&m_csThreadEnd); myLoc.Lock(); // ÀÌ¹Ì ³¡³­ Thread.. if(m_iThreadEnd[iScan][iThread] == 1) { myLoc.Unlock(); return FALSE; } BOOL bEnd = FALSE; if(CheckProcessEnd(iThread,stFrame) == TRUE) { m_iThreadEnd[iScan][iThread] = 1; bEnd = TRUE; myLoc.Unlock(); } 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) { myLoc.Lock(); SaveFullImageCopy(iScan); myLoc.Unlock(); 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; } */ //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(); return bEnd; } int CInspectCamera::GetThreadEndCount(int iScan) { int nCount = 0; for(int i=0;iGetSideData(emDim); if(pSideData == NULL) return 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); 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 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 dRotateArea_T_Rad = dMarkToArea_T_Rad + dDiff_T_Rad; double dDirection = (dMarkToArea_Y_pxl < 0.0) ? -1.0 : 1.0; 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.InflateRect(rtSetArea.Width()/2, rtSetArea.Height()/2); return TRUE; } BOOL CInspectCamera::CopyRectImg(LPBYTE pOrg,LPBYTE pTgt,CSize szImg,CRect &rectIns) { if(pOrg == NULL || pTgt == NULL) return FALSE; int v; int dv = 0; for(v=rectIns.top;vm_bUse_SaveDebugImage == FALSE) return; // #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 } void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, IplImage* pBuffer, CString strFileName) { if(m_pHardparm == NULL) return; if(m_pHardparm->m_bUse_SaveDebugImage == FALSE) return; // #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); USES_CONVERSION; //cvSaveImage(W2A(str), pBuffer); try { cv::Mat image = cv::cvarrToMat(pBuffer); CT2A asciiStr(str); std::string filePath(asciiStr); cv::imwrite(filePath, image); } catch (...) { g_pLog->DisplayMessage(_T("SaveDebugImage error...")); } // #endif } void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, cv::Mat image, CString strFileName) { if (m_pHardparm == NULL) return; if (m_pHardparm->m_bUse_SaveDebugImage == FALSE) return; // #ifdef _DEBUG 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 { g_pStatus->CheckDirectory(str); USES_CONVERSION; CT2A asciiStr(str); std::string filePath(asciiStr); cv::imwrite(filePath, image); } catch (...) { g_pLog->DisplayMessage(_T("SaveDebugImage error...")); } // #endif } CString CInspectCamera::GetSideName(DimensionDir eDim) { switch(eDim) { case DIMENSION_A: return _T("SideA_UP"); break; case DIMENSION_B: return _T("SideB_UP"); break; case DIMENSION_C: return _T("SideC_UP"); break; case DIMENSION_D: return _T("SideD_UP"); break; case DIMENSION_A_DN: return _T("SideA_DN"); break; case DIMENSION_B_DN: return _T("SideB_DN"); break; case DIMENSION_C_DN: return _T("SideC_DN"); break; case DIMENSION_D_DN: return _T("SideD_DN"); break; } return _T("Unknown"); } void CInspectCamera::SaveFullImageCopy(int iScan) { // 4/17 // ³ëÆ®ºÏ ¸Þ¸ð¸®°¡ µþ·Á¼­ ´Ù¿îµÇ´Âµí.. // return; if(m_pGlassData == NULL) return; 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) return; int nSetEnd = (pSideData->m_nGlassEndLine <= 0) ? pSideData->m_nPreGlassEndLine : pSideData->m_nGlassEndLine; int nOffset = 1000; int nStartLine = pSideData->m_nGlassStartLine - nOffset / 2; int nEndLine = nSetEnd + nOffset / 2; int nFullSize = nEndLine - nStartLine; g_pLog->DisplayMessage(_T("%s Copy Full Image : nStartLine=%d, nEndLine=%d, nFullSize=%d"), PANEL_SIDE[eDim], nStartLine, nEndLine, nFullSize); if(nStartLine < 0) { nStartLine = 0; } if(nFullSize <= 0 || nEndLine < 0) return; //if(nFullSize <= nStartLine) // return; pINSPECTFULLIMAGE_BUFFER pImgBuf = GetFullImgBuffer(iScan); int nFrameWidth,nFrameHeight; GetFrameSize(m_iCamera,iScan,nFrameWidth,nFrameHeight); if(nFrameWidth <= 0 || nFrameHeight <= 0) return; if(nFullSize/nFrameHeight > m_pGrabber->GetFrameBuffer()->GetFrameCount()) nFullSize = (m_pGrabber->GetFrameBuffer()->GetFrameCount()-1)*nFrameHeight; if(nFullSize <= 100) return; pImgBuf->iCamIdx = m_iCamera; pImgBuf->iScanIdx = iScan; 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); 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); return; } 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); } BOOL CInspectCamera::CheckProcessEnd(int iThread, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; if(m_pGrabber == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(GetDimension(stFrame.nScanIdx)); if(pSideData == NULL) return FALSE; if(g_pStatus->GetGrabFrameCount(stFrame.nScanIdx)-1 <= 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) return TRUE; return FALSE; } void CInspectCamera::ScanRegionSet(stFrameIndex stFrame) { g_pLog->DisplayMessage(_T("Scan Region Set")); SetGrabEnd(stFrame.nScanIdx); } BOOL CInspectCamera::CheckStartLineFrame(DimensionDir eDim,int iFrame) { CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; if(pSideData->m_nGlassStartFrame > iFrame) return FALSE; return TRUE; } int CInspectCamera::GetLeftMargin(int iCam,int iScan) { 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) { nFrameWidth = nFrameHeight = 0; 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) { CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; 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); #define BOUNDARY_GLASSSTARTWIDTH_ENDLINE 140 #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 nCountinueCount = 0; int nHStart, nGab; 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); 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); CSISBuffer pVertBuffer(lpHeader,nFrameWidth,nCalculateFrame*nFrameHeight); if(lpHeader == NULL || pVertBuffer.IsValidBuffer() == FALSE) return FALSE; int* pnSum = new 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); CBufferAttach saveImage(str); saveImage.AttachToFile(pVertBuffer); #endif for (int j = pVertBuffer.GetHeight()-1 ; j >= 0; j--) { for (int k = nHStart; k < nHStart+BOUNDARY_GLASSSTARTWIDTH_ENDLINE; k++) { pnSum[j] += *pVertBuffer.GetDataAddress(k,j); } if (j <= (pVertBuffer.GetHeight()-1-BOUNDARYHORIZ_LEVELDIST_ENDLINE)) { if(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] == 0 || pnSum[j] == 0) // Àß ¸ø µÈ À̹ÌÁö.. continue; nGab = abs(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] - pnSum[j]); if (nGab > nThreshold) nCountinueCount++; else nCountinueCount = 0; if (nCountinueCount >= 2) { // 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); /* // Log g_pLog->DisplayMessage(_T( "")); g_pLog->DisplayMessage(_T( "%s Glass EndLine :: %d,%d (nFrameNo=%d)") , PANEL_SIDE[emDim] , pEdgeInfo->nGlassEdgeXPos[1] , pEdgeInfo->nGlassEndLine , pEdgeInfo->nGlassEndLine / nFrameHeight); */ delete [] pnSum; // SaveGlassLineImage(stFrame.nScanIdx,pSideData->m_nGlassEndLine,pSideData->m_nGlassEdgeXPos[1],emDim,_T("EndLine")); return TRUE; } } } pSideData->m_nGlassEndLine = pSideData->m_nPreGlassEndLine; pSideData->m_nGlassEndFrame = pSideData->m_nPreGlassEndFrame; pSideData->m_bFindGlassEndLine = TRUE; delete [] pnSum; 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) { 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 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; int nFrameYPos = stFrame.nFrameIdx * 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_Frame = nTopCorner_Bottom / nFrameHeight; int nBotCorner_Top_Frame = nBotCorner_Top / nFrameHeight; int nYPos_pxl = 0; 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) { rtROI.bottom = (nBotCorner_Top_Frame < rtROI.bottom) ? nBotCorner_Top : rtROI.bottom; // Frame gap.. if(rtROI.Height() < m_nFrameHeight/3) { int nExtraArea = m_nFrameHeight - rtROI.Height(); int nOffSetY = nFrameYPos - nExtraArea; rtROI.top = rtROI.bottom - m_nFrameHeight; nYPos_pxl = nOffSetY; rtROI.OffsetRect(0, -nOffSetY); } else { nYPos_pxl = rtROI.top; rtROI.OffsetRect(0, -nFrameYPos); } } else { nYPos_pxl = rtROI.top; rtROI.OffsetRect(0, -nFrameYPos); } if(nSearchHeight < rtROI.Height()) { 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; // 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) return nFindLine; 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; pSideData->m_nSideLineFrame[stFrame.nFrameIdx] = nFindLine; pSideData->m_nSideLinePosY[stFrame.nFrameIdx] = rtROI.CenterPoint().y + nFrameYPos; // 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); } return TRUE; } BOOL CInspectCamera::FindSideLine_ExceptNotch(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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 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; 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_Frame = nTopCorner_Bottom / nFrameHeight; int nBotCorner_Top_Frame = nBotCorner_Top / nFrameHeight; // 1. Make Side Area (Except Top/Bottom Corner) CRect rtAllSide_pxl; rtAllSide_pxl.left = 0; rtAllSide_pxl.top = nTopCorner_Bottom; 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); rtFrame_pxl.OffsetRect(0, nFrameYPos); // 3. Make Find Side Line Area. CRect rtROI; rtROI.IntersectRect(rtFrame_pxl, rtAllSide_pxl); if(rtROI.IsRectEmpty() || rtROI.IsRectNull()) return FALSE; // 4. Exception Notch Area... std::vector vectorInspectAreaList_New; vectorInspectAreaList_New.push_back(rtROI); std::vector vectorInspectAreaList_Old; vectorInspectAreaList_Old.clear(); std::vector vecExceptionNotchAreaList; int nNotchCount = pSideData->m_nNotchCount; std::vector vecInspectArea; for(int i=0; im_rtNotchArea_pxl[i]; 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()); vectorInspectAreaList_New.clear(); for(int j=0; jm_SideParam[(int) emDim].m_nChamferLineThreshold; #if HALCON_VISION_KEY CBlSideData *pBlSideData = BlVision_GetVisionRecipe()->getSideData(emDim); #endif int stepSide = m_pGrabber->GetFrameBuffer()->GetFrameHeight(); for(int i=0; iGetFrameHeaderLine(stFrame.nScanIdx, vecInspectArea[i].top),nFrameWidth,vecInspectArea[i].Height()); if(frameBuffer.IsValidBuffer() == FALSE) continue; #ifdef _DEBUG CString str; str.Format(_T("D:\\Inspection\\Image\\Side\\%s_Frame_%d_Region_%d_FindSideImage.bmp"), PANEL_SIDE[emDim], stFrame.nFrameIdx, i); CBufferAttach attach(str); attach.AttachToFile(frameBuffer); #endif // _DEBUG CRect rtFindROI = vecInspectArea[i]; rtFindROI.OffsetRect(0, -rtFindROI.top); if(nSearchHeight < rtFindROI.Height()) { CPoint ptCenter = rtFindROI.CenterPoint(); 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) { #if HALCON_VISION_KEY if (NULL != pBlSideData){ SideLineInf inf; inf.left = 0; inf.top = vecInspectArea[i].top; inf.width = nFrameWidth; inf.height = vecInspectArea[i].Height(); inf.nThres = nThres; inf.nSideLine = nSideLine; 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, // inf.left, inf.top, inf.width, inf.height, // __LINE__); } #endif // HALCON_VISION_KEY nFindSideLineSum += nSideLine; nFindSideLineCount++; CChamferInspect chamferIns; double dLine = -1; COwnerBuffer ImgInsBin; chamferIns.Binarization(frameBuffer,ImgInsBin,nChamferLineThres); chamferIns.FindRightLine_Bin(ImgInsBin,nSideLine,dLine); if(dLine != -1) { nFindSideChamferLineSum += (int)dLine; nFindSideChamferLineCount++; } } } if(nFindSideLineCount > 0) { int nAvgSideLine = (int) (nFindSideLineSum / nFindSideLineCount); // Average.. m_iSideLine[stFrame.nScanIdx] = 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 } return TRUE; } BOOL CInspectCamera::FindTopCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame) { CSingleLock localLock(&m_csTopCorner); localLock.Lock(); if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim]; if(pSideData == NULL || pSideParam == NULL) return FALSE; if(pSideData->m_bFindGlassStartLine == FALSE) return FALSE; if(pSideData->m_bTopCorner_Find == TRUE) return TRUE; /* BOOL bTopCornerUse = (BOOL) (m_pRecipe->m_SideParam[emDim].m_nTopCornerShape == 0) ? FALSE : TRUE; // Not Use Corner Inspection if(bTopCornerUse == FALSE) 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; int nTopCornerFrameIndex = (nFindStartLine + nCornerSizeY_Pixel) / nFrameHeight; if(stFrame.nFrameIdx < nTopCornerFrameIndex+1) return FALSE; int nSideLine = pSideData->m_nSideLineFrame[nTopCornerFrameIndex+1]; if(nSideLine == -1) return FALSE; 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; pSideData->m_rtTopCornerArea = rtTopCornerArea; int nTopCornerType = m_pRecipe->m_SideParam[emDim].m_nTopCornerShape; pSideData->m_nTopCornerShape = m_pRecipe->m_SideParam[emDim].m_nTopCornerShape;; if(pSideParam->m_bTopCornerFindDefect == FALSE) return FALSE; 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; } BOOL CInspectCamera::FindTopCorner_None(int iThread, DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == FALSE) return FALSE; CRect rtTopCornerArea = pSideData->m_rtTopCornerArea; rtTopCornerArea.right = rtTopCornerArea.left + ALIGN_4BYTE(rtTopCornerArea.Width()); if(rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull()) return FALSE; int nFrameWidth = m_nFrameWidth; // 1. Inspect ROI COwnerBuffer pBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); m_pGrabber->GetSmallImage(stFrame.nScanIdx, pBuffer.GetDataAddress(), rtTopCornerArea.left, rtTopCornerArea.top, rtTopCornerArea.Width(), rtTopCornerArea.Height()); int nInsStart = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_StartOffset; int nInsRange = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Range; int nThreshold_Low = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Thres_Min; int nThreshold_High = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Thres_Max; int nMinSize = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Min_Size; int nDilation = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation; // For Draw.. pSideData->m_rtTopCornerArea_Offset = rtTopCornerArea; pSideData->m_rtTopCornerArea_Offset.top = rtTopCornerArea.top + nInsStart; pSideData->m_rtTopCornerArea_Offset.left = rtTopCornerArea.left + nInsStart; pSideData->m_rtTopCornerArea_Ins = pSideData->m_rtTopCornerArea_Offset; pSideData->m_rtTopCornerArea_Ins.top = pSideData->m_rtTopCornerArea_Ins.top + nInsRange; pSideData->m_rtTopCornerArea_Ins.left = pSideData->m_rtTopCornerArea_Ins.left + nInsRange; // 2. Make Masking.. COwnerBuffer pMaskBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); pMaskBuffer.MemSet(0); for (int i = nInsStart; i < rtTopCornerArea.Height(); i++) { int nImageX = nInsStart; int nImageY = i; if (nImageX < 0 ||rtTopCornerArea.Width() <= nImageX || nImageY < 0 || rtTopCornerArea.Height() <= nImageY) continue; int nRange = (rtTopCornerArea.Width() <= nImageX + nInsRange) ? (rtTopCornerArea.Width() - 1 - nImageX) : nInsRange; memset(pMaskBuffer.GetDataAddress(nImageX, nImageY), 255, nRange); } // 3. Processing COwnerBuffer pBinBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); pBinBuffer.MemSet(0); for (int i = 0; i < rtTopCornerArea.Height(); i++) { for (int j = 0; j < rtTopCornerArea.Width(); j++) { if (pMaskBuffer.GetPixel(j, i) != 255) continue; BYTE pixelValue = pBuffer.GetPixel(j, i); if (pixelValue < nThreshold_Low) pBinBuffer.SetPixel(j, i, 255); if (nThreshold_High < pixelValue) pBinBuffer.SetPixel(j, i, 255); } } #ifdef _DEBUG // Debug Image Save SaveDebugImage(emDim, stFrame, &pBuffer, _T("Corner\\TopCornerArea_Ins")); SaveDebugImage(emDim, stFrame, &pMaskBuffer, _T("Corner\\TopCornerArea_Mask")); SaveDebugImage(emDim, stFrame, &pBinBuffer, _T("Corner\\TopCornerArea_Bin")); #endif // _DEBUG // 3. Blob std::vector vecDefectCandidateList; DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pBuffer, &pBinBuffer, rtTopCornerArea, nMinSize, 0, 0, nDilation, 0, 0, DefectLoc_Top_Corner, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Side(emDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::FindTopCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == FALSE) return FALSE; CRect rtTopCornerArea = pSideData->m_rtTopCornerArea; rtTopCornerArea.right = rtTopCornerArea.left + ALIGN_4BYTE(rtTopCornerArea.Width()); if(rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull()) return FALSE; int nFrameWidth = m_nFrameWidth; // 1. Inspect ROI COwnerBuffer pBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); m_pGrabber->GetSmallImage(stFrame.nScanIdx, pBuffer.GetDataAddress(), rtTopCornerArea.left, rtTopCornerArea.top, rtTopCornerArea.Width(), rtTopCornerArea.Height()); int nInsStart = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_StartOffset; int nInsRange = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Range; int nThreshold_Low = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Thres_Min; int nThreshold_High = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Thres_Max; int nMinSize = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Min_Size; int nDilation = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation; // For Draw.. pSideData->m_rtTopCornerArea_Offset = rtTopCornerArea; pSideData->m_rtTopCornerArea_Offset.top = rtTopCornerArea.top + nInsStart; pSideData->m_rtTopCornerArea_Offset.bottom = rtTopCornerArea.bottom + nInsStart; pSideData->m_rtTopCornerArea_Ins = pSideData->m_rtTopCornerArea_Offset; pSideData->m_rtTopCornerArea_Ins.top = pSideData->m_rtTopCornerArea_Ins.top + nInsRange; pSideData->m_rtTopCornerArea_Ins.bottom = pSideData->m_rtTopCornerArea_Ins.bottom + nInsRange; double dScaleY = (double)rtTopCornerArea.Height() / (double)rtTopCornerArea.Width(); // 2. Make Masking.. COwnerBuffer pMaskBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); pMaskBuffer.MemSet(0); for (int i = 0; i < rtTopCornerArea.Width(); i++) { int nX = rtTopCornerArea.Width() - 1 - i; int nY = (int) (((double)i * dScaleY) + nInsStart); 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) continue; for(int j=0; j vecDefectCandidateList; DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pBuffer, &pBinBuffer, rtTopCornerArea, nMinSize, 0, 0, nDilation, 0, 0, DefectLoc_Top_Corner, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Side(emDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::FindTopCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == FALSE) return FALSE; CRect rtTopCornerArea = pSideData->m_rtTopCornerArea; rtTopCornerArea.right = rtTopCornerArea.left + ALIGN_4BYTE(rtTopCornerArea.Width()); if(rtTopCornerArea.IsRectEmpty() || rtTopCornerArea.IsRectNull()) return FALSE; int nFrameWidth = m_nFrameWidth; // 1. Inspect ROI COwnerBuffer pBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); m_pGrabber->GetSmallImage(stFrame.nScanIdx, pBuffer.GetDataAddress(), rtTopCornerArea.left, rtTopCornerArea.top, rtTopCornerArea.Width(), rtTopCornerArea.Height()); int nInsStart = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_StartOffset; int nInsRange = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Range; cv::Mat pMaskImage = cv::Mat::zeros(rtTopCornerArea.Height(), rtTopCornerArea.Width(), CV_8UC1); int nMaskingRadiusWidth = pMaskImage.cols - nInsStart; int nMaskingRadiusHeight = pMaskImage.rows - nInsStart; nMaskingRadiusWidth = (nMaskingRadiusWidth < 0) ? 0 : nMaskingRadiusWidth; nMaskingRadiusHeight = (nMaskingRadiusHeight < 0) ? 0 : nMaskingRadiusHeight; int nInspectRadiusWidth = nMaskingRadiusWidth - nInsRange; int nInspectRadiusHeight = nMaskingRadiusHeight - nInsRange; nInspectRadiusWidth = (nInspectRadiusWidth < 0) ? 0 : nInspectRadiusWidth; nInspectRadiusHeight = (nInspectRadiusHeight < 0) ? 0 : nInspectRadiusHeight; cv::ellipse(pMaskImage, cv::Point(pMaskImage.cols, pMaskImage.rows), cv::Size(nMaskingRadiusWidth, nMaskingRadiusHeight), 0.0, 180.0, 360.0, CV_RGB(255, 255, 255), cv::FILLED); cv::ellipse(pMaskImage, cv::Point(pMaskImage.cols, pMaskImage.rows), cv::Size(nInspectRadiusWidth, nInspectRadiusHeight), 0.0, 180.0, 360.0, CV_RGB(128, 128, 128), cv::FILLED); // 2. Processing COwnerBuffer pBinBuffer(rtTopCornerArea.Width(), rtTopCornerArea.Height()); pBinBuffer.MemSet(0); int nThreshold_Low = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Thres_Min; int nThreshold_High = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Thres_Max; int nMinSize = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Min_Size; int nDilation = m_pRecipe->m_SideParam[emDim].m_nTopCornerIns_Defect_Size_Dilation; // For Draw.. pSideData->m_rtTopCornerArea_Offset = rtTopCornerArea; pSideData->m_rtTopCornerArea_Offset.top = rtTopCornerArea.top + nInsStart; pSideData->m_rtTopCornerArea_Offset.left = rtTopCornerArea.left + nInsStart; pSideData->m_rtTopCornerArea_Ins = pSideData->m_rtTopCornerArea_Offset; pSideData->m_rtTopCornerArea_Ins.top = pSideData->m_rtTopCornerArea_Ins.top + nInsRange; pSideData->m_rtTopCornerArea_Ins.left = pSideData->m_rtTopCornerArea_Ins.left + nInsRange; for (int i = 0; i < pBuffer.GetHeight(); i++) { for (int j = 0; j < pBuffer.GetWidth(); j++) { if (pMaskImage.data[i * pMaskImage.step1() + j] != 255) continue; BYTE pixelValue = pBuffer.GetPixel(j, i); if (pixelValue < nThreshold_Low) pBinBuffer.SetPixel(j, i, 255); if (nThreshold_High < pixelValue) pBinBuffer.SetPixel(j, i, 255); } } /* #ifdef _DEBUG // Debug Image Save SaveDebugImage(emDim, stFrame, &pBuffer, _T("Corner\\TopCornerArea_Ins")); SaveDebugImage(emDim, stFrame, &pBinBuffer, _T("Corner\\TopCornerArea_Bin")); #endif // _DEBUG */ // 3. Blob std::vector vecDefectCandidateList; DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pBuffer, &pBinBuffer, rtTopCornerArea, nMinSize, 0, 0, nDilation, 0, 0, DefectLoc_Top_Corner, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Side(emDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::FindTopAlignMark(int iThread,DimensionDir eDim, stFrameIndex stFrame) { CSingleLock localLock(&m_csThreadTopAlignMark); localLock.Lock(); if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassStartLine == FALSE) return FALSE; if(pSideData->m_bTopMark_Find == TRUE) return TRUE; if(pSideData->m_bTopCorner_Find == FALSE) return FALSE; BOOL bTopAlignMark = (BOOL) (m_pRecipe->m_SideParam[eDim].m_bTopMark_Use == 1) ? TRUE : FALSE; if(bTopAlignMark == FALSE) return FindTopAlignMark_Virtual(iThread, eDim, stFrame); else { if(FindTopAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) return FindTopAlignMark_Virtual(iThread, eDim, stFrame); else return TRUE; } } BOOL CInspectCamera::FindTopAlignMark_Virtual(int iThread,DimensionDir eDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassStartLine == FALSE) return FALSE; 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) 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; CRect rtSearchArea = CRect(nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel, nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel); rtSearchArea.InflateRect(50, 50); pSideData->m_ptTopMark_FindResult = CPoint(nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel); pSideData->m_rtTopMark_SearchArea = rtSearchArea; pSideData->m_bTopMark_Find = TRUE; return TRUE; } BOOL CInspectCamera::FindTopAlignMark_TempleteMatching(int iThread,DimensionDir eDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassStartLine == FALSE) return FALSE; 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) return FALSE; int nSideLine = pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1]; if(nSideLine <= 0) { CRect rectSide = CRect(0,nTopAlignMarkY_Pixel,nFrameWidth-1,nTopAlignMarkY_Pixel); rectSide.InflateRect(0,30); CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rectSide.top),nFrameWidth,rectSide.Height()); if(frameBuffer.IsValidBuffer() == FALSE) return FALSE; rectSide.OffsetRect(0, -rectSide.top); 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); } 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 dTarget_Rate = m_pRecipe->m_SideParam[(int) eDim].m_dTopMarkTemplateMatchingRate / 100.0; CvPoint ptMax_Point; double dMat_Max_Rate; double dMat_Min_Rate; try { for (int i = 0; i < MAX_MARKER_COUNT; i++) { USES_CONVERSION; char str_filename[256]; // Make Mark Image Path sprintf_s(str_filename, "%s\\%s\\Side_%d_TopAlign_%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) continue; CRect rtSearchArea = CRect(nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel, nTopAlignMarkX_Pixel, nTopAlignMarkY_Pixel); rtSearchArea.InflateRect(pTemplateImage->width * 2, pTemplateImage->height * 2); CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtSearchArea.top), nFrameWidth, rtSearchArea.Height()); if (!frameBuffer.IsValidBuffer()) continue; pSideData->m_rtTopMark_SearchArea = rtSearchArea; IplImage* scr = cvCreateImage(cvSize(rtSearchArea.Width(), rtSearchArea.Height()), 8, 1); 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); 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; int nTemplateW = pTemplateImage->width; int nTemplateH = pTemplateImage->height; cvReleaseImage(&ResultImage); cvReleaseImage(&pTemplateImage); cvReleaseImage(&scr); if (dMat_Max_Rate > dTarget_Rate) { pSideData->m_bTopMark_Find = TRUE; pSideData->m_rtTopMark_SearchArea = rtSearchArea; pSideData->m_ptTopMark_FindResult = CPoint(ptMax_Point.x, ptMax_Point.y); pSideData->m_ptTopMark_FindResult.Offset(rtSearchArea.left, rtSearchArea.top); pSideData->m_rtTopMark_FindResult = CRect(pSideData->m_ptTopMark_FindResult, pSideData->m_ptTopMark_FindResult); pSideData->m_rtTopMark_FindResult.InflateRect(nTemplateW / 2, nTemplateH / 2); return TRUE; } } } catch (...) { g_pLog->DisplayMessage(_T("FindTopAlignMark_TempleteMatching error...")); } // 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; m_pDefectControl->ExtractDefect_Mark(eDim, m_iCamera, stFrame.nScanIdx, defectInfo); return FALSE; } BOOL CInspectCamera::FindBotCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame) { CSingleLock localLock(&m_csBotCorner); localLock.Lock(); if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim]; if(pSideData == NULL || pSideParam == NULL) return FALSE; if (pSideData->m_bFindGlassStartLine == FALSE || pSideData->m_bFindGlassEndLine == FALSE) return FALSE; if(pSideData->m_bBotCorner_Find == TRUE) return TRUE; /* BOOL bBotCornerUse = (BOOL) (m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape == 0) ? FALSE : TRUE; if(bBotCornerUse == FALSE) 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; int nBottomCornerFrameIndex = (nFindBottomLine - nCornerSizeY_Pixel) / nFrameHeight; if((int) stFrame.nFrameIdx < nBottomCornerFrameIndex) return FALSE; // À½.. ÄÚ³Ê Side ¶óÀÎÀÌ ÀÌÀü ÇÁ·¹ÀÓ¿¡ ÀÖÀ¸¸é ¾î¼Áö.. ÇѸ鿡 Thread °¡ ¿©·¯°³ µ¹¸é?... À§ ÇÁ·¹ÀÓÀÇ Thread °¡ ¾ÆÁ÷ Side ¶óÀÎÀ» ¸øÃ£¾ÒÀ¸¸é.. °í¹Î Á» ÇØº¸ÀÚ.. // »çÀ̵庰 Thread´Â Çϳª¸¸ µ¹°í °Ë»ç Thread¸¦ ¿©·¯°³ µ¹¸®´Â ±¸Á¶·Î ¹Ù²ã¾ß°Ú´Ù int nSideLine = pSideData->m_nSideLineFrame[nBottomCornerFrameIndex]; nSideLine = (nSideLine == -1) ? pSideData->m_nSideLineFrame[nBottomCornerFrameIndex] : nSideLine; if(nSideLine == -1) return FALSE; 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); pSideData->m_bBotCorner_Find = TRUE; pSideData->m_rtBotCornerArea = rtBottomCornerArea; int nBotCornerType = m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape; pSideData->m_nBotCornerShape = m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape; int nBottomCornerType = m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape; if(pSideParam->m_bBottomCornerFindDefect == FALSE) return FALSE; 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) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == FALSE) return FALSE; CRect rtBotCornerArea = pSideData->m_rtBotCornerArea; rtBotCornerArea.right = rtBotCornerArea.left + ALIGN_4BYTE(rtBotCornerArea.Width()); if(rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull()) return FALSE; int nFrameWidth = m_nFrameWidth; // 1. Inspect ROI COwnerBuffer pBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); m_pGrabber->GetSmallImage(stFrame.nScanIdx, pBuffer.GetDataAddress(), rtBotCornerArea.left, rtBotCornerArea.top, rtBotCornerArea.Width(), rtBotCornerArea.Height()); int nInsStart = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_StartOffset; int nInsRange = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Range; int nThreshold_Low = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Thres_Min; int nThreshold_High = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Thres_Max; int nMinSize = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Min_Size; int nDilation = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Defect_Size_Dilation; // For Draw.. pSideData->m_rtBotCornerArea_Offset = rtBotCornerArea; pSideData->m_rtBotCornerArea_Offset.bottom = rtBotCornerArea.bottom - nInsStart; pSideData->m_rtBotCornerArea_Offset.left = rtBotCornerArea.left + nInsStart; pSideData->m_rtBotCornerArea_Ins = pSideData->m_rtBotCornerArea_Offset; pSideData->m_rtBotCornerArea_Ins.bottom = pSideData->m_rtBotCornerArea_Offset.bottom - nInsRange; pSideData->m_rtBotCornerArea_Ins.left = pSideData->m_rtBotCornerArea_Offset.left + nInsRange; // 2. Make Masking.. COwnerBuffer pMaskBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); pMaskBuffer.MemSet(0); for (int i = nInsStart; i < rtBotCornerArea.Height(); i++) { int nImageX = nInsStart; int nImageY = rtBotCornerArea.Height() - 1 - i; if (nImageX < 0 ||rtBotCornerArea.Width() <= nImageX || nImageY < 0 || rtBotCornerArea.Height() <= nImageY) continue; int nRange = (rtBotCornerArea.Width() <= nImageX + nInsRange) ? (rtBotCornerArea.Width() - 1 - nImageX) : nInsRange; memset(pMaskBuffer.GetDataAddress(nImageX, nImageY), 255, nRange); } // 3. Processing COwnerBuffer pBinBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); pBinBuffer.MemSet(0); for (int i = 0; i < rtBotCornerArea.Height(); i++) { for (int j = 0; j < rtBotCornerArea.Width(); j++) { if (pMaskBuffer.GetPixel(j, i) != 255) continue; BYTE pixelValue = pBuffer.GetPixel(j, i); if (pixelValue < nThreshold_Low) pBinBuffer.SetPixel(j, i, 255); if (nThreshold_High < pixelValue) pBinBuffer.SetPixel(j, i, 255); } } /* #ifdef _DEBUG // Debug Image Save SaveDebugImage(emDim, stFrame, &pBuffer, _T("Corner\\BotCornerArea_Ins")); SaveDebugImage(emDim, stFrame, &pBinBuffer, _T("Corner\\BotCornerArea_Bin")); #endif // _DEBUG */ // 3. Blob std::vector vecDefectCandidateList; DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pBuffer, &pBinBuffer, rtBotCornerArea, nMinSize, 0, 0, nDilation, 0, 0, DefectLoc_Bot_Corner, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Side(emDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::FindBotCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == FALSE) return FALSE; CRect rtBotCornerArea = pSideData->m_rtBotCornerArea; rtBotCornerArea.right = rtBotCornerArea.left + ALIGN_4BYTE(rtBotCornerArea.Width()); if(rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull()) return FALSE; int nFrameWidth = m_nFrameWidth; // 1. Inspect ROI COwnerBuffer pBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); m_pGrabber->GetSmallImage(stFrame.nScanIdx, pBuffer.GetDataAddress(), rtBotCornerArea.left, rtBotCornerArea.top, rtBotCornerArea.Width(), rtBotCornerArea.Height()); int nInsStart = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_StartOffset; int nInsRange = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Range; int nThreshold_Low = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Thres_Min; int nThreshold_High = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Thres_Max; int nMinSize = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Min_Size; int nDilation = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Defect_Size_Dilation; // For Draw.. pSideData->m_rtBotCornerArea_Offset = rtBotCornerArea; pSideData->m_rtBotCornerArea_Offset.bottom = rtBotCornerArea.bottom - nInsStart; pSideData->m_rtBotCornerArea_Offset.top = rtBotCornerArea.top - nInsStart; pSideData->m_rtBotCornerArea_Ins = pSideData->m_rtBotCornerArea_Offset; 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(); // 2. Make Masking.. COwnerBuffer pMaskBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); pMaskBuffer.MemSet(0); for (int i = 0; i < pMaskBuffer.GetWidth(); i++) { int nX = i; 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) continue; for(int j=0; j vecDefectCandidateList; DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pBuffer, &pBinBuffer, rtBotCornerArea, nMinSize, 0, 0, nDilation, 0, 0, DefectLoc_Bot_Corner, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Side(emDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::FindBotCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == FALSE) return FALSE; CRect rtBotCornerArea = pSideData->m_rtBotCornerArea; rtBotCornerArea.right = rtBotCornerArea.left + ALIGN_4BYTE(rtBotCornerArea.Width()); if(rtBotCornerArea.IsRectEmpty() || rtBotCornerArea.IsRectNull()) return FALSE; int nFrameWidth = m_nFrameWidth; // 1. Inspect ROI COwnerBuffer pBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); m_pGrabber->GetSmallImage(stFrame.nScanIdx, pBuffer.GetDataAddress(), rtBotCornerArea.left, rtBotCornerArea.top, rtBotCornerArea.Width(), rtBotCornerArea.Height()); int nInsStart = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_StartOffset; int nInsRange = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Range; cv::Mat pMaskImage = cv::Mat::zeros(rtBotCornerArea.Height(), rtBotCornerArea.Width(), CV_8UC1); int nMaskingRadiusWidth = pMaskImage.cols - nInsStart; int nMaskingRadiusHeight = pMaskImage.rows - nInsStart; nMaskingRadiusWidth = (nMaskingRadiusWidth < 0) ? 0 : nMaskingRadiusWidth; nMaskingRadiusHeight = (nMaskingRadiusHeight < 0) ? 0 : nMaskingRadiusHeight; int nInspectRadiusWidth = nMaskingRadiusWidth - nInsRange; int nInspectRadiusHeight = nMaskingRadiusHeight - nInsRange; nInspectRadiusWidth = (nInspectRadiusWidth < 0) ? 0 : nInspectRadiusWidth; nInspectRadiusHeight = (nInspectRadiusHeight < 0) ? 0 : nInspectRadiusHeight; cv::ellipse(pMaskImage, cv::Point(pMaskImage.cols, 0), cv::Size(nMaskingRadiusWidth, nMaskingRadiusHeight), 0.0, 90.0, 180.0, CV_RGB(255, 255, 255), cv::FILLED); cv::ellipse(pMaskImage, cv::Point(pMaskImage.cols, 0), cv::Size(nInspectRadiusWidth, nInspectRadiusHeight), 0.0, 90.0, 180.0, CV_RGB(128, 128, 128), cv::FILLED); // 2. Processing COwnerBuffer pBinBuffer(rtBotCornerArea.Width(), rtBotCornerArea.Height()); pBinBuffer.MemSet(0); int nThreshold_Low = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Thres_Min; int nThreshold_High = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Thres_Max; int nMinSize = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Min_Size; int nDilation = m_pRecipe->m_SideParam[emDim].m_nBottomCornerIns_Defect_Size_Dilation; // For Draw.. pSideData->m_rtBotCornerArea_Offset = rtBotCornerArea; pSideData->m_rtBotCornerArea_Offset.bottom = rtBotCornerArea.bottom - nInsStart; pSideData->m_rtBotCornerArea_Offset.left = rtBotCornerArea.left + nInsStart; pSideData->m_rtBotCornerArea_Ins = pSideData->m_rtBotCornerArea_Offset; pSideData->m_rtBotCornerArea_Ins.bottom = pSideData->m_rtBotCornerArea_Offset.bottom - nInsRange; pSideData->m_rtBotCornerArea_Ins.left = pSideData->m_rtBotCornerArea_Offset.left + nInsRange; for (int i = 0; i < pBuffer.GetHeight(); i++) { for (int j = 0; j < pBuffer.GetWidth(); j++) { if (pMaskImage.data[i * pMaskImage.step1() + j] != 255) continue; BYTE pixelValue = pBuffer.GetPixel(j, i); if (pixelValue < nThreshold_Low) pBinBuffer.SetPixel(j, i, 255); if (nThreshold_High < pixelValue) pBinBuffer.SetPixel(j, i, 255); } } /* #ifdef _DEBUG // Debug Image Save SaveDebugImage(emDim, stFrame, &pBuffer, _T("Corner\\BotCornerArea_Ins")); SaveDebugImage(emDim, stFrame, &pBinBuffer, _T("Corner\\BotCornerArea_Bin")); #endif // _DEBUG */ // 3. Blob std::vector vecDefectCandidateList; DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pBuffer, &pBinBuffer, rtBotCornerArea, nMinSize, 0, 0, nDilation, 0, 0, DefectLoc_Bot_Corner, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Side(emDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::FindBotAlignMark(int iThread,DimensionDir eDim, stFrameIndex stFrame) { CSingleLock localLock(&m_csThreadBotAlignMark); localLock.Lock(); if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; //if(pSideData->m_bBotCorner_Find == FALSE) // return FALSE; if(pSideData->m_bBotMark_Find == TRUE) return TRUE; BOOL bBotAlignMark = (BOOL) (m_pRecipe->m_SideParam[eDim].m_bBottomMark_Use == 1) ? TRUE : FALSE; if(bBotAlignMark == FALSE) return FindBotAlignMark_Virtual(iThread, eDim, stFrame); else { if(FindBotAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) return FindBotAlignMark_Virtual(iThread, eDim, stFrame); else return TRUE; } } BOOL CInspectCamera::FindBotAlignMark_Virtual(int iThread,DimensionDir eDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; //if(pSideData->m_bBotCorner_Find == FALSE) // return FALSE; if(pSideData->m_bBotMark_Find == TRUE) return TRUE; // 1. Make ROI 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 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) 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; CRect rtSearchArea = CRect(nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel, nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel); rtSearchArea.InflateRect(50, 50); pSideData->m_ptBotMark_FindResult = CPoint(nBottomAlignMarkX_Pixel, nBottomAlignMarkY_Pixel); pSideData->m_rtBotMark_SearchArea = rtSearchArea; pSideData->m_bBotMark_Find = TRUE; return TRUE; } BOOL CInspectCamera::FindBotAlignMark_TempleteMatching(int iThread,DimensionDir eDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bBotMark_Find == TRUE) return TRUE; //if(pSideData->m_bBotCorner_Find == FALSE) // return FALSE; // 1. Make ROI 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 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) return FALSE; int nSideLine = pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex]; if(nSideLine <= 0) { CRect rectSide = CRect(0,nBottomAlignMarkY_Pixel,nFrameWidth-1,nBottomAlignMarkY_Pixel); rectSide.InflateRect(0,30); CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rectSide.top),nFrameWidth,rectSide.Height()); if(frameBuffer.IsValidBuffer() == FALSE) return FALSE; rectSide.OffsetRect(0, -rectSide.top); 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); } 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 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 ; iGetRecipeName()), (int) eDim, i); IplImage* pTemplateImage = cvLoadImage(str_filename, CV_LOAD_IMAGE_GRAYSCALE); 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()); if(!frameBuffer.IsValidBuffer()) continue; pSideData->m_rtBotMark_SearchArea = rtSearchArea; IplImage* scr = cvCreateImage(cvSize(rtSearchArea.Width(),rtSearchArea.Height()),8,1); for(int i=0; iimageData[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); 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; int nTemplateW = pTemplateImage->width; int nTemplateH = pTemplateImage->height; cvReleaseImage(&ResultImage); cvReleaseImage(&pTemplateImage); cvReleaseImage(&scr); 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); 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; m_pDefectControl->ExtractDefect_Mark(eDim, m_iCamera, stFrame.nScanIdx, defectInfo); return FALSE; } 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) return FALSE; // Inspect Area. m_pGlassData->GetSideData(eDim)->m_rtInspectArea[stFrame.nFrameIdx] = rtInspectArea; std::vector vecDefectCandidateList; for(int i=0; iExtractDefect_Side(eDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); return TRUE; } BOOL CInspectCamera::InspectDefect_Side(int iThread,DimensionDir eDim, stFrameIndex stFrame) { std::vector vecInspectAreaList; // For Notch Region Divide.. int nCutLine = 0; 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; nRegionIdxGetSideData(eDim)->m_rtInspectArea[stFrame.nFrameIdx] = vecInspectAreaList[nRegionIdx]; m_pGlassData->GetSideData(eDim)->m_rtSideInspectArea[stFrame.nFrameIdx][nRegionIdx] = vecInspectAreaList[nRegionIdx]; std::vector vecDefectCandidateList; for(int i=0; iExtractDefect_Side(eDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList); } return TRUE; } 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) return FALSE; 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 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 ³ª´²Áø °æ¿ì ¹®Á¦°¡ µÇ´Ï, Áߺ¹ °Ë»çÇÏÀÚ.. int nMaxInspectRange = 0; for(int i=0; im_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 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; nCutLine = rtFrame.CenterPoint().x; // 3. Return Inspect Area.. rtInspectArea.IntersectRect(rtFrame, rtGlassSideROI); if(rtInspectArea.IsRectEmpty() || rtInspectArea.IsRectNull()) return FALSE; rtInspectArea.right = rtInspectArea.left + align_4byte(rtInspectArea.Width()); return TRUE; } BOOL CInspectCamera::MakeInspectRegion(int iThread,DimensionDir eDim,int iScan,int iFrame, std::vector & vecInspectArea, int& nCutLine) { CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); if(pSideData == NULL) return FALSE; 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 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 ³ª´²Áø °æ¿ì ¹®Á¦°¡ µÇ´Ï, Áߺ¹ °Ë»çÇÏÀÚ.. int nMaxInspectRange = 0; for(int i=0; im_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 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; nCutLine = rtFrame.CenterPoint().x; // 3. Return Inspect Area.. CRect rtInspectArea; rtInspectArea.IntersectRect(rtFrame, rtGlassSideROI); if(rtInspectArea.IsRectEmpty() || rtInspectArea.IsRectNull()) return FALSE; // 4. Exception Notch Area... std::vector vectorInspectAreaList_New; vectorInspectAreaList_New.push_back(rtInspectArea); std::vector vectorInspectAreaList_Old; vectorInspectAreaList_Old.clear(); std::vector vecExceptionNotchAreaList; int nNotchCount = m_pRecipe->m_SideParam[(int) eDim].m_nNotchCount; for(int i=0; im_SideParam[(int) eDim].m_NotchPrm[i].m_nGlassStartLine_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()); vectorInspectAreaList_New.clear(); for(int j=0; j* pDefectList) { if (rtInspectArea.IsRectEmpty() == TRUE || m_pGlassData == NULL) return FALSE; int nSideLine = m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[iFrame]; if (nSideLine < 0) return FALSE; DefectLocation defectLoc = DefectLoc_None; switch(emInsType) { case eSideInsType_Chip: defectLoc = DefectLoc_Chip; break; case eSideInsType_Crack: defectLoc = DefectLoc_Crack; break; case eSideInsType_Burr: defectLoc = DefectLoc_Burr; nCutLine = nSideLine; break; case eSideInsType_Chamfer: defectLoc = DefectLoc_Chamfer; break; case eSideInsType_In_Chip: defectLoc = DefectLoc_In_Chip; break; case eSideInsType_In_Crack: defectLoc = DefectLoc_In_Crack; break; case eSideInsType_In_Burr: defectLoc = DefectLoc_In_Burr; nCutLine = nSideLine; break; case eSideInsType_In_Chamfer: defectLoc = DefectLoc_In_Chamfer; break; default: return 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; 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; 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) { int nTemp = rtProcessArea.right; rtProcessArea.right = rtProcessArea.left; rtProcessArea.left = nTemp; nStartNearFilterRange = abs(nStartNearFilterRange) * (-1); } if (rtProcessArea.IsRectEmpty() || rtProcessArea.IsRectNull()) return FALSE; CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(iScan, rtInspectArea.top), m_nFrameWidth, m_nFrameHeight); if(frameBuffer.IsValidBuffer() == FALSE) return FALSE; // Set Insert Area.. For UI.. 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; // 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()); // 2. Inspect Algorithm COwnerBuffer pBinImage; if (nMethod == 0) Binarization_Threshold_Suppress(&pDefectProcessImage, &pBinImage, nThreshold_Low, nThreshold_High); else if (nMethod == 1) Binarization_Threshold_Pitch_Y(&pDefectProcessImage, &pBinImage, nPitch, nPitch_Threshold); else if (nMethod == 2) Binarization_Threshold_Pitch_Y_Suppress(&pDefectProcessImage, &pBinImage, nPitch, nPitch_Threshold, nThreshold_Low, nThreshold_High); // 3. Find Defect.. 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); 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); SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), &pBinImage, str); return TRUE; } BOOL CInspectCamera::Binarization_Threshold_Suppress(COwnerBuffer* pImageData, COwnerBuffer* pBinImage, int nThresholdLow, int nThresholdHigh) { if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->GetWidth() == 0 || pImageData->GetHeight() == 0) return FALSE; pBinImage->SetSize(pImageData->GetWidth(), pImageData->GetHeight()); pBinImage->MemSet(0); BYTE* pSrcAddress = NULL; BYTE* pBinAddress = NULL; __m128i ThresLow = _mm_set1_epi8(UCHAR(nThresholdLow)); __m128i ThresHigh = _mm_set1_epi8(UCHAR(nThresholdHigh)); __m128i imageSource; const __m128i K_INV_ZERO = _mm_set1_epi8((char)0xFF);//_mm_set1_epi8(-1); __m128i compareLow; __m128i compareHigh; __m128i compareResult; for (int i = 0; i < pImageData->GetHeight(); i++) { int nMul = 0; for (int j = 0; j < pImageData->GetWidth(); j += 16) { pSrcAddress = pImageData->GetDataAddress(j, i); //data[(i * pImageData->step1()) + j]; imageSource = _mm_loadu_si128((__m128i*) (pSrcAddress)); compareLow = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_min_epu8(imageSource, ThresLow), ThresLow), K_INV_ZERO); // Greater Than compareHigh = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(imageSource, ThresHigh), ThresHigh), K_INV_ZERO); // Less Than compareResult = _mm_or_si128(compareLow, compareHigh); int nProcCount = (pImageData->GetWidth() - (16 * nMul)); int nRange = (16 <= nProcCount) ? 16 : nProcCount; if (nRange != 16) { for (int k = 0; k < nRange; k++) { if (compareResult.m128i_u8[k] != 0) { pBinImage->SetPixel(j+k, i, 255); //[i * pBinImage->step1() + j + k] = (char)255; } } } else { pBinAddress = pBinImage->GetDataAddress(j, i); // [(i * pBinImage->step1()) + j]; _mm_storeu_si128((__m128i*) pBinAddress, compareResult); } nMul++; } } return TRUE; } BOOL CInspectCamera::Binarization_Threshold_Pitch_X(COwnerBuffer* pImageData, COwnerBuffer* pBinImage, int nPitch, int nThreshold) { if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->GetWidth() == 0 || pImageData->GetHeight() == 0) return FALSE; pBinImage->SetSize(pImageData->GetWidth(), pImageData->GetHeight()); pBinImage->MemSet(0); BYTE* pSrcAddress = NULL; BYTE* pBinAddress = NULL; __m128i imageSource; __m128i imageSource_Up; __m128i imageSource_Down; const __m128i K_INV_ZERO = _mm_set1_epi8((char)0xFF);//_mm_set1_epi8(-1); __m128i compare_Up; __m128i compare_Down; __m128i compareResult; __m128i Threshold = _mm_set1_epi8(UCHAR(nThreshold)); for (int i = 0; i < pImageData->GetHeight(); i++)//tbb::parallel_for(0, rtChippingArea.Height(), [&](int i) { int nMul = 0; for (int j = 0; j < pImageData->GetWidth(); j += 16) { pSrcAddress = pImageData->GetDataAddress(j, i); imageSource = _mm_loadu_si128((__m128i*) (pSrcAddress)); // Left if (j < nPitch) { pSrcAddress = pImageData->GetDataAddress((j + (nPitch * 2)), i); // [((i + (nPitch * 2)) * pImageData->step1()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j - nPitch, i); // [((i - nPitch) * pImageData->step1()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } // Right if (pImageData->GetWidth() - nPitch <= j) { pSrcAddress = pImageData->GetDataAddress(j - (nPitch * 2), i); //[((i - (nPitch * 2)) * pImageData->step1()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j + nPitch, i); // [((i + nPitch) * pImageData->step1()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } compare_Up = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Up)); compare_Down = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Down)); // Less Than // compareResult = _mm_min_epu8(compare_Up, compare_Down); compareResult = _mm_max_epu8(compare_Up, compare_Down); compareResult = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(compareResult, Threshold), Threshold), K_INV_ZERO); // Less Than int nProcCount = (pImageData->GetWidth() - (16 * nMul)); int nRange = (16 <= nProcCount) ? 16 : nProcCount; if (nRange != 16) { for (int k = 0; k < nRange; k++) { if (compareResult.m128i_u8[k] != 0) { pBinImage->SetPixel(j+k, i, 255); // [i * pBinImage->step1() + j + k] = (char)255; } } } else { pBinAddress = pBinImage->GetDataAddress(j, i); // [(i * pBinImage->step1()) + j]; _mm_storeu_si128((__m128i*) pBinAddress, compareResult); } nMul++; } } return TRUE; } BOOL CInspectCamera::Binarization_Threshold_Pitch_Y(COwnerBuffer* pImageData, COwnerBuffer* pBinImage, int nPitch, int nThreshold) { if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->GetWidth() == 0 || pImageData->GetHeight() == 0) return FALSE; pBinImage->SetSize(pImageData->GetWidth(), pImageData->GetHeight()); pBinImage->MemSet(0); BYTE* pSrcAddress = NULL; BYTE* pBinAddress = NULL; __m128i imageSource; __m128i imageSource_Up; __m128i imageSource_Down; const __m128i K_INV_ZERO = _mm_set1_epi8((char)0xFF);//_mm_set1_epi8(-1); __m128i compare_Up; __m128i compare_Down; __m128i compareResult; __m128i Threshold = _mm_set1_epi8(UCHAR(nThreshold)); for (int i = 0; i < pImageData->GetHeight(); i++)//tbb::parallel_for(0, rtChippingArea.Height(), [&](int i) { int nMul = 0; for (int j = 0; j < pImageData->GetWidth(); j += 16) { pSrcAddress = pImageData->GetDataAddress(j, i); imageSource = _mm_loadu_si128((__m128i*) (pSrcAddress)); // UP if (i < nPitch) { pSrcAddress = pImageData->GetDataAddress(j, (i + (nPitch * 2))); // [((i + (nPitch * 2)) * pImageData->step1()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j, (i - nPitch)); // [((i - nPitch) * pImageData->step1()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } // Down if (pImageData->GetHeight() - nPitch <= i) { pSrcAddress = pImageData->GetDataAddress(j, (i - (nPitch * 2))); //[((i - (nPitch * 2)) * pImageData->step1()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j, (i + nPitch)); // [((i + nPitch) * pImageData->step1()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } compare_Up = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Up)); compare_Down = _mm_abs_epi8(_mm_sub_epi8(imageSource, imageSource_Down)); // Less Than // compareResult = _mm_min_epu8(compare_Up, compare_Down); compareResult = _mm_max_epu8(compare_Up, compare_Down); compareResult = _mm_andnot_si128(_mm_cmpeq_epi8(_mm_max_epu8(compareResult, Threshold), Threshold), K_INV_ZERO); // Less Than int nProcCount = (pImageData->GetWidth() - (16 * nMul)); int nRange = (16 <= nProcCount) ? 16 : nProcCount; if (nRange != 16) { for (int k = 0; k < nRange; k++) { if (compareResult.m128i_u8[k] != 0) { pBinImage->SetPixel(j+k, i, 255); // [i * pBinImage->step1() + j + k] = (char)255; } } } else { pBinAddress = pBinImage->GetDataAddress(j, i); // [(i * pBinImage->step1()) + j]; _mm_storeu_si128((__m128i*) pBinAddress, compareResult); } nMul++; } } return TRUE; } BOOL CInspectCamera::Binarization_Threshold_Pitch_X_Suppress(COwnerBuffer* pImageData, COwnerBuffer* pBinImage, int nPitch, int nThresholdPitch, int nThresholdLow, int nThresholdHigh) { if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->GetWidth() == 0 || pImageData->GetHeight() == 0) return FALSE; pBinImage->SetSize(pImageData->GetWidth(), pImageData->GetHeight()); pBinImage->MemSet(0); BYTE* pSrcAddress = NULL; BYTE* pBinAddress = NULL; // Image __m128i imageSource; __m128i imageSource_Up; __m128i imageSource_Down; // Threshold __m128i thresLow = _mm_set1_epi8(UCHAR(nThresholdLow)); __m128i thresHigh = _mm_set1_epi8(UCHAR(nThresholdHigh)); __m128i thresPitch = _mm_set1_epi8(UCHAR(nThresholdPitch)); // Result __m128i compare_Thres_Low; __m128i compare_Thres_High; __m128i compare_Thres_Result; __m128i compare_Pitch_Up; __m128i compare_Pitch_Down; __m128i compare_Pitch_Result; __m128i compare_Result; const __m128i K_INV_ZERO = _mm_set1_epi8((char)0xFF);//_mm_set1_epi8(-1); for (int i = 0; i < pImageData->GetHeight(); i++)//tbb::parallel_for(0, rtChippingArea.Height(), [&](int i) { int nMul = 0; for (int j = 0; j < pImageData->GetWidth(); j += 16) { // 1. Image Load.. pSrcAddress = pImageData->GetDataAddress(j, i); //[(i * pImageData->GetWidth()) + j]; imageSource = _mm_loadu_si128((__m128i*) (pSrcAddress)); // Left if (i < nPitch) { pSrcAddress = pImageData->GetDataAddress(j + (nPitch * 2), i); //[((i + (nPitch * 2)) * pImageData->GetWidth()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j - nPitch, i); //[((i - nPitch) * pImageData->GetWidth()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } // Right if (pImageData->GetHeight() - nPitch <= i) { pSrcAddress = pImageData->GetDataAddress(j - (nPitch * 2), i); //[((i - (nPitch * 2)) * pImageData->GetWidth()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j + nPitch, i); //[((i + nPitch) * pImageData->GetWidth()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } // 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); // 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_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 // 4. And compare_Result = _mm_and_si128(compare_Thres_Result, compare_Pitch_Result); int nProcCount = (pImageData->GetWidth() - (16 * nMul)); int nRange = (16 <= nProcCount) ? 16 : nProcCount; if (nRange != 16) { for (int k = 0; k < nRange; k++) { if (compare_Result.m128i_u8[k] != 0) { pBinImage->SetPixel(j+k, i, 255); //[i * pBinImage->GetWidth() + j + k] = (char)255; } } } else { pBinAddress = pBinImage->GetDataAddress(j, i); // [(i * pBinImage->GetWidth()) + j]; _mm_storeu_si128((__m128i*) pBinAddress, compare_Result); } nMul++; } } return TRUE; } BOOL CInspectCamera::Binarization_Threshold_Pitch_Y_Suppress(COwnerBuffer* pImageData, COwnerBuffer* pBinImage, int nPitch, int nThresholdPitch, int nThresholdLow, int nThresholdHigh) { if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->GetWidth() == 0 || pImageData->GetHeight() == 0) return FALSE; pBinImage->SetSize(pImageData->GetWidth(), pImageData->GetHeight()); pBinImage->MemSet(0); BYTE* pSrcAddress = NULL; BYTE* pBinAddress = NULL; // Image __m128i imageSource; __m128i imageSource_Up; __m128i imageSource_Down; // Threshold __m128i thresLow = _mm_set1_epi8(UCHAR(nThresholdLow)); __m128i thresHigh = _mm_set1_epi8(UCHAR(nThresholdHigh)); __m128i thresPitch = _mm_set1_epi8(UCHAR(nThresholdPitch)); // Result __m128i compare_Thres_Low; __m128i compare_Thres_High; __m128i compare_Thres_Result; __m128i compare_Pitch_Up; __m128i compare_Pitch_Down; __m128i compare_Pitch_Result; __m128i compare_Result; const __m128i K_INV_ZERO = _mm_set1_epi8((char)0xFF);//_mm_set1_epi8(-1); for (int i = 0; i < pImageData->GetHeight(); i++)//tbb::parallel_for(0, rtChippingArea.Height(), [&](int i) { int nMul = 0; for (int j = 0; j < pImageData->GetWidth(); j += 16) { // 1. Image Load.. pSrcAddress = pImageData->GetDataAddress(j, i); //[(i * pImageData->GetWidth()) + j]; imageSource = _mm_loadu_si128((__m128i*) (pSrcAddress)); // UP if (i < nPitch) { pSrcAddress = pImageData->GetDataAddress(j, (i + (nPitch * 2))); //[((i + (nPitch * 2)) * pImageData->GetWidth()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j, (i - nPitch)); //[((i - nPitch) * pImageData->GetWidth()) + j]; imageSource_Up = _mm_loadu_si128((__m128i*) (pSrcAddress)); } // Down if (pImageData->GetHeight() - nPitch <= i) { pSrcAddress = pImageData->GetDataAddress(j, (i - (nPitch * 2))); //[((i - (nPitch * 2)) * pImageData->GetWidth()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } else { pSrcAddress = pImageData->GetDataAddress(j, (i + nPitch)); //[((i + nPitch) * pImageData->GetWidth()) + j]; imageSource_Down = _mm_loadu_si128((__m128i*) (pSrcAddress)); } // 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); // 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_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 // 4. And compare_Result = _mm_and_si128(compare_Thres_Result, compare_Pitch_Result); int nProcCount = (pImageData->GetWidth() - (16 * nMul)); int nRange = (16 <= nProcCount) ? 16 : nProcCount; if (nRange != 16) { for (int k = 0; k < nRange; k++) { if (compare_Result.m128i_u8[k] != 0) { pBinImage->SetPixel(j+k, i, 255); //[i * pBinImage->GetWidth() + j + k] = (char)255; } } } else { pBinAddress = pBinImage->GetDataAddress(j, i); // [(i * pBinImage->GetWidth()) + j]; _mm_storeu_si128((__m128i*) pBinAddress, compare_Result); } nMul++; } } return TRUE; } 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* pDefectList) { if(pDefectList == NULL) return FALSE; if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->GetWidth() == 0 || pImageData->GetHeight() == 0) return FALSE; if (pImageData->GetWidth() != pBinImage->GetWidth() || pImageData->GetHeight() != pBinImage->GetHeight()) return FALSE; cv::Mat pBinMat = cv::Mat::zeros(pBinImage->GetHeight(), pBinImage->GetWidth(), CV_8UC1); // OwnerBuffer ³»ºÎ·Î 16¹è¼ö ¸Þ¸ð¸® °®°í À־ Çѹø¿¡ Ä«ÇÇ ¾ÈµÅ.. for(int i=0; iGetHeight(); i++) CopyMemory(&pBinMat.data[pBinMat.step1() * i], pBinImage->GetDataAddress(0, i), pBinImage->GetWidth()); /* if(0 < nDilation) { IplImage* pImageHeader = cvCreateImageHeader(cvSize(pBinImage->GetWidth(), pBinImage->GetHeight()), 8, 1); cvSetData(pImageHeader,pBinMat.data,pBinMat.step1()); cvDilate(pImageHeader, pImageHeader, 0, nDilation); cvReleaseImageHeader(&pImageHeader); } */ // 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]); SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), pImageData, strFileName); 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) // ¹è°æ Çϳª¸¸ ÀÖÀ½.. return TRUE; std::vector vecMin, vecMax, vecSum, vecPixelCount; vecMin.resize(numOfLables, INT_MAX); vecMax.resize(numOfLables, INT_MIN); vecSum.resize(numOfLables, 0); vecPixelCount.resize(numOfLables, 0); BOOL backgroundLables[MAX_DEFECT_COUNT_SIDE]; ZeroMemory(backgroundLables, sizeof(backgroundLables)); for (int i = 0; i < matLabel.rows; i++) { int* label = matLabel.ptr(i); for (int j = 0; j < matLabel.cols; j++) { int nLabelIdx = (int)label[j]; int nPxlValue = (int)pImageData->GetPixel(j, i); if(nLabelIdx == 0) continue; if(pBinImage->GetPixel(j, i) == 0 && nLabelIdx < MAX_DEFECT_COUNT_SIDE) backgroundLables[nLabelIdx] = TRUE; if (nPxlValue < vecMin[nLabelIdx]) vecMin[nLabelIdx] = nPxlValue; if (nPxlValue > vecMax[nLabelIdx]) vecMax[nLabelIdx] = nPxlValue; vecSum[nLabelIdx] = vecSum[nLabelIdx] + nPxlValue; vecPixelCount[nLabelIdx] = vecPixelCount[nLabelIdx] + 1; } } int nDefectIdx = (int) pDefectList->size(); for (int nIdx = 0; nIdx < numOfLables; nIdx++) { BOOL bFiltering = FALSE; BOOL bStartNear = FALSE; int area = matStats.at(nIdx, cv::CC_STAT_AREA); int left = matStats.at(nIdx, cv::CC_STAT_LEFT); int top = matStats.at(nIdx, cv::CC_STAT_TOP); int width = matStats.at(nIdx, cv::CC_STAT_WIDTH); int height = matStats.at(nIdx, cv::CC_STAT_HEIGHT); int x = (int)matCentrois.at(nIdx, 0); //Áß½ÉÁÂÇ¥ int y = (int)matCentrois.at(nIdx, 1); if(MAX_DEFECT_COUNT_SIDE < nIdx) continue; if(backgroundLables[nIdx] == TRUE) continue; if(nIdx == 0) continue; if ((0 < nStartNearFilterRange && left <= nStartNearFilterRange) || (nStartNearFilterRange < 0 && pBinImage->GetWidth() + nStartNearFilterRange <= left + width)) bStartNear = TRUE; if (vecPixelCount[nIdx] < nMinSize) bFiltering = TRUE; if(width < nMinSizeX) bFiltering = TRUE; if(height < nMinSizeY) bFiltering = TRUE; if (bStartNearFilter == TRUE && bStartNear == FALSE) bFiltering = TRUE; if (bFiltering == FALSE) { CRect rtDefectArea; rtDefectArea.left = left; rtDefectArea.top = top; rtDefectArea.right = left + width; rtDefectArea.bottom = top + height; rtDefectArea.OffsetRect(rtROIPos.left, rtROIPos.top); 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_ptDefectPos_pxl = rtDefectArea.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectArea; 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; pDefectList->push_back(defectInfo); } } 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* pDefectList) { if(pDefectList == NULL) return FALSE; if (pImageData == NULL || pBinImage == NULL) return FALSE; if (pImageData->width == 0 || pImageData->height == 0) return FALSE; if (pImageData->width != pBinImage->width || pImageData->height != pBinImage->height) return FALSE; cv::Mat pBinMat = cv::Mat::zeros(pBinImage->height, pBinImage->width, CV_8UC1); // OwnerBuffer ³»ºÎ·Î 16¹è¼ö ¸Þ¸ð¸® °®°í À־ Çѹø¿¡ Ä«ÇÇ ¾ÈµÅ.. for(int i=0; iheight; i++) CopyMemory(&pBinMat.data[pBinMat.step1() * i], &pBinImage->imageData[pBinImage->widthStep*i], pBinImage->width); /* if(0 < nDilation) { IplImage* pImageHeader = cvCreateImageHeader(cvSize(pBinImage->width, pBinImage->height), 8, 1); cvSetData(pImageHeader,pBinMat.data,pBinMat.step1()); cvDilate(pImageHeader, pImageHeader, 0, nDilation); cvReleaseImageHeader(&pImageHeader); } */ // 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]); SaveDebugImage(eDim, stFrameIndex(iScan, iFrame), pImageData, strFileName); 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) // ¹è°æ Çϳª¸¸ ÀÖÀ½.. return TRUE; std::vector vecMin, vecMax, vecSum, vecPixelCount; vecMin.resize(numOfLables, INT_MAX); vecMax.resize(numOfLables, INT_MIN); vecSum.resize(numOfLables, 0); vecPixelCount.resize(numOfLables, 0); BOOL backgroundLables[MAX_DEFECT_COUNT_SIDE]; ZeroMemory(backgroundLables, sizeof(backgroundLables)); for (int i = 0; i < matLabel.rows; i++) { int* label = matLabel.ptr(i); for (int j = 0; j < matLabel.cols; j++) { int nLabelIdx = (int)label[j]; int nPxlValue = (int)pImageData->imageData[i*pImageData->widthStep+j]; if(nLabelIdx == 0) continue; if(pBinImage->imageData[i*pImageData->widthStep+j] == 0 && nLabelIdx < MAX_DEFECT_COUNT_SIDE) backgroundLables[nLabelIdx] = TRUE; if (nPxlValue < vecMin[nLabelIdx]) vecMin[nLabelIdx] = nPxlValue; if (nPxlValue > vecMax[nLabelIdx]) vecMax[nLabelIdx] = nPxlValue; vecSum[nLabelIdx] = vecSum[nLabelIdx] + nPxlValue; vecPixelCount[nLabelIdx] = vecPixelCount[nLabelIdx] + 1; } } int nDefectIdx = (int) pDefectList->size(); for (int nIdx = 0; nIdx < numOfLables; nIdx++) { BOOL bFiltering = FALSE; BOOL bStartNear = FALSE; int area = matStats.at(nIdx, cv::CC_STAT_AREA); int left = matStats.at(nIdx, cv::CC_STAT_LEFT); int top = matStats.at(nIdx, cv::CC_STAT_TOP); int width = matStats.at(nIdx, cv::CC_STAT_WIDTH); int height = matStats.at(nIdx, cv::CC_STAT_HEIGHT); int x = (int)matCentrois.at(nIdx, 0); //Áß½ÉÁÂÇ¥ int y = (int)matCentrois.at(nIdx, 1); if(MAX_DEFECT_COUNT_SIDE < nIdx) continue; if(backgroundLables[nIdx] == TRUE) continue; if(nIdx == 0) continue; if ((0 < nStartNearFilterRange && left <= nStartNearFilterRange) || (nStartNearFilterRange < 0 && pBinImage->width + nStartNearFilterRange <= left + width)) bStartNear = TRUE; if (vecPixelCount[nIdx] < nMinSize) bFiltering = TRUE; if (nMinSizeX != 0) { if(width < nMinSizeX) bFiltering = TRUE; } if (nMinSizeY!= 0) { if (height < nMinSizeY) bFiltering = TRUE; } if (bStartNearFilter == TRUE && bStartNear == FALSE) bFiltering = TRUE; if (bFiltering == FALSE) { CRect rtDefectArea; rtDefectArea.left = left; rtDefectArea.top = top; rtDefectArea.right = left + width; rtDefectArea.bottom = top + height; rtDefectArea.OffsetRect(rtROIPos.left, rtROIPos.top); 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_ptDefectPos_pxl = rtDefectArea.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectArea; 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; pDefectList->push_back(defectInfo); } } return TRUE; } BOOL CInspectCamera::Notch_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame) { //CTime tCurrentTime = CTime::GetCurrentTime(); //CTime tLimitTime = CTime(2023,3,31,11,59,59); //CTimeSpan tSpanTime = tLimitTime - tCurrentTime; //if(tSpanTime.GetTotalSeconds() < 0) // return FALSE; if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassEndLine == FALSE) // Notch ProcessingÀº End Line ãÀº FrameÀÌ.. return FALSE; if(m_pRecipe == NULL) return FALSE; if(m_pDefectControl == NULL) return FALSE; if(pSideData->m_bNotchInspection_Complete == TRUE) return TRUE; 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); pSideData->m_nNotchCount = nNotchCount; for(int i=0; im_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; CRect rtRotateArea; 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); pSideData->m_rtNotchArea_pxl[i] = rtRotateArea; IplImage* pOriginImage; IplImage* pEdgeImage; IplImage* pBinImage; 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); g_pLog->DisplayMessage(_T("1. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i); // 1. Image PreProcess.. Notch_Process_PreProcess(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea); // Notch_Process_PreProcess_2(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea); g_pLog->DisplayMessage(_T("2. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i); // 2. Notch Dimension/Chamfer Find.. Notch_Process_Measure(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea); g_pLog->DisplayMessage(_T("3. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i); // 3. Notch Dimension/Chamfer Calculate Result.. bool bResult = Notch_Process_Calculate(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea); g_pLog->DisplayMessage(_T("4. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i); // 4. Notch Dimension/Chamfer Judge Notch_Process_Judge(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea); if (!bResult) { CDefect_Info defectInfo; defectInfo.m_iFrameIdx = stFrame.nFrameIdx; defectInfo.m_nCamID = m_iCamera; defectInfo.m_nScanIdx = stFrame.nScanIdx; defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(emDim)->m_nGlassStartLine; defectInfo.m_nSideIdx = (int)emDim; defectInfo.m_ptDefectPos_pxl = rtRotateArea.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtRotateArea; defectInfo.m_DefectLoc = DefectLoc_Notch_Crack; m_pDefectControl->ExtractDefect(emDim, m_iCamera, stFrame.nScanIdx, defectInfo); cvReleaseImageHeader(&pOriginImage); cvReleaseImage(&pEdgeImage); cvReleaseImage(&pBinImage); return FALSE; } g_pLog->DisplayMessage(_T("5. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i); // 5. Notch Defect Inspect (Chip/Crack) Notch_Process_Defect(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea); g_pLog->DisplayMessage(_T("6. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i); // 6. Notch Find Circle Notch_Process_FindCircle(emDim, stFrame, 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); } pSideData->m_bNotchInspection_Complete = TRUE; g_pLog->DisplayMessage(_T("7. Notch_Process End %s : %d"),g_SideName[(int) emDim], stFrame.nFrameIdx); return TRUE; } void CInspectCamera::Notch_Process_PreProcess(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI) { if(m_pRecipe == NULL) return; if(nNotchIdx < 0 || MAX_SIDE_NOTCH_COUNT <= nNotchIdx) return; CString strTemp; int sigma1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter; int sigma2 = 7; if(sigma1 % 2 == 0) sigma1 = sigma1 - 1; if(1 < sigma1) cvSmooth(scr,img_Bin,CV_MEDIAN,sigma1); // double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold * 10; // double th2 = 40.0; // int sigma=5; // // cvCanny(img_Bin,img_Edge,th1,th2,sigma); double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold; cvThreshold(scr,img_Edge,th1,255,CV_THRESH_BINARY_INV); strTemp.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Edge, strTemp); th1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold; cvThreshold(scr,img_Bin,th1,255,CV_THRESH_BINARY); strTemp.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Bin, strTemp); } void CInspectCamera::Notch_Process_PreProcess_2(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr, IplImage* img_Edge, IplImage* img_Bin, CRect rtROI) { if(m_pRecipe == NULL) return; if(nNotchIdx < 0 || MAX_SIDE_NOTCH_COUNT <= nNotchIdx) return; int sigma1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter; CString strTemp; cvThreshold(scr,img_Edge,sigma1,255,CV_THRESH_BINARY_INV); double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold; double th2 = 40.0; int sigma=5; cvCanny(img_Edge, img_Edge,th1,th2,sigma); strTemp.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Edge, strTemp); th1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold; cvThreshold(scr,img_Bin,th1,255,CV_THRESH_BINARY); strTemp.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Bin, strTemp); } 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) return; double dPixelSizeX = m_dPixelSizeX; double dPixelSizeY = m_dPixelSizeY; IplImage* img_Bin_MeasureLine = cvCloneImage(scr); 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; cvThreshold(scr, img_Bin_MeasureLine, th, 50, CV_THRESH_BINARY); // 1. Find Seed CvPoint ptSeed; ptSeed.x = rtROI.CenterPoint().x + nNotchCenterOffset; ptSeed.y = img_Bin_MeasureLine->height / 2; img_Find_MeasureLine = cvCloneImage(img_Bin_MeasureLine); // 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µµ´Â ½ºÅµÇÑ´Ù. IplImage* img_Find_MeasureLine_Point = cvCloneImage(scr); std::vector vecPointList; for(int i=nSkipStep; i < nFindStep-nSkipStep; i++) { double dFindAngle = ((double) i) * dStepAngle; double dSearchRadius = 1800.0 + abs(nNotchCenterOffset); 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)); if(nX < 0 ||img_Find_MeasureLine->width <= nX) continue; if(nY < 0 ||img_Find_MeasureLine->height <= nY) continue; 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; vecPointList.push_back(CPoint(nX, nY)); break; } img_Find_MeasureLine_Point->imageData[nY * img_Find_MeasureLine_Point->widthStep + nX] = 200; } } // 3. Meausre int nCount = vecPointList.size()-2; if(nCount < MAX_SIDE_NOTCH_MEASURE_COUNT) // ÃøÁ¤ Æ÷ÀÎÆ® ¿¡·¯ { cvReleaseImage(&img_Bin_MeasureLine); cvReleaseImage(&img_Find_MeasureLine); cvReleaseImage(&img_Find_MeasureLine_Point); cvReleaseImage(&img_Result); return; } double dPointStep = (double) nCount / (MAX_SIDE_NOTCH_MEASURE_COUNT-1); // 16 Point ÃøÁ¤.. for(int nMeasureIdx=0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++) { int nPointIdx = nMeasureIdx * dPointStep; 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]; 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; double dDiff_X = abs(pt_End.x - pt_Start.x); double dDiff_y = abs(pt_End.y - pt_Start.y); double dAngle_Radian = ToRadian(-90.0); if(dDiff_X != 0.0) dAngle_Radian = atan(dDiff_y/dDiff_X); dAngle_Radian = ToRadian( 90.0 - abs(ToDegree(dAngle_Radian)) ); if(pt_End.x - pt_Start.x < 0.0) dAngle_Radian = dAngle_Radian * -1.0; double dSearchRadius = 100.0; BOOL bFindEdge = FALSE; CPoint ptFindEdge; BOOL bFindChamfer = FALSE; CPoint ptFindChamfer; BOOL bEdgeCheck = FALSE; 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); img_Result->imageData[pt_Measure.y * img_Result->widthStep + pt_Measure.x] = 0; if(nX < 0 ||img_Edge->width <= nX) continue; if(nY < 0 ||img_Edge->height <= nY) continue; CPoint ptCheck = CPoint(nX, nY); // img_Result->imageData[nY * img_Canny->widthStep + nX] = 0; BOOL bEdgeFind = FALSE; BOOL bBinEdgeFind = FALSE; for(int nCheckX = 0; nCheckX < 3; nCheckX++) { for(int nCheckY = 0; nCheckY < 3; nCheckY++) { int nFindX = nX - 1 + nCheckX; int nFindY = nY - 1 + nCheckY; if(nFindX < 0 ||img_Edge->width <= nFindX) continue; if(nFindY < 0 ||img_Edge->height <= nFindY) continue; if(img_Edge->imageData[nFindY * img_Edge->widthStep + nFindX] != 0) { bEdgeFind = TRUE; //break; } if(img_Bin->imageData[nFindY * img_Bin->widthStep + nFindX] != 0) { bBinEdgeFind = TRUE; //break; } if(bEdgeFind == TRUE && bBinEdgeFind == TRUE) break; } if(bEdgeFind == TRUE && bBinEdgeFind == TRUE) break; } if(bEdgeCheck == FALSE && (bEdgeFind == TRUE || bBinEdgeFind == TRUE)) { if(bFindEdge == FALSE && bEdgeFind == TRUE) { img_Result->imageData[nY * img_Result->widthStep + nX] = 255; bFindEdge = TRUE; ptFindEdge = ptCheck; bEdgeCheck = TRUE; m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x = ptFindEdge.x;// + rtROI.left; m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y = ptFindEdge.y + rtROI.top; continue; } //if(ptCheck != ptFindEdge && bFindEdge == TRUE && bFindChamfer == FALSE) if(ptCheck != ptFindEdge && bBinEdgeFind == TRUE && bFindChamfer == FALSE) { img_Result->imageData[nY * img_Result->widthStep + nX] = 200; bFindChamfer = TRUE; ptFindChamfer = ptCheck; m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x = ptFindChamfer.x;// + rtROI.left; m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y = ptFindChamfer.y + rtROI.top; } } else if(bEdgeCheck == TRUE && bEdgeFind == FALSE) { bEdgeCheck = FALSE; } if(bFindEdge == TRUE && bFindChamfer == TRUE) break; } } CString strTemp; strTemp.Format(_T("Notch\\Notch_%d_Bin_MeasureLine.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Bin_MeasureLine, strTemp); strTemp.Format(_T("Notch\\Notch_%d_Find_MeasureLine.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Find_MeasureLine, strTemp); strTemp.Format(_T("Notch\\Notch_%d_Find_MeasureLine_Point.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Find_MeasureLine_Point, strTemp); strTemp.Format(_T("Notch\\Notch_%d_Measure_Result.jpg"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Result, strTemp); cvReleaseImage(&img_Bin_MeasureLine); cvReleaseImage(&img_Find_MeasureLine); cvReleaseImage(&img_Find_MeasureLine_Point); cvReleaseImage(&img_Result); return; } 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) return FALSE; 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]; CPoint ptChamfer_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx]; // Dimension double dX_dim_um = (double)(ptRef_pxl.x - ptDim_pxl.x) * m_dPixelSizeX; double dY_dim_um = (double)(ptRef_pxl.y - ptDim_pxl.y) * m_dPixelSizeY; double dDimension = sqrtf((dX_dim_um * dX_dim_um) + (dY_dim_um * dY_dim_um)); m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx] = dDimension; 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 && dChamfer > 2000) { return FALSE; } } return TRUE; } 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) return; 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) { double dDimension_um = m_pGlassData->GetSideData(emDim)->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_Diff_um = dDimension_std_um - dDimension_um; m_pGlassData->GetSideData(emDim)->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 1; m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Result_Diff_um[nNotchIdx][nMeasureIdx] = dDimension_Diff_um; m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] = dDimension_std_um; m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Judge_Min_um[nNotchIdx][nMeasureIdx] = dDimension_min_um; m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Judge_Max_um[nNotchIdx][nMeasureIdx] = dDimension_max_um; if(dDimension_um > dDimension_std_um + dDimension_max_um) m_pGlassData->GetSideData(emDim)->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 2; else if(dDimension_um < dDimension_std_um - dDimension_min_um) m_pGlassData->GetSideData(emDim)->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 3; if(m_pGlassData->GetSideData(emDim)->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] != 1) { // Make °áÇÔ.. CRect rtDefectArea = CRect(m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x, m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y, m_pGlassData->GetSideData(emDim)->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x, m_pGlassData->GetSideData(emDim)->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 = m_pGlassData->GetSideData(emDim)->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) { double dChamfer_um = m_pGlassData->GetSideData(emDim)->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_Diff_um = dChamfer_std_um - dChamfer_um; m_pGlassData->GetSideData(emDim)->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 1; //ѡȡ²âÁ¿ÑÐÄ¥³ß´ç×î´óÖµ if (m_nChamferOffset_um < dChamfer_um) { m_nChamferOffset_um = dChamfer_um; } m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Result_Diff_um[nNotchIdx][nMeasureIdx] = dChamfer_std_um - dChamfer_um; m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] = dChamfer_std_um; m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Judge_Min_um[nNotchIdx][nMeasureIdx] = dChamfer_min_um; m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Judge_Max_um[nNotchIdx][nMeasureIdx] = dChamfer_max_um; if(dChamfer_um > dChamfer_std_um + dChamfer_max_um) m_pGlassData->GetSideData(emDim)->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 2; else if(dChamfer_um < dChamfer_std_um - dChamfer_min_um) m_pGlassData->GetSideData(emDim)->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 3; if(m_pGlassData->GetSideData(emDim)->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] != 1) { // Make °áÇÔ.. CRect rtDefectArea = CRect(m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x, m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y, m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x, m_pGlassData->GetSideData(emDim)->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 = m_pGlassData->GetSideData(emDim)->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"}; sprintf(m_pGlassData->GetSideData(emDim)->m_strNotchMeasure_Comment[nNotchIdx][nMeasureIdx], "NOTCH[%d]-POINT[%d]-DIM[%.1f/STD:%.1f][%s], CHAMFER[%.1f/STD:%.1f][%s]" , nNotchIdx+1, nMeasureIdx+1 , m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx] , m_pGlassData->GetSideData(emDim)->m_dNotch_Dimension_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] , strJudge[m_pGlassData->GetSideData(emDim)->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx]] , m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx] , m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] , strJudge[m_pGlassData->GetSideData(emDim)->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) { if(m_pGlassData == NULL || m_pRecipe == NULL) return; if(scr == NULL) return; CNOTCH_PARM* pNotchParam = &m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx]; if(pNotchParam->m_bNotch_Inspect_Defect_Use == FALSE) return; CString strTemp; 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 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", nNotchIdx, nEdgeThres, nThreshold, nOffset, nNgType, rtROI.left, rtROI.top, rtROI.right, rtROI.bottom, __LINE__); //Êä³ö¼ÆËãÐÅÏ¢ std::vector vNorchPoints; 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); } CRect defectResult[100]; //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); std::vector vecDefectCandidateList; for (size_t i = 0; i < nRet; i++) { CDefect_Info defectInfo; CRect rtDefectPos_pxl(defectResult[i].left, defectResult[i].top, defectResult[i].right, defectResult[i].bottom); defectInfo.m_iFrameIdx = stFrame.nFrameIdx; defectInfo.m_nCamID = m_iCamera; defectInfo.m_nScanIdx = stFrame.nScanIdx; defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(emDim)->m_nGlassStartLine; defectInfo.m_nSideIdx = (int)emDim; defectInfo.m_ptDefectPos_pxl = rtDefectPos_pxl.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectPos_pxl; defectInfo.m_DefectLoc = DefectLoc_Notch_Crack; vecDefectCandidateList.push_back(defectInfo); } m_pDefectControl->ExtractDefect_Notch(emDim, m_iCamera, stFrame.nScanIdx, nNotchIdx, &vecDefectCandidateList); #else nOffset = m_nChamferOffset_um / m_pGlassData->GetSideData(emDim)->m_dPixelSizeX; nOffset += pNotchParam->m_nNotch_Inspect_Defect_Offset; m_nChamferOffset_um = 0; CRect rcIns = rtROI; 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); IplImage* pProcessBin = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1); IplImage* pMaskImage = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1); for(int i=0; iimageData+(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); SaveDebugImage(emDim, stFrame, img_Edge, strTemp); strTemp.Format(_T("Notch\\Notch_%d_Defect_Bin"), nNotchIdx); SaveDebugImage(emDim, stFrame, img_Bin, strTemp); cvZero(pMaskImage); cvOr(pProcessCanny, pProcessBin, pMaskImage); strTemp.Format(_T("Notch\\Notch_%d_Defect_EdgeOrBin"), nNotchIdx); SaveDebugImage(emDim, stFrame, pMaskImage, strTemp); BOOL bFind; int nFindX; for(int y=0;yheight;y++) { bFind = FALSE; nFindX = 0; for(int x=0;xwidth;x++) { if(pMaskImage->imageData[y*pMaskImage->widthStep + x] != 0) { bFind = TRUE; nFindX = x; break; } } if(bFind == TRUE) { memset(&pMaskImage->imageData[y*pMaskImage->widthStep], 255, nFindX); memset(&pMaskImage->imageData[y*pMaskImage->widthStep+nFindX], 0, pMaskImage->width - nFindX); //for (int x = 0; x < nFindX; x++) // pMaskImage->imageData[y * pMaskImage->widthStep + x] = 255; //for (int x = nFindX; x < pMaskImage->width; x++) // pMaskImage->imageData[y * pMaskImage->widthStep + x] = 0; } } strTemp.Format(_T("Notch\\Notch_%d_Defect_MaskPreImage"), nNotchIdx); SaveDebugImage(emDim, stFrame, pMaskImage, strTemp); 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; iheight; i++) for(int j=0; jwidth; 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); cvThreshold(pProcImage, pProcBinImage, nThreshold, 255, CV_THRESH_BINARY_INV); strTemp.Format(_T("Notch\\Notch_%d_Defect_ProcBinImage"), nNotchIdx); SaveDebugImage(emDim, stFrame, pProcBinImage, strTemp); // 3. Blob 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 = 0; int nDilation = 0; BOOL bStartNearFilterUse = FALSE; int nStartNearFilterRange = 0; DefectLocation defectLoc = DefectLoc_Notch_Crack; std::vector vecDefectCandidateList; DefectProcess(emDim, iScan, iFrame, pProcImage, pProcBinImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_Notch(emDim, m_iCamera, stFrame.nScanIdx, nNotchIdx, &vecDefectCandidateList); cvReleaseImage(&pMaskImage); cvReleaseImage(&pProcImage); cvReleaseImage(&pProcBinImage); cvReleaseImage(&pProcessCanny); cvReleaseImage(&pProcessBin); #endif } void CInspectCamera::Notch_Process_FindCircle(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx) { if(m_pGlassData == NULL) return; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return; if(pSideData->m_bFindGlassEndLine == FALSE) // Notch ProcessingÀº End Line ãÀº FrameÀÌ.. return; if(m_pRecipe == NULL) return; if(m_pDefectControl == NULL) return; CNOTCH_PARM* pNotchParam = &m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx]; if(pNotchParam == NULL) return; int nNotchCircleCount = pNotchParam->m_nNotch_Circle_Count; pSideData->m_nNotchCircleCount[nNotchIdx] = nNotchCircleCount; for(int nCircleIdx = 0; nCircleIdx < nNotchCircleCount; nCircleIdx++) { BOOL bUse = pNotchParam->m_bNotch_Circle_Use[nCircleIdx]; if(bUse == FALSE) continue; // 1. Make ROI CPoint ptSet_TopMark = pNotchParam->m_ptNotch_Circle_TopMarkPos[nCircleIdx]; CPoint ptSet_BotMark = pNotchParam->m_ptNotch_Circle_BotMarkPos[nCircleIdx]; CRect rtSet_Area = pNotchParam->m_rtNotch_Circle_Area_pxl[nCircleIdx]; CRect rtRotateArea; if(GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE) continue; CRect rtROI = rtRotateArea; pSideData->m_rtNotchCircleArea_pxl[nNotchIdx][nCircleIdx] = rtROI; VectorDouble vectorX; VectorDouble vectorY; VectorDouble vectorR; /* for(int nMeasureIdx=0; nMeasureIdxm_nNotch_Dimension_Edge_Judge[nMeasureIdx] ==0) continue; vectorX.push_back((double) pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x); vectorY.push_back((double) pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y); } */ // 2. Get Edge Line int nThreshold = m_pRecipe->m_SideParam[(int) emDim].m_nChamferLineThreshold; LPBYTE pFrameBuffer = m_pGrabber->GetFrameHeader(stFrame.nScanIdx, 0); IplImage* pEdgeImage = cvCreateImage(cvSize(rtROI.Width(), rtROI.Height()), 8, 1); IplImage* pCannyEdgeImage = cvCreateImage(cvSize(rtROI.Width(), rtROI.Height()), 8, 1); for(int i=0; iimageData[(i*pEdgeImage->widthStep)], (pFrameBuffer + ((rtROI.top+i)*m_nFrameWidth) + rtROI.left), rtROI.Width()); int sigma1 = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter; if(sigma1 % 2 == 0) sigma1 = sigma1 - 1; if(1 < sigma1) cvSmooth(pEdgeImage,pEdgeImage,CV_MEDIAN,sigma1); double th1 = (double) m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold * 10; double th2 = 40.0; int sigma=5; cvCanny(pEdgeImage,pCannyEdgeImage,th1,th2,sigma); CString strTemp; strTemp.Format(_T("Notch\\Notch_%d_Circle_%d_Ori.jpg"), nNotchIdx, nCircleIdx); SaveDebugImage(emDim, stFrame, pEdgeImage, strTemp); strTemp.Format(_T("Notch\\Notch_%d_Circle_%d_Edge.jpg"), nNotchIdx, nCircleIdx); SaveDebugImage(emDim, stFrame, pCannyEdgeImage, strTemp); // Find Edge for(int i=0; iimageData[i * pCannyEdgeImage->widthStep + j]; if(nGray != 0 ) { double dX_um = j * m_dPixelSizeX; // rtROI.left + j; double dY_um = i * m_dPixelSizeY; // rtROI.top + i; vectorX.push_back(dX_um); vectorY.push_back(dY_um); break; } } } cvReleaseImage(&pEdgeImage); cvReleaseImage(&pCannyEdgeImage); // 3. Circle Fitting if(CCHDataFitting::CircleFitting(vectorX, vectorY, vectorR) == 1) { double dCenterPos_X_um = vectorR[0]; double dCenterPos_Y_um = vectorR[1]; double dRadiuse_um = vectorR[2]; double dCenterPos_X_pxl = rtROI.left + (dCenterPos_X_um / m_dPixelSizeX); 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_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 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_Result_Diff_um[nNotchIdx][nCircleIdx] = dResult_um; if(dResult_um < dMin_um || dMax_um < dResult_um) { pSideData->m_nNotchCircle_Radius_Judge[nNotchIdx][nCircleIdx] = 2; // NG CDefect_Info measureDefect; measureDefect.m_nIndex = nNotchIdx; measureDefect.m_iFrameIdx = nCircleIdx; measureDefect.m_nCamID = m_iCamera; measureDefect.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine; 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); } else { sprintf(pSideData->m_strNotchCircle_Radius_Comment[nNotchIdx][nCircleIdx], "Rad. [OK] %.1f um / %.1f um", dRadiuse_um, dResult_um); } } } } BOOL CInspectCamera::Measure(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; int nEndFrame = pSideData->m_nGlassEndLine/m_nFrameHeight; //if(nEndFrame != stFrame.nFrameIdx) // return FALSE; 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 ÀÌ ÃøÁ¤ ÇÑ´Ù.. return FALSE; 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); return TRUE; } BOOL CInspectCamera::Measure_Side(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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]; 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]); return FALSE; } /////////////////////////////////////////////////////////////////////////////////////// #if HALCON_VISION_KEY //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; pBlSideData->m_dPixelSizeY = pSideData->m_dPixelSizeY; pBlSideData->m_bTopMark_Find = FALSE; pBlSideData->m_bBotMark_Find = FALSE; pBlSideData->m_mTopMark.x = 0; pBlSideData->m_mTopMark.y = 0; pBlSideData->m_mBotMark.x = 0; pBlSideData->m_mBotMark.y = 0; pBlSideData->m_nStartLine = 0; pBlSideData->m_nEndLine = 0; //Set MarkPos if (pSideData->m_bTopMark_Find) { pBlSideData->m_bTopMark_Find = pSideData->m_bTopMark_Find; pBlSideData->m_mTopMark.x = pSideData->m_ptTopMark_FindResult.x; pBlSideData->m_mTopMark.y = pSideData->m_ptTopMark_FindResult.y; } if (pSideData->m_bBotMark_Find) { pBlSideData->m_bBotMark_Find = pSideData->m_bBotMark_Find; pBlSideData->m_mBotMark.x = pSideData->m_ptBotMark_FindResult.x; 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(); #endif // HALCON_VISION_KEY ////////////////////////////////////////////////////////////////////////////////// CPoint ptTopAlignMark = pSideData->m_ptTopMark_FindResult; CPoint ptBottomAlignMark = pSideData->m_ptBotMark_FindResult; // int nTopEdgeToMark_X_pxl = pSideData->m_nTopMarkToEdge_X_pxl; // int nTopEdgeToMark_X_um = (int) GetPixelToUm_X(nTopEdgeToMark_X_pxl); int nTopEdgeToMark_X_um = pSideParam->m_nTopMarkToEdgeX_um; if (ptBottomAlignMark.y == ptTopAlignMark.y) { g_pLog->DisplayMessage(_T("Error : Top Align Mark to Bottom Align Mark Y Distance is Zero..")); return FALSE; } 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); int nMeasureCount = pSideParam->m_nSideDimensionCount; for (int nMeasurePointIdx = 0; nMeasurePointIdx < nMeasureCount; nMeasurePointIdx++) { if(MAX_SIDE_DIMENSION_MEASURE_COUNT <= nMeasurePointIdx) break; 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); 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 nFindRangeX = 100; int nFindRangeY = 20; 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 >= rtFindPos.right) continue; if(rtFindPos.top >= rtFindPos.bottom) continue; if(rtFindPos.Width() <= 20 || rtFindPos.Height() <= 2) continue; LPBYTE pFrameBuffer = m_pGrabber->GetFrameHeader(stFrame.nScanIdx, 0); if(pFrameBuffer == NULL) continue; COwnerBuffer pFindImage = COwnerBuffer(rtFindPos.Width(), rtFindPos.Height()); for(int i=0; im_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); int nFindEdgeLine = -1; int nFindChamferLine = -1; #define DEFECT_EDGE_AUTO_RATIO 0.3 #define DEFECT_EDGE_AUTO_PITCH 10 #define DEFECT_EDGE_CONTINUE 3 CSISEdgeFind EdgeFind; EdgeFind.FindEdge_ToRightROI(&pFindImage, nFindEdgeLine, DEFECT_EDGE_AUTO_PITCH, nSideLineThres, DEFECT_EDGE_AUTO_RATIO, 0, rtFindROI); rtFindROI.left = nFindEdgeLine + 3; CChamferInspect chamferIns; 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); //} double dLine = -1; 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¿¡¼­ ´ëÇ¥·Î ãÀº°É·Î ÃøÁ¤ °á°ú·Î ¾²°Ô Çߴµ¥.... À̹ÌÁö¿¡¼­ ´Ù½Ã ãµµ·Ï ¼öÁ¤ÀÌ ÇÊ¿ä..ÇÒ±î?? int nFrameIdx = (int)(nEndPointPosY / m_nFrameHeight); /* int nSideLine = pSideData->m_nSideLineFrame[nFrameIdx]; int nChamferLine = pSideData->m_nSide_Chamfer_LineFrame[nFrameIdx]; */ CPoint ptStart = CPoint(nMeasurePointPosX, nMeasurePointPosY); CPoint ptEnd_CutLine = CPoint(nSideLine, nMeasurePointPosY); double dDistance_CutLine_mm = GetUm_Distance(ptStart, ptEnd_CutLine) / 1000.0; pSideData->m_ptSideMeasure_Start[nMeasurePointIdx] = ptStart; pSideData->m_ptSideMeasure_CutLine[nMeasurePointIdx] = ptEnd_CutLine; pSideData->m_dSideMeasrue_CutLine_Result_mm[nMeasurePointIdx] = dDistance_CutLine_mm; pSideData->m_dSideMeasrue_CutLine_Offset_mm[nMeasurePointIdx] = pSideParam->m_dSideDimensionSpec_mm_Off[nMeasurePointIdx]; CPoint ptEnd_ChamferLine = CPoint(nChamferLine, nMeasurePointPosY); double dDistance_ChamferLine_mm = GetUm_Distance(ptEnd_CutLine, ptEnd_ChamferLine) / 1000.0; 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 ´Ù¿î. // continue; // Dimension double dTempValue = pSideParam->m_dSideDimensionSpec_mm_Std[nMeasurePointIdx]; 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])); double dMax_mm = (dStd_mm + abs(pSideParam->m_dSideDimensionSpec_mm_Max[nMeasurePointIdx])); double dResult_mm = dDistance_CutLine_mm; if(dResult_mm < dMin_mm || dMax_mm < dResult_mm) { pSideData->m_nSideMeasure_CutLine_Status[nMeasurePointIdx] = 2; // NG // Make Defect /* CDefect measureDefect; measureDefect.m_dSizeX_um = dDistance_CutLine_mm; measureDefect.m_dSizeY_um = dResult_mm; measureDefect.m_bJudge_NG = TRUE; measureDefect.m_DefectInfo.m_nIndex = 0; measureDefect.m_DefectInfo.m_iFrameIdx = nFrameIdx; measureDefect.m_DefectInfo.m_nCamID = m_iCamera; measureDefect.m_DefectInfo.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_DefectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine; measureDefect.m_DefectInfo.m_nSideIdx = (int) emDim; measureDefect.m_DefectInfo.m_DefectLoc = DefectLoc_Measure_Dimension; measureDefect.m_DefectInfo.m_ptDefectPos_pxl = CPoint(nEndPointPosX, nEndPointPosY); measureDefect.m_DefectInfo.m_rtDefectPos_pxl = CRect(nEndPointPosX - 100, nEndPointPosY - 100, nEndPointPosX + 100, nEndPointPosY + 100); */ CDefect_Info measureDefect; measureDefect.m_nIndex = nMeasurePointIdx; measureDefect.m_iFrameIdx = nFrameIdx; measureDefect.m_nCamID = m_iCamera; measureDefect.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine; 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); 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); } else pSideData->m_nSideMeasure_CutLine_Status[nMeasurePointIdx] = 1; // OK } else if (pSideParam->m_bSideDimension_Use[nMeasurePointIdx] == TRUE && dTempValue < -0.01) { #if HALCON_VISION_KEY //ÇиîÏߵij¤¶È¼ÆËã, 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]; Point2I ptEndCutLine; BOOL isFindSuccess = pSideData->m_bBotMark_Find && pSideData->m_bTopMark_Find; if (isFindSuccess && BlVision_GetSoftVisionApp()->findCutLine((int)emDim, toTopY, toLineDist, nThres, ptEndCutLine)) { Point2I m_Points[2]; m_Points[0].x = pSideData->m_ptTopMark_FindResult.x; m_Points[0].y = pSideData->m_ptTopMark_FindResult.y; m_Points[1].x = pSideData->m_ptBotMark_FindResult.x; m_Points[1].y = pSideData->m_ptBotMark_FindResult.y; double dPixelSizeX = pSideData->m_dPixelSizeX; double dPixelSizeY = pSideData->m_dPixelSizeY; Point2D pose; pose.x = dPixelSizeX * (ptEndCutLine.x - m_Points[0].x); pose.y = dPixelSizeY * (ptEndCutLine.y - m_Points[0].y); Line2D line; line.pt0.x = 0.0f; line.pt0.y = 0.0f; line.pt1.x = dPixelSizeX * (m_Points[1].x - m_Points[0].x); line.pt1.y = dPixelSizeY * (m_Points[1].y - m_Points[0].y); // double dResult_mm = -0.001 * BlVision_GetSoftVisionApp()->DistancePL(pose, line); // pSideData->m_dSideMeasrue_CutLine_Result_mm[nMeasurePointIdx] = dResult_mm; // CPoint ptEnd_CutLine = CPoint(nSideLine, nMeasurePointPosY); ptEnd_CutLine.x = ptEndCutLine.x; ptEnd_CutLine.y = ptEndCutLine.y; double dDistance_CutLine_mm = -1.0 * GetUm_Distance(ptStart, ptEnd_CutLine) / 1000.0 + pSideParam->m_dSideDimensionSpec_mm_Off[nMeasurePointIdx]; pSideData->m_ptSideMeasure_Start[nMeasurePointIdx] = ptStart; pSideData->m_ptSideMeasure_CutLine[nMeasurePointIdx] = ptEnd_CutLine; pSideData->m_dSideMeasrue_CutLine_Result_mm[nMeasurePointIdx] = dDistance_CutLine_mm; pSideData->m_dSideMeasrue_CutLine_Offset_mm[nMeasurePointIdx] = pSideParam->m_dSideDimensionSpec_mm_Off[nMeasurePointIdx]; CPoint ptEnd_ChamferLine = CPoint(nChamferLine, nMeasurePointPosY); double dDistance_ChamferLine_mm = GetUm_Distance(ptEnd_CutLine, ptEnd_ChamferLine) / 1000.0; 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; double dResult_mm = dDistance_CutLine_mm; double dStd_mm = pSideParam->m_dSideDimensionSpec_mm_Std[nMeasurePointIdx]; double dMin_mm = (dStd_mm - abs(pSideParam->m_dSideDimensionSpec_mm_Min[nMeasurePointIdx])); double dMax_mm = (dStd_mm + abs(pSideParam->m_dSideDimensionSpec_mm_Max[nMeasurePointIdx])); if (dResult_mm < dMin_mm || dMax_mm < dResult_mm) { pSideData->m_nSideMeasure_CutLine_Status[nMeasurePointIdx] = 2; // NG // Make Defect /* CDefect measureDefect; measureDefect.m_dSizeX_um = dDistance_CutLine_mm; measureDefect.m_dSizeY_um = dResult_mm; measureDefect.m_bJudge_NG = TRUE; measureDefect.m_DefectInfo.m_nIndex = 0; measureDefect.m_DefectInfo.m_iFrameIdx = nFrameIdx; measureDefect.m_DefectInfo.m_nCamID = m_iCamera; measureDefect.m_DefectInfo.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_DefectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine; measureDefect.m_DefectInfo.m_nSideIdx = (int) emDim; measureDefect.m_DefectInfo.m_DefectLoc = DefectLoc_Measure_Dimension; measureDefect.m_DefectInfo.m_ptDefectPos_pxl = CPoint(nEndPointPosX, nEndPointPosY); measureDefect.m_DefectInfo.m_rtDefectPos_pxl = CRect(nEndPointPosX - 100, nEndPointPosY - 100, nEndPointPosX + 100, nEndPointPosY + 100); */ CDefect_Info measureDefect; measureDefect.m_nIndex = nMeasurePointIdx; measureDefect.m_iFrameIdx = nFrameIdx; measureDefect.m_nCamID = m_iCamera; measureDefect.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine; 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); 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); } else { pSideData->m_nSideMeasure_CutLine_Status[nMeasurePointIdx] = 1; // OK } } #endif // HALCON_VISION_KEY } // Chamfer 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])); double dMax_mm = (dStd_mm + abs(pSideParam->m_dSideChamfer_Spec_mm_Max[nMeasurePointIdx])); double dResult_mm = dDistance_ChamferLine_mm; if(dResult_mm < dMin_mm || dMax_mm < dResult_mm) { pSideData->m_nSideMeasure_ChamferLine_Status[nMeasurePointIdx] = 2; // NG CDefect_Info measureDefect; measureDefect.m_nIndex = nMeasurePointIdx; measureDefect.m_iFrameIdx = nFrameIdx; measureDefect.m_nCamID = m_iCamera; measureDefect.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine; 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); 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); /* // Make Defect CDefect measureDefect; measureDefect.m_dSizeX_um = dDistance_ChamferLine_mm; measureDefect.m_dSizeY_um = dResult_mm; measureDefect.m_bJudge_NG = TRUE; measureDefect.m_DefectInfo.m_nIndex = 0; measureDefect.m_DefectInfo.m_iFrameIdx = nFrameIdx; measureDefect.m_DefectInfo.m_nCamID = m_iCamera; measureDefect.m_DefectInfo.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_DefectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine; measureDefect.m_DefectInfo.m_nSideIdx = (int) emDim; measureDefect.m_DefectInfo.m_DefectLoc = DefectLoc_Measure_Chamfer; measureDefect.m_DefectInfo.m_ptDefectPos_pxl = CPoint(nEndPointPosX, nEndPointPosY); measureDefect.m_DefectInfo.m_rtDefectPos_pxl = CRect(nEndPointPosX - 100, nEndPointPosY - 100, nEndPointPosX + 100, nEndPointPosY + 100); m_pDefectControl->ExtractDefect_Measure(emDim, m_iCamera, stFrame.nScanIdx, measureDefect); */ } else 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); } return TRUE; } BOOL CInspectCamera::Measure_TopCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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]; if(pSideData == NULL || pSideParam == NULL) return FALSE; if(pSideParam->m_bTopCornerMeasureSize == FALSE) return FALSE; if (pSideData->m_bTopCorner_Find == FALSE) return FALSE; if (pSideData->m_bTopCorner_Measure == TRUE) return FALSE; 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); else pSideData->m_bTopCorner_Measure = TRUE; return TRUE; } BOOL CInspectCamera::Measure_TopCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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]; if(pSideData == NULL || pSideParam == NULL) return FALSE; CRect rtTopCornerArea = pSideData->m_rtTopCornerArea; rtTopCornerArea.InflateRect(50,50); int iCornerFrame = rtTopCornerArea.bottom/m_nFrameHeight; if(iCornerFrame > stFrame.nFrameIdx) return FALSE; // 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; double dXSizeMax_um = pSideParam->m_nTopCorner_Measure_Judge_Max_um_X; double dYSizeStd_um = pSideParam->m_nTopCorner_Measure_Judge_Std_um_Y; double dYSizeMin_um = pSideParam->m_nTopCorner_Measure_Judge_Min_um_Y; double dYSizeMax_um = pSideParam->m_nTopCorner_Measure_Judge_Max_um_Y; int nOpt = pSideParam->m_nTopCorner_Measure_Judge_OR_AND; 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( (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)) { pSideData->m_bTopCornerMeasureResult = FALSE; // NG } } if(pSideData->m_bTopCornerMeasureResult == FALSE) { // Make Defect CDefect_Info measureDefect; measureDefect.m_nIndex = 0; measureDefect.m_iFrameIdx = stFrame.nFrameIdx; measureDefect.m_nCamID = m_iCamera; measureDefect.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine; 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); 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); } } 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); 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; // 2. Get Image Buffer 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); if(pBuffer == NULL) return FALSE; for(int i=0; iimageData+(i*pConnerOriginImage->widthStep), (char*) &pBuffer[rtConnerRoi.left + (i*m_nFrameWidth)], rtConnerRoi.Width()); pConnerEdgeImage = cvCloneImage(pConnerOriginImage); cvZero(pConnerEdgeOutLineImage); CString strTemp; strTemp.Format(_T("Corner\\Corner_Origin_%d.jpg"), nPos); SaveDebugImage(emDim, stFrame, pConnerOriginImage, strTemp); BOOL bFind = FALSE; int nContinueCount = 5; UINT nTarget = 0; UINT nCompare = 0; int nDiff = 0; int nEdgeFilter; double dCornerEdgeTh1; if(nPos == 0) { nEdgeFilter = pSideParam->m_nTopCornerEdgeFilterSize; dCornerEdgeTh1 = pSideParam->m_nTopCornerEdgeThreshold; } else { nEdgeFilter = pSideParam->m_nBottomCornerEdgeFilterSize; dCornerEdgeTh1 = pSideParam->m_nBottomCornerEdgeThreshold; } if(nEdgeFilter % 2 == 0) nEdgeFilter = nEdgeFilter - 1; if(1 < nEdgeFilter) cvSmooth(pConnerEdgeImage, pConnerEdgeImage, CV_MEDIAN, nEdgeFilter); dCornerEdgeTh1 *= 10.; double dCornerEdgeTh2 = 40.0; int sigma=5; cvCanny(pConnerEdgeImage, pConnerEdgeImage, dCornerEdgeTh1, dCornerEdgeTh2, sigma); // Side for(int i=0; iheight; i++) { for(int j=0; jwidth; j++) { nTarget = (UINT) pConnerEdgeImage->imageData[pConnerOriginImage->widthStep*i + j]; if(nTarget != 0) { pConnerEdgeOutLineImage->imageData[pConnerOriginImage->widthStep*i + j] = 255; break; } } } // Top, Bottom if(nPos == 0) { for(int i=0; iwidth; i++) { for(int j=0; jheight; j++) { nTarget = (UINT) pConnerEdgeImage->imageData[pConnerOriginImage->widthStep*j + i]; if(nTarget != 0) { pConnerEdgeOutLineImage->imageData[pConnerEdgeOutLineImage->widthStep*j + i] = 255; break; } } } } else { for(int i=0; iwidth; i++) { for(int j=0; jheight; j++) { nTarget = (UINT) pConnerEdgeImage->imageData[pConnerOriginImage->widthStep*(pConnerOriginImage->height- 1 -j) + i]; if(nTarget != 0) { pConnerEdgeOutLineImage->imageData[pConnerEdgeOutLineImage->widthStep*(pConnerEdgeOutLineImage->height- 1 -j) + i] = 255; break; } } } } strTemp.Format(_T("Corner\\ConnerProcess_%d.jpg"), nPos); SaveDebugImage(emDim, stFrame, pConnerEdgeImage, strTemp); strTemp.Format(_T("Corner\\ConnerProcess_OutLine_%d.jpg"), nPos); SaveDebugImage(emDim, stFrame, pConnerEdgeOutLineImage, strTemp); // 4. OutLine Projection Data std::vector vecProjectionX; std::vector vecProjectionY; vecProjectionX.resize(rtConnerRoi.Width(), 0); vecProjectionY.resize(rtConnerRoi.Height(), 0); int nValue; for(int i=0; iimageData[j+(i*pConnerEdgeOutLineImage->widthStep)]; if(pConnerEdgeOutLineImage->imageData[i*pConnerEdgeOutLineImage->widthStep + j] != 0) { vecProjectionX[j]++; vecProjectionY[i]++; } } } // 5. Find Edge CPoint ptConner[3]; int nMaxCount = -1; int nMaxIdx = 0; for(int i=0; im_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) { 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%¿¡¼­ ãÀ½.. nSearchRangeX = nSearchRangeY = 10; for(int i=ptConner[0].x ; iwidth; i++) { if(i < 0 || i >= pConnerEdgeOutLineImage->width) continue; if(nPos == 0) { //for(int j=0; j= pConnerEdgeOutLineImage->height) continue; if(pConnerEdgeOutLineImage->imageData[i+(((ptConner[0].y)+j) * pConnerEdgeOutLineImage->widthStep)] != 0) { dAddDistance = (((double)j)*m_dPixelSizeY)/m_dPixelSizeX; ptConner[1].x = i + (int) dAddDistance; bFind = TRUE; break; } } } else { //for(int j=0; j= pConnerEdgeOutLineImage->height) continue; if(pConnerEdgeOutLineImage->imageData[i+(((ptConner[0].y)-j) * pConnerEdgeOutLineImage->widthStep)] != 0) { dAddDistance = (((double)j)*m_dPixelSizeY)/m_dPixelSizeX; ptConner[1].x = i + (int) dAddDistance; bFind = TRUE; break; } } } if(bFind) break; } bFind = FALSE; if(nPos == 0) { for(int i=ptConner[0].y ; iheight; i++) { if(i < 0 || i >= pConnerEdgeOutLineImage->height) continue; //for(int j=0; j= pConnerEdgeOutLineImage->widthStep) continue; if(pConnerEdgeOutLineImage->imageData[ptConner[0].x+j+(i * pConnerEdgeOutLineImage->widthStep)] != 0) { dAddDistance = (((double)j)*m_dPixelSizeX)/m_dPixelSizeY; ptConner[2].y = i + (int) dAddDistance; bFind = TRUE; break; } } if(bFind) break; } } else { for(int i=ptConner[0].y ; 0 <= i; i--) { if(i < 0 || i >= pConnerEdgeOutLineImage->height) continue; //for(int j=0; j= pConnerEdgeOutLineImage->widthStep) continue; if(pConnerEdgeOutLineImage->imageData[ptConner[0].x+j+(i * pConnerEdgeOutLineImage->widthStep)] != 0) { dAddDistance = (((double)j)*m_dPixelSizeX)/m_dPixelSizeY; ptConner[2].y = i - (int) dAddDistance; bFind = TRUE; break; } } 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) { 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_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; 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; } 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_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; } cvReleaseImage(&pConnerEdgeImage); cvReleaseImage(&pConnerOriginImage); cvReleaseImage(&pConnerEdgeOutLineImage); vecProjectionX.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); return TRUE; } BOOL CInspectCamera::Measure_TopCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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]; if(pSideData == NULL || pSideParam == NULL) return FALSE; // R Corner ÃøÁ¤ return TRUE; } BOOL CInspectCamera::Measure_BotCorner(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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]; if(pSideData == NULL || pSideParam == NULL) return FALSE; if(pSideParam->m_bBottomCornerMeasureSize == FALSE) return FALSE; if (pSideData->m_bBotCorner_Find == FALSE) return FALSE; if (pSideData->m_bBotCorner_Measure == TRUE) return FALSE; 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); else pSideData->m_bBotCorner_Measure = TRUE; return TRUE; } BOOL CInspectCamera::Measure_BotCorner_CCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { 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]; if(pSideData == NULL || pSideParam == NULL) return FALSE; CRect rtBottomCornerArea = pSideData->m_rtBotCornerArea; rtBottomCornerArea.InflateRect(50,50); int iCornerFrame = rtBottomCornerArea.bottom/m_nFrameHeight; if(iCornerFrame > stFrame.nFrameIdx) return FALSE; // 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; double dXSizeMax_um = pSideParam->m_nBottomCorner_Measure_Judge_Max_um_X; double dYSizeStd_um = pSideParam->m_nBottomCorner_Measure_Judge_Std_um_Y; double dYSizeMin_um = pSideParam->m_nBottomCorner_Measure_Judge_Min_um_Y; double dYSizeMax_um = pSideParam->m_nBottomCorner_Measure_Judge_Max_um_Y; int nOpt = pSideParam->m_nBottomCorner_Measure_Judge_OR_AND; 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( (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)) { pSideData->m_bBottomMeasureResult = FALSE; // NG } } if(pSideData->m_bBottomMeasureResult == FALSE) { // Make Defect CDefect_Info measureDefect; measureDefect.m_nIndex = 0; measureDefect.m_iFrameIdx = stFrame.nFrameIdx; measureDefect.m_nCamID = m_iCamera; measureDefect.m_nScanIdx = stFrame.nScanIdx; measureDefect.m_nGlassStartLine = pSideData->m_nGlassStartLine; 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); 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); } } return TRUE; } BOOL CInspectCamera::Measure_BotCorner_RCut(int iThread,DimensionDir emDim, stFrameIndex stFrame) { return TRUE; } BOOL CInspectCamera::UserDefect_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassEndLine == FALSE) // User Defect ProcessingÀº End Line ãÀº FrameÀÌ.. return FALSE; if(m_pRecipe == NULL) return FALSE; if(m_pDefectControl == NULL) return FALSE; std::vector vecDefectCandidateList; int nUserDefectAreaCount = m_pRecipe->m_SideParam[(int) emDim].m_nUserDefectAreaCount; pSideData->m_nUserDefectAreaCount = nUserDefectAreaCount; for(int i=0; im_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; CRect rtRotateArea; if(GetAlignRotate(emDim, ptSet_TopMark, ptSet_BotMark, rtSet_Area, rtRotateArea) == FALSE) continue; pSideData->m_rtUserDefectArea_pxl[i] = rtRotateArea; InspectDefect_UserDefectProcess(iThread, emDim, stFrame, i, rtRotateArea, &vecDefectCandidateList); m_pDefectControl->ExtractDefect_UserDefect(emDim, m_iCamera, stFrame.nScanIdx, i, &vecDefectCandidateList); } return TRUE; } BOOL CInspectCamera::InspectDefect_UserDefectProcess(int iThread,DimensionDir emDim, stFrameIndex stFrame, int nUserDefectIdx, CRect rtUserDefectArea, std::vector* 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) 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 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) 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()); // 2. Inspect Algorithm COwnerBuffer pBinImage; if (nMethod == 0) Binarization_Threshold_Suppress(&pDefectProcessImage, &pBinImage, nThreshold_Low, nThreshold_High); else if (nMethod == 1) Binarization_Threshold_Pitch_Y(&pDefectProcessImage, &pBinImage, nPitch, nPitch_Threshold); else if (nMethod == 2) Binarization_Threshold_Pitch_X(&pDefectProcessImage, &pBinImage, nPitch, nPitch_Threshold); // 3. Find Defect.. DefectProcess(emDim, stFrame.nScanIdx, stFrame.nFrameIdx, &pDefectProcessImage, &pBinImage, rtUserDefectArea, nMinSize, 0, 0, 0, FALSE, 0, DefectLoc_UserDefect, pDefectList); /* #ifdef _DEBUG CString str; str.Format(_T("D:\\InspectionData\\Debug\\InsArea_Ori_Frame%d_%d_%d_%d_%d.bmp"),iFrame, rtInspectArea.left, rtInspectArea.top, rtInspectArea.right, rtInspectArea.bottom); CBufferAttach attach_ori(str); attach_ori.AttachToFile(pDefectProcessImage); str.Format(_T("D:\\InspectionData\\Debug\\InsArea_Bin_Frame%d_%d_%d_%d_%d.bmp"),iFrame, rtInspectArea.left, rtInspectArea.top, rtInspectArea.right, rtInspectArea.bottom); CBufferAttach attach_bin(str); attach_bin.AttachToFile(pBinImage); #endif */ return TRUE; } BOOL CInspectCamera::ExceptionArea_Process(int iThread,DimensionDir emDim, stFrameIndex stFrame) { if(m_pGlassData == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassEndLine == FALSE) // Exception Area ProcessingÀº End Line ãÀº FrameÀÌ.. return FALSE; if(m_pRecipe == NULL) return FALSE; if(m_pDefectControl == NULL) return FALSE; int nExceptionCount = m_pRecipe->m_SideParam[(int) emDim].m_nExptionCount; pSideData->m_nExceptionAreaCount = nExceptionCount; for(int i=0; im_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; CRect rtRotateArea; 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; nDefectIdxGetDefect(nDefectIdx); if(pDefect == NULL) continue; CRect rtDefectArea = pDefect->m_DefectInfo.m_rtDefectPos_pxl; CRect rtIntersect; rtIntersect.IntersectRect(rtRotateArea, rtDefectArea); if(rtIntersect == rtDefectArea) pDefect->m_nExceptionArea = 2; 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; if(nFilterType == 0) continue; 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) pDefect->m_DefectInfo.m_DefectLoc = DefectLoc_Exception; } } return TRUE; } 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 iStartV = nLine-nImgHeight; if(iStartV < 0) iStartV = 0; LPBYTE pImg = m_pGrabber->GetFrameHeaderLine(iScan,iStartV); if(pImg == NULL) return; IplImage *IpImg = cvCreateImage(cvSize(saveRect.width,saveRect.height),8,1); cvZero(IpImg); int 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); 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); g_pStatus->CheckDirectory(strFile); 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); cvReleaseImage(&IpImg); } BOOL CInspectCamera::OnThreadEnd(int iThread, CInspectThread *pInspectThread) { return TRUE; } BOOL CInspectCamera::OnThreadEndAll() { return TRUE; } void CInspectCamera::ReleaseFullBuffer() { int i; for(i=0;iSetSimulation(bSimulation); } void CInspectCamera::SetParameter(CGlassRecipe *pRecipe,CHardwareSettings *pHW) { 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)); m_pRecipe = pRecipe; m_pHardparm = pHW; if(m_pGrabber != NULL) { m_pGrabber->ClearGrabIdx(); //m_pGrabber->ClearBuffer(); } if(m_pDefectControl != NULL) { m_pDefectControl->SetHWRecipe(pHW); m_pDefectControl->ResetDefectControl(); } g_pLog->DisplayMessage(_T("SetParameter Cam[%d] end"),m_iCamera); } void CInspectCamera::SetGlassData(CGlass_Data *pGlassData) { m_pGlassData = pGlassData; if(m_pGrabber != NULL) { for(int i=0;iGetSideData((DimensionDir)i); if(pSideData == NULL) continue; pSideData->m_nPreGlassEndFrame = m_pGrabber->GetFrameBuffer()->GetFrameCount()-1; } } } void CInspectCamera::SetGrabber(CGrabberControl *pGrabber) { m_pGrabber = pGrabber; if(m_pDefectControl != NULL) m_pDefectControl->SetGrabber(pGrabber); } DimensionDir CInspectCamera::GetDimension(int iScan) { CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,iScan); if(pCamera == NULL) return DIMENSION_NONE; return pCamera->m_eDimension; } void CInspectCamera::SetGrabEnd(int iScan) { g_pLog->DisplayMessage(_T("Set Grab End")); CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,iScan); if(pCamera == NULL) { g_pLog->DisplayMessage(_T("Camera Setting NULL")); return; } DimensionDir emDim = pCamera->m_eDimension; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return; int nStageNo = g_pBase->m_nStageNo; if(nStageNo < 0 || nStageNo > 1) nStageNo = 0; 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; 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); } BOOL CInspectCamera::FindGlassStartLine(DimensionDir emDim,stFrameIndex stFrame) { CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; CCameraSettings *pCamera = m_pHardparm->GetCameraSettings(m_iCamera,stFrame.nScanIdx); if(pCamera == NULL) return FALSE; 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; 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]; LPBYTE lpHeader; int nCountinueCount = 0; int nRet,nHStart; DWORD dwT1 = GetTickCount(); g_pLog->DisplayMessage(_T("%s Find Glass Start Start : Scan %d "),PANEL_SIDE[emDim],stFrame.nScanIdx); for(int iFrame=0;iFrameIsAcqFrame(iFrame); 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; return FALSE; } Sleep(1); } else break; } if (nSkipFrame > iFrame) continue; 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; return FALSE; } ZeroMemory(pnSum, sizeof(int) * (nFrameHeight + BOUNDARYHORIZ_LEVELDIST)); int nLine = 0; nHStart = nSetHor - BOUNDARY_GLASSSTARTWIDTH / 2; BOOL bChangeBuffer = FALSE; for (j = 0; j < nFrameHeight + BOUNDARYHORIZ_LEVELDIST; j++) //for (j = 0; j < nFrameHeight; j++) { for (k = nHStart; k < nHStart + BOUNDARY_GLASSSTARTWIDTH; k++) { // 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; return FALSE; } if(m_pGrabber->IsAcqFrame(iFrame + 1) > 1) { 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++; if (j >= BOUNDARYHORIZ_LEVELDIST) { nGab = abs(pnSum[j - BOUNDARYHORIZ_LEVELDIST] - pnSum[j]); if (nGab > nThreshold) nCountinueCount++; else nCountinueCount = 0; 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ÀÇ ½ÃÀÛÁöÁ¡À» ã¾Æ¼­ ±¸Á¶Ã¼¿¡ ³Ö´Â´Ù. pSideData->m_nGlassStartLine = iFrame * nFrameHeight + j - 2; 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); 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; return TRUE; } } } } delete [] pnSum; return FALSE; } BOOL CInspectCamera::MakeNotchArea(DimensionDir emDim) { if(m_pGlassData == NULL || m_pRecipe == NULL) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); if(pSideData == NULL) return FALSE; if(pSideData->m_bFindGlassStartLine == FALSE) return FALSE; 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); for(int i=0; im_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].OffsetRect(0, nStartLine_Offset); } return TRUE; } BOOL CInspectCamera::ProcessFrame(int iThread,DimensionDir emDim,stFrameIndex stFrame) { // 1. Find End Line.. (Corner¸¦ Á¦¿ÜÇÑ Side¶óÀÎÀ» ã±â À§ÇØ End LineºÎÅÍ Ã£´Â´Ù) FindEndLine(iThread, emDim, stFrame); // 2. Find Side Line.. (ÇØ´ç ÇÁ·¹ÀÓ¿¡¼­ Corner/Notch ¸¦ Á¦¿ÜÇÑ Side ¶óÀΠã±â) #if USE_AI_DETECT FindSideLine(iThread, emDim, stFrame); #else FindSideLine_ExceptNotch(iThread, emDim, stFrame); #endif // USE_AI_DETECT // 3. Find Top Corner FindTopCorner(iThread,emDim,stFrame); // 4. Find Top Align Mark FindTopAlignMark(iThread,emDim,stFrame); // 5. Find Bot Corner FindBotCorner(iThread,emDim,stFrame); // 6. Find Bot Align Mark FindBotAlignMark(iThread,emDim,stFrame); #if USE_AI_DETECT SendFrameScanDataOverAI(iThread, emDim, stFrame); #else // 7. Inspect Defect InspectDefect_Side(iThread, emDim, stFrame); // 8. Notch Process Notch_Process(iThread, emDim, stFrame); #endif // USE_WEBSOCKET // 9. Measure Measure(iThread,emDim,stFrame); // 10. User Defect UserDefect_Process(iThread,emDim,stFrame); // 11. Exception Area Process ExceptionArea_Process(iThread,emDim,stFrame); return TRUE; } int CInspectCamera::GetDefectCount() { if(m_pDefectControl == NULL) return 0; return m_pDefectControl->GetDefectCount(); } CDefect *CInspectCamera::GetDefect(int iDefect) { if(m_pDefectControl == NULL) return NULL; return m_pDefectControl->GetDefect(iDefect); } #if USE_WEBSOCKET void CInspectCamera::SetWebSocketClients(WebSocketClientPool* wsClients) { m_wsClients = wsClients; HandleAlarmNotification(); } std::string CInspectCamera::CreateJsonWSSendData(const WSSendData& data) { nlohmann::json json_data = { {"CheckType", data.nCheckType}, {"Reciepe", data.nRecipe}, {"nLineType", data.nLineType}, {"nIndex", data.nIndex}, {"nScanIdx", data.nScanIdx}, {"nFrameIdx", data.nFrameIdx}, {"SN", data.strSN.substr(0, data.strSN.find('\0'))}, {"NGType", data.nNGType}, {"EdgeX", data.nEdgeX}, {"EdgeY", data.nEdgeY}, {"NGPointY", data.nNPointY}, {"Position", data.nPosition}, {"State", data.nState}, {"ImageWidth", data.nWidth}, {"ImageHeight", data.nHeight}, {"Left", data.nLeft}, {"Top", data.nTop}, {"TimeStamp", data.dTimeStamp}, }; return json_data.dump(); } double CInspectCamera::GetCurrentTimestamp() { auto now = std::chrono::system_clock::now(); auto seconds = std::chrono::duration_cast(now.time_since_epoch()).count(); auto microseconds = std::chrono::duration_cast(now.time_since_epoch()).count(); double timestamp = seconds + (microseconds % 1000000) / 1000000.0; return timestamp; } void CInspectCamera::HandleAlarmNotification() { if (m_wsClients != nullptr) { m_wsClients->set_message_handler([this](const std::string& msg) { // JSON ¸ñʽ if (!msg.empty() && msg.size() > 3) { try { nlohmann::json json_data = nlohmann::json::parse(msg); DimensionDir emDim = (DimensionDir)(json_data.value("nLineType", 0) - 1); WSReceiveData wsReceiveData; // ½âÎö JSON Êý¾Ý²¢Ìî³ä wsReceiveData wsReceiveData.nRecipe = json_data.value("Reciepe", 0); wsReceiveData.nLineType = json_data.value("nLineType", 0); wsReceiveData.nIndex = json_data.value("nIndex", 0); wsReceiveData.nScanIdx = json_data.value("nScanIdx", 0); 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 ÊýÁ¿ // ¸ñʽ»¯²¢ÏÔʾ»ù±¾ÐÅÏ¢ 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 && wsReceiveData.nGNum != 0 && g_pBase->m_strHPanelID.Compare(CString(wsReceiveData.strSN.c_str())) == 0) { // ±éÀú²¢Ìî³ä ngPosArray auto ngPosArray = json_data["NGPosArray"]; for (auto& ngPos : ngPosArray) { WSReceiveData::NGPosition ngPosition; ngPosition.nNGType = ngPos.value("NGType", 0); ngPosition.nLeft = ngPos.value("Left", 0); ngPosition.nTop = ngPos.value("Top", 0); ngPosition.nRight = ngPos.value("Right", 0); ngPosition.nBottom = ngPos.value("Bottom", 0); wsReceiveData.ngPosArray.push_back(ngPosition); CDefect_Info defectInfo; CRect rtDefectPos_pxl(ngPosition.nLeft, ngPosition.nTop, ngPosition.nRight, ngPosition.nBottom); defectInfo.m_iFrameIdx = wsReceiveData.nFrameIdx; defectInfo.m_nCamID = m_iCamera; defectInfo.m_nScanIdx = wsReceiveData.nScanIdx; defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(emDim)->m_nGlassStartLine; defectInfo.m_nSideIdx = (int)wsReceiveData.nLineType - 1; defectInfo.m_ptDefectPos_pxl = rtDefectPos_pxl.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectPos_pxl; defectInfo.m_DefectLoc = (DefectLocation)ngPosition.nNGType; m_pDefectControl->ExtractDefect(emDim, m_iCamera, wsReceiveData.nScanIdx, defectInfo); CString ngPosText; ngPosText.Format(_T("NGType: %d, Left: %d, Top: %d, Right: %d, Bottom: %d\n"), ngPosition.nNGType, ngPosition.nLeft, ngPosition.nTop, ngPosition.nRight, ngPosition.nBottom); strText += ngPosText; } } g_pLog->DisplayMessage(strText); } catch (const nlohmann::json::parse_error& e) { // ´¦Àí JSON ½âÎö´íÎó std::cerr << "JSON parse error: " << e.what() << std::endl; } } else { // ´¦Àí¿ÕÏûÏ¢ std::cerr << "Empty message" << std::endl; } }); } } void CInspectCamera::SendImageDataOverWebSocket(DimensionDir emDim, stFrameIndex stFrame, int index, BYTE* data, int state, int left, int top, int width, int height) { if (!m_pGlassData || !m_pRecipe) return; CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)emDim]; if (!pSideData || !pSideParam || !pSideData->m_bFindGlassStartLine) return; WSSendData wsData; USES_CONVERSION; wsData.nCheckType = 2; wsData.nRecipe = _ttoi(g_pBase->m_strRecipeName); wsData.nLineType = (uint8_t)(emDim + 1); wsData.nIndex = index; wsData.nFrameIdx = stFrame.nFrameIdx; wsData.nScanIdx = stFrame.nScanIdx; wsData.strSN = T2A(g_pBase->m_strHPanelID); wsData.nNGType = 0; wsData.nEdgeX = pSideData->m_nSideLineFrame[stFrame.nFrameIdx]; wsData.nEdgeY = 0; wsData.nNPointY = 0; wsData.nPosition = state; wsData.nState = state; wsData.nWidth = width; wsData.nHeight = height; wsData.nLeft = left; wsData.nTop = top; wsData.dTimeStamp = GetCurrentTimestamp(); std::string jsonMetadata = CreateJsonWSSendData(wsData); // Ô¤ÏÈ·ÖÅäÄڴ棬¼õÉÙ¶¯Ì¬À©ÈÝ std::vector message; message.reserve(jsonMetadata.size() + width * height); // ²åÈë JSON Êý¾ÝºÍͼÏñÊý¾Ý message.insert(message.end(), jsonMetadata.begin(), jsonMetadata.end()); message.insert(message.end(), data, data + width * height); // ʹÓà 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; defectInfo.m_nCamID = m_iCamera; defectInfo.m_nScanIdx = stFrame.nScanIdx; defectInfo.m_nGlassStartLine = m_pGlassData->GetSideData(emDim)->m_nGlassStartLine; defectInfo.m_nSideIdx = (int)emDim; defectInfo.m_ptDefectPos_pxl = rtDefectPos_pxl.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectPos_pxl; defectInfo.m_DefectLoc = DefectLoc_WS_Fail; m_pDefectControl->ExtractDefect(emDim, m_iCamera, stFrame.nScanIdx, defectInfo); g_pLog->DisplayMessage(_T("%s Failed to send image data over WebSocket."), g_SideName[(int)emDim]); } } BOOL CInspectCamera::SliceAndSendImageViaWebSocket(int iThread, DimensionDir eDim, stFrameIndex stFrame) { if (!m_pGlassData || !m_pRecipe) return FALSE; CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int)eDim]; if (!pSideData || !pSideParam || !pSideData->m_bFindGlassStartLine) return FALSE; if (!pSideData->m_bTopMark_Find || !pSideData->m_bBotMark_Find) { g_pLog->DisplayMessage(_T("Error: [%s] Top/Bottom Mark not detected.."), g_SideName[(int)eDim]); return FALSE; } CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, pSideData->m_nGlassStartLine), m_nFrameWidth, m_nFrameHeight); if (!frameBuffer.IsValidBuffer()) return FALSE; CRect rtROI(m_nFrameWidth - 2048, pSideData->m_nGlassStartLine, m_nFrameWidth, (pSideData->m_nGlassEndLine <= 0) ? pSideData->m_nPreGlassEndLine : pSideData->m_nGlassEndLine); if (rtROI.right < rtROI.left || rtROI.bottom < rtROI.top || rtROI.left < 0 || rtROI.bottom < 0) return FALSE; cv::Mat scr(rtROI.Height(), rtROI.Width(), CV_8UC1); for (int i = 0; i < rtROI.Height(); i++) memcpy(scr.ptr(i), frameBuffer.GetDataAddress(rtROI.left, i), rtROI.Width()); if (scr.empty()) { g_pLog->DisplayMessage(_T("%s Could not open or find the image!"), GetSideName(eDim)); return FALSE; } auto start = std::chrono::high_resolution_clock::now(); int maxImageHeight = scr.rows - IMAGE_HEIGHT; for (int i = 0; i <= scr.rows / IMAGE_HEIGHT; i++) { int currentHeight = (IMAGE_HEIGHT * i > maxImageHeight) ? scr.rows - IMAGE_HEIGHT * i : IMAGE_HEIGHT; cv::Rect cvRoi(0, IMAGE_HEIGHT * i, scr.cols, currentHeight); if (cvRoi.width <= 0 || cvRoi.height <= 0) { g_pLog->DisplayMessage(_T("%s Picture size anomaly."), GetSideName(eDim)); return FALSE; } cv::Mat cvImage = scr(cvRoi); CString str; str.Format(_T("Test\\%s[%d]img_Frame%d_%d_%d_%d_%d"), GetSideName(eDim), i, stFrame.nFrameIdx, cvRoi.x, cvRoi.y, cvRoi.width, cvRoi.height); SaveDebugImage(eDim, stFrame, cvImage, str); int state = (i == 0) ? 1 : (cvImage.rows < IMAGE_HEIGHT ? 2 : 3); SendImageDataOverWebSocket(eDim, stFrame, i, cvImage.data, state, rtROI.left, IMAGE_HEIGHT * i + rtROI.top, cvImage.cols, cvImage.rows); } auto end = std::chrono::high_resolution_clock::now(); g_pLog->DisplayMessage(_T("%s TestSendWebSocketMessage time: %ld"), GetSideName(eDim), std::chrono::duration_cast(end - start).count()); return TRUE; } BOOL CInspectCamera::SendFrameScanDataOverWebSocket(int iThread, DimensionDir eDim, stFrameIndex stFrame) { if (!m_pGlassData || !m_pRecipe) return FALSE; for (int i = 0; i < MAX_SIDE_INSPECT_TYPE; i++) { m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_bUseInspect = TRUE; } int nSideLine = m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[stFrame.nFrameIdx]; if (nSideLine < 0) return FALSE; std::vector vecInspectAreaList; // For Notch Region Divide.. int nCutLine = 0; 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++) { if (MAX_SIDE_INSPECT_AREA_COUNT <= nRegionIdx) continue; m_pGlassData->GetSideData(eDim)->m_rtInspectArea[stFrame.nFrameIdx] = vecInspectAreaList[nRegionIdx]; CRect rtProcessArea(nSideLine, vecInspectAreaList[nRegionIdx].top, nSideLine + 2048, vecInspectAreaList[nRegionIdx].bottom); if (rtProcessArea.IsRectEmpty() || rtProcessArea.IsRectNull() || nSideLine + 2048 > m_nFrameWidth) return FALSE; if (rtProcessArea.right < rtProcessArea.left) { int nTemp = rtProcessArea.right; rtProcessArea.right = rtProcessArea.left; rtProcessArea.left = nTemp; } CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, vecInspectAreaList[nRegionIdx].top), m_nFrameWidth, m_nFrameHeight); if (frameBuffer.IsValidBuffer() == FALSE) return FALSE; // 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()); // ·¢ËÍ´ÓÁÙʱ»º³åÇøÖлñÈ¡µÄÊý¾Ý 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()); CString str; str.Format(_T("Test\\%sInsArea_Ori_Frame%d_%d_%d_%d_%d"), GetSideName(eDim), stFrame.nFrameIdx, rtProcessArea.left, rtProcessArea.top, rtProcessArea.right, rtProcessArea.bottom); SaveDebugImage(eDim, stFrameIndex(stFrame.nScanIdx, stFrame.nFrameIdx), &pDefectProcessImage, str); } return TRUE; } #endif // USE_WEBSOCKET #if USE_AI_DETECT void CInspectCamera::SetUseAIDetect(bool bUseAIDetect) { m_bUseAIDetect = bUseAIDetect; } long long CInspectCamera::GetCurrentTimestamp() { auto now = std::chrono::system_clock::now(); auto microseconds = std::chrono::duration_cast(now.time_since_epoch()).count(); return microseconds; } BOOL CInspectCamera::SendFrameScanDataOverAI(int iThread, DimensionDir eDim, stFrameIndex stFrame) { if (!m_pGlassData || !m_pRecipe) return FALSE; for (int i = 0; i < MAX_SIDE_INSPECT_TYPE; i++) { m_pRecipe->m_SideParam[(int)eDim].m_InspectPrm[i].m_bUseInspect = TRUE; } int nSideLine = m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[stFrame.nFrameIdx]; if (nSideLine < 0) return FALSE; std::vector vecInspectAreaList; // For Notch Region Divide.. int nCutLine = 0; 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++) { if (MAX_SIDE_INSPECT_AREA_COUNT <= nRegionIdx) continue; if (!m_bUseAIDetect) { CDefect_Info defectInfo; CRect rtDefectPos_pxl(nSideLine, vecInspectAreaList[nRegionIdx].top, nSideLine + 100, vecInspectAreaList[nRegionIdx].top + 100); 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 = rtDefectPos_pxl.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectPos_pxl; defectInfo.m_DefectLoc = DefectLoc_Unknown; m_pDefectControl->ExtractDefect(eDim, m_iCamera, stFrame.nScanIdx, defectInfo); } m_pGlassData->GetSideData(eDim)->m_rtInspectArea[stFrame.nFrameIdx] = vecInspectAreaList[nRegionIdx]; CRect rtProcessArea(nSideLine - 100, vecInspectAreaList[nRegionIdx].top, nSideLine + 1500, vecInspectAreaList[nRegionIdx].bottom); if (rtProcessArea.IsRectEmpty() || rtProcessArea.IsRectNull() || nSideLine + 2048 > m_nFrameWidth) return FALSE; if (rtProcessArea.right < rtProcessArea.left) { int nTemp = rtProcessArea.right; rtProcessArea.right = rtProcessArea.left; rtProcessArea.left = nTemp; } int nHeightOff = m_nFrameHeight - rtProcessArea.Height(); int nState = (stFrame.nFrameIdx == 0) ? 1 : (rtProcessArea.Height() < IMAGE_HEIGHT ? 2 : 3); if (nState == 1) { rtProcessArea.top -= nHeightOff; continue; } else { rtProcessArea.bottom += nHeightOff; } // ±£Ö¤Í¼Ïñ¸ß¶ÈΪ4µÄ±¶Êý nHeightOff = rtProcessArea.Height() % 4; if (nHeightOff != 0) { int nHeight = rtProcessArea.Height() + 4 - nHeightOff; rtProcessArea.bottom = rtProcessArea.top + nHeight; //rtProcessArea.bottom -= nHeightOff; } CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, rtProcessArea.top), m_nFrameWidth, m_nFrameHeight); if (frameBuffer.IsValidBuffer() == FALSE) return FALSE; CSingleLock myLoc(&m_csThreadGlassStart); myLoc.Lock(); cv::Mat frame(rtProcessArea.Height(), rtProcessArea.Width(), CV_8UC1); for (int i = 0; i < rtProcessArea.Height(); i++) memcpy(frame.ptr(i), frameBuffer.GetDataAddress(rtProcessArea.left, i), rtProcessArea.Width()); myLoc.Unlock(); if (frame.empty() || frame.data == NULL) { g_pLog->DisplayMessage(_T("%s Could not open or find the image!"), GetSideName(eDim)); return FALSE; } myLoc.Lock(); long long dStartTime = GetCurrentTimestamp(); // ·¢ËÍ´ÓÁÙʱ»º³åÇøÖлñÈ¡µÄÊý¾Ý std::vector results; if (m_pAiDetectEx->detect(frame, results, m_strChannel)) { for (auto& result : results) { CDefect_Info defectInfo; CRect rtDefectPos_pxl(result.x + nSideLine, result.y + vecInspectAreaList[nRegionIdx].top, result.x + result.width + nSideLine, result.y + result.height + vecInspectAreaList[nRegionIdx].top); 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 = rtDefectPos_pxl.CenterPoint(); defectInfo.m_rtDefectPos_pxl = rtDefectPos_pxl; defectInfo.m_DefectLoc = (DefectLocation)result.type; m_pDefectControl->ExtractDefect(eDim, m_iCamera, stFrame.nScanIdx, defectInfo); cv::rectangle(frame, cv::Rect(result.x, result.y, result.width, result.height), cv::Scalar(0, 255, 0), 2); } } long long dEndTime = GetCurrentTimestamp(); myLoc.Unlock(); g_pLog->DisplayMessage(_T("strSideName = %s, nFrameIdx = %d, width = %d, height = %d, timestamp = %ld"), g_SideName[(int)eDim], stFrame.nFrameIdx, rtProcessArea.Width(), rtProcessArea.Height(), dEndTime - dStartTime); CString str; str.Format(_T("Test\\%sInsArea_Ori_Frame%d_%d_%d_%d_%d"), GetSideName(eDim), stFrame.nFrameIdx, rtProcessArea.left, rtProcessArea.top, rtProcessArea.right, rtProcessArea.bottom); SaveDebugImage(eDim, stFrameIndex(stFrame.nScanIdx, stFrame.nFrameIdx), frame, str); } return TRUE; } #endif // USE_WEBSOCKET