| | |
| | | #include "StdAfx.h" |
| | | #include "StdAfx.h" |
| | | #include "InspectCamera.h" |
| | | #include "GlassRecipe.h" |
| | | #include "HardwareSettings.h" |
| | |
| | | #endif // USE_WEBSOCKET |
| | | |
| | | #define BOUNDARY_GLASSSTARTWIDTH 160 |
| | | #define BOUNDARYHORIZ_LEVELDIST 8 // 荐乞 版拌急阑 茫阑 锭狼 厚背芭府 |
| | | #define BOUNDARYHORIZ_LEVELDIST 8 // 수평 경계선을 찾을 때의 비교거리 |
| | | #define TIME_WAIT_GLASS_START 3000 |
| | | |
| | | #define align_4byte(in) ((in + 3)/4)*4 |
| | |
| | | if(m_bFindGlassStart[stFrame.nScanIdx] == TRUE) |
| | | return ERR_FINDGLASSSTART_SUCCESS; |
| | | |
| | | // 磊悼老锭 橇饭烙 荐甫 面盒洒 棱栏搁 巩力啊 救登绰芭 鞍促父... 橇饭烙 荐啊 何练窍搁 咯扁辑 公茄栏肺 吧覆.. 弊府绊 矫累急 茫疽栏搁 弊成 逞绢啊搁 登瘤 臼唱? |
| | | // 자동일때 프레임 수를 충분히 잡으면 문제가 안되는거 같다만... 프레임 수가 부족하면 여기서 무한으로 걸림.. 그리고 시작선 찾았으면 그냥 넘어가면 되지 않나? |
| | | if(m_pGrabber->GetGrabFrameCount() < 1) |
| | | { |
| | | Sleep(0); |
| | |
| | | |
| | | while(TRUE) |
| | | { |
| | | Sleep(1); // Sleep 1肺 吧绢拎具 茄促... 0栏肺 吧搁 八荤啊 救瞪嫐啊 乐澜.. 恐? |
| | | Sleep(1); // Sleep 1로 걸어줘야 한다... 0으로 걸면 검사가 안될가 있음.. 왜? |
| | | |
| | | if(GetCheckExit() == TRUE) |
| | | { |
| | |
| | | break; |
| | | } |
| | | |
| | | // 1. 0锅 Thread肺 Start Line 茫扁 |
| | | // 1. 0번 Thread로 Start Line 찾기 |
| | | int iRetScan; |
| | | switch(IsGlassStartLine(iThread,iRetScan)) |
| | | { |
| | |
| | | break; |
| | | } |
| | | |
| | | // 2. Start Line阑 茫疽栏搁, 茄橇饭烙究 波郴辑 八荤 矫累 |
| | | // 2. Start Line을 찾았으면, 한프레임씩 꺼내서 검사 시작 |
| | | stFrameIndex stFrame = m_pGrabber->GetGrabFrame(); |
| | | if(stFrame.nScanIdx < 0 || stFrame.nFrameIdx < 0) |
| | | continue; |
| | |
| | | |
| | | m_pGlassData->GetSideData(emDim)->SetFrameProc(stFrame.nFrameIdx); |
| | | |
| | | // 3. Start Line Frame 焊促 捞傈牢瘤 眉农.. |
| | | // 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); |
| | |
| | | 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(); |
| | |
| | | for (int i = 0; i < ngNum; i++) { |
| | | NgInfo ng = ngArray[i]; |
| | | |
| | | //if (ng.isRes) continue; //结果OK,继续 |
| | | //这里添加结果 |
| | | //if (ng.isRes) continue; //써벎OK,셨崎 |
| | | //侶쟁警속써벎 |
| | | |
| | | if (5 == ng.ngType && (ng.result < ng.minValue || ng.result > ng.maxValue)) |
| | | { |
| | |
| | | |
| | | BOOL CInspectCamera::CheckThreadEnd(int iThread,stFrameIndex stFrame) |
| | | { |
| | | int iScan = stFrame.nScanIdx; |
| | | |
| | | CSingleLock myLoc(&m_csThreadEnd); |
| | | myLoc.Lock(); |
| | | |
| | | // 捞固 场抄 Thread.. |
| | | if(m_iThreadEnd[iScan][iThread] == 1) |
| | | { |
| | | int iScan = stFrame.nScanIdx; |
| | | if (m_iThreadEnd[iScan][iThread] == 1) { |
| | | myLoc.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | BOOL bEnd = FALSE; |
| | | |
| | | if(CheckProcessEnd(iThread,stFrame) == TRUE) |
| | | { |
| | | if (CheckProcessEnd(iThread, stFrame) == TRUE) { |
| | | m_iThreadEnd[iScan][iThread] = 1; |
| | | bEnd = TRUE; |
| | | myLoc.Unlock(); |
| | | } |
| | | |
| | | if(bEnd == TRUE) |
| | | { |
| | | if (bEnd == TRUE) { |
| | | DimensionDir emDim = GetDimension(iScan); |
| | | |
| | | m_pGlassData->GetSideData(emDim)->m_bInspection_Complete = TRUE; |
| | | |
| | | g_pLog->DisplayMessage(_T("%s Thread %d Process End : Scan %d, Frame %d"),PANEL_SIDE[emDim],iThread,iScan,stFrame.nFrameIdx); |
| | | |
| | | if(GetThreadEndCount(iScan) == MAX_THREAD) |
| | | { |
| | | 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) |
| | | 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); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | m_nFrameFinishIdx[nCurrentScanIdx] = -1; |
| | | |
| | | for(int i=0; i<MAX_FRAM_COUNT; i++) |
| | | for (int i = 0; i < MAX_FRAM_COUNT; i++) { |
| | | m_bFrameFinish[nCurrentScanIdx][i] = FALSE; |
| | | } |
| | | |
| | | cslocalLock.Unlock(); |
| | | } |
| | |
| | | CSingleLock cslocalLock(&m_csFrameFinishCheck); |
| | | cslocalLock.Lock(); |
| | | |
| | | if(m_nFrameFinishIdx[nCurrentScanIdx] == -1) |
| | | if (m_nFrameFinishIdx[nCurrentScanIdx] == -1) { |
| | | cslocalLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | for(int i=0; i<m_nFrameFinishIdx[nCurrentScanIdx]; i++) |
| | | if(m_bFrameFinish[nCurrentScanIdx][i] == FALSE) |
| | | for (int i = 0; i < m_nFrameFinishIdx[nCurrentScanIdx]; i++) { |
| | | if (m_bFrameFinish[nCurrentScanIdx][i] == FALSE) { |
| | | cslocalLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | } |
| | | |
| | | cslocalLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | |
| | |
| | | double dRotate_X_pxl = sin(dRotateArea_T_Rad) * dMarkToArea_Distance_pxl * dDirection; |
| | | double dRotate_Y_pxl = cos(dRotateArea_T_Rad) * dMarkToArea_Distance_pxl * dDirection; |
| | | |
| | | bRotateArea.left = bRotateArea.right = (int) ptFind_TopMark.x + dRotate_X_pxl; |
| | | bRotateArea.top = bRotateArea.bottom = (int) ptFind_TopMark.y + dRotate_Y_pxl; |
| | | bRotateArea.left = bRotateArea.right = ptFind_TopMark.x + (LONG)dRotate_X_pxl; |
| | | bRotateArea.top = bRotateArea.bottom = ptFind_TopMark.y + (LONG)dRotate_Y_pxl; |
| | | |
| | | bRotateArea.InflateRect(rtSetArea.Width()/2, rtSetArea.Height()/2); |
| | | |
| | |
| | | |
| | | void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, cv::Mat image, CString strFileName) |
| | | { |
| | | if (m_pHardparm == NULL) |
| | | if (m_pHardparm == NULL) { |
| | | return; |
| | | } |
| | | |
| | | if (m_pHardparm->m_bUse_SaveDebugImage == FALSE) |
| | | if (m_pHardparm->m_bUse_SaveDebugImage == FALSE) { |
| | | return; |
| | | } |
| | | |
| | | // #ifdef _DEBUG |
| | | if (image.empty() || image.data == NULL) |
| | | if (image.empty() || image.data == NULL) { |
| | | return; |
| | | } |
| | | |
| | | CString str; |
| | | str.Format(_T("D:\\Inspection\\DebugFullImg\\%s_Side[%s]_Frame[%d].jpg"), strFileName, GetSideName(eDim), stFrame.nFrameIdx); |
| | | |
| | | try |
| | | { |
| | | try { |
| | | g_pStatus->CheckDirectory(str); |
| | | |
| | | USES_CONVERSION; |
| | |
| | | std::string filePath(asciiStr); |
| | | cv::imwrite(filePath, image); |
| | | } |
| | | catch (...) |
| | | { |
| | | catch (...) { |
| | | g_pLog->DisplayMessage(_T("SaveDebugImage error...")); |
| | | } |
| | | |
| | |
| | | |
| | | void CInspectCamera::SaveFullImageCopy(int iScan) |
| | | { |
| | | // 4/17 |
| | | // 畴飘合 皋葛府啊 叠妨辑 促款登绰淀.. |
| | | // return; |
| | | if (m_pGlassData == NULL) { |
| | | return; |
| | | } |
| | | |
| | | if(m_pGlassData == NULL) |
| | | if (m_pGrabber == 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) |
| | | if (pSideData == NULL) { |
| | | cLock.Unlock(); |
| | | return; |
| | | } |
| | | |
| | | int nSetEnd = (pSideData->m_nGlassEndLine <= 0) ? pSideData->m_nPreGlassEndLine : pSideData->m_nGlassEndLine; |
| | | int nOffset = 1000; |
| | |
| | | |
| | | g_pLog->DisplayMessage(_T("%s Copy Full Image : nStartLine=%d, nEndLine=%d, nFullSize=%d"), PANEL_SIDE[eDim], nStartLine, nEndLine, nFullSize); |
| | | |
| | | if(nStartLine < 0) |
| | | { |
| | | if (nStartLine < 0) { |
| | | nStartLine = 0; |
| | | } |
| | | |
| | | if(nFullSize <= 0 || nEndLine < 0) |
| | | if (nFullSize <= 0 || nEndLine < 0) { |
| | | cLock.Unlock(); |
| | | return; |
| | | } |
| | | |
| | | //if(nFullSize <= nStartLine) |
| | | // return; |
| | | if (nFullSize <= nStartLine) { |
| | | cLock.Unlock(); |
| | | return; |
| | | } |
| | | |
| | | pINSPECTFULLIMAGE_BUFFER pImgBuf = GetFullImgBuffer(iScan); |
| | | int nFrameWidth,nFrameHeight; |
| | | |
| | | GetFrameSize(m_iCamera,iScan,nFrameWidth,nFrameHeight); |
| | | |
| | | if(nFrameWidth <= 0 || nFrameHeight <= 0) |
| | | if (nFrameWidth <= 0 || nFrameHeight <= 0) { |
| | | cLock.Unlock(); |
| | | return; |
| | | } |
| | | |
| | | if(nFullSize/nFrameHeight > m_pGrabber->GetFrameBuffer()->GetFrameCount()) |
| | | if (nFullSize / nFrameHeight > m_pGrabber->GetFrameBuffer()->GetFrameCount()) { |
| | | nFullSize = (m_pGrabber->GetFrameBuffer()->GetFrameCount()-1)*nFrameHeight; |
| | | } |
| | | |
| | | if(nFullSize <= 100) |
| | | if (nFullSize <= 100) { |
| | | cLock.Unlock(); |
| | | return; |
| | | } |
| | | |
| | | pImgBuf->iCamIdx = m_iCamera; |
| | | pImgBuf->iScanIdx = iScan; |
| | |
| | | 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) |
| | | { |
| | | if (lpHeader == NULL) { |
| | | cLock.Unlock(); |
| | | g_pLog->DisplayMessage(_T("%s Full Image Memory Copy fail : Start[%d]-End[%d]"),PANEL_SIDE[eDim],nStartLine,nEndLine); |
| | | return; |
| | | } |
| | |
| | | if(pSideData->m_nPreGlassEndFrame+MAX_THREAD <= stFrame.nFrameIdx) |
| | | return TRUE; |
| | | |
| | | // Glass End Line阑 茫绰 Thread 鳖瘤 柳青 吝捞搁 促 场抄芭瘤.. |
| | | // Glass End Line을 찾는 Thread 까지 진행 중이면 다 끝난거지.. |
| | | if(pSideData->m_bFindGlassEndLine == TRUE || pSideData->GetFrameProc(pSideData->m_nPreGlassEndFrame) == TRUE) |
| | | return TRUE; |
| | | |
| | |
| | | ::SendMessage(m_hWndViewScan, WM_POCESS_STATUS,(WPARAM)&m_MsgJob, (int)emDim); |
| | | |
| | | #define BOUNDARY_GLASSSTARTWIDTH_ENDLINE 140 |
| | | #define BOUNDARYHORIZ_LEVELDIST_ENDLINE 50 // 荐乞 版拌急阑 茫阑 锭狼 厚背芭府 |
| | | #define BOUNDARYHORIZ_LEVELDIST_ENDLINE 50 // 수평 경계선을 찾을 때의 비교거리 |
| | | |
| | | int nFrameWidth = m_nFrameWidth; |
| | | int nFrameHeight = m_nFrameHeight; |
| | |
| | | |
| | | if (j <= (pVertBuffer.GetHeight()-1-BOUNDARYHORIZ_LEVELDIST_ENDLINE)) |
| | | { |
| | | if(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] == 0 || pnSum[j] == 0) // 肋 给 等 捞固瘤.. |
| | | if (pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] == 0 || pnSum[j] == 0) // 잘 못 된 이미지.. |
| | | continue; |
| | | |
| | | nGab = abs(pnSum[j + BOUNDARYHORIZ_LEVELDIST_ENDLINE] - pnSum[j]); |
| | |
| | | |
| | | if (nCountinueCount >= 2) |
| | | { |
| | | // Glass狼 矫累瘤痢阑 茫酒辑 备炼眉俊 持绰促. |
| | | // Glass의 시작지점을 찾아서 구조체에 넣는다. |
| | | pSideData->m_nGlassEndLine = nStartFrame*nFrameHeight + j + 2; |
| | | pSideData->m_nGlassEndFrame = pSideData->m_nGlassEndLine/nFrameHeight; |
| | | pSideData->m_bFindGlassEndLine = TRUE; |
| | |
| | | pSideData->m_nSideLineFrame[stFrame.nFrameIdx] = nFindLine; |
| | | pSideData->m_nSideLinePosY[stFrame.nFrameIdx] = rtROI.CenterPoint().y + nFrameYPos; |
| | | |
| | | // Side 茫绊, Chamfer 茫绰芭 眠啊 鞘夸... |
| | | // Side 찾고, Chamfer 찾는거 추가 필요... |
| | | pSideData->m_nSide_Chamfer_LineFrame[stFrame.nFrameIdx] = nFindLine + 0; |
| | | |
| | | g_pLog->DisplayMessage(_T("Find Side Line Frame[%d], Side[%d]"), stFrame.nFrameIdx, nFindLine); |
| | |
| | | { |
| | | CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); |
| | | |
| | | if(pSideData == NULL) |
| | | { |
| | | if (pSideData == NULL) { |
| | | g_pLog->DisplayMessage(_T("Side Line Find Fail - Glass Data or HW Setting Error")); |
| | | return FALSE; |
| | | } |
| | |
| | | CRect rtROI; |
| | | rtROI.IntersectRect(rtFrame_pxl, rtAllSide_pxl); |
| | | |
| | | if(rtROI.IsRectEmpty() || rtROI.IsRectNull()) |
| | | if (rtROI.IsRectEmpty() || rtROI.IsRectNull()) { |
| | | return FALSE; |
| | | } |
| | | |
| | | // 4. Exception Notch Area... |
| | | std::vector<CRect> vectorInspectAreaList_New; |
| | |
| | | |
| | | std::vector<CRect> vecInspectArea; |
| | | |
| | | for(int i=0; i<nNotchCount; i++) |
| | | { |
| | | for (int i = 0; i < nNotchCount; i++) { |
| | | CRect rtNotchArea = pSideData->m_rtNotchArea_pxl[i]; |
| | | rtNotchArea.left = GetLeftMargin(m_iCamera,stFrame.nScanIdx); |
| | | rtNotchArea.right = m_nFrameWidth-1; |
| | |
| | | std::copy(vectorInspectAreaList_New.begin(), vectorInspectAreaList_New.end(), vectorInspectAreaList_Old.begin()); |
| | | vectorInspectAreaList_New.clear(); |
| | | |
| | | for(int j=0; j<vectorInspectAreaList_Old.size(); j++) |
| | | { |
| | | for (int j = 0; j < vectorInspectAreaList_Old.size(); j++) { |
| | | CRect rtTemp = vectorInspectAreaList_Old[j]; |
| | | |
| | | CRect rtNotchInterSectRect; |
| | | rtNotchInterSectRect.IntersectRect(rtTemp, rtNotchArea); |
| | | |
| | | if(rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) // 畴摹啊 救吧府绰 版快俊绰 促矫 持绢霖促.. |
| | | { |
| | | if (rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) { |
| | | vectorInspectAreaList_New.push_back(rtTemp); |
| | | continue; |
| | | } |
| | | |
| | | if(rtTemp.Height() == rtNotchInterSectRect.Height()) // Notch啊 康开狼 傈眉牢 版快 |
| | | if (rtTemp.Height() == rtNotchInterSectRect.Height()) { |
| | | continue; |
| | | } |
| | | |
| | | if(rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) // 1. Notch Frame 困俊 吧赴 版快 |
| | | { |
| | | if (rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) { |
| | | CRect rtNew = rtTemp; |
| | | rtNew.top = rtNotchInterSectRect.bottom; |
| | | vectorInspectAreaList_New.push_back(rtNew); |
| | | } |
| | | else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) // 2. Notch Frame 吝埃俊 吧赴 版快 |
| | | { |
| | | else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) { |
| | | CRect rtNewTop = rtTemp; |
| | | rtNewTop.top = rtNotchInterSectRect.bottom; |
| | | vectorInspectAreaList_New.push_back(rtNewTop); |
| | |
| | | rtNewBot.bottom = rtNotchInterSectRect.top; |
| | | vectorInspectAreaList_New.push_back(rtNewBot); |
| | | } |
| | | else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) // 3. Notch Frame 酒贰俊 吧赴 版快 |
| | | { |
| | | else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) { |
| | | CRect rtNew = rtTemp; |
| | | rtNew.bottom = rtNotchInterSectRect.top; |
| | | vectorInspectAreaList_New.push_back(rtNew); |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | // 5. Side List.. |
| | | vecInspectArea.clear(); |
| | | |
| | | for(int i=0; i<vectorInspectAreaList_New.size(); i++) |
| | | { |
| | | for (int i = 0; i < vectorInspectAreaList_New.size(); i++) { |
| | | CRect rtInspectArea = vectorInspectAreaList_New[i]; |
| | | vecInspectArea.push_back(rtInspectArea); |
| | | } |
| | |
| | | #endif |
| | | |
| | | int stepSide = m_pGrabber->GetFrameBuffer()->GetFrameHeight(); |
| | | |
| | | for(int i=0; i<vecInspectArea.size(); i++) |
| | | { |
| | | for (int i = 0; i < vecInspectArea.size(); i++) { |
| | | CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(stFrame.nScanIdx, vecInspectArea[i].top),nFrameWidth,vecInspectArea[i].Height()); |
| | | |
| | | if(frameBuffer.IsValidBuffer() == FALSE) |
| | | if (frameBuffer.IsValidBuffer() == FALSE) { |
| | | continue; |
| | | } |
| | | |
| | | #ifdef _DEBUG |
| | | CString str; |
| | |
| | | CRect rtFindROI = vecInspectArea[i]; |
| | | rtFindROI.OffsetRect(0, -rtFindROI.top); |
| | | |
| | | if(nSearchHeight < rtFindROI.Height()) |
| | | { |
| | | if (nSearchHeight < rtFindROI.Height()) { |
| | | CPoint ptCenter = rtFindROI.CenterPoint(); |
| | | rtFindROI.top = ptCenter.y - (nSearchHeight/2); |
| | | rtFindROI.bottom = ptCenter.y + (nSearchHeight/2); |
| | |
| | | int nSideLine = -1; |
| | | EdgeFind.FindEdge_ToRightROI(&frameBuffer,nSideLine,DEFECT_EDGE_AUTO_PITCH,nThres,DEFECT_EDGE_AUTO_RATIO,0,rtFindROI); |
| | | |
| | | if(nSideLine != -1) |
| | | { |
| | | if (nSideLine != -1) { |
| | | #if HALCON_VISION_KEY |
| | | if (NULL != pBlSideData){ |
| | | SideLineInf inf; |
| | |
| | | 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, |
| | |
| | | chamferIns.Binarization(frameBuffer,ImgInsBin,nChamferLineThres); |
| | | |
| | | chamferIns.FindRightLine_Bin(ImgInsBin,nSideLine,dLine); |
| | | if(dLine != -1) |
| | | { |
| | | if (dLine != -1) { |
| | | nFindSideChamferLineSum += (int)dLine; |
| | | nFindSideChamferLineCount++; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if(nFindSideLineCount > 0) |
| | | { |
| | | int nAvgSideLine = (int) (nFindSideLineSum / nFindSideLineCount); // Average.. |
| | | if (nFindSideLineCount > 0) { |
| | | int nAvgSideLine = (int)(nFindSideLineSum / nFindSideLineCount); |
| | | m_iSideLine[stFrame.nScanIdx] = nAvgSideLine; |
| | | pSideData->m_nSideLineFrame[stFrame.nFrameIdx] = nAvgSideLine; |
| | | pSideData->m_nSideLinePosY[stFrame.nFrameIdx] = rtROI.CenterPoint().y + nFrameYPos; |
| | | } |
| | | |
| | | if(nFindSideChamferLineCount > 0) |
| | | { |
| | | if (nFindSideChamferLineCount > 0) { |
| | | int nAvgChamferLine = (int) (nFindSideChamferLineSum / nFindSideChamferLineCount); // Average.. |
| | | pSideData->m_nSide_Chamfer_LineFrame[stFrame.nFrameIdx] = nAvgChamferLine; // Chamfer Line |
| | | } |
| | |
| | | CSingleLock localLock(&m_csTopCorner); |
| | | localLock.Lock(); |
| | | |
| | | if(m_pGlassData == NULL) |
| | | if (m_pGlassData == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); |
| | | CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim]; |
| | | |
| | | if(pSideData == NULL || pSideParam == NULL) |
| | | if (pSideData == NULL || pSideParam == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if(pSideData->m_bFindGlassStartLine == FALSE) |
| | | if (pSideData->m_bFindGlassStartLine == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if(pSideData->m_bTopCorner_Find == TRUE) |
| | | if (pSideData->m_bTopCorner_Find == TRUE) { |
| | | localLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | |
| | | /* |
| | | BOOL bTopCornerUse = (BOOL) (m_pRecipe->m_SideParam[emDim].m_nTopCornerShape == 0) ? FALSE : TRUE; |
| | | |
| | | // Not Use Corner Inspection |
| | | if(bTopCornerUse == FALSE) |
| | | if (bTopCornerUse == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | */ |
| | | } |
| | | |
| | | double dCornerSizeY_Um = (double) m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeY_um; |
| | | |
| | | int nCornerSizeY_Pixel = (int) GetUmToPixel_Y(dCornerSizeY_Um); |
| | | |
| | | int nFrameHeight = m_nFrameHeight; |
| | | |
| | | int nFindStartLine = pSideData->m_nGlassStartLine; |
| | | |
| | | int nTopCornerFrameIndex = (nFindStartLine + nCornerSizeY_Pixel) / nFrameHeight; |
| | | |
| | | if(stFrame.nFrameIdx < nTopCornerFrameIndex+1) |
| | | if (stFrame.nFrameIdx < nTopCornerFrameIndex + 1) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | int nSideLine = pSideData->m_nSideLineFrame[nTopCornerFrameIndex+1]; |
| | | int nSideLine = (int)pSideData->m_nSideLineFrame[nTopCornerFrameIndex + 1]; |
| | | |
| | | if(nSideLine == -1) |
| | | if (nSideLine == -1) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | double dCornerSizeX_Um = (double) m_pRecipe->m_SideParam[emDim].m_nTopCornerSizeX_um; |
| | | |
| | | int nCornerSizeX_Pixel = (int) GetUmToPixel_X(dCornerSizeX_Um); |
| | | |
| | | CRect rtTopCornerArea(0, 0, nCornerSizeX_Pixel, nCornerSizeY_Pixel); |
| | | |
| | | rtTopCornerArea.OffsetRect(nSideLine, nFindStartLine); |
| | | |
| | | pSideData->m_bTopCorner_Find = TRUE; |
| | |
| | | int nTopCornerType = m_pRecipe->m_SideParam[emDim].m_nTopCornerShape; |
| | | pSideData->m_nTopCornerShape = m_pRecipe->m_SideParam[emDim].m_nTopCornerShape;; |
| | | |
| | | if(pSideParam->m_bTopCornerFindDefect == FALSE) |
| | | if (pSideParam->m_bTopCornerFindDefect == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | localLock.Unlock(); |
| | | |
| | | if(nTopCornerType == (int) 1) return FindTopCorner_CCut(iThread, emDim, stFrame); |
| | | else if(nTopCornerType == (int) 2) return FindTopCorner_RCut(iThread, emDim, stFrame); |
| | |
| | | CSingleLock localLock(&m_csThreadTopAlignMark); |
| | | localLock.Lock(); |
| | | |
| | | if(m_pGlassData == NULL) |
| | | if (m_pGlassData == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); |
| | | |
| | | if(pSideData == NULL) |
| | | if (pSideData == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if(pSideData->m_bFindGlassStartLine == FALSE) |
| | | if (pSideData->m_bFindGlassStartLine == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if(pSideData->m_bTopMark_Find == TRUE) |
| | | if (pSideData->m_bTopMark_Find == TRUE) { |
| | | localLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | |
| | | if(pSideData->m_bTopCorner_Find == FALSE) |
| | | if (pSideData->m_bTopCorner_Find == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | BOOL bTopAlignMark = (BOOL) (m_pRecipe->m_SideParam[eDim].m_bTopMark_Use == 1) ? TRUE : FALSE; |
| | | |
| | | if(bTopAlignMark == FALSE) |
| | | if (bTopAlignMark == FALSE) { |
| | | localLock.Unlock(); |
| | | return FindTopAlignMark_Virtual(iThread, eDim, stFrame); |
| | | else |
| | | { |
| | | if(FindTopAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) |
| | | } |
| | | else { |
| | | if (FindTopAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) { |
| | | localLock.Unlock(); |
| | | return FindTopAlignMark_Virtual(iThread, eDim, stFrame); |
| | | else |
| | | } |
| | | else { |
| | | localLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | if((int) stFrame.nFrameIdx < nTopAlignMarkYPramIdx + 1) |
| | | return FALSE; |
| | | |
| | | int nSideLine = pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1]; |
| | | int nSideLine = (int)pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1]; |
| | | double nEdgeToTopAlignMarkX_Um = m_pRecipe->m_SideParam[eDim].m_nTopMarkToEdgeX_um; |
| | | int nEdgeToTopAlignMarkX_Pixel = (int) GetUmToPixel_X(nEdgeToTopAlignMarkX_Um); |
| | | int nTopAlignMarkX_Pixel = nSideLine + nEdgeToTopAlignMarkX_Pixel; |
| | |
| | | if((int) stFrame.nFrameIdx < nTopAlignMarkYPramIdx + 1) |
| | | return FALSE; |
| | | |
| | | int nSideLine = pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1]; |
| | | int nSideLine = (int)pSideData->m_nSideLineFrame[nTopAlignMarkYPramIdx + 1]; |
| | | |
| | | if(nSideLine <= 0) |
| | | { |
| | |
| | | CSingleLock localLock(&m_csBotCorner); |
| | | localLock.Lock(); |
| | | |
| | | if(m_pGlassData == NULL) |
| | | if (m_pGlassData == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | CSide_Data* pSideData = m_pGlassData->GetSideData(emDim); |
| | | CSIDE_PARM* pSideParam = &m_pRecipe->m_SideParam[(int) emDim]; |
| | | |
| | | if(pSideData == NULL || pSideParam == NULL) |
| | | if (pSideData == NULL || pSideParam == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if (pSideData->m_bFindGlassStartLine == FALSE || pSideData->m_bFindGlassEndLine == FALSE) |
| | | if (pSideData->m_bFindGlassStartLine == FALSE || pSideData->m_bFindGlassEndLine == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if(pSideData->m_bBotCorner_Find == TRUE) |
| | | if (pSideData->m_bBotCorner_Find == TRUE) { |
| | | localLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | |
| | | /* |
| | | BOOL bBotCornerUse = (BOOL) (m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape == 0) ? FALSE : TRUE; |
| | | |
| | | if(bBotCornerUse == FALSE) |
| | | if (bBotCornerUse == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | */ |
| | | } |
| | | |
| | | double dCornerSizeY_Um = (double) m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeY_um; |
| | | |
| | | int nCornerSizeY_Pixel = (int) GetUmToPixel_Y(dCornerSizeY_Um); |
| | | |
| | | int nFrameHeight = m_nFrameHeight; |
| | | |
| | | int nFindBottomLine = (pSideData->m_bFindGlassEndLine == TRUE) ? pSideData->m_nGlassEndLine : pSideData->m_nPreGlassEndLine; |
| | | |
| | | int nBottomCornerFrameIndex = (nFindBottomLine - nCornerSizeY_Pixel) / nFrameHeight; |
| | | |
| | | if((int) stFrame.nFrameIdx < nBottomCornerFrameIndex) |
| | | if ((int)stFrame.nFrameIdx < nBottomCornerFrameIndex) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | // 澜.. 内呈 Side 扼牢捞 捞傈 橇饭烙俊 乐栏搁 绢录瘤.. 茄搁俊 Thread 啊 咯矾俺 倒搁?... 困 橇饭烙狼 Thread 啊 酒流 Side 扼牢阑 给茫疽栏搁.. 绊刮 粱 秦焊磊.. |
| | | // 荤捞靛喊 Thread绰 窍唱父 倒绊 八荤 Thread甫 咯矾俺 倒府绰 备炼肺 官层具摆促 |
| | | int nSideLine = pSideData->m_nSideLineFrame[nBottomCornerFrameIndex]; |
| | | nSideLine = (nSideLine == -1) ? pSideData->m_nSideLineFrame[nBottomCornerFrameIndex] : nSideLine; |
| | | // 음.. 코너 Side 라인이 이전 프레임에 있으면 어쩌지.. 한면에 Thread 가 여러개 돌면?... 위 프레임의 Thread 가 아직 Side 라인을 못찾았으면.. 고민 좀 해보자.. |
| | | // 사이드별 Thread는 하나만 돌고 검사 Thread를 여러개 돌리는 구조로 바꿔야겠다 |
| | | int nSideLine = (int)pSideData->m_nSideLineFrame[nBottomCornerFrameIndex]; |
| | | nSideLine = (nSideLine == -1) ? (int)pSideData->m_nSideLineFrame[nBottomCornerFrameIndex] : nSideLine; |
| | | |
| | | if(nSideLine == -1) |
| | | if (nSideLine == -1) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | double dCornerSizeX_Um = (double) m_pRecipe->m_SideParam[emDim].m_nBottomCornerSizeX_um; |
| | | |
| | | int nCornerSizeX_Pixel = (int) GetUmToPixel_X(dCornerSizeX_Um); |
| | | |
| | | CRect rtBottomCornerArea(0, 0, nCornerSizeX_Pixel, nCornerSizeY_Pixel); |
| | | |
| | | rtBottomCornerArea.OffsetRect(nSideLine, nFindBottomLine-nCornerSizeY_Pixel); |
| | | |
| | | pSideData->m_bBotCorner_Find = TRUE; |
| | |
| | | |
| | | int nBottomCornerType = m_pRecipe->m_SideParam[emDim].m_nBottomCornerShape; |
| | | |
| | | if(pSideParam->m_bBottomCornerFindDefect == FALSE) |
| | | if (pSideParam->m_bBottomCornerFindDefect == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | localLock.Unlock(); |
| | | |
| | | if(nBottomCornerType == (int) 1) return FindBotCorner_CCut(iThread, emDim, stFrame); |
| | | else if(nBottomCornerType == (int) 2) return FindBotCorner_RCut(iThread, emDim, stFrame); |
| | |
| | | CSingleLock localLock(&m_csThreadBotAlignMark); |
| | | localLock.Lock(); |
| | | |
| | | if(m_pGlassData == NULL) |
| | | if (m_pGlassData == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | CSide_Data* pSideData = m_pGlassData->GetSideData(eDim); |
| | | |
| | | if(pSideData == NULL) |
| | | if (pSideData == NULL) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | //if(pSideData->m_bBotCorner_Find == FALSE) |
| | | // return FALSE; |
| | | if (pSideData->m_bBotCorner_Find == FALSE) { |
| | | localLock.Unlock(); |
| | | return FALSE; |
| | | } |
| | | |
| | | if(pSideData->m_bBotMark_Find == TRUE) |
| | | if (pSideData->m_bBotMark_Find == TRUE) { |
| | | localLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | |
| | | BOOL bBotAlignMark = (BOOL) (m_pRecipe->m_SideParam[eDim].m_bBottomMark_Use == 1) ? TRUE : FALSE; |
| | | |
| | | if(bBotAlignMark == FALSE) |
| | | if (bBotAlignMark == FALSE) { |
| | | localLock.Unlock(); |
| | | return FindBotAlignMark_Virtual(iThread, eDim, stFrame); |
| | | else |
| | | { |
| | | if(FindBotAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) |
| | | } |
| | | else { |
| | | if (FindBotAlignMark_TempleteMatching(iThread, eDim, stFrame) == FALSE) { |
| | | localLock.Unlock(); |
| | | return FindBotAlignMark_Virtual(iThread, eDim, stFrame); |
| | | else |
| | | } |
| | | else { |
| | | localLock.Unlock(); |
| | | return TRUE; |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | if((int) stFrame.nFrameIdx < nGlassEndLineFrame) |
| | | return FALSE; |
| | | |
| | | int nSideLine = pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex]; |
| | | int nSideLine = (int)pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex]; |
| | | double nEdgeToBotAlignMarkX_Um = m_pRecipe->m_SideParam[eDim].m_nBottomMarkToEdgeX_um; |
| | | int nEdgeToBotAlignMarkX_Pixel = (int) GetUmToPixel_X(nEdgeToBotAlignMarkX_Um); |
| | | int nBottomAlignMarkX_Pixel = nSideLine + nEdgeToBotAlignMarkX_Pixel; |
| | |
| | | if((int) stFrame.nFrameIdx < nGlassEndLineFrame) |
| | | return FALSE; |
| | | |
| | | int nSideLine = pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex]; |
| | | int nSideLine = (int)pSideData->m_nSideLineFrame[nBottomCornerTopFrameIndex]; |
| | | if(nSideLine <= 0) |
| | | { |
| | | CRect rectSide = CRect(0,nBottomAlignMarkY_Pixel,nFrameWidth-1,nBottomAlignMarkY_Pixel); |
| | |
| | | if(pSideData == NULL) |
| | | return FALSE; |
| | | |
| | | if(pSideData->m_nSideLineFrame[iFrame] < 0) // Side Line阑 给茫篮 版快.. |
| | | if (pSideData->m_nSideLineFrame[iFrame] < 0) // Side Line을 못찾은 경우.. |
| | | return FALSE; |
| | | |
| | | // 1. Make Corner Area |
| | |
| | | |
| | | // 2. Max Inspect Area.. |
| | | CRect rtFrame; |
| | | rtFrame.left = pSideData->m_nSide_Chamfer_LineFrame[iFrame]; |
| | | rtFrame.left = (LONG)pSideData->m_nSide_Chamfer_LineFrame[iFrame]; |
| | | rtFrame.top = iFrame * m_nFrameHeight; |
| | | rtFrame.right = rtFrame.left; |
| | | rtFrame.bottom = rtFrame.top + m_nFrameHeight; |
| | | |
| | | //rtFrame.top = rtFrame.top; // 困肺 炼陛 歹 八荤秦辑 搬窃捞 钦媚瘤霸 秦焊磊.. |
| | | rtFrame.top = rtFrame.top - 100; // 100 Pixel Frame 唱床柳 版快 巩力啊 登聪, 吝汗 八荤窍磊.. |
| | | //rtFrame.top = rtFrame.top; // 위로 조금 더 검사해서 결함이 합쳐지게 해보자.. |
| | | rtFrame.top = rtFrame.top - 100; // 100 Pixel Frame 나눠진 경우 문제가 되니, 중복 검사하자.. |
| | | |
| | | int nMaxInspectRange = 0; |
| | | |
| | |
| | | if(pSideData == NULL) |
| | | return FALSE; |
| | | |
| | | if(pSideData->m_nSideLineFrame[iFrame] < 0) // Side Line阑 给茫篮 版快.. |
| | | if (pSideData->m_nSideLineFrame[iFrame] < 0) // Side Line을 못찾은 경우.. |
| | | return FALSE; |
| | | |
| | | // 1. Make Corner Area |
| | |
| | | |
| | | // 2. Max Inspect Area.. |
| | | CRect rtFrame; |
| | | rtFrame.left = pSideData->m_nSide_Chamfer_LineFrame[iFrame]; |
| | | rtFrame.left = (LONG)pSideData->m_nSide_Chamfer_LineFrame[iFrame]; |
| | | rtFrame.top = iFrame * m_nFrameHeight; |
| | | rtFrame.right = rtFrame.left; |
| | | rtFrame.bottom = rtFrame.top + m_nFrameHeight; |
| | | |
| | | //rtFrame.top = rtFrame.top; // 困肺 炼陛 歹 八荤秦辑 搬窃捞 钦媚瘤霸 秦焊磊.. |
| | | rtFrame.top = rtFrame.top - 100; // 100 Pixel Frame 唱床柳 版快 巩力啊 登聪, 吝汗 八荤窍磊.. |
| | | //rtFrame.top = rtFrame.top; // 위로 조금 더 검사해서 결함이 합쳐지게 해보자.. |
| | | rtFrame.top = rtFrame.top - 100; // 100 Pixel Frame 나눠진 경우 문제가 되니, 중복 검사하자.. |
| | | |
| | | int nMaxInspectRange = 0; |
| | | |
| | |
| | | CRect rtNotchInterSectRect; |
| | | rtNotchInterSectRect.IntersectRect(rtTemp, rtNotchArea); |
| | | |
| | | if(rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) // 畴摹啊 救吧府绰 版快俊绰 促矫 持绢霖促.. |
| | | if (rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) // 노치가 안걸리는 경우에는 다시 넣어준다.. |
| | | { |
| | | vectorInspectAreaList_New.push_back(rtTemp); |
| | | continue; |
| | | } |
| | | |
| | | if(rtTemp.Height() == rtNotchInterSectRect.Height()) // Notch啊 康开狼 傈眉牢 版快 |
| | | if (rtTemp.Height() == rtNotchInterSectRect.Height()) // Notch가 영역의 전체인 경우 |
| | | continue; |
| | | |
| | | if(rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) // 1. Notch Frame 困俊 吧赴 版快 |
| | | if (rtTemp.top == rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) // 1. Notch Frame 위에 걸린 경우 |
| | | { |
| | | CRect rtNew = rtTemp; |
| | | rtNew.top = rtNotchInterSectRect.bottom; |
| | | vectorInspectAreaList_New.push_back(rtNew); |
| | | } |
| | | else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) // 2. Notch Frame 吝埃俊 吧赴 版快 |
| | | else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom < rtTemp.bottom) // 2. Notch Frame 중간에 걸린 경우 |
| | | { |
| | | CRect rtNewTop = rtTemp; |
| | | rtNewTop.top = rtNotchInterSectRect.bottom; |
| | |
| | | rtNewBot.bottom = rtNotchInterSectRect.top; |
| | | vectorInspectAreaList_New.push_back(rtNewBot); |
| | | } |
| | | else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) // 3. Notch Frame 酒贰俊 吧赴 版快 |
| | | else if (rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) // 3. Notch Frame 아래에 걸린 경우 |
| | | { |
| | | CRect rtNew = rtTemp; |
| | | rtNew.bottom = rtNotchInterSectRect.top; |
| | |
| | | if (rtInspectArea.IsRectEmpty() == TRUE || m_pGlassData == NULL) |
| | | return FALSE; |
| | | |
| | | int nSideLine = m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[iFrame]; |
| | | int nSideLine = (int)m_pGlassData->GetSideData(eDim)->m_nSideLineFrame[iFrame]; |
| | | |
| | | if (nSideLine < 0) |
| | | return FALSE; |
| | |
| | | |
| | | cv::Mat pBinMat = cv::Mat::zeros(pBinImage->GetHeight(), pBinImage->GetWidth(), CV_8UC1); |
| | | |
| | | // OwnerBuffer 郴何肺 16硅荐 皋葛府 爱绊 乐绢辑 茄锅俊 墨乔 救蹬.. |
| | | // OwnerBuffer 내부로 16배수 메모리 갖고 있어서 한번에 카피 안돼.. |
| | | for(int i=0; i<pBinImage->GetHeight(); i++) |
| | | CopyMemory(&pBinMat.data[pBinMat.step1() * i], pBinImage->GetDataAddress(0, i), pBinImage->GetWidth()); |
| | | |
| | |
| | | |
| | | int numOfLables = cv::connectedComponentsWithStats(pBinMat, matLabel, matStats, matCentrois, 8); |
| | | |
| | | if(numOfLables <= 1) // 硅版 窍唱父 乐澜.. |
| | | if (numOfLables <= 1) // 배경 하나만 있음.. |
| | | return TRUE; |
| | | |
| | | std::vector<int> vecMin, vecMax, vecSum, vecPixelCount; |
| | |
| | | int width = matStats.at<int>(nIdx, cv::CC_STAT_WIDTH); |
| | | int height = matStats.at<int>(nIdx, cv::CC_STAT_HEIGHT); |
| | | |
| | | int x = (int)matCentrois.at<double>(nIdx, 0); //吝缴谅钎 |
| | | int x = (int)matCentrois.at<double>(nIdx, 0); //중심좌표 |
| | | int y = (int)matCentrois.at<double>(nIdx, 1); |
| | | |
| | | if(MAX_DEFECT_COUNT_SIDE < nIdx) |
| | |
| | | |
| | | cv::Mat pBinMat = cv::Mat::zeros(pBinImage->height, pBinImage->width, CV_8UC1); |
| | | |
| | | // OwnerBuffer 郴何肺 16硅荐 皋葛府 爱绊 乐绢辑 茄锅俊 墨乔 救蹬.. |
| | | // OwnerBuffer 내부로 16배수 메모리 갖고 있어서 한번에 카피 안돼.. |
| | | for(int i=0; i<pBinImage->height; i++) |
| | | CopyMemory(&pBinMat.data[pBinMat.step1() * i], &pBinImage->imageData[pBinImage->widthStep*i], pBinImage->width); |
| | | |
| | |
| | | |
| | | int numOfLables = cv::connectedComponentsWithStats(pBinMat, matLabel, matStats, matCentrois, 8); |
| | | |
| | | if(numOfLables <= 1) // 硅版 窍唱父 乐澜.. |
| | | if (numOfLables <= 1) // 배경 하나만 있음.. |
| | | return TRUE; |
| | | |
| | | std::vector<int> vecMin, vecMax, vecSum, vecPixelCount; |
| | |
| | | int width = matStats.at<int>(nIdx, cv::CC_STAT_WIDTH); |
| | | int height = matStats.at<int>(nIdx, cv::CC_STAT_HEIGHT); |
| | | |
| | | int x = (int)matCentrois.at<double>(nIdx, 0); //吝缴谅钎 |
| | | int x = (int)matCentrois.at<double>(nIdx, 0); //중심좌표 |
| | | int y = (int)matCentrois.at<double>(nIdx, 1); |
| | | |
| | | if(MAX_DEFECT_COUNT_SIDE < nIdx) |
| | |
| | | if(pSideData == NULL) |
| | | return FALSE; |
| | | |
| | | if(pSideData->m_bFindGlassEndLine == FALSE) // Notch Processing篮 End Line 茫篮 Frame捞.. |
| | | if (pSideData->m_bFindGlassEndLine == FALSE) // Notch Processing은 End Line 찾은 Frame이.. |
| | | return FALSE; |
| | | |
| | | if(m_pRecipe == NULL) |
| | |
| | | g_pLog->DisplayMessage(_T("Notch_Process %s : %d, idx %d - %d,%d,%d,%d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i,rtRotateArea.left,rtRotateArea.top,rtRotateArea.right,rtRotateArea.bottom); |
| | | |
| | | pSideData->m_rtNotchArea_pxl[i] = rtRotateArea; |
| | | //屏蔽Notch 区域上下位置 |
| | | //팁귁Notch 혐堵 龜쫍뿟? |
| | | rtRotateArea.top += 15; |
| | | rtRotateArea.bottom -= 15; |
| | | IplImage* pOriginImage; |
| | |
| | | return; |
| | | } |
| | | |
| | | // 中值滤波器大小,用于去噪,必须为奇数(若偶数会自动减1) |
| | | // 櫓令쫀꺼포댕鬼,痰黨혼臀,극伎槨펜鑒(흼탉鑒삔菱땡숑1) |
| | | const int nSmoothFilter = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter; |
| | | |
| | | // 磨边区域阈值,控制反二值化阈值,主要用于提取 Notch 边缘特征 |
| | | // 칠긋혐堵埴令,왠齡럽랗令뺏埴令,寮狼痰黨瓊혤 Notch 긋鍍景瀝 |
| | | const int nGrindThreshold = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold; |
| | | |
| | | // 玻璃区域阈值,控制正二值化阈值,用于提取玻璃主体区域 |
| | | // 깼젝혐堵埴令,왠齡攣랗令뺏埴令,痰黨瓊혤깼젝寮竟혐堵 |
| | | const int nGlassThreshold = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGlass_Threshold; |
| | | |
| | | // 确保奇数滤波器大小 |
| | | // 횅괏펜鑒쫀꺼포댕鬼 |
| | | int nFilterSize = (nSmoothFilter % 2 == 0) ? (nSmoothFilter - 1) : nSmoothFilter; |
| | | |
| | | if (nFilterSize > 1) { |
| | | // 中值滤波降噪 |
| | | // 櫓令쫀꺼슉臀 |
| | | cvSmooth(scr, img_Bin, CV_MEDIAN, nFilterSize); |
| | | } |
| | | |
| | | // Edge图:反二值化阈值处理 |
| | | // Edge暠:럽랗令뺏埴令뇹잿 |
| | | cvThreshold(scr, img_Edge, nGrindThreshold, 255, CV_THRESH_BINARY_INV); |
| | | CString strEdgeFileName; |
| | | strEdgeFileName.Format(_T("Notch\\Notch_%d_Edge.jpg"), nNotchIdx); |
| | | SaveDebugImage(emDim, stFrame, img_Edge, strEdgeFileName); |
| | | |
| | | // Bin图:正常二值化 |
| | | // Bin暠:攣끽랗令뺏 |
| | | cvThreshold(scr, img_Bin, nGlassThreshold, 255, CV_THRESH_BINARY); |
| | | CString strBinFileName; |
| | | strBinFileName.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx); |
| | |
| | | ptSeed.y = img_Bin_MeasureLine->height / 2; |
| | | |
| | | img_Find_MeasureLine = cvCloneImage(img_Bin_MeasureLine); |
| | | // cvFloodFill(img_Find_MeasureLine, ptSeed, CV_RGB(255,255,255)); // 拱 锭巩俊 急捞 谗绢瘤绰 版快啊 乐绢辑 救茄促. |
| | | // cvFloodFill(img_Find_MeasureLine, ptSeed, CV_RGB(255,255,255)); // 물 때문에 선이 끊어지는 경우가 있어서 안한다. |
| | | // cvThreshold(img_Find_MeasureLine, img_Find_MeasureLine, 100, 255, CV_THRESH_BINARY); |
| | | |
| | | // 2. Find Curve Line |
| | | double dStepAngle = 1.0; |
| | | int nFindStep = (int) (360.0 / dStepAngle); |
| | | int nSkipStep = 30; // 贸澜 30档, 场 30档绰 胶诺茄促. |
| | | int nSkipStep = 30; // 처음 30도, 끝 30도는 스킵한다. |
| | | |
| | | IplImage* img_Find_MeasureLine_Point = cvCloneImage(scr); |
| | | |
| | |
| | | // 3. Meausre |
| | | int nCount = vecPointList.size()-2; |
| | | |
| | | if(nCount < MAX_SIDE_NOTCH_MEASURE_COUNT) // 螟沥 器牢飘 俊矾 |
| | | if (nCount < MAX_SIDE_NOTCH_MEASURE_COUNT) // 측정 포인트 에러 |
| | | { |
| | | cvReleaseImage(&img_Bin_MeasureLine); |
| | | cvReleaseImage(&img_Find_MeasureLine); |
| | |
| | | return; |
| | | } |
| | | |
| | | double dPointStep = (double) nCount / (MAX_SIDE_NOTCH_MEASURE_COUNT-1); // 16 Point 螟沥.. |
| | | double dPointStep = (double)nCount / (MAX_SIDE_NOTCH_MEASURE_COUNT - 1); // 16 Point 측정.. |
| | | |
| | | for(int nMeasureIdx=0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++) |
| | | { |
| | | int nPointIdx = nMeasureIdx * dPointStep; |
| | | int nPointIdx = nMeasureIdx * (int)dPointStep; |
| | | |
| | | if(nPointIdx == 0) nPointIdx = 1; |
| | | else if(vecPointList.size() <= nPointIdx) nPointIdx = vecPointList.size() - 1; |
| | |
| | | { |
| | | double dMeasureRadius = dSearchRadius - dRadius; |
| | | |
| | | int nX = pt_Measure.x - (cos(dAngle_Radian) * dMeasureRadius); |
| | | int nY = pt_Measure.y + (sin(dAngle_Radian) * dMeasureRadius); |
| | | int nX = (int)(pt_Measure.x - (cos(dAngle_Radian) * dMeasureRadius)); |
| | | int nY = (int)(pt_Measure.y + (sin(dAngle_Radian) * dMeasureRadius)); |
| | | |
| | | img_Result->imageData[pt_Measure.y * img_Result->widthStep + pt_Measure.x] = 0; |
| | | |
| | |
| | | |
| | | if(pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] != 1) |
| | | { |
| | | // Make 搬窃.. |
| | | // Make 결함.. |
| | | CRect rtDefectArea = CRect(pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x, |
| | | pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y, |
| | | pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x, |
| | |
| | | pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 1; |
| | | |
| | | #if MINI_LED |
| | | //选取测量研磨尺寸最大值 |
| | | //朞혤꿎좆桔칠넹당離댕令 |
| | | if (m_nChamferOffset_um < dChamfer_um) { |
| | | m_nChamferOffset_um = dChamfer_um; |
| | | } |
| | |
| | | |
| | | if(pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] != 1) |
| | | { |
| | | // Make 搬窃.. |
| | | // Make 결함.. |
| | | CRect rtDefectArea = CRect(pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x, |
| | | pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y, |
| | | pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x, |
| | |
| | | int nThreshold = pNotchParam->m_nNotch_Inspect_Defect_Threshold; |
| | | int nOffset = pNotchParam->m_nNotch_Inspect_Defect_Offset; |
| | | |
| | | #if MINI_NOTCH //Defect检测开关, jiang |
| | | #if MINI_NOTCH //Defect쇱꿎역밑, jiang |
| | | int nEdgeThres = pNotchParam->m_nGrind_Threshold; |
| | | int nNgType = pNotchParam->m_nNotch_Inspect_Defect_Judge_And; |
| | | int xNgSize = pNotchParam->m_nNotch_Inspect_Defect_Judge_X_um; |
| | |
| | | nNotchIdx, nEdgeThres, nThreshold, nOffset, nNgType, |
| | | rtROI.left, rtROI.top, rtROI.right, rtROI.bottom, __LINE__); |
| | | |
| | | //输出计算信息 |
| | | //渴놔셕炬斤口 |
| | | std::vector<Point2D> vNorchPoints; |
| | | for (int nMeasureIdx = 0; nMeasureIdx < MAX_SIDE_NOTCH_MEASURE_COUNT; nMeasureIdx++){ |
| | | CPoint ptChamfer_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx]; |
| | |
| | | vNorchPoints.push_back(point); |
| | | } |
| | | CRect defectResult[100]; |
| | | //nRet为缺陷数量,当前缺陷数 < 1时,表示为OK |
| | | //nRet槨홧屈鑒좆,뎠품홧屈鑒 < 1珂,깊刻槨OK |
| | | int nRet = BlVision_GetSoftVisionApp()->findNorchDefect(nSide, vNorchPoints, rtROI, nEdgeThres, nOffset, nThreshold, nNgType, xNgSize, yNgSize, defectResult); |
| | | printf("Norch Defect Number:%d\n", nRet); |
| | | |
| | |
| | | m_nChamferOffset_um = 0; |
| | | #endif // MINI_LED |
| | | |
| | | // 防止过大导致耗时或内存问题 |
| | | // 렝岺법댕돔鈴봬珂샀코닸狂痙 |
| | | if (nOffset > 50) { |
| | | g_pLog->DisplayMessage(_T("[WARN] Notch defect offset capped to 50 pixels, original: %d"), nOffset); |
| | | nOffset = 50; |
| | |
| | | SaveDebugImage(emDim, stFrame, pProcBinImage, strTemp); |
| | | |
| | | #if MINI_LED == 0 |
| | | // 限制膨胀次数,防止过大导致耗时或内存问题 |
| | | // 掘齡툇郞늴鑒,렝岺법댕돔鈴봬珂샀코닸狂痙 |
| | | int nDilateCount = pNotchParam->m_nNotch_Inspect_Defect_dilate; |
| | | nDilateCount = std::max(0, std::min(nDilateCount, 50)); |
| | | if (pNotchParam->m_nNotch_Inspect_Defect_dilate != nDilateCount) { |
| | |
| | | int iFrame = stFrame.nFrameIdx; |
| | | CRect rtProcessArea = rtROI; |
| | | |
| | | int nMinSize_X = pNotchParam->m_nNotch_Inspect_Defect_Min_X_um / m_pGlassData->GetSideData(emDim)->m_dPixelSizeX; |
| | | int nMinSize_Y = pNotchParam->m_nNotch_Inspect_Defect_Min_Y_um / m_pGlassData->GetSideData(emDim)->m_dPixelSizeY; |
| | | int nMinSize_X = (pNotchParam->m_nNotch_Inspect_Defect_Min_X_um / (int)m_pGlassData->GetSideData(emDim)->m_dPixelSizeX); |
| | | int nMinSize_Y = (pNotchParam->m_nNotch_Inspect_Defect_Min_Y_um / (int)m_pGlassData->GetSideData(emDim)->m_dPixelSizeY); |
| | | int nMinSize = 0; |
| | | |
| | | int nDilation = 0; |
| | |
| | | if(pSideData == NULL) |
| | | return; |
| | | |
| | | if(pSideData->m_bFindGlassEndLine == FALSE) // Notch Processing篮 End Line 茫篮 Frame捞.. |
| | | if (pSideData->m_bFindGlassEndLine == FALSE) // Notch Processing은 End Line 찾은 Frame이.. |
| | | return; |
| | | |
| | | if(m_pRecipe == NULL) |
| | |
| | | double dCenterPos_Y_pxl = rtROI.top + (dCenterPos_Y_um / m_dPixelSizeY); |
| | | |
| | | pSideData->m_nNotchCircle_Radius_Judge[nNotchIdx][nCircleIdx] = 1; |
| | | pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].x = dCenterPos_X_pxl; |
| | | pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].y = dCenterPos_Y_pxl; |
| | | pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].x = (LONG)dCenterPos_X_pxl; |
| | | pSideData->m_ptNotchCircle_Center_pxl[nNotchIdx][nCircleIdx].y = (LONG)dCenterPos_Y_pxl; |
| | | pSideData->m_ptNotchCircle_Radius_Result_X_pxl[nNotchIdx][nCircleIdx] = dRadiuse_um / m_dPixelSizeX; |
| | | pSideData->m_ptNotchCircle_Radius_Result_Y_pxl[nNotchIdx][nCircleIdx] = dRadiuse_um / m_dPixelSizeY; |
| | | pSideData->m_ptNotchCircle_Radius_Result_um[nNotchIdx][nCircleIdx] = dRadiuse_um; |
| | |
| | | |
| | | Measure_BotCorner(iThread, emDim, stFrame); |
| | | |
| | | if(pSideData->m_bFindGlassEndLine == FALSE) // Side Line篮 End Line 茫篮 Frame 捞 螟沥 茄促.. |
| | | if (pSideData->m_bFindGlassEndLine == FALSE) // Side Line은 End Line 찾은 Frame 이 측정 한다.. |
| | | return FALSE; |
| | | |
| | | g_pLog->DisplayMessage(_T("Side Measure Start %s - %d"),g_SideName[(int) emDim],stFrame.nFrameIdx); |
| | |
| | | |
| | | /////////////////////////////////////////////////////////////////////////////////////// |
| | | #if HALCON_VISION_KEY |
| | | //Set Info, 将MARK信息输入到SDK |
| | | //Set Info, 쉥MARK斤口渴흙돕SDK |
| | | CBlSideData* pBlSideData = BlVision_GetVisionRecipe()->getSideData(emDim); // ->m_bInspection_Complete = TRUE; |
| | | pBlSideData->m_bInspection_Complete = TRUE; |
| | | pBlSideData->m_dPixelSizeX = pSideData->m_dPixelSizeX; |
| | |
| | | int nSideLine = rtFindPos.left + nFindEdgeLine; |
| | | int nChamferLine = rtFindPos.left + ((nFindChamferLine != -1 && pSideParam->m_bSideChamfer_Use[nMeasurePointIdx] == TRUE) ? nFindChamferLine : nFindEdgeLine); |
| | | |
| | | // Frame俊辑 措钎肺 茫篮吧肺 螟沥 搬苞肺 静霸 沁绰单.... 捞固瘤俊辑 促矫 茫档废 荐沥捞 鞘夸..且鳖?? |
| | | // Frame에서 대표로 찾은걸로 측정 결과로 쓰게 했는데.... 이미지에서 다시 찾도록 수정이 필요..할까?? |
| | | int nFrameIdx = (int)(nEndPointPosY / m_nFrameHeight); |
| | | /* |
| | | int nSideLine = pSideData->m_nSideLineFrame[nFrameIdx]; |
| | |
| | | |
| | | pSideData->m_bSideMeasureLine[nMeasurePointIdx] = TRUE; |
| | | |
| | | // 烙矫肺 阜澜. SW 促款. |
| | | // 임시로 막음. SW 다운. |
| | | // continue; |
| | | |
| | | // Dimension |
| | |
| | | } |
| | | else if (pSideParam->m_bSideDimension_Use[nMeasurePointIdx] == TRUE && dTempValue < -0.01) { |
| | | #if HALCON_VISION_KEY |
| | | //切割线的长度计算, jiang, 09-27, 2024 |
| | | //학몇窟돨낀똑셕炬, jiang, 09-27, 2024 |
| | | int nThres = pSideParam->m_nSideDimensionSpec_Thres[nMeasurePointIdx]; |
| | | int toLineDist = 1000 * pSideParam->m_dSideDimensionSpec_mm_Std[nMeasurePointIdx]; |
| | | int toTopY = pSideParam->m_nSideDimensionPos_TopMarkToDistance_um[nMeasurePointIdx]; |
| | |
| | | if(iCornerFrame > stFrame.nFrameIdx) |
| | | return FALSE; |
| | | |
| | | // Corner 八荤 父甸扁.. |
| | | // Corner 검사 만들기.. |
| | | if(FindCorner(iThread,emDim,stFrame,0,rtTopCornerArea) == TRUE) |
| | | { |
| | | double dXSizeStd_um = pSideParam->m_nTopCorner_Measure_Judge_Std_um_X; |
| | |
| | | |
| | | int nSearchRange = 8; |
| | | |
| | | int nSearchRangeX = (int) ((double)nCornerSizeX_Pixel * 0.10); // 10%俊辑 茫澜.. |
| | | int nSearchRangeY = (int) ((double)nCornerSizeY_Pixel * 0.10); // 10%俊辑 茫澜.. |
| | | int nSearchRangeX = (int)((double)nCornerSizeX_Pixel * 0.10); // 10%에서 찾음.. |
| | | int nSearchRangeY = (int)((double)nCornerSizeY_Pixel * 0.10); // 10%에서 찾음.. |
| | | |
| | | nSearchRangeX = nSearchRangeY = 10; |
| | | |
| | |
| | | if(pSideData == NULL || pSideParam == NULL) |
| | | return FALSE; |
| | | |
| | | // R Corner 螟沥 |
| | | // R Corner 측정 |
| | | |
| | | return TRUE; |
| | | } |
| | |
| | | if(iCornerFrame > stFrame.nFrameIdx) |
| | | return FALSE; |
| | | |
| | | // Corner 八荤 父甸扁.. |
| | | // Corner 검사 만들기.. |
| | | if(FindCorner(iThread,emDim,stFrame,1,rtBottomCornerArea) == TRUE) |
| | | { |
| | | double dXSizeStd_um = pSideParam->m_nBottomCorner_Measure_Judge_Std_um_X; |
| | |
| | | if(pSideData == NULL) |
| | | return FALSE; |
| | | |
| | | if(pSideData->m_bFindGlassEndLine == FALSE) // User Defect Processing篮 End Line 茫篮 Frame捞.. |
| | | if (pSideData->m_bFindGlassEndLine == FALSE) // User Defect Processing은 End Line 찾은 Frame이.. |
| | | return FALSE; |
| | | |
| | | if(m_pRecipe == NULL) |
| | |
| | | if(pSideData == NULL) |
| | | return FALSE; |
| | | |
| | | if(pSideData->m_bFindGlassEndLine == FALSE) // Exception Area Processing篮 End Line 茫篮 Frame捞.. |
| | | if (pSideData->m_bFindGlassEndLine == FALSE) // Exception Area Processing은 End Line 찾은 Frame이.. |
| | | return FALSE; |
| | | |
| | | if(m_pRecipe == NULL) |
| | |
| | | while (TRUE) |
| | | { |
| | | nRet = m_pGrabber->IsAcqFrame(iFrame); |
| | | if (nRet < 2) // 酒流 救嘛躯栏骨肺 措扁. |
| | | if (nRet < 2) // 아직 안찍혔으므로 대기. |
| | | { |
| | | if (GetTickCount() - dwT1 > TIME_WAIT_GLASS_START) |
| | | { |
| | |
| | | { |
| | | for (k = nHStart; k < nHStart + BOUNDARY_GLASSSTARTWIDTH; k++) |
| | | { |
| | | // Grab牢 版快 滚欺狼 版拌俊辑 1024扼牢阑 逞绢哎 版快 促澜 滚欺甫 啊廉客具 茄促. |
| | | // Grab인 경우 버퍼의 경계에서 1024라인을 넘어갈 경우 다음 버퍼를 가져와야 한다. |
| | | if (j == nFrameHeight && nLine != 0 && bChangeBuffer == FALSE) |
| | | { |
| | | DWORD dwTick = GetTickCount(); |
| | |
| | | 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狼 矫累瘤痢阑 茫酒辑 备炼眉俊 持绰促. |
| | | // Glass의 시작지점을 찾아서 구조체에 넣는다. |
| | | pSideData->m_nGlassStartLine = iFrame * nFrameHeight + j - 2; |
| | | pSideData->m_nGlassStartFrame = pSideData->m_nGlassStartLine/nFrameHeight; |
| | | pSideData->m_bFindGlassStartLine = TRUE; |
| | |
| | | BOOL CInspectCamera::ProcessFrame(int iThread,DimensionDir emDim,stFrameIndex stFrame) |
| | | { |
| | | try { |
| | | // 1. Find End Line.. (Corner甫 力寇茄 Side扼牢阑 茫扁 困秦 End Line何磐 茫绰促) |
| | | // 1. Find End Line.. (Corner를 제외한 Side라인을 찾기 위해 End Line부터 찾는다) |
| | | FindEndLine(iThread, emDim, stFrame); |
| | | |
| | | // 2. Find Side Line.. (秦寸 橇饭烙俊辑 Corner/Notch 甫 力寇茄 Side 扼牢 茫扁) |
| | | // 2. Find Side Line.. (해당 프레임에서 Corner/Notch 를 제외한 Side 라인 찾기) |
| | | #if USE_AI_DETECT |
| | | FindSideLine(iThread, emDim, stFrame); |
| | | #else |
| | |
| | | if (m_wsClients != nullptr) |
| | | { |
| | | m_wsClients->set_message_handler([this](const std::string& msg) { |
| | | // JSON 格式 |
| | | // JSON 목駕 |
| | | if (!msg.empty() && msg.size() > 3) { |
| | | try { |
| | | nlohmann::json json_data = nlohmann::json::parse(msg); |
| | |
| | | DimensionDir emDim = (DimensionDir)(json_data.value("nLineType", 0) - 1); |
| | | WSReceiveData wsReceiveData; |
| | | |
| | | // 解析 JSON 数据并填充 wsReceiveData |
| | | // 썩驕 JSON 鑒앴깻輕념 wsReceiveData |
| | | wsReceiveData.nRecipe = json_data.value("Reciepe", 0); |
| | | wsReceiveData.nLineType = json_data.value("nLineType", 0); |
| | | wsReceiveData.nIndex = json_data.value("nIndex", 0); |
| | |
| | | wsReceiveData.nFrameIdx = json_data.value("nFrameIdx", 0); |
| | | wsReceiveData.strSN = json_data.value("SN", ""); |
| | | wsReceiveData.dTimeStamp = json_data.value("TimeStamp", 0.0); |
| | | wsReceiveData.nGNum = json_data.value("NGnum", 0); // NG 数量 |
| | | wsReceiveData.nGNum = json_data.value("NGnum", 0); // NG 鑒좆 |
| | | |
| | | // 格式化并显示基本信息 |
| | | // 목駕뺏깻鞫刻샘굶斤口 |
| | | CString strText; |
| | | strText.Format(_T("Reciepe: %d, LineType: %d, Index: %d, SN: %s, NGNum: %d, TimeStamp: %f\n"), |
| | | wsReceiveData.nRecipe, wsReceiveData.nLineType, wsReceiveData.nIndex, wsReceiveData.strSN.c_str(), wsReceiveData.nGNum, wsReceiveData.dTimeStamp); |
| | |
| | | && wsReceiveData.nGNum != 0 |
| | | && g_pBase->m_strHPanelID.Compare(CString(wsReceiveData.strSN.c_str())) == 0) |
| | | { |
| | | // 遍历并填充 ngPosArray |
| | | // 깁저깻輕념 ngPosArray |
| | | auto ngPosArray = json_data["NGPosArray"]; |
| | | for (auto& ngPos : ngPosArray) { |
| | | WSReceiveData::NGPosition ngPosition; |
| | |
| | | g_pLog->DisplayMessage(strText); |
| | | } |
| | | catch (const nlohmann::json::parse_error& e) { |
| | | // 处理 JSON 解析错误 |
| | | // 뇹잿 JSON 썩驕댄轎 |
| | | std::cerr << "JSON parse error: " << e.what() << std::endl; |
| | | } |
| | | } |
| | | else { |
| | | // 处理空消息 |
| | | // 뇹잿왕句口 |
| | | std::cerr << "Empty message" << std::endl; |
| | | } |
| | | }); |
| | |
| | | |
| | | std::string jsonMetadata = CreateJsonWSSendData(wsData); |
| | | |
| | | // 预先分配内存,减少动态扩容 |
| | | // 渡邱롸토코닸,숑 帽檄윈휭 |
| | | std::vector<char> message; |
| | | message.reserve(jsonMetadata.size() + width * height); |
| | | |
| | | // 插入 JSON 数据和图像数据 |
| | | // 꿨흙 JSON 鑒앴뵨暠獗鑒앴 |
| | | message.insert(message.end(), jsonMetadata.begin(), jsonMetadata.end()); |
| | | message.insert(message.end(), data, data + width * height); |
| | | |
| | | // 使用 std::move 传递 message,避免拷贝 |
| | | // 賈痰 std::move 눈뒵 message,긁출옙굔 |
| | | bool isSucceed = m_wsClients->send_binary_to_idle_client_with_retry(std::move(message), 1000, 50); |
| | | if (!isSucceed) |
| | | { |
| | |
| | | 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()); |
| | | |
| | |
| | | rtProcessArea.bottom += nHeightOff; |
| | | } |
| | | |
| | | // 保证图像高度为4的倍数 |
| | | // 괏聯暠獗멕똑槨4돨굡鑒 |
| | | nHeightOff = rtProcessArea.Height() % 4; |
| | | if (nHeightOff != 0) |
| | | { |
| | |
| | | |
| | | myLoc.Lock(); |
| | | long long dStartTime = GetCurrentTimestamp(); |
| | | // 发送从临时缓冲区中获取的数据 |
| | | // 랙箇닖줄珂뻠녑혐櫓삿혤돨鑒앴 |
| | | std::vector<AiDetectResult> results; |
| | | if (m_pAiDetectEx->detect(frame, results, m_strChannel)) { |
| | | for (auto& result : results) { |