#include "StdAfx.h" #include "BlobStorage.h" #include "math.h" #include "StopWatch3.h" CBlobStorage::CBlobStorage(void) { m_nBlobSpace= m_maxBlob= m_nBlob= 0; m_pBlobDefect= NULL; } CBlobStorage::~CBlobStorage(void) { if(m_pBlobDefect) delete[] m_pBlobDefect; } void CBlobStorage::ResetBlobStorage() { m_nSkipUnpaired = 0; m_nSkipClassify = 0; m_nMoveClassify = 0; m_nSkipMerged = 0; int i; int nBlob; if(m_nBlobSpace < m_nBlob) nBlob= m_nBlobSpace; else nBlob= m_nBlob; for(i= 0; i< nBlob; i++) { m_pBlobDefect[i].Reset(); } m_nBlob= 0; } void CBlobStorage::TotalResetBlobStorage() { m_nSkipUnpaired = 0; m_nSkipClassify = 0; m_nMoveClassify = 0; m_nSkipMerged = 0; int i; for(i= 0; i< m_maxBlob; i++) { m_pBlobDefect[i].Reset(); } m_nBlob= 0; } int CBlobStorage::InitBlobStorage(int maxBlob) { if(maxBlob <= m_nBlobSpace) { m_maxBlob= maxBlob; return m_maxBlob; } if(m_pBlobDefect != NULL) { delete[] m_pBlobDefect; } // 16°³ÀÇ ¿©ºÐÀ» µÐ´Ù..¿Ö? ³»¸É.. int BlobSapce= maxBlob+ 16; m_pBlobDefect= new CDefectBlob[BlobSapce]; if(m_pBlobDefect == NULL) { m_maxBlob= m_nBlobSpace= 0; return m_maxBlob; } m_maxBlob= m_nBlobSpace= maxBlob; TotalResetBlobStorage();// ÃʱâÈ­ ½Ã°£ ´ÜÃàÀ» À§ÇØ TotalReset °è¿­ ÇÔ¼ö Ãß°¡. return m_maxBlob; } DIT_RESULT CBlobStorage::BlobDefectVert() { DIT_RESULT Ret = DIT_CONV_SUCCESS; CStopWatch stopWatch; stopWatch.Start(); int x, y; // Index ¸Å±â±â. ZeroMemory(m_bMerged, m_nPair * sizeof(BOOL)); ZeroMemory(m_bTemp, m_nPair * sizeof(BOOL)); for (x = 0; x < m_nPair; x++) m_lFirstIndex[x] = x; CDefectPair *pPair; CDefectPair *pPairNext; m_nSkipClassify= 0; // ÀÎÁ¢ µðÆå ¸ÓÁöÇϱâ. // 0. °áÇÔ Çȼ¿ ¹à±â ¿Ö°î º¸Á¤. CPairStorage::CorrectDefGray(); // 1. Filtering Pairing to Delete. CPairStorage::Filtering_Vert(); // 2. Áö¿ì°í ³²Àº Pairing Blob Index ¸¸µé±â. int idx, idy; for(x = 0; x < m_nPair; x++) { pPair= m_pPairDefect+ x; if(pPair->s_DefectType == DEFTYPE_DELETE) continue; for (y = x + 1; y < m_nPair; y++) { pPairNext= m_pPairDefect+ y; if(pPairNext->s_DefectType == DEFTYPE_DELETE) continue; if (m_bMerged[y] || (pPair->s_DefectType != pPairNext->s_DefectType)) continue; idx= pPairNext->s_nDefectX- pPair->s_nDefectX; idy= pPairNext->s_nDefectY- pPair->s_nDefectY; if(idx > 16) break; if((idy > 3 || idy < -3)) // continue; if((idx > 3 || idx < -3)) // continue; m_lFirstIndex[y] = m_lFirstIndex[x]; m_bMerged[y] = TRUE; } } ////////////////////////////////////////////////////////////////////////// int nStart = m_nBlob; // µðÆåµéÀÇ ¼ö¸¸Å­ ó¸®. - Blobing int nBlobNum = 0; int nLevelDiff = 0; CDefectBlob *pBlob= m_pBlobDefect+ m_nBlob; CDefectBlob *pBlobNext; for (x = 0; x < m_nPair; x++) { pPair= m_pPairDefect+ x; if (pPair->s_DefectType == DEFTYPE_DELETE) { m_nSkipClassify++; continue; } if (!m_bTemp[m_lFirstIndex[x]]) // óÀ½ ³ªÅ¸³­ °áÇÔ Ã³¸®. { if (m_nBlob >= m_maxBlob) continue; // 20150811 °Å´ë CS ////////////////////////////////////////////////////////////////////////// //Junho °Å´ëCS if(pPair->s_nZone != 0) // ZONEÀÌ ¾øÀ¸¸é °Å´ë CS´Â ÇÏÁö ¾Ê´Â´Ù. { if(m_Param.m_nCSThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_BLACK) { if(pPair->s_nGraySrc >= m_Param.m_nCSThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } if(m_Param.m_nOriThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(pPair->s_nGraySrc - pPair->s_nGrayRef); if(nLevelDiff < m_Param.m_nOriThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } } ////////////////////////////////////////////////////////////////////////// m_bTemp[m_lFirstIndex[x]] = TRUE; pBlob->CreateBlob(pPair, m_lFirstIndex[x]); m_nBlob++; nBlobNum++; pBlob= m_pBlobDefect+ m_nBlob; } else // ³ªÁß¿¡ ³ªÅ¸³­ °áÇÔ Ã³¸®. { for(y = m_nBlob - 1; y >= 0; y--) { pBlobNext= m_pBlobDefect+ y; if (pBlobNext->s_nIndex == m_lFirstIndex[x]) { // 20150811 °Å´ë CS ////////////////////////////////////////////////////////////////////////// //Junho °Å´ëCS if(pPair->s_nZone != 0) // ZONEÀÌ ¾øÀ¸¸é °Å´ë CS´Â ÇÏÁö ¾Ê´Â´Ù. { if(m_Param.m_nCSThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_BLACK) { if(pPair->s_nGraySrc >= m_Param.m_nCSThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } if(m_Param.m_nOriThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(pPair->s_nGraySrc - pPair->s_nGrayRef); if(nLevelDiff < m_Param.m_nOriThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } } ////////////////////////////////////////////////////////////////////////// pBlobNext->IncludePair(pPair); break; } } } } // ÁÂÇ¥ º¸Á¤. for (x = nStart; x < m_nBlob; x++) { pBlob= m_pBlobDefect+ x; if (pBlob->s_nDefectArea > 0) { pBlob->s_nDefectX = pBlob->s_nDefectX / pBlob->s_nDefectArea; pBlob->s_nDefectY = pBlob->s_nDefectY / pBlob->s_nDefectArea; pBlob->s_sLevelSrcAvg = pBlob->s_nLevelSrcSum / pBlob->s_nDefectArea; pBlob->s_sLevelRefAvg = pBlob->s_nLevelRefSum / pBlob->s_nDefectArea; pBlob->s_sLevelDiffAvg = pBlob->s_nLevelDiffSum / pBlob->s_nDefectArea; pBlob->s_sThresholdAvg = pBlob->s_nThresholdSum / pBlob->s_nDefectArea; pBlob->s_nRegionType = m_Param.s_nRegionType; pBlob->s_nDefectRScale = CalcRScale(pBlob->s_ptVertex); } else pBlob->s_bRemoved = TRUE; } stopWatch.End(); m_BlobTime= stopWatch.GetDurationMilliSecond(); return Ret; } DIT_RESULT CBlobStorage::BlobDefectVert(CPairStorage *pPairStrg) { DIT_RESULT Ret = DIT_CONV_SUCCESS; // °áÇÔ Çȼ¿ ¹à±â ¿Ö°î º¸Á¤. pPairStrg->CorrectDefGray(); // PairDefect ÇÊÅ͸µÇϱâ. pPairStrg->Filtering_Vert(); int x, y; int nPair= m_nPair; CDefectPair *pPairDefect= m_pPairDefect; if(pPairStrg != NULL) { nPair= pPairStrg->m_nPair; pPairDefect= pPairStrg->m_pPairDefect; } // Index ¸Å±â±â. ZeroMemory(m_bMerged, nPair * sizeof(BOOL)); ZeroMemory(m_bTemp, nPair * sizeof(BOOL)); for (x = 0; x < nPair; x++) m_lFirstIndex[x] = x; CDefectPair *pPair; CDefectPair *pPairNext; m_nSkipClassify= 0; // ÀÎÁ¢ µðÆå ¸ÓÁöÇϱâ. int idx, idy; for(x = 0; x < nPair; x++) { pPair= pPairDefect+ x; if(pPair->s_DefectType == DEFTYPE_DELETE) continue; for (y = x + 1; y < nPair; y++) { pPairNext= pPairDefect+ y; if(pPairNext->s_DefectType == DEFTYPE_DELETE) continue; if (m_bMerged[y] || pPair->s_DefectType != pPairNext->s_DefectType) continue; idx= pPairNext->s_nDefectX- pPair->s_nDefectX; idy= pPairNext->s_nDefectY- pPair->s_nDefectY; if(idx > 16) break; if((idy > 3 || idy < -3)) // continue; if((idx > 3 || idx < -3)) // continue; m_lFirstIndex[y] = m_lFirstIndex[x]; m_bMerged[y] = TRUE; } } ////////////////////////////////////////////////////////////////////////// int nStart = m_nBlob; // µðÆåµéÀÇ ¼ö¸¸Å­ ó¸®. - Blobing int nBlobNum = 0; int nLevelDiff = 0; CDefectBlob *pBlob= m_pBlobDefect+ m_nBlob; CDefectBlob *pBlobNext; for (x = 0; x < nPair; x++) { pPair= pPairDefect+ x; if (pPair->s_DefectType == DEFTYPE_DELETE) { m_nSkipClassify++; continue; } if (!m_bTemp[m_lFirstIndex[x]]) // óÀ½ ³ªÅ¸³­ °áÇÔ Ã³¸®. { if (m_nBlob >= m_maxBlob) continue; // 20150811 °Å´ë CS ////////////////////////////////////////////////////////////////////////// //Junho °Å´ëCS if(pPair->s_nZone != 0) // ZONEÀÌ ¾øÀ¸¸é °Å´ë CS´Â ÇÏÁö ¾Ê´Â´Ù. { if(m_Param.m_nCSThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_BLACK) { if(pPair->s_nGraySrc >= m_Param.m_nCSThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } if(m_Param.m_nOriThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(pPair->s_nGraySrc - pPair->s_nGrayRef); if(nLevelDiff < m_Param.m_nOriThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } } ////////////////////////////////////////////////////////////////////////// m_bTemp[m_lFirstIndex[x]] = TRUE; pBlob->CreateBlob(pPair, m_lFirstIndex[x]); m_nBlob++; nBlobNum++; pBlob= m_pBlobDefect+ m_nBlob; } else // ³ªÁß¿¡ ³ªÅ¸³­ °áÇÔ Ã³¸®. { for(y = m_nBlob - 1; y >= 0; y--) { pBlobNext= m_pBlobDefect+ y; if (pBlobNext->s_nIndex == m_lFirstIndex[x]) { // 20150811 °Å´ë CS ////////////////////////////////////////////////////////////////////////// //Junho °Å´ëCS if(pPair->s_nZone != 0) // ZONEÀÌ ¾øÀ¸¸é °Å´ë CS´Â ÇÏÁö ¾Ê´Â´Ù. { if(m_Param.m_nCSThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_BLACK) { if(pPair->s_nGraySrc >= m_Param.m_nCSThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } if(m_Param.m_nOriThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(pPair->s_nGraySrc - pPair->s_nGrayRef); if(nLevelDiff < m_Param.m_nOriThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } } ////////////////////////////////////////////////////////////////////////// pBlobNext->IncludePair(pPair); break; } } } } // ÁÂÇ¥ º¸Á¤. for (x = nStart; x < m_nBlob; x++) { pBlob= m_pBlobDefect+ x; if (pBlob->s_nDefectArea > 0) { pBlob->s_nDefectX = pBlob->s_nDefectX / pBlob->s_nDefectArea; pBlob->s_nDefectY = pBlob->s_nDefectY / pBlob->s_nDefectArea; pBlob->s_sLevelSrcAvg = pBlob->s_nLevelSrcSum / pBlob->s_nDefectArea; pBlob->s_sLevelRefAvg = pBlob->s_nLevelRefSum / pBlob->s_nDefectArea; pBlob->s_sLevelDiffAvg = pBlob->s_nLevelDiffSum / pBlob->s_nDefectArea; pBlob->s_sThresholdAvg = pBlob->s_nThresholdSum / pBlob->s_nDefectArea; pBlob->s_nRegionType = m_Param.s_nRegionType; pBlob->s_nDefectRScale = CalcRScale(pBlob->s_ptVertex); } else pBlob->s_bRemoved = TRUE; } return Ret; } DIT_RESULT CBlobStorage::BlobDefect() { DIT_RESULT Ret = DIT_CONV_SUCCESS; int x, y; // Index ¸Å±â±â. ZeroMemory(m_bMerged, m_nPairSpace * sizeof(BOOL)); ZeroMemory(m_bTemp, m_nPairSpace * sizeof(BOOL)); for (x = 0; x < m_nPair; x++) m_lFirstIndex[x] = x; CDefectPair *pPair; CDefectPair *pPairNext; m_nSkipClassify= 0; // °áÇÔ Çȼ¿ ¹à±â ¿Ö°î º¸Á¤. CPairStorage::CorrectDefGray(); // PairDefect ÇÊÅ͸µÇϱâ. CPairStorage::Filtering_Hori(); for(x = 0; x < m_nPair; x++) { pPair= m_pPairDefect+ x; if(pPair->s_DefectType == DEFTYPE_DELETE) continue; for (y = x + 1; y < m_nPair; y++) { pPairNext= m_pPairDefect+ y; if(pPairNext->s_DefectType == DEFTYPE_DELETE) continue; if (m_bMerged[y] || pPair->s_DefectType != pPairNext->s_DefectType) continue; if (pPairNext->s_nDefectY - pPair->s_nDefectY > 1) // y´Â xº¸´Ù Å©´Ù. break; if (pPairNext->s_nDefectX - pPair->s_nDefectX > 1 || pPairNext->s_nDefectX - pPair->s_nDefectX < -1) continue; m_lFirstIndex[y] = m_lFirstIndex[x]; m_bMerged[y] = TRUE; } } ////////////////////////////////////////////////////////////////////////// int nStart = m_nBlob; // µðÆåµéÀÇ ¼ö¸¸Å­ ó¸®. - Blobing int nBlobNum = 0; int nLevelDiff = 0; CDefectBlob *pBlob= m_pBlobDefect+ m_nBlob; CDefectBlob *pBlobNext; for (x = 0; x < m_nPair; x++) { pPair= m_pPairDefect+ x; if (pPair->s_DefectType == DEFTYPE_DELETE) { m_nSkipClassify++; continue; } if (!m_bTemp[m_lFirstIndex[x]]) // óÀ½ ³ªÅ¸³­ °áÇÔ Ã³¸®. { if (m_nBlob >= m_maxBlob) continue; // 20150811 °Å´ë CS ////////////////////////////////////////////////////////////////////////// //Junho °Å´ëCS if(pPair->s_nZone != 0) // ZONEÀÌ ¾øÀ¸¸é °Å´ë CS´Â ÇÏÁö ¾Ê´Â´Ù. { if(m_Param.m_nCSThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_BLACK) { if(pPair->s_nGraySrc >= m_Param.m_nCSThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } if(m_Param.m_nOriThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(pPair->s_nGraySrc - pPair->s_nGrayRef); if(nLevelDiff < m_Param.m_nOriThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } } ////////////////////////////////////////////////////////////////////////// m_bTemp[m_lFirstIndex[x]] = TRUE; pBlob->CreateBlob(pPair, m_lFirstIndex[x]); m_nBlob++; nBlobNum++; pBlob= m_pBlobDefect+ m_nBlob; } else // ³ªÁß¿¡ ³ªÅ¸³­ °áÇÔ Ã³¸®. { for(y = m_nBlob - 1; y >= 0; y--) { pBlobNext= m_pBlobDefect+ y; if (pBlobNext->s_nIndex != m_lFirstIndex[x]) continue; // 20150811 °Å´ë CS ////////////////////////////////////////////////////////////////////////// //Junho °Å´ëCS if(pPair->s_nZone != 0) // ZONEÀÌ ¾øÀ¸¸é °Å´ë CS´Â ÇÏÁö ¾Ê´Â´Ù. { if(m_Param.m_nCSThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_BLACK) { if(pPair->s_nGraySrc >= m_Param.m_nCSThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } if(m_Param.m_nOriThres[pPair->s_nZone] != 0) { if(pPair->s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(pPair->s_nGraySrc - pPair->s_nGrayRef); if(nLevelDiff < m_Param.m_nOriThres[pPair->s_nZone]) { pPair->s_DefectType = DEFTYPE_DELETE; m_nSkipClassify++; continue; } } } } ////////////////////////////////////////////////////////////////////////// pBlobNext->IncludePair(pPair); break; } } } // ÁÂÇ¥ º¸Á¤. for (x = nStart; x < m_nBlob; x++) { pBlob= m_pBlobDefect+ x; if (pBlob->s_nDefectArea > 0) { pBlob->s_nDefectX = pBlob->s_nDefectX / pBlob->s_nDefectArea; pBlob->s_nDefectY = pBlob->s_nDefectY / pBlob->s_nDefectArea; pBlob->s_sLevelSrcAvg = pBlob->s_nLevelSrcSum / pBlob->s_nDefectArea; pBlob->s_sLevelRefAvg = pBlob->s_nLevelRefSum / pBlob->s_nDefectArea; pBlob->s_sLevelDiffAvg = pBlob->s_nLevelDiffSum / pBlob->s_nDefectArea; pBlob->s_sThresholdAvg = pBlob->s_nThresholdSum / pBlob->s_nDefectArea; pBlob->s_nRegionType = m_Param.s_nRegionType; pBlob->s_nDefectRScale = CalcRScale(pBlob->s_ptVertex); } else pBlob->s_bRemoved = TRUE; } return Ret; } void CBlobStorage::ShadowFilterVert(int nStart, double yPitch) { CDefectBlob *pBlob; CDefectBlob *pBlobNext; int x, y; // Shadow Filtering : unpairÀÇ °æ¿ì... pitch °Ç³Ê¿¡ °áÇÔÀÌ ÀÖ´Ù¸é.. unpair¸¦ Á¦°Å ÇϰڴÙ. CRect rect; CPoint pt; for (x= nStart; x < m_nBlob; x++) { pBlob= m_pBlobDefect+ x; pt.x= pBlob->s_nDefectX; if (pBlob->s_DefectPos == DEFPOS_LEFT) { pt.y= (LONG)(pBlob->s_nDefectY+ yPitch); }else if(pBlob->s_DefectPos == DEFPOS_RIGHT) { pt.y= (LONG)(pBlob->s_nDefectY- yPitch); }else { continue; } for (y = nStart; y < m_nBlob; y++) { if(x == y) continue; pBlobNext= m_pBlobDefect+ y; rect= pBlobNext->s_DefectRect; rect.left -= 3; rect.top -= 3; rect.right += 3; rect.bottom += 3; if(rect.PtInRect(pt)) { pBlob->s_bRemoved = TRUE; break; } } } // ÀÌ°É ÀÌ·± ½ÄÀ¸·Î ÇØ¾ß Çϳª?? ¿ì¼±Àº... Ä«ÇÇÇÏ°í ³ªÁß¿¡ ¼öÁ¤ int i; int nRemovedIdx = 0; for (i = nStart; i < m_nBlob; i++) { if (!m_pBlobDefect[i].s_bRemoved) { m_pBlobDefect[nStart+ nRemovedIdx] = m_pBlobDefect[i]; nRemovedIdx++; } } m_nBlob = nStart+ nRemovedIdx; } void CBlobStorage::ShadowFilter(int nStart, double xPitch) { CDefectBlob *pBlob; CDefectBlob *pBlobNext; int x, y; // Shadow Filtering : unpairÀÇ °æ¿ì... pitch °Ç³Ê¿¡ °áÇÔÀÌ ÀÖ´Ù¸é.. unpair¸¦ Á¦°Å ÇϰڴÙ. CRect rect; CPoint pt; for (x= nStart; x < m_nBlob; x++) { pBlob= m_pBlobDefect+ x; pt.y= pBlob->s_nDefectY; if (pBlob->s_DefectPos == DEFPOS_LEFT) { pt.x= (LONG)(pBlob->s_nDefectX+ xPitch); }else if(pBlob->s_DefectPos == DEFPOS_RIGHT) { pt.x= (LONG)(pBlob->s_nDefectX- xPitch); }else { continue; } for (y = nStart; y < m_nBlob; y++) { if(x == y) continue; pBlobNext= m_pBlobDefect+ y; rect= pBlobNext->s_DefectRect; rect.left -= 3; rect.top -= 3; rect.right += 3; rect.bottom += 3; if(rect.PtInRect(pt)) { pBlob->s_bRemoved = TRUE; break; } } } // ÀÌ°É ÀÌ·± ½ÄÀ¸·Î ÇØ¾ß Çϳª?? ¿ì¼±Àº... Ä«ÇÇÇÏ°í ³ªÁß¿¡ ¼öÁ¤ int i; int nRemovedIdx = 0; for (i = nStart; i < m_nBlob; i++) { if (!m_pBlobDefect[i].s_bRemoved) { m_pBlobDefect[nStart+ nRemovedIdx] = m_pBlobDefect[i]; nRemovedIdx++; } } m_nBlob = nStart+ nRemovedIdx; } DIT_RESULT CBlobStorage::MergeDivision(int nStart, int nMergePixel) { int i, j; // return DIT_CONV_SUCCESS; // °³Ã¼ÀÇ °áÇÔÁ¤º¸¸¦ Merge CDefectBlob *pBlob; CDefectBlob *pBlobNext; for (i = nStart; i < m_nBlob; i++) { pBlob= m_pBlobDefect+ i; for (j = i + 1; j < m_nBlob; j++) { pBlobNext= m_pBlobDefect+ j; //choigudal ´Ù¸¥ °áÇÔÀÌ µ¿ÀÏÇÑ À§Ä¡¿¡¼­ ÀâÈú °æ¿ì Çϳª¸¸ DefectÀ¸·Î º¸°í. 20090725 if (pBlob->s_DefectType != pBlobNext->s_DefectType) continue; if (pBlob->s_DefectRect.bottom + nMergePixel < pBlobNext->s_DefectRect.top || pBlob->s_DefectRect.top - nMergePixel > pBlobNext->s_DefectRect.bottom) continue; if (pBlob->s_DefectRect.right + nMergePixel < pBlobNext->s_DefectRect.left || pBlob->s_DefectRect.left - nMergePixel > pBlobNext->s_DefectRect.right) continue; // ÀÎÁ¢ÇØ ÀÖÀ¸¹Ç·Î ÇÕÄ£´Ù. if (!pBlob->s_bRemoved && !pBlobNext->s_bRemoved) { //choigudal ´Ù¸¥ °áÇÔÀÌ µ¿ÀÏÇÑ À§Ä¡¿¡¼­ ÀâÈú °æ¿ì Çϳª¸¸ DefectÀ¸·Î º¸°í. 20090725 //if(pBlob->s_DefectType == DEFTYPE_WHITE || pBlobNext->s_DefectType == DEFTYPE_WHITE) // pBlob->s_DefectType = DEFTYPE_WHITE; //m_pBlobDefect[i] = m_pBlobDefect[i] + m_pBlobDefect[j]; pBlob->MergeBlob(*pBlobNext); pBlobNext->s_bRemoved = TRUE; m_nSkipMerged++; } } } // °áÇÔÀ» Áö¿î´Ù. int nRemovedIdx = 0; for (i = nStart; i < m_nBlob; i++) { if (!m_pBlobDefect[i].s_bRemoved) { m_pBlobDefect[nStart+ nRemovedIdx] = m_pBlobDefect[i]; nRemovedIdx++; } } m_nBlob = nStart+ nRemovedIdx; for (i = nStart; i < m_nBlob; i++) m_pBlobDefect[i].s_nDefectRScale = CalcRScale(m_pBlobDefect[i].s_ptVertex); return DIT_CONV_SUCCESS; } DIT_RESULT CBlobStorage::MergeMix(int nStart, int nMergePixel) { int i, j; // °³Ã¼ÀÇ °áÇÔÁ¤º¸¸¦ Merge for (i = nStart; i < m_nBlob; i++) { for (j = m_nBlob - 1; j > i; j--) { if (m_pBlobDefect[j].s_DefectRect.bottom + 1 + nMergePixel < m_pBlobDefect[j].s_DefectRect.top || m_pBlobDefect[j].s_DefectRect.top - 1 - nMergePixel > m_pBlobDefect[j].s_DefectRect.bottom) continue; if (m_pBlobDefect[j].s_DefectRect.right + nMergePixel < m_pBlobDefect[j].s_DefectRect.left || m_pBlobDefect[j].s_DefectRect.left - nMergePixel > m_pBlobDefect[j].s_DefectRect.right) continue; // ÀÎÁ¢ÇØ ÀÖÀ¸¹Ç·Î ÇÕÄ£´Ù. -> TypeÀÌ ´Ù¸£¸é TypeÀ» MIXED·Î ¹Ù²Û´Ù. if (m_pBlobDefect[j].s_DefectType != m_pBlobDefect[j].s_DefectType) m_pBlobDefect[j].s_DefectType = DEFTYPE_MIXED; if (!m_pBlobDefect[j].s_bRemoved && !m_pBlobDefect[j].s_bRemoved) { m_pBlobDefect[i].MergeBlob(m_pBlobDefect[j]); m_pBlobDefect[j].s_bRemoved = TRUE; m_nSkipMerged++; } } } // °áÇÔÀ» Áö¿î´Ù. int nRemovedIdx = 0; for (i = nStart; i < m_nBlob; i++) { if (!m_pBlobDefect[i].s_bRemoved) { m_pBlobDefect[nStart+ nRemovedIdx] = m_pBlobDefect[i]; nRemovedIdx++; } } m_nBlob = nStart+ nRemovedIdx; for (i = nStart; i < m_nBlob; i++) m_pBlobDefect[i].s_nDefectRScale = CalcRScale(m_pBlobDefect[i].s_ptVertex); return DIT_CONV_SUCCESS; } void CBlobStorage::CheckDefectRect(CDefectBlob& Defect, int nX, int nY) // CPoint* pVertex, CRect* pRect, int nX, int nY) { CPoint *points= Defect.s_ptVertex; if (nY <= Defect.s_DefectRect.top) { Defect.s_DefectRect.top = nY; if (Defect.s_ptVertex[2].y == nY) // Top Left { if (nX < Defect.s_ptVertex[2].x) { Defect.s_ptVertex[2].x = nX; Defect.s_ptVertex[2].y = nY; } } else { Defect.s_ptVertex[2].x = nX; Defect.s_ptVertex[2].y = nY; } if (Defect.s_ptVertex[3].y == nY) // Top Right { if (nX + 1 > Defect.s_ptVertex[3].x) { Defect.s_ptVertex[3].x = nX + 1; Defect.s_ptVertex[3].y = nY; } } else { Defect.s_ptVertex[3].x = nX + 1; Defect.s_ptVertex[3].y = nY; } } if (nY + 1 >= Defect.s_DefectRect.bottom) { Defect.s_DefectRect.bottom = nY + 1; if (Defect.s_ptVertex[6].y == nY + 1) // Bottom Left { if (nX < Defect.s_ptVertex[6].x) { Defect.s_ptVertex[6].x = nX; Defect.s_ptVertex[6].y = nY + 1; } } else { Defect.s_ptVertex[6].x = nX; Defect.s_ptVertex[6].y = nY + 1; } if (Defect.s_ptVertex[7].y == nY + 1) // Bottom Right { if (nX + 1 > Defect.s_ptVertex[7].x) { Defect.s_ptVertex[7].x = nX + 1; Defect.s_ptVertex[7].y = nY + 1; } } else { Defect.s_ptVertex[7].x = nX + 1; Defect.s_ptVertex[7].y = nY + 1; } } if (nX <= Defect.s_DefectRect.left) { Defect.s_DefectRect.left = nX; if (Defect.s_ptVertex[1].x == nX) // Left Bottom { if (nY + 1 > Defect.s_ptVertex[1].y) { Defect.s_ptVertex[1].x = nX; Defect.s_ptVertex[1].y = nY + 1; } } else { Defect.s_ptVertex[1].x = nX; Defect.s_ptVertex[1].y = nY + 1; } if (Defect.s_ptVertex[0].x == nX) // Left Top { if (nY < Defect.s_ptVertex[0].y) { Defect.s_ptVertex[0].x = nX; Defect.s_ptVertex[0].y = nY; } } else { Defect.s_ptVertex[0].x = nX; Defect.s_ptVertex[0].y = nY; } } if (nX + 1 >= Defect.s_DefectRect.right) { Defect.s_DefectRect.right = nX + 1; if (Defect.s_ptVertex[5].x == nX + 1) // Right Bottom { if (nY + 1 > Defect.s_ptVertex[5].y) { Defect.s_ptVertex[5].x = nX + 1; Defect.s_ptVertex[5].y = nY + 1; } } else { Defect.s_ptVertex[5].x = nX + 1; Defect.s_ptVertex[5].y = nY + 1; } if (Defect.s_ptVertex[4].x == nX + 1) // Right Top { if (nY < Defect.s_ptVertex[4].y) { Defect.s_ptVertex[4].x = nX + 1; Defect.s_ptVertex[4].y = nY; } } else { Defect.s_ptVertex[4].x = nX + 1; Defect.s_ptVertex[4].y = nY; } } } int CBlobStorage::CalcRScale(CPoint* pVertex) { double dDeltaX, dDeltaY; double dTemp, dRScale = 0.0; for (int i = 0; i < 8; i++) { for (int j = i; j < 8; j++) { #ifdef MOSIS_DELETE_CalcRScale if (pVertex[i].x == 0 || pVertex[i].x == 32760 || pVertex[i].y == 0 ||pVertex[i].y == 32760 || pVertex[j].x == 0 || pVertex[j].x == 32760 || pVertex[j].y == 0 ||pVertex[j].y == 32760) continue; #endif dDeltaX = (pVertex[i].x - pVertex[j].x) * m_Param.s_dConvResolution; dDeltaY = (pVertex[i].y - pVertex[j].y) * m_Param.s_dScanResolution; dTemp = sqrt(dDeltaX * dDeltaX + dDeltaY * dDeltaY); if (dRScale < dTemp) dRScale = dTemp; } } if (dRScale < 0.0) dRScale = 0.0; return static_cast(dRScale + 0.5); } int CBlobStorage::GetConvolutionValue(int nX, int nY, double dDist, int nSuppress) { LPBYTE lpBuffer = NULL; int nPitch; double dRestRight; double dRestLeft; int nConvWidth, nConvHeight; lpBuffer = m_Param.s_lpBuffer; nConvWidth = m_Param.s_nConvWidth; nConvHeight = m_Param.s_nConvHeight; // if (dDist < 0) // -10.4 // { // dDist -= 1; // -11.4 // nPitch = static_cast(dDist); // -11 // dRestRight = nPitch - dDist; // 0.4 // dRestLeft = 1.0 - dRestRight; // 0.6 // } // else // 10.4 // { // nPitch = static_cast(dDist); // 10 // dRestLeft = dDist - nPitch; // 0.4 // dRestRight = 1.0 - dRestLeft; // 0.6 // } if (dDist < 0) // -10.4 { dDist -= 1; // -11.4 nPitch = static_cast(dDist); // -11 dRestLeft = nPitch - dDist; // 0.4 dRestRight = 1.0 - dRestLeft; // 0.6 } else // 10.4 { nPitch = static_cast(dDist); // 10 dRestRight = dDist - nPitch; // 0.4 dRestLeft = 1.0 - dRestRight; // 0.6 } int nConvolution = 0; int nSourColor = 0, nDestColor = 0, nValue; for (int i = 0; i < nConvWidth; i++) { for (int j = 0; j < nConvHeight; j++) { nValue = lpBuffer[(nY + j) * m_Param.s_nFrameWidth + (nX + i)]; if (nValue > nSuppress) nValue = nSuppress; nSourColor += nValue; nValue = static_cast((lpBuffer[(nY + j) * m_Param.s_nFrameWidth + (nX + i) + nPitch] * dRestLeft) + (lpBuffer[(nY + j) * m_Param.s_nFrameWidth + (nX + i) + nPitch + 1] * dRestRight)); if (nValue > nSuppress) nValue = nSuppress; nDestColor += nValue; } } nConvolution = nSourColor - nDestColor; return nConvolution; } int CBlobStorage::GetAreaValue(int nXStart, int nYStart, int nWidth, int nHeight, double dDist, int nSuppress) { LPBYTE lpBuffer = NULL; int nPitch; double dRestRight; double dRestLeft; int nConvWidth, nConvHeight; lpBuffer = m_Param.s_lpBuffer; nConvWidth = m_Param.s_nConvWidth; nConvHeight = m_Param.s_nConvHeight; nPitch = static_cast(dDist); dRestRight = dDist - nPitch; dRestLeft = 1.0 - dRestRight; int nConvolution = 0, nValue; double dSourColor = 0.0, dDestColor = 0.0; for (int i = 0; i < nHeight; i++) { for (int j = 0; j < nWidth; j++) { nValue = lpBuffer[(nYStart + i) * m_Param.s_nFrameWidth + (nXStart + j)]; if (nValue > nSuppress) nValue = nSuppress; dSourColor += nValue; nValue = static_cast((lpBuffer[(nYStart + j) * m_Param.s_nFrameWidth + (nXStart + i) + nPitch] * dRestLeft) + (lpBuffer[(nYStart + j) * m_Param.s_nFrameWidth + (nXStart + i) + nPitch + 1] * dRestRight)); if (nValue > nSuppress) nValue = nSuppress; dDestColor += nValue; } } nConvolution = static_cast((dSourColor - dDestColor) / (nWidth * nHeight)); return nConvolution; } int CBlobStorage::GetConvolutionValueVert(int nX, int nY, double dDist, int nSuppress) { LPBYTE lpBuffer = NULL; int nPitch; double dRestRight; double dRestLeft; int nConvWidth, nConvHeight; lpBuffer = m_Param.s_lpBuffer; nConvWidth = m_Param.s_nConvWidth; nConvHeight = m_Param.s_nConvHeight; if (dDist < 0) // -10.4 { dDist -= 1; // -11.4 nPitch = static_cast(dDist); // -11 dRestLeft = nPitch - dDist; // 0.4 dRestRight = 1.0 - dRestLeft; // 0.6 } else // 10.4 { nPitch = static_cast(dDist); // 10 dRestRight = dDist - nPitch; // 0.4 dRestLeft = 1.0 - dRestRight; // 0.6 } if(nY+nPitch+1 >= m_Param.s_nFrameHeight || nY+nPitch+1 <= 0) return 0; int nConvolution = 0; int nSourColor = 0, nDestColor = 0, nValue; for (int i = 0; i < nConvWidth; i++) { for (int j = 0; j < nConvHeight; j++) { nValue = lpBuffer[(nY + j) * m_Param.s_nFrameWidth + (nX + i)]; if (nValue > nSuppress) nValue = nSuppress; nSourColor += nValue; nValue = static_cast((lpBuffer[(nY + j + nPitch) * m_Param.s_nFrameWidth + (nX + i)] * dRestLeft) + (lpBuffer[(nY + j + nPitch + 1) * m_Param.s_nFrameWidth + (nX + i)] * dRestRight)); if (nValue > nSuppress) nValue = nSuppress; nDestColor += nValue; } } nConvolution = nSourColor - nDestColor; return nConvolution; } int CBlobStorage::GetAreaValueVert(int nXStart, int nYStart, int nWidth, int nHeight, double dDist, int nSuppress) { LPBYTE lpBuffer = NULL; int nPitch; double dRestRight; double dRestLeft; int nConvWidth, nConvHeight; lpBuffer = m_Param.s_lpBuffer; nConvWidth = m_Param.s_nConvWidth; nConvHeight = m_Param.s_nConvHeight; nPitch = static_cast(dDist); dRestRight = dDist - nPitch; dRestLeft = 1.0 - dRestRight; if(nYStart+nPitch+1 >= m_Param.s_nFrameHeight) return 0; int nConvolution = 0, nValue; double dSourColor = 0.0, dDestColor = 0.0; for (int i = 0; i < nHeight; i++) { for (int j = 0; j < nWidth; j++) { nValue = lpBuffer[(nYStart + i) * m_Param.s_nFrameWidth + (nXStart + j)]; if (nValue > nSuppress) nValue = nSuppress; dSourColor += nValue; nValue = static_cast((lpBuffer[(nYStart + j + nPitch) * m_Param.s_nFrameWidth + (nXStart + i)] * dRestLeft) + (lpBuffer[(nYStart + j + nPitch + 1) * m_Param.s_nFrameWidth + (nXStart + i)] * dRestRight)); if (nValue > nSuppress) nValue = nSuppress; dDestColor += nValue; } } nConvolution = static_cast((dSourColor - dDestColor) / (nWidth * nHeight)); return nConvolution; } // »ó/ÇÏ ÇÇÄ¡¿µ¿ª¿¡¼­ °áÇÔ À籸ºÐÇÑ´Ù. DIT_RESULT CBlobStorage::ClassificationDefectVert(int nStart) { // ÁÂ/¿ì °Ë»ç¿µ¿ª Àç°Ë»ç. int nPitch = static_cast(m_Param.s_dPitchScanReal * m_Param.s_nPitchCycleScan); double dPitch = m_Param.s_dPitchScanReal * m_Param.s_nPitchCycleScan; int nCR, nCL, nCRValue, nCLValue; int nX, nY; int nStartIdx = m_nBlob - 1; int i; CDefectBlob *pBlob; for (i = nStartIdx; i >= nStart; i--) { pBlob= m_pBlobDefect+ i; if (pBlob->s_DefectPos == DEFPOS_LEFT && pBlob->s_DefectPair == DEFPAIR_UNPAIR) { //if (pBlob->s_sDefectPeak * (m_Param.s_nConvWidth * m_Param.s_nConvHeight) > m_Param.s_nSideThreshold) //if (pBlob->s_sDefectPeak > m_Param.s_nThreshold) { nX = pBlob->s_nDefectX; nY = pBlob->s_nDefectY % m_Param.s_nFrameHeight; nCL = GetConvolutionValueVert(nX, nY, dPitch, m_Param.s_nThresholdSupress); nCR = GetConvolutionValueVert(nX, static_cast(nY+dPitch), dPitch, m_Param.s_nThresholdSupress); nCLValue = abs(nCL); nCRValue = abs(nCR); if (nCLValue >= m_Param.s_nThreshold && nCRValue < m_Param.s_nThreshold) // À§ÂÊ °áÇÔ. { // ¿ÞÂÊÀ¸·Î Shift // pBlob->s_nDefectY += nPitch; // pBlob->s_DefectRect.top += nPitch; // pBlob->s_DefectRect.bottom += nPitch; if (nCL < 0) pBlob->s_DefectType = DEFTYPE_WHITE; else pBlob->s_DefectType = DEFTYPE_BLACK; pBlob->s_DefectPair = DEFPAIR_SIDE; m_nMoveClassify++; } else if (nCLValue >= m_Param.s_nThreshold && nCRValue >= m_Param.s_nThreshold) // À§/¾Æ·¡ ¹à±âÂ÷°¡ °°À¸¸é ÇöÀçÀ§Ä¡ÀÇ °áÇÔÀÌ´Ù. pBlob->s_DefectPair = DEFPAIR_SIDE; } } else if (pBlob->s_DefectPos == DEFPOS_CENTER && pBlob->s_DefectPair == DEFPAIR_UNPAIR) { if (pBlob->s_DefectRect.Width() <= 1 || pBlob->s_DefectRect.Height() <= 1) continue; int nXStart = pBlob->s_DefectRect.left; int nYStart = pBlob->s_DefectRect.top % m_Param.s_nFrameHeight; int nWidth = pBlob->s_DefectRect.Width(); if (nWidth > nPitch) nWidth = nPitch; int nHeight = pBlob->s_DefectRect.Height(); int nThreshold = m_Param.s_nThreshold;// / (m_Param.s_nConvWidth * m_Param.s_nConvHeight); nCR = GetAreaValueVert(nXStart, nYStart, nWidth, nHeight, dPitch, m_Param.s_nThresholdSupress); nCL = GetAreaValueVert(nXStart, static_cast(nYStart-dPitch), nWidth, nHeight, dPitch, m_Param.s_nThresholdSupress); nCLValue = abs(nCL); nCRValue = abs(nCR); if (nCRValue <= nThreshold && nCLValue > nThreshold) // À§ÂÊÀÌ °áÇÔÀÌ´Ù. { // À§·Î Shift pBlob->s_nDefectY -= nPitch; pBlob->s_DefectRect.top -= nPitch; pBlob->s_DefectRect.bottom -= nPitch; if (nCL < 0) pBlob->s_DefectType = DEFTYPE_BLACK; else pBlob->s_DefectType = DEFTYPE_WHITE; pBlob->s_DefectPair = DEFPAIR_LARGE; m_nMoveClassify++; } else if (nCRValue > nThreshold && nCLValue <= nThreshold) // ¾Æ·¡ÂÊÀÌ °áÇÔÀÌ´Ù. { // ¾Æ·¡ÂÊÀ¸·Î Shift pBlob->s_nDefectY += nPitch; pBlob->s_DefectRect.top += nPitch; pBlob->s_DefectRect.bottom += nPitch; if (nCR > 0) pBlob->s_DefectType = DEFTYPE_BLACK; else pBlob->s_DefectType = DEFTYPE_WHITE; pBlob->s_DefectPair = DEFPAIR_LARGE; m_nMoveClassify++; m_nMoveClassify++; } else if (nCRValue > nThreshold && nCLValue > nThreshold) // i¹ø °áÇÔÀ» Áö¿î´Ù. pBlob->s_DefectPair = DEFPAIR_LARGE; } } for (i = m_nBlob - 1; i >= nStart; i--) { pBlob= m_pBlobDefect+ i; if (pBlob->s_DefectPair == DEFPAIR_UNPAIR) pBlob->s_bRemoved = TRUE; } // °áÇÔÀ» Áö¿î´Ù. int nRemovedIdx = 0; for (i = nStart; i < m_nBlob; i++) { pBlob= m_pBlobDefect+ i; if (!pBlob->s_bRemoved) { m_pBlobDefect[nStart+ nRemovedIdx] = m_pBlobDefect[i]; nRemovedIdx++; } } m_nBlob = nStart+ nRemovedIdx; return DIT_CONV_SUCCESS; } BOOL CBlobStorage::ClassifyVertical(int nPairedIdx, int nThreshold) { ////////////////////////////////////////////////////////////////////// // Vertical ºñ±³ int nVertGab = static_cast(m_Param.s_dPitchScanReal * m_Param.s_nPitchCycleScan); double dVRight = (m_Param.s_dPitchScanReal * m_Param.s_nPitchCycleScan) - nVertGab; double dVLeft = 1 - dVRight; int nVApplyPitch = nVertGab; double dLevelSrc, dLevelTemp, dLevelRef; int nLevelDiff; if (m_Param.s_RectConv.Height() > nVApplyPitch * 2) { if (m_pPairDefect[nPairedIdx].s_nDefectY + nVApplyPitch + 1 >= m_Param.s_RectConv.bottom) { nVApplyPitch = -nVertGab - 1; double dTemp = dVRight; dVLeft = dVRight; dVRight = dTemp; } dLevelSrc = *(m_Param.s_lpBuffer + m_pPairDefect[nPairedIdx].s_nDefectY * m_Param.s_nFrameWidth + m_pPairDefect[nPairedIdx].s_nDefectX); dLevelTemp = *(m_Param.s_lpBuffer + (m_pPairDefect[nPairedIdx].s_nDefectY + nVApplyPitch) * m_Param.s_nFrameWidth + m_pPairDefect[nPairedIdx].s_nDefectX); dLevelRef = dLevelTemp * dVLeft; dLevelTemp = *(m_Param.s_lpBuffer + (m_pPairDefect[nPairedIdx].s_nDefectY + nVApplyPitch + 1) * m_Param.s_nFrameWidth + m_pPairDefect[nPairedIdx].s_nDefectX); dLevelRef += dLevelTemp * dVRight; // Pixel ´ÜÀ§·Î ¹®ÅΰªÀ» ³ÑÁö ¾ÊÀ» °æ¿ì »èÁ¦. if (m_pPairDefect[nPairedIdx].s_DefectType == DEFTYPE_BLACK) { nLevelDiff = static_cast(dLevelRef - dLevelSrc); if (nLevelDiff < nThreshold) { m_pPairDefect[nPairedIdx].s_DefectType = DEFTYPE_DELETE; return FALSE; } } else if (m_pPairDefect[nPairedIdx].s_DefectType == DEFTYPE_WHITE) { nLevelDiff = static_cast(dLevelSrc - dLevelRef); if (nLevelDiff < nThreshold) { m_pPairDefect[nPairedIdx].s_DefectType = DEFTYPE_DELETE; return FALSE; } } return TRUE; } // °ËÁõÇÒ ¼ö ¾øÀ¸¸é °áÇÔÀ¸·Î ³ÖÁö ¸»¶ó´Â »ÇºüÀÌ ¾ÆÀú¾¾ÀÇ ¸»¾¸. return FALSE; } BOOL CBlobStorage::ReadBlob(CBlobStorage *pBlobStrg) { if(pBlobStrg == NULL) return FALSE; CDefectBlob *pBlob; int nBlob= pBlobStrg->GetBlobCount(); for(int iBlob= 0; iBlob < nBlob; iBlob++) { pBlob= pBlobStrg->GetBlobDefect(iBlob); if(AddBlob(pBlob) == FALSE) return FALSE; } return TRUE; } BOOL CBlobStorage::AddBlob(CDefectBlob *pBlob) { if(m_nBlob < m_maxBlob) { *GetBlobDefect(m_nBlob)= *pBlob; m_nBlob++; return m_nBlob < m_maxBlob; } return FALSE; }