#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 <nlohmann/json.hpp>
|
#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;i<MAX_THREAD;i++)
|
if(m_iThreadEnd[iScan][i] == 1)
|
nCount++;
|
|
return nCount;
|
}
|
|
void CInspectCamera::ResetFrameFinish(int nCurrentScanIdx)
|
{
|
CSingleLock cslocalLock(&m_csFrameFinishCheck);
|
cslocalLock.Lock();
|
|
m_nFrameFinishIdx[nCurrentScanIdx] = -1;
|
|
for(int i=0; i<MAX_FRAM_COUNT; i++)
|
m_bFrameFinish[nCurrentScanIdx][i] = FALSE;
|
|
cslocalLock.Unlock();
|
}
|
|
void CInspectCamera::SetFrameFinishEndFrame(int nCurrentScanIdx, int nFrameIdx)
|
{
|
CSingleLock cslocalLock(&m_csFrameFinishCheck);
|
cslocalLock.Lock();
|
|
m_nFrameFinishIdx[nCurrentScanIdx] = nFrameIdx;
|
|
cslocalLock.Unlock();
|
}
|
|
void CInspectCamera::SetFrameFinish(int nCurrentScanIdx, int nCurrentFrameIdx)
|
{
|
CSingleLock cslocalLock(&m_csFrameFinishCheck);
|
cslocalLock.Lock();
|
|
m_bFrameFinish[nCurrentScanIdx][nCurrentFrameIdx] = TRUE;
|
|
cslocalLock.Unlock();
|
}
|
|
BOOL CInspectCamera::CheckAllFrameFinish(int nCurrentScanIdx)
|
{
|
CSingleLock cslocalLock(&m_csFrameFinishCheck);
|
cslocalLock.Lock();
|
|
if(m_nFrameFinishIdx[nCurrentScanIdx] == -1)
|
return FALSE;
|
|
for(int i=0; i<m_nFrameFinishIdx[nCurrentScanIdx]; i++)
|
if(m_bFrameFinish[nCurrentScanIdx][i] == FALSE)
|
return FALSE;
|
|
return TRUE;
|
}
|
|
double CInspectCamera::GetPixelToUm_X(double dPixel_X)
|
{
|
return dPixel_X * m_dPixelSizeX;
|
}
|
|
double CInspectCamera::GetPixelToUm_Y(double dPixel_Y)
|
{
|
return dPixel_Y * m_dPixelSizeY;
|
}
|
|
double CInspectCamera::GetUmToPixel_X(double dUm_X)
|
{
|
return dUm_X / m_dPixelSizeX;
|
}
|
|
double CInspectCamera::GetUmToPixel_Y(double dUm_Y)
|
{
|
return dUm_Y / m_dPixelSizeY;
|
}
|
|
double CInspectCamera::GetUm_Distance(CPoint ptStart_pxl, CPoint ptEnd_pxl)
|
{
|
double dX_um = GetPixelToUm_X(ptEnd_pxl.x - ptStart_pxl.x);
|
double dY_um = GetPixelToUm_Y(ptEnd_pxl.y - ptStart_pxl.y);
|
|
return sqrt((dX_um*dX_um) + (dY_um*dY_um));
|
}
|
|
BOOL CInspectCamera::GetAlignRotate(DimensionDir emDim, CPoint ptSetTopMark, CPoint ptSetBotMark, CRect rtSetArea, CRect& bRotateArea)
|
{
|
if(rtSetArea.IsRectEmpty() || rtSetArea.IsRectNull())
|
return FALSE;
|
|
if(m_pGlassData == NULL)
|
return FALSE;
|
|
CSide_Data* pSideData = m_pGlassData->GetSideData(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;v<rectIns.bottom;v++,dv++)
|
{
|
CopyMemory(pTgt+dv*rectIns.Width(),pOrg+v*szImg.cx+rectIns.left,rectIns.Width());
|
}
|
|
return TRUE;
|
}
|
|
void CInspectCamera::SaveDebugImage(DimensionDir eDim, stFrameIndex stFrame, COwnerBuffer* 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);
|
|
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<CRect> vectorInspectAreaList_New;
|
vectorInspectAreaList_New.push_back(rtROI);
|
|
std::vector<CRect> vectorInspectAreaList_Old;
|
vectorInspectAreaList_Old.clear();
|
|
std::vector<CRect> vecExceptionNotchAreaList;
|
int nNotchCount = pSideData->m_nNotchCount;
|
|
std::vector<CRect> vecInspectArea;
|
|
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;
|
|
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<vectorInspectAreaList_Old.size(); j++)
|
{
|
CRect rtTemp = vectorInspectAreaList_Old[j];
|
|
CRect rtNotchInterSectRect;
|
rtNotchInterSectRect.IntersectRect(rtTemp, rtNotchArea);
|
|
if(rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) // ³ëÄ¡°¡ ¾È°É¸®´Â °æ¿ì¿¡´Â ´Ù½Ã ³Ö¾îÁØ´Ù..
|
{
|
vectorInspectAreaList_New.push_back(rtTemp);
|
continue;
|
}
|
|
if(rtTemp.Height() == rtNotchInterSectRect.Height()) // Notch°¡ ¿µ¿ªÀÇ ÀüüÀÎ °æ¿ì
|
continue;
|
|
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 Áß°£¿¡ °É¸° °æ¿ì
|
{
|
CRect rtNewTop = rtTemp;
|
rtNewTop.top = rtNotchInterSectRect.bottom;
|
vectorInspectAreaList_New.push_back(rtNewTop);
|
|
CRect rtNewBot = rtTemp;
|
rtNewBot.bottom = rtNotchInterSectRect.top;
|
vectorInspectAreaList_New.push_back(rtNewBot);
|
}
|
else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) // 3. Notch Frame ¾Æ·¡¿¡ °É¸° °æ¿ì
|
{
|
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++)
|
{
|
CRect rtInspectArea = vectorInspectAreaList_New[i];
|
vecInspectArea.push_back(rtInspectArea);
|
}
|
|
// Find Side Line
|
#define DEFECT_EDGE_AUTO_RATIO 0.3
|
#define DEFECT_EDGE_AUTO_PITCH 20
|
#define DEFECT_EDGE_CONTINUE 3
|
|
int nFindSideLineSum = 0;
|
int nFindSideLineCount = 0;
|
int nFindSideChamferLineSum = 0;
|
int nFindSideChamferLineCount = 0;
|
int nChamferLineThres = m_pRecipe->m_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; i<vecInspectArea.size(); i++)
|
{
|
CSISBuffer frameBuffer(m_pGrabber->GetFrameHeaderLine(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<CDefect_Info> 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<nRange; j++)
|
pMaskBuffer.SetPixel(nX, nY+j, 255);
|
|
/*
|
int nRange = (rtTopCornerArea.Width() <= nX + nInsRange) ? (rtTopCornerArea.Width() - 1 - nX) : nInsRange;
|
|
if(nRange == 0)
|
continue;
|
|
memset(pMaskBuffer.GetDataAddress(nX, nY), 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<CDefect_Info> 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<CDefect_Info> 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<CDefect_Info> 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<nRange; j++)
|
pMaskBuffer.SetPixel(nX, nY-j, 255);
|
}
|
|
// 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, &pMaskBuffer, _T("Corner\\BotCornerArea_Mask"));
|
SaveDebugImage(emDim, stFrame, &pBinBuffer, _T("Corner\\BotCornerArea_Bin"));
|
#endif // _DEBUG
|
|
// 3. Blob
|
std::vector<CDefect_Info> 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<CDefect_Info> 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 ; i<MAX_MARKER_COUNT ; i++)
|
{
|
USES_CONVERSION;
|
char str_filename[256];
|
sprintf_s(str_filename, "%s\\%s\\Side_%d_BotAlign_%d.bmp", W2A(RECIPE_ALIGN_PATH), W2A(m_pRecipe->GetRecipeName()), (int) eDim, i);
|
|
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; 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_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<CDefect_Info> vecDefectCandidateList;
|
|
for(int i=0; i<MAX_SIDE_INSPECT_TYPE; i++)
|
{
|
InspectDefect_Process(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, rtInspectArea, nCutLine, (eSideInsType) i, &vecDefectCandidateList);
|
}
|
|
m_pDefectControl->ExtractDefect_Side(eDim, m_iCamera, stFrame.nScanIdx, &vecDefectCandidateList);
|
|
return TRUE;
|
}
|
|
BOOL CInspectCamera::InspectDefect_Side(int iThread,DimensionDir eDim, stFrameIndex stFrame)
|
{
|
std::vector<CRect> vecInspectAreaList; // For Notch Region Divide..
|
int nCutLine = 0;
|
|
if(MakeInspectRegion(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, vecInspectAreaList, nCutLine) == FALSE)
|
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];
|
|
m_pGlassData->GetSideData(eDim)->m_rtSideInspectArea[stFrame.nFrameIdx][nRegionIdx] = vecInspectAreaList[nRegionIdx];
|
|
std::vector<CDefect_Info> vecDefectCandidateList;
|
|
for(int i=0; i<MAX_SIDE_INSPECT_TYPE; i++)
|
{
|
InspectDefect_Process(iThread, eDim, stFrame.nScanIdx, stFrame.nFrameIdx, vecInspectAreaList[nRegionIdx], nCutLine, (eSideInsType) i, &vecDefectCandidateList);
|
}
|
|
m_pDefectControl->ExtractDefect_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; i<MAX_SIDE_INSPECT_TYPE; i++)
|
{
|
if(m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_bUseInspect == TRUE)
|
{
|
int nSideLineOffset_pxl = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_SideLine_Offset_um);
|
int nInspect_Range_pxl = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_Range_um);
|
|
int 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<CRect> & 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; i<MAX_SIDE_INSPECT_TYPE; i++)
|
{
|
if(m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_bUseInspect == TRUE)
|
{
|
int nSideLineOffset_pxl = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_SideLine_Offset_um);
|
int nInspect_Range_pxl = (int) GetUmToPixel_X((double) m_pRecipe->m_SideParam[(int) eDim].m_InspectPrm[i].m_nInspect_Range_um);
|
|
int 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<CRect> vectorInspectAreaList_New;
|
vectorInspectAreaList_New.push_back(rtInspectArea);
|
|
std::vector<CRect> vectorInspectAreaList_Old;
|
vectorInspectAreaList_Old.clear();
|
|
std::vector<CRect> vecExceptionNotchAreaList;
|
int nNotchCount = m_pRecipe->m_SideParam[(int) eDim].m_nNotchCount;
|
|
for(int i=0; i<nNotchCount; i++)
|
{
|
int nDiff_StartLine = nFindStartLine - m_pRecipe->m_SideParam[(int) eDim].m_NotchPrm[i].m_nGlassStartLine_pxl;
|
|
CRect rtNotchArea = m_pRecipe->m_SideParam[(int) eDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
|
|
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<vectorInspectAreaList_Old.size(); j++)
|
{
|
CRect rtTemp = vectorInspectAreaList_Old[j];
|
|
CRect rtNotchInterSectRect;
|
rtNotchInterSectRect.IntersectRect(rtTemp, rtNotchArea);
|
|
if(rtNotchInterSectRect.IsRectEmpty() || rtNotchInterSectRect.IsRectNull()) // ³ëÄ¡°¡ ¾È°É¸®´Â °æ¿ì¿¡´Â ´Ù½Ã ³Ö¾îÁØ´Ù..
|
{
|
vectorInspectAreaList_New.push_back(rtTemp);
|
continue;
|
}
|
|
if(rtTemp.Height() == rtNotchInterSectRect.Height()) // Notch°¡ ¿µ¿ªÀÇ ÀüüÀÎ °æ¿ì
|
continue;
|
|
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 Áß°£¿¡ °É¸° °æ¿ì
|
{
|
CRect rtNewTop = rtTemp;
|
rtNewTop.top = rtNotchInterSectRect.bottom;
|
vectorInspectAreaList_New.push_back(rtNewTop);
|
|
CRect rtNewBot = rtTemp;
|
rtNewBot.bottom = rtNotchInterSectRect.top;
|
vectorInspectAreaList_New.push_back(rtNewBot);
|
}
|
else if(rtTemp.top < rtNotchInterSectRect.top && rtNotchInterSectRect.bottom == rtTemp.bottom) // 3. Notch Frame ¾Æ·¡¿¡ °É¸° °æ¿ì
|
{
|
CRect rtNew = rtTemp;
|
rtNew.bottom = rtNotchInterSectRect.top;
|
vectorInspectAreaList_New.push_back(rtNew);
|
}
|
}
|
}
|
|
// 5. Make Return
|
vecInspectArea.clear();
|
|
for(int i=0; i<vectorInspectAreaList_New.size(); i++)
|
{
|
CRect rtInspectArea = vectorInspectAreaList_New[i];
|
rtInspectArea.right = rtInspectArea.left + align_4byte(rtInspectArea.Width());
|
|
vecInspectArea.push_back(rtInspectArea);
|
}
|
|
return TRUE;
|
}
|
|
BOOL CInspectCamera::InspectDefect_Process(int iThread,DimensionDir eDim,int iScan,int iFrame, CRect rtInspectArea, int nCutLine, eSideInsType emInsType, std::vector<CDefect_Info>* pDefectList)
|
{
|
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<CDefect_Info>* 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; i<pBinImage->GetHeight(); 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<int> 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<int>(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<int>(nIdx, cv::CC_STAT_AREA);
|
int left = matStats.at<int>(nIdx, cv::CC_STAT_LEFT);
|
int top = matStats.at<int>(nIdx, cv::CC_STAT_TOP);
|
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 y = (int)matCentrois.at<double>(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<CDefect_Info>* 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; i<pBinImage->height; 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<int> 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<int>(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<int>(nIdx, cv::CC_STAT_AREA);
|
int left = matStats.at<int>(nIdx, cv::CC_STAT_LEFT);
|
int top = matStats.at<int>(nIdx, cv::CC_STAT_TOP);
|
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 y = (int)matCentrois.at<double>(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)
|
{
|
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; i<nNotchCount; i++)
|
{
|
if(m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_bNotch_Use == FALSE)
|
continue;
|
|
CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_ptTopMarkPos;
|
CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_ptBotMarkPos;
|
CRect rtSet_Area = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_rtNotch_Area_pxl;
|
|
CRect rtRotateArea;
|
CRect rtNotchAreaTemp;
|
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;
|
//ÆÁ±ÎNotch ÇøÓòÉÏÏÂλÖÃ
|
rtRotateArea.top += 15;
|
rtRotateArea.bottom -= 15;
|
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);
|
|
// 1. Image PreProcess..
|
g_pLog->DisplayMessage(_T("1. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
|
Notch_Process_PreProcess(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
|
|
// 2. Notch Dimension/Chamfer Find..
|
g_pLog->DisplayMessage(_T("2. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
|
Notch_Process_Measure(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
|
|
// 3. Notch Dimension/Chamfer Calculate Result..
|
g_pLog->DisplayMessage(_T("3. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
|
bool bResult = Notch_Process_Calculate(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
|
|
// 4. Notch Dimension/Chamfer Judge
|
g_pLog->DisplayMessage(_T("4. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
|
Notch_Process_Judge(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
|
|
if (!bResult)
|
{
|
m_nChamferOffset_um = 0;
|
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);
|
|
pSideData->m_bNotchInspection_Complete = TRUE;
|
|
return FALSE;
|
}
|
|
// 5. Notch Defect Inspect (Chip/Crack)
|
g_pLog->DisplayMessage(_T("5. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
|
Notch_Process_Defect(emDim, stFrame, i, pOriginImage, pEdgeImage, pBinImage, rtRotateArea);
|
|
// 6. Notch Find Circle
|
g_pLog->DisplayMessage(_T("6. Notch_Process %s : %d, idx %d"), g_SideName[(int)emDim], stFrame.nFrameIdx, i);
|
Notch_Process_FindCircle(emDim, stFrame, i);
|
|
// 7. Notch Process End
|
g_pLog->DisplayMessage(_T("7. Notch_Process %s : %d, idx %d"),g_SideName[(int) emDim], stFrame.nFrameIdx,i);
|
cvReleaseImageHeader(&pOriginImage);
|
cvReleaseImage(&pEdgeImage);
|
cvReleaseImage(&pBinImage);
|
}
|
|
pSideData->m_bNotchInspection_Complete = TRUE;
|
|
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 == nullptr) {
|
return;
|
}
|
|
if (nNotchIdx < 0 || nNotchIdx >= MAX_SIDE_NOTCH_COUNT) {
|
return;
|
}
|
|
// ÖÐÖµÂ˲¨Æ÷´óС£¬ÓÃÓÚÈ¥Ô룬±ØÐëÎªÆæÊý£¨ÈôżÊý»á×Ô¶¯¼õ1£©
|
const int nSmoothFilter = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
|
|
// Ä¥±ßÇøÓòãÐÖµ£¬¿ØÖÆ·´¶þÖµ»¯ãÐÖµ£¬Ö÷ÒªÓÃÓÚÌáÈ¡ 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ͼ£º·´¶þÖµ»¯ãÐÖµ´¦Àí
|
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ͼ£ºÕý³£¶þÖµ»¯
|
cvThreshold(scr, img_Bin, nGlassThreshold, 255, CV_THRESH_BINARY);
|
CString strBinFileName;
|
strBinFileName.Format(_T("Notch\\Notch_%d_Bin.jpg"), nNotchIdx);
|
SaveDebugImage(emDim, stFrame, img_Bin, strBinFileName);
|
}
|
|
void CInspectCamera::Notch_Process_Measure(DimensionDir emDim, stFrameIndex stFrame, int nNotchIdx, IplImage* scr,IplImage* img_Edge,IplImage* img_Bin, CRect rtROI)
|
{
|
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, 255, 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<CPoint> 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];
|
|
if (ptRef_pxl.x < 0 || ptRef_pxl.y < 0) {
|
g_pLog->DisplayMessage(_T("[ERROR] Invalid Ref Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptRef_pxl.x, ptRef_pxl.y);
|
continue;
|
}
|
|
if (ptDim_pxl.x < 0 || ptDim_pxl.y < 0) {
|
g_pLog->DisplayMessage(_T("[ERROR] Invalid Dim Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptDim_pxl.x, ptDim_pxl.y);
|
continue;
|
}
|
|
// Dimension
|
double dX_dim_um = (double)(ptRef_pxl.x - ptDim_pxl.x) * m_dPixelSizeX;
|
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;
|
|
CPoint ptChamfer_pxl = m_pGlassData->GetSideData(emDim)->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx];
|
if (ptChamfer_pxl.x < 0 || ptChamfer_pxl.y < 0) {
|
g_pLog->DisplayMessage(_T("[ERROR] Invalid Chamfer Point at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Point: (%d, %d)"), nNotchIdx, nMeasureIdx, ptChamfer_pxl.x, ptChamfer_pxl.y);
|
continue;
|
}
|
|
double dX_Chamfer = (double)(ptChamfer_pxl.x - ptDim_pxl.x) * m_dPixelSizeX;
|
double dY_Chamfer = (double)(ptChamfer_pxl.y - ptDim_pxl.y) * m_dPixelSizeY;
|
double dChamfer = sqrtf((dX_Chamfer * dX_Chamfer) + (dY_Chamfer * dY_Chamfer));
|
m_pGlassData->GetSideData(emDim)->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx] = dChamfer;
|
|
if (dDimension > 2000.0 && dChamfer > 2000.0) {
|
g_pLog->DisplayMessage(_T("[ERROR] Abnormal Dimension & Chamfer too large at Notch_Process_Calculate, NotchIdx: %d, MeasureIdx: %d, Dimension: %.2f, Chamfer: %.2f"), nNotchIdx, nMeasureIdx, dDimension, dChamfer);
|
continue;
|
}
|
}
|
|
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) {
|
g_pLog->DisplayMessage(_T("[ERROR] Recipe or Glass Data is NULL in Notch_Process_Judge"));
|
return;
|
}
|
|
CSide_Data* pSideData = m_pGlassData->GetSideData(emDim);
|
if (pSideData == NULL) {
|
g_pLog->DisplayMessage(_T("[ERROR] Side Data is NULL in Notch_Process_Judge, Dimension: %d"), (int)emDim);
|
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 = pSideData->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx];
|
double dDimension_std_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_STD_mm[nMeasureIdx] * 1000.0;
|
double dDimension_min_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_Diff_MIN_mm[nMeasureIdx] * 1000.0;
|
double dDimension_max_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Dimension_Diff_MAX_mm[nMeasureIdx] * 1000.0;
|
double dDimension_Diff_um = dDimension_std_um - dDimension_um;
|
|
pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 1;
|
pSideData->m_dNotch_Dimension_Edge_Result_Diff_um[nNotchIdx][nMeasureIdx] = dDimension_Diff_um;
|
pSideData->m_dNotch_Dimension_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] = dDimension_std_um;
|
pSideData->m_dNotch_Dimension_Edge_Judge_Min_um[nNotchIdx][nMeasureIdx] = dDimension_min_um;
|
pSideData->m_dNotch_Dimension_Edge_Judge_Max_um[nNotchIdx][nMeasureIdx] = dDimension_max_um;
|
|
if(dDimension_um > dDimension_std_um + dDimension_max_um)
|
pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 2;
|
else if(dDimension_um < dDimension_std_um - dDimension_min_um)
|
pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] = 3;
|
|
if(pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx] != 1)
|
{
|
// Make °áÇÔ..
|
CRect rtDefectArea = CRect(pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x,
|
pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y,
|
pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].x,
|
pSideData->m_ptNotch_Dimension_Edge[nNotchIdx][nMeasureIdx].y);
|
|
rtDefectArea.InflateRect(10, 10);
|
|
CDefect_Info defectInfo;
|
defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
|
defectInfo.m_nCamID = m_iCamera;
|
defectInfo.m_nScanIdx = stFrame.nScanIdx;
|
defectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine;
|
defectInfo.m_nSideIdx = (int) emDim;
|
defectInfo.m_ptDefectPos_pxl = rtDefectArea.CenterPoint();
|
defectInfo.m_rtDefectPos_pxl = rtDefectArea;
|
defectInfo.m_DefectLoc = DefectLoc_Notch_Dimension;
|
|
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 = pSideData->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx];
|
double dChamfer_std_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_STD_mm[nMeasureIdx] * 1000.0;
|
double dChamfer_min_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_Diff_MIN_mm[nMeasureIdx] * 1000.0;
|
double dChamfer_max_um = m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[nNotchIdx].m_dNotch_Chamfer_Diff_MAX_mm[nMeasureIdx] * 1000.0;
|
double dChamfer_Diff_um = dChamfer_std_um - dChamfer_um;
|
|
pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 1;
|
//ѡȡ²âÁ¿ÑÐÄ¥³ß´ç×î´óÖµ
|
if (m_nChamferOffset_um < dChamfer_um)
|
{
|
m_nChamferOffset_um = dChamfer_um;
|
}
|
pSideData->m_dNotch_Chamfer_Edge_Result_Diff_um[nNotchIdx][nMeasureIdx] = dChamfer_std_um - dChamfer_um;
|
pSideData->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx] = dChamfer_std_um;
|
pSideData->m_dNotch_Chamfer_Edge_Judge_Min_um[nNotchIdx][nMeasureIdx] = dChamfer_min_um;
|
pSideData->m_dNotch_Chamfer_Edge_Judge_Max_um[nNotchIdx][nMeasureIdx] = dChamfer_max_um;
|
|
if(dChamfer_um > dChamfer_std_um + dChamfer_max_um)
|
pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 2;
|
else if(dChamfer_um < dChamfer_std_um - dChamfer_min_um)
|
pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] = 3;
|
|
if(pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx] != 1)
|
{
|
// Make °áÇÔ..
|
CRect rtDefectArea = CRect(pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x,
|
pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y,
|
pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].x,
|
pSideData->m_ptNotch_Chamfer_Edge[nNotchIdx][nMeasureIdx].y);
|
|
rtDefectArea.InflateRect(10, 10);
|
|
CDefect_Info defectInfo;
|
defectInfo.m_iFrameIdx = stFrame.nFrameIdx;
|
defectInfo.m_nCamID = m_iCamera;
|
defectInfo.m_nScanIdx = stFrame.nScanIdx;
|
defectInfo.m_nGlassStartLine = pSideData->m_nGlassStartLine;
|
defectInfo.m_nSideIdx = (int) emDim;
|
defectInfo.m_ptDefectPos_pxl = rtDefectArea.CenterPoint();
|
defectInfo.m_rtDefectPos_pxl = rtDefectArea;
|
defectInfo.m_DefectLoc = DefectLoc_Notch_Chamfer;
|
|
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(pSideData->m_strNotchMeasure_Comment[nNotchIdx][nMeasureIdx], "NOTCH[%d]-POINT[%d]-DIM[%.1f/STD:%.1f][%s], CHAMFER[%.1f/STD:%.1f][%s]"
|
, nNotchIdx+1, nMeasureIdx+1
|
, pSideData->m_dNotch_Dimension_Edge_Result_um[nNotchIdx][nMeasureIdx]
|
, pSideData->m_dNotch_Dimension_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx]
|
, strJudge[pSideData->m_nNotch_Dimension_Edge_Judge[nNotchIdx][nMeasureIdx]]
|
, pSideData->m_dNotch_Chamfer_Edge_Result_um[nNotchIdx][nMeasureIdx]
|
, pSideData->m_dNotch_Chamfer_Edge_Judge_Std_um[nNotchIdx][nMeasureIdx]
|
, strJudge[pSideData->m_nNotch_Chamfer_Edge_Judge[nNotchIdx][nMeasureIdx]]);
|
}
|
}
|
|
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<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];
|
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<CDefect_Info> 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);
|
IplImage* pMaskImage1 = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);
|
IplImage* pdstImage = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);//»æ»ÂÖÀª
|
IplImage* ptempImage1 = cvCreateImage(cvSize(rcIns.Width(), rcIns.Height()), 8, 1);//͹°ü
|
for(int i=0; i<rcIns.Height(); i++)
|
{
|
memcpy(pProcImage->imageData+(i*pProcImage->widthStep), scr->imageData+(rtROI.left + (i*scr->widthStep)), rcIns.Width());
|
memcpy(pProcessCanny->imageData+(i*pProcessCanny->widthStep), img_Edge->imageData+(rtROI.left + (i*img_Edge->widthStep)), rcIns.Width());
|
memcpy(pProcessBin->imageData+(i*pProcessBin->widthStep), img_Bin->imageData+(rtROI.left + (i*img_Bin->widthStep)), rcIns.Width());
|
}
|
|
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;y<pMaskImage->height;y++)
|
{
|
bFind = FALSE;
|
nFindX = 0;
|
for(int x=0;x<pMaskImage->width;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; i<pMaskImage->height; i++)
|
for(int j=0; j<pMaskImage->width; j++)
|
if(pMaskImage->imageData[i*pMaskImage->widthStep + j] != 0)
|
pProcImage->imageData[i*pProcImage->widthStep+j] = (char) 255;
|
|
strTemp.Format(_T("Notch\\Notch_%d_Defect_ProcImage"), nNotchIdx);
|
SaveDebugImage(emDim, stFrame, pProcImage, strTemp);
|
|
cvThreshold(pProcImage, pProcBinImage, nThreshold, 255, CV_THRESH_BINARY_INV);
|
|
strTemp.Format(_T("Notch\\Notch_%d_Defect_ProcBinImage"), nNotchIdx);
|
SaveDebugImage(emDim, stFrame, pProcBinImage, strTemp);
|
#if MINI_LED == TRUE
|
cvDilate(pMaskImage, pMaskImage1, 0, pNotchParam->m_nNotch_Inspect_Defect_dilate);
|
strTemp.Format(_T("Notch\\Notch_%d_Defect_pMaskImage2"), nNotchIdx);
|
SaveDebugImage(emDim, stFrame, pMaskImage1, strTemp);
|
|
cvAnd(pMaskImage1, pProcBinImage, pMaskImage1);
|
strTemp.Format(_T("Notch\\Notch_%d_Defect_pMaskImage3"), nNotchIdx);
|
SaveDebugImage(emDim, stFrame, pMaskImage1, strTemp);
|
#endif
|
// 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<CDefect_Info> vecDefectCandidateList;
|
if (MINI_LED == TRUE)
|
DefectProcess(emDim, iScan, iFrame, pProcImage, pMaskImage1, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList);
|
else
|
DefectProcess(emDim, iScan, iFrame, pProcImage, pProcBinImage, rtProcessArea, nMinSize, nMinSize_X, nMinSize_Y, nDilation, bStartNearFilterUse, nStartNearFilterRange, defectLoc, &vecDefectCandidateList);
|
|
|
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) {
|
g_pLog->DisplayMessage(_T("Notch Circle %d Rotate Area Error"), nCircleIdx);
|
continue;
|
}
|
|
CRect rtROI = rtRotateArea;
|
if (rtROI.Width() <= 0 || rtROI.Height() <= 0) {
|
g_pLog->DisplayMessage(_T("Invalid ROI size: %d x %d"), rtROI.Width(), rtROI.Height());
|
continue;
|
}
|
pSideData->m_rtNotchCircleArea_pxl[nNotchIdx][nCircleIdx] = rtROI;
|
|
VectorDouble vectorX;
|
VectorDouble vectorY;
|
VectorDouble vectorR;
|
|
// 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; i < rtROI.Height(); i++) {
|
memcpy(&pEdgeImage->imageData[(i * pEdgeImage->widthStep)], (pFrameBuffer + ((rtROI.top + i) * m_nFrameWidth) + rtROI.left), rtROI.Width());
|
}
|
|
int nMedianFilterSize = m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nSmooth_Filter;
|
nMedianFilterSize = std::max(3, std::min(nMedianFilterSize, 31));
|
if (nMedianFilterSize % 2 == 0) {
|
nMedianFilterSize--;
|
}
|
cvSmooth(pEdgeImage, pEdgeImage, CV_MEDIAN, nMedianFilterSize);
|
|
double th1 = 40.0;
|
double th2 = std::max(1.0, std::min((double)m_pRecipe->m_SideParam[(int)emDim].m_NotchPrm[nNotchIdx].m_nGrind_Threshold * 10, 255.0));
|
|
if (th1 > th2) {
|
std::swap(th1, th2);
|
}
|
|
g_pLog->DisplayMessage(_T("Smooth Filter: %d, Canny th1: %.1f, th2: %.1f"), nMedianFilterSize, th1, th2);
|
|
cvCanny(pEdgeImage, pCannyEdgeImage, th1, th2, nMedianFilterSize);
|
|
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; i<rtROI.Height(); i+=4)
|
{
|
for(int j=0; j<rtROI.Width(); j++)
|
{
|
BYTE nGray = pCannyEdgeImage->imageData[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; i<rtFindPos.Height(); i++)
|
memcpy(pFindImage.GetDataAddress(0, i), pFrameBuffer + (m_nFrameWidth * (rtFindPos.top + i)) + rtFindPos.left, rtFindPos.Width());
|
|
//{
|
// CString str;
|
// str.Format(_T("D:\\Inspection\\DebugFullImg\\Side\\Org_%s_%02d.bmp"),g_SideName[(int) emDim],nMeasurePointIdx);
|
// CBufferAttach attach(str);
|
// attach.AttachToFile(pFindImage);
|
//}
|
|
int nSideLineThres = m_pRecipe->m_SideParam[(int) emDim].m_nSideLineThreshold;
|
int nChamferLineThres = m_pRecipe->m_SideParam[(int) emDim].m_nChamferLineThreshold;
|
|
CRect rtFindROI = CRect(0,0,rtFindPos.Width()-1, rtFindPos.Height()-1);
|
|
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);
|
|
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; i<rtConnerRoi.Height(); i++)
|
memcpy(pConnerOriginImage->imageData+(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; i<pConnerEdgeImage->height; i++)
|
{
|
for(int j=0; j<pConnerEdgeImage->width; 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; i<pConnerEdgeImage->width; i++)
|
{
|
for(int j=0; j<pConnerEdgeImage->height; 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; i<pConnerEdgeImage->width; i++)
|
{
|
for(int j=0; j<pConnerEdgeImage->height; 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<int> vecProjectionX;
|
std::vector<int> vecProjectionY;
|
|
vecProjectionX.resize(rtConnerRoi.Width(), 0);
|
vecProjectionY.resize(rtConnerRoi.Height(), 0);
|
|
int nValue;
|
|
for(int i=0; i<rtConnerRoi.Height(); i++)
|
{
|
for(int j=0; j<rtConnerRoi.Width(); j++)
|
{
|
nValue = (int) pConnerEdgeOutLineImage->imageData[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; i<rtConnerRoi.Width(); i++)
|
{
|
if(nMaxCount < vecProjectionX[i])
|
{
|
nMaxIdx = i;
|
nMaxCount = vecProjectionX[i];
|
}
|
}
|
ptConner[0].x = ptConner[1].x = ptConner[2].x = nMaxIdx;
|
|
if(nPos == 0)
|
{
|
nMaxCount = -1;
|
nMaxIdx = 0;
|
|
for(int i=0; i<rtConnerRoi.Height(); i++)
|
{
|
if(nMaxCount < vecProjectionY[i])
|
{
|
nMaxIdx = i;
|
nMaxCount = vecProjectionY[i];
|
}
|
}
|
|
ptConner[0].y = ptConner[1].y = ptConner[2].y = nMaxIdx;
|
}
|
else
|
{
|
nMaxCount = -1;
|
nMaxIdx = 0;
|
|
for(int i=rtConnerRoi.Height()-1; 0 <= i; i--)
|
{
|
if(nMaxCount < vecProjectionY[i])
|
{
|
nMaxIdx = i;
|
nMaxCount = vecProjectionY[i];
|
}
|
}
|
|
ptConner[0].y = ptConner[1].y = ptConner[2].y = nMaxIdx;
|
}
|
|
double dCornerSizeY_Um = (double)pSideParam->m_nTopCornerSizeY_um;
|
int nCornerSizeY_Pixel = (int) GetUmToPixel_Y(dCornerSizeY_Um);
|
double dCornerSizeX_Um = (double) pSideParam->m_nTopCornerSizeX_um;
|
int nCornerSizeX_Pixel = (int) GetUmToPixel_X(dCornerSizeX_Um);
|
|
// 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 ; i<pConnerEdgeOutLineImage->width; i++)
|
{
|
if(i < 0 || i >= pConnerEdgeOutLineImage->width)
|
continue;
|
|
if(nPos == 0)
|
{
|
//for(int j=0; j<nSearchRangeX; j++)
|
for(int j=-nSearchRangeX;j<nSearchRangeX;j++)
|
{
|
if((ptConner[0].y)+j < 0 || (ptConner[0].y)+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<nSearchRangeX; j++)
|
for(int j=-nSearchRangeX;j<nSearchRangeX;j++)
|
{
|
if((ptConner[0].y)-j < 0 || (ptConner[0].y)-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 ; i<pConnerEdgeOutLineImage->height; i++)
|
{
|
if(i < 0 || i >= pConnerEdgeOutLineImage->height)
|
continue;
|
|
//for(int j=0; j<nSearchRangeY; j++)
|
for(int j=-nSearchRangeY;j<nSearchRangeY;j++)
|
{
|
if(ptConner[0].x+j < 0 || ptConner[0].x+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<nSearchRangeY; j++)
|
for(int j=-nSearchRangeY;j<nSearchRangeY;j++)
|
{
|
if(ptConner[0].x+j < 0 || ptConner[0].x+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<CDefect_Info> vecDefectCandidateList;
|
|
int nUserDefectAreaCount = m_pRecipe->m_SideParam[(int) emDim].m_nUserDefectAreaCount;
|
|
pSideData->m_nUserDefectAreaCount = nUserDefectAreaCount;
|
|
for(int i=0; i<nUserDefectAreaCount; i++)
|
{
|
if(m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_bUseInspect == 0)
|
continue;
|
|
CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_ptTopMarkPos;
|
CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_ptBotMarkPos;
|
CRect rtSet_Area = m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[i].m_rtUserDefectArea;
|
|
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<CDefect_Info>* pDefectList)
|
{
|
if (rtUserDefectArea.IsRectEmpty() == TRUE || m_pGlassData == NULL)
|
return FALSE;
|
|
DefectLocation defectLoc = DefectLoc_UserDefect;
|
|
if(m_pRecipe->m_SideParam[(int) emDim].m_UserDefectPrm[nUserDefectIdx].m_bUseInspect == FALSE)
|
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; i<nExceptionCount; i++)
|
{
|
if(m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_nFilterType == 0)
|
continue;
|
|
CPoint ptSet_TopMark = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_ptTopMarkPos;
|
CPoint ptSet_BotMark = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_ptBotMarkPos;
|
CRect rtSet_Area = m_pRecipe->m_SideParam[(int) emDim].m_ExpAreaPrm[i].m_rtExceptionArea;
|
|
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; nDefectIdx<nDefectCount; nDefectIdx++)
|
{
|
CDefect* pDefect = m_pDefectControl->GetDefect(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;i<MAX_SCAN_COUNT;i++)
|
{
|
m_FullImgBuffer[i].Reset();
|
}
|
}
|
|
void CInspectCamera::SetSimulation(BOOL bSimulation)
|
{
|
m_bSimulation = bSimulation;
|
|
if(m_pGlassData == NULL)
|
return;
|
|
m_pGlassData->SetSimulation(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;i<MAX_DIMENSION_COUNT;i++)
|
{
|
CSide_Data* pSideData = m_pGlassData->GetSideData((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;iFrame<nFrame;iFrame++)
|
{
|
while (TRUE)
|
{
|
nRet = m_pGrabber->IsAcqFrame(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; i<nNotchCount; i++)
|
{
|
if(MAX_SIDE_NOTCH_COUNT <= i)
|
break;
|
|
int nStartLine_Offset = pSideData->m_nGlassStartLine - m_pRecipe->m_SideParam[(int) emDim].m_NotchPrm[i].m_nGlassStartLine_pxl;
|
|
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)
|
{
|
try {
|
// 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);
|
}
|
catch (const std::exception&) {
|
g_pLog->DisplayMessage(_T("Exception in ProcessFrame for Camera %d, Dimension %d"), m_iCamera, (int)emDim);
|
return FALSE;
|
}
|
|
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<std::chrono::seconds>(now.time_since_epoch()).count();
|
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(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<char> 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<std::chrono::milliseconds>(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<CRect> 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<std::chrono::microseconds>(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<CRect> 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<AiDetectResult> 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
|