#include "stdafx.h" #include "LineChecker.h" #include #include #include #define SAVE_PROJECTION_VALUE int m_nLineCheckerLocalPeakPeriod; //x 좌표를 기준으로 Local Peak nPeriod 범위( x - nPeriod/2 ~ x + nPeriod/2 ) 내에서 최소값을 찾음 //Input // pProjection : Review Image의 Projection Graph // x : 탐색 위치 // nWidth : Projection Graph의 nWidth(side = TOP인 경우 최대 Review Image의 Height) //Output // pPos : 탐색 범위 내 최소값의 좌표 //Return // 탐색 범위 내 최소값(gray value) BYTE LocalMinima(int *pProjection, int *pPos, int x, int nWidth, int nPeriod) { if(pProjection == NULL) { TRACE(_T("LocalMinima : Projection Graph Is Not Allocated\n")); return 0; } if(pPos == NULL) { TRACE(_T("LocalMinima : pPosition Coordi Is Not Allocated\n")); return 0; } int i = x - nPeriod / 2 ; if(i < 0) i = 0; BYTE local_minima = *(pProjection + i); *pPos = i; for(; i < x + nPeriod / 2; i++) { if(i > nWidth - 1) break; if(local_minima > *(pProjection + i)) { local_minima = *(pProjection + i); *pPos = i; } } return local_minima; } //x 좌표를 기준으로 Local Peak nPeriod 범위( x - nPeriod/2 ~ x + nPeriod/2 ) 내에서 최대값을 찾음 //Input // pProjection : Review Image의 Projection Graph // x : 탐색 위치 // nWidth : Projection Graph의 nWidth //Output // pos : 탐색 범위 내 최대값의 좌표 //Return // 탐색 범위 내 최대값(gray value) BYTE LocalMaxima(int *pProjection, int x, int nWidth, int nPeriod) { if(pProjection == NULL) { TRACE(_T("LocalMaxima : Projection Graph Is Not Allocated\n")); return 0; } int i = x - nPeriod / 2 ; if(i < 0) i = 0; BYTE local_maxima = *(pProjection + i); for(; i < x + nPeriod / 2; i++) { if(i > nWidth - 1) break; if(local_maxima < *(pProjection + i)) local_maxima = *(pProjection + i); } return local_maxima; } //x 좌표를 기준으로 Local Peak Period 범위( x - period/2 ~ x + period/2 ) 내에서 최소값을 찾음 //Input // pProjection : Review Image의 Projection Graph // x : 탐색 위치 // width : Projection Graph의 width(side = TOP인 경우 최대 Review Image의 Height) //Output // pos : 탐색 범위 내 최소값의 좌표 //Return // 탐색 범위 내 최소값(gray value) BYTE LocalMinima(int *pProjection, int *pos, int x, int width) { if(pProjection == NULL) { TRACE(_T("LocalMinima : Projection Graph Is Not Allocated\n")); return 0; } if(pos == NULL) { TRACE(_T("LocalMinima : Position Coordi Is Not Allocated\n")); return 0; } int i = x - m_nLineCheckerLocalPeakPeriod / 2 ; if(i < 0) i = 0; BYTE local_minima = *(pProjection + i); *pos = i; for(; i < x + m_nLineCheckerLocalPeakPeriod / 2; i++) { if(i > width - 1) break; if(local_minima > *(pProjection + i)) { local_minima = *(pProjection + i); *pos = i; } } return local_minima; } //x 좌표를 기준으로 Local Peak Period 범위( x - period/2 ~ x + period/2 ) 내에서 최대값을 찾음 //Input // pProjection : Review Image의 Projection Graph // x : 탐색 위치 // width : Projection Graph의 width //Output // pos : 탐색 범위 내 최대값의 좌표 //Return // 탐색 범위 내 최대값(gray value) BYTE LocalMaxima(int *pProjection, int x, int width) { if(pProjection == NULL) { TRACE(_T("LocalMaxima : Projection Graph Is Not Allocated\n")); return 0; } int i = x - m_nLineCheckerLocalPeakPeriod / 2 ; if(i < 0) i = 0; BYTE local_maxima = *(pProjection + i); for(; i < x + m_nLineCheckerLocalPeakPeriod / 2; i++) { if(i > width - 1) break; if(local_maxima < *(pProjection + i)) local_maxima = *(pProjection + i); } return local_maxima; } //x 좌표를 기준으로 Local Peak Period * 2 범위( x - period ~ x + period ) 내에서 저점 2개를 찾음 //dam2의 안쪽 line이 넘쳤을 때 1 line, 넘치지 않았을 때 2 line이 보이기 때문 //즉, dam2의 안쪽 line을 검사하는 메소드 //focus에 따라 2 line이 blur되는 경우가 있어 보완 필요 //Input // pProjection : Review Image의 Projection Graph // x : 탐색 위치 // width : Projection Graph의 width // threshold : 검사 threshold. localmax - localmin > threshold인 경우 넘치지 않았다고 판정 // bForward : 탐색 방향. TRUE(좌 > 우, 상 > 하). FALSE(우 > 좌) //Output // pos : dam2의 위치. 검출된 line들의 중간 지점 //Return // dam2 overflow 여부 T/F BOOL CheckTwoLines(int *pProjection, int x, int width, int threshold, BOOL bForward, int *pos) { if(pProjection == NULL) { TRACE(_T("CheckTwoLines : Projection Graph Is Not Allocated\n")); return FALSE; } if(pos == NULL) { TRACE(_T("CheckTwoLines : Position Coordi Is Not Allocated\n")); return 0; } int i; int nSearchEnd; if(bForward) { //i = x - LOCAL_PEAK_PERIOD / 2; //nSearchEnd = x + LOCAL_PEAK_PERIOD * 9 / 2; i = x - m_nLineCheckerLocalPeakPeriod; nSearchEnd = x + m_nLineCheckerLocalPeakPeriod; } else { //i = x + LOCAL_PEAK_PERIOD / 2; //nSearchEnd = x - LOCAL_PEAK_PERIOD * 9 / 2; i = x + m_nLineCheckerLocalPeakPeriod; nSearchEnd = x - m_nLineCheckerLocalPeakPeriod; } if(i < 1) i = 1; if(nSearchEnd < 1) nSearchEnd = 01; if(i > width - 2) i = width - 2; if(nSearchEnd > width - 2) nSearchEnd = width - 2; int nPeakCount = 0; *pos = 0; if(bForward) { BOOL bIncreaseSlope = (*(pProjection + i + 1) >= *(pProjection + i - 1)); i++; for(; i < nSearchEnd; i++) { //if(!(bIncreaseSlope & (*(pDifference_lpf + i) >= 0))) if(bIncreaseSlope ^ (*(pProjection + i + 1) >= *(pProjection + i - 1)))//기울기 방향이 바뀌는 시점(Peak) { if(LocalMaxima(pProjection, i, width) - *(pProjection + i) > threshold) { nPeakCount++; *pos += i; } bIncreaseSlope = !bIncreaseSlope; } } } else { BOOL bIncreaseSlope = (*(pProjection + i - 1) >= *(pProjection + i + 1)); i--; for(; i >= nSearchEnd; i--) { //if(!(bIncreaseSlope & (*(pDifference_lpf + i) >= 0))) if(bIncreaseSlope ^ (*(pProjection + i - 1) >= *(pProjection + i + 1)))//기울기 방향이 바뀌는 시점(Peak) { if(LocalMaxima(pProjection, i, width) - *(pProjection + i) > threshold) { nPeakCount++; *pos += i; } bIncreaseSlope = !bIncreaseSlope; } } } if(nPeakCount >= 2) { *pos /= nPeakCount; return TRUE; } return FALSE; } //Color Image를 Gray Buffer로 변환 //Color Channel = 1인 경우는 단순 복사 //Color Channel = 2인 경우는 미구현 //Color Channel = 3, 4인 경우는 r+b+g / 3으로 변환 //Input // pImageOrigin : Input Image Buffer(Color Image) // nImageWidth : Image Width // nImageHeight : Image Height // nChannel : Image Color Channel // nImageWidthStep : Image Width * Channel + Margin(0 이상). Input Image가 실제 Image보다 큰 Memory를 확보하는 경우 Margin을 제거하기 위해 필요함 //Output // pImage : 변환된 Gray Image //Return // 변환 성공 여부 T/F. Input Image에 오류가 있는 경우 False int RGB2GRAY(BYTE* pImage, BYTE* pImageOrigin, int nImageWidth, int nImageHeight, int nChannel, int nImageWidthStep) { if(nImageWidth <= 0 && nImageHeight <= 0) { TRACE(_T("RGB2GRAY : Input Image Not Loaded\n")); return -1; // image not loaded } if(pImageOrigin == NULL) { TRACE(_T("RGB2GRAY : Input Image Not Loaded\n")); return -1; } if(pImage == NULL) { TRACE(_T("RGB2GRAY : Output Image Not Loaded\n")); return -1; } if(nChannel == 1) { BYTE* temp; //for(int y = 0 ; y < nImageHeight; y++) //{ // temp = pImageOrigin + y * nImageWidth; // memcpy((pImage + y * nImageWidth), temp, sizeof(BYTE) * nImageWidth); //} memcpy(pImage, pImageOrigin, sizeof(BYTE) * nImageWidth * nImageHeight); } else { BYTE* temp; //COLORREF rgb; for(int y = 0 ; y < nImageHeight; y++) { temp = pImageOrigin + y * nImageWidthStep; for(int x = 0; x < nImageWidth; x++) { pImage[y * nImageWidth + x] = (*(temp + x * nChannel) + *(temp + x * nChannel + 1) + *(temp + x * nChannel + 2)) / 3; } } //m_ImageBuffer.m_ImageBuffer = temp; } return 0; } //1D Image Matching //Review Image와 Master Image를 Matching하여 Review Image 내 ROI를 설정함 //Side = Top의 경우 호출됨 => 가로 방향 Projection Graph를 도출하여 세로 방향으로 Matching함 //Matching Method는 Correlation 사용 //Input // pImage : Review Image(Gray Image) // nImageWidth : Review Image Width // nImageHeight : Review Image Height // pMaster : Master Image Buffer(Gray Image) // nMasterWidth : Master Image Width // nMasterHeight : Master Image Height //Output // rtMatch : Matching 결과 ROI(세로 방향으로 Matching하였기 때문에 top, bottom이 Master Image Height만큼 줄어들고, left right는 변함 없음) //Return // Match 성공 여부 T/F // Matching Score 0.9 이상인 경우 TRUE(No Reflow와 DAM2 Reflow Matching 시 0.917) BOOL Match_Vertical(BYTE *pImage, int nImageWidth, int nImageHeight, BYTE *pMaster, int nMasterWidth, int nMasterHeight, CRect *rtMatch) { int *pImageProjection = NULL; pImageProjection = new int[nImageHeight]; int *pMasterProjection = NULL; pMasterProjection = new int[nMasterHeight]; double *pResult = NULL; pResult = new double[nImageHeight]; memset(pImageProjection, 0, sizeof(int) * nImageHeight); memset(pMasterProjection, 0, sizeof(int) * nMasterHeight); BYTE *pIm = pImage; BYTE *pMs = pMaster; for(int j = 0; j < nImageWidth; j++)//Review Image Projection { for(int i = 0; i < nImageHeight; i++) { pImageProjection[i] += *(pIm + i * nImageWidth + j); } } for(int i = 0; i < nImageHeight; i++) { pImageProjection[i] /= nMasterWidth; } for(int j = 0; j < nMasterWidth; j++)//Master Image Projection { for(int i = 0; i < nMasterHeight; i++) { pMasterProjection[i] += *(pMs + i * nMasterWidth + j); } } for(int i = 0; i < nMasterHeight; i++) { pMasterProjection[i] /= nMasterWidth; } //Match double dMasterAvg = 0; double dMasterVar; double dMasterVarSqSum = 0; double dImageAvg = 0; double dImageVar; double dImageVarSqSum = 0; double dNumerSum = 0; double dDenomSum = 0; int nMaxPos = 0; double dMaxScore = 0; TRACE(_T("Reflow Match Vertical\n")); TRACE(_T("Reflow Match SearchArea(ROI) : (%d, %d) - (%d, %d)\n"), rtMatch->left, rtMatch->top, rtMatch->right, rtMatch->bottom); //Master Image Avg for(int j = 0; j < nMasterHeight; j++) { dMasterAvg += pMasterProjection[j]; } dMasterAvg /= nMasterHeight; //for(int i = 0; i < (nImageHeight - nMasterHeight); i++) for(int i = rtMatch->top; i < (rtMatch->bottom - nMasterHeight); i++) { dMasterVarSqSum = 0; dImageAvg = 0; dImageVarSqSum = 0; dNumerSum = 0; dDenomSum = 0; //Avg for(int j = 0; j < nMasterHeight; j++) { dImageAvg += pImageProjection[i + j]; } dImageAvg /= nMasterHeight; //Var for(int j = 0; j < nMasterHeight; j++) { dMasterVar = abs(pMasterProjection[j] - dMasterAvg); dImageVar = abs(pImageProjection[i + j] - dImageAvg); dNumerSum += dMasterVar * dImageVar; dMasterVarSqSum += dMasterVar * dMasterVar; dImageVarSqSum += dImageVar * dImageVar; } dDenomSum = sqrt(dMasterVarSqSum * dImageVarSqSum); //Denom if(dDenomSum != 0) pResult[i] = dNumerSum / dDenomSum; else pResult[i] = 0; if(dMaxScore < pResult[i]) { dMaxScore = pResult[i]; nMaxPos = i; } } TRACE(_T("Reflow Match Matching Result(yCoordi) : %d\n"), nMaxPos); if(dMaxScore < 0.9) { TRACE(_T("Reflow Match Matching Fail : Matching Score = %.2f\n"), dMaxScore * 100); if(pImageProjection) { delete [] pImageProjection; pImageProjection = NULL; } if(pMasterProjection) { delete [] pMasterProjection; pMasterProjection = NULL; } if(pResult) { delete [] pResult; pResult = NULL; } return FALSE; } TRACE(_T("Reflow Match Matching Success : Matching Score = %.2f\n"), dMaxScore * 100); //if(nMaxPos == 0 || nMaxPos == nImageHeight - nMasterHeight - 1) //{ rtMatch->top = nMaxPos; //} //else //{ // double dNum = pResult[nMaxPos - 1] - pResult[nMaxPos + 1]; // double dDenom = pResult[nMaxPos - 1] + pResult[nMaxPos + 1] - 2 * pResult[nMaxPos]; // if(dDenom == 0) dDenom = 0.00000001; //} rtMatch->bottom = nMaxPos + nMasterHeight; //rtMatch->left = 0; //rtMatch->right = nImageWidth - 1; if(pImageProjection) { delete [] pImageProjection; pImageProjection = NULL; } if(pMasterProjection) { delete [] pMasterProjection; pMasterProjection = NULL; } if(pResult) { delete [] pResult; pResult = NULL; } return TRUE; } //Review Image와 Master Image를 Matching하여 Review Image 내 ROI를 설정함 //Side = Left, Right의 경우 호출됨 => 세로 방향 Projection Graph를 도출하여 가로 방향으로 Matching함 //Matching Method는 Correlation 사용 //Input // pImage : Review Image(Gray Image) // nImageWidth : Review Image Width // nImageHeight : Review Image Height // pMaster : Master Image Buffer(Gray Image) // nMasterWidth : Master Image Width // nMasterHeight : Master Image Height //Output // rtMatch : Matching 결과 ROI(가로 방향으로 Matching하였기 때문에 left right가 Master Image Height만큼 줄어들고, top, bottom은 변함 없음) //Return // Match 성공 여부 T/F // Matching Score 0.9 이상인 경우 TRUE(No Reflow와 DAM2 Reflow Matching 시 0.917) BOOL Match_Horizontal(BYTE *pImage, int nImageWidth, int nImageHeight, BYTE *pMaster, int nMasterWidth, int nMasterHeight, CRect *rtMatch) { int *pImageProjection = NULL; pImageProjection = new int[nImageWidth]; int *pMasterProjection = NULL; pMasterProjection = new int[nMasterWidth]; double *pResult = NULL; pResult = new double[nImageWidth]; memset(pImageProjection, 0, sizeof(int) * nImageWidth); memset(pMasterProjection, 0, sizeof(int) * nMasterWidth); BYTE *pIm = pImage; BYTE *pMs = pMaster; for(int j = 0; j < nImageHeight; j++)//Review Image Projection { for(int i = 0; i < nImageWidth; i++) { pImageProjection[i] += *(pIm + j * nImageWidth + i); } } for(int i = 0; i < nImageWidth; i++) { pImageProjection[i] /= nMasterHeight; } for(int j = 0; j < nMasterHeight; j++)//Master Image Projection { for(int i = 0; i < nMasterWidth; i++) { pMasterProjection[i] += *(pMs + j * nMasterWidth + i); } } for(int i = 0; i < nMasterWidth; i++) { pMasterProjection[i] /= nMasterHeight; } //Match double dMasterAvg = 0; double dMasterVar; double dMasterVarSqSum = 0; double dImageAvg = 0; double dImageVar; double dImageVarSqSum = 0; double dNumerSum = 0; double dDenomSum = 0; int nMaxPos = 0; double dMaxScore = 0; TRACE(_T("Reflow Match Horizontal\n")); TRACE(_T("Reflow Match SearchArea(ROI) : (%d, %d) - (%d, %d)\n"), rtMatch->left, rtMatch->top, rtMatch->right, rtMatch->bottom); //Master Image Avg for(int j = 0; j < nMasterWidth; j++) { dMasterAvg += pMasterProjection[j]; } dMasterAvg /= nMasterWidth; //for(int i = 0; i < (nImageWidth - nMasterWidth); i++) for(int i = rtMatch->left; i < (rtMatch->right - nMasterWidth); i++) { dMasterVarSqSum = 0; dImageAvg = 0; dImageVarSqSum = 0; dNumerSum = 0; dDenomSum = 0; //Avg for(int j = 0; j < nMasterWidth; j++) { dImageAvg += pImageProjection[i + j]; } dImageAvg /= nMasterWidth; //Var for(int j = 0; j < nMasterWidth; j++) { dMasterVar = abs(pMasterProjection[j] - dMasterAvg); dImageVar = abs(pImageProjection[i + j] - dImageAvg); dNumerSum += dMasterVar * dImageVar; dMasterVarSqSum += dMasterVar * dMasterVar; dImageVarSqSum += dImageVar * dImageVar; } dDenomSum = sqrt(dMasterVarSqSum * dImageVarSqSum); //Denom if(dDenomSum != 0) pResult[i] = dNumerSum / dDenomSum; else pResult[i] = 0; if(dMaxScore < pResult[i]) { dMaxScore = pResult[i]; nMaxPos = i; } } TRACE(_T("Reflow Match Matching Result(xCoordi) : %d\n"), nMaxPos); if(dMaxScore < 0.9) { TRACE(_T("Reflow Match Matching Fail : Matching Score = %.2f\n"), dMaxScore * 100); if(pImageProjection) { delete [] pImageProjection; pImageProjection = NULL; } if(pMasterProjection) { delete [] pMasterProjection; pMasterProjection = NULL; } if(pResult) { delete [] pResult; pResult = NULL; } return FALSE; } TRACE(_T("Reflow Match Matching Success : Matching Score = %.2f\n"), dMaxScore * 100); //if(nMaxPos == 0 || nMaxPos == nImageHeight - nMasterHeight - 1) //{ rtMatch->left = nMaxPos; //} //else //{ // double dNum = pResult[nMaxPos - 1] - pResult[nMaxPos + 1]; // double dDenom = pResult[nMaxPos - 1] + pResult[nMaxPos + 1] - 2 * pResult[nMaxPos]; // if(dDenom == 0) dDenom = 0.00000001; //} rtMatch->right = nMaxPos + nMasterWidth; //rtMatch->top = 0; //rtMatch->bottom = nImageHeight - 1; if(pImageProjection) { delete [] pImageProjection; pImageProjection = NULL; } if(pMasterProjection) { delete [] pMasterProjection; pMasterProjection = NULL; } if(pResult) { delete [] pResult; pResult = NULL; } return TRUE; } //2D Image Matching. 속도 문제로 사용하지 않고 있음 //Image의 pixel 값의 제곱의 합을 계산 //Master Image의 제곱의 합을 계산하기 위해 사용 //Input // pIn : Image Buffer(Master Image) // nSize : Image Size(Master Image Width * Height) //Return // Image Buffer의 Image Size만큼의 pixel 값의 제곱의 합 INT64 GetSquareSumSmallImage(BYTE *pIn, int nSize) { if(pIn == NULL) return -1; int i, s = 0; INT64 sum = 0; __m128i mmResult, mmResult2; __m128i mmA; __m128i mmAA, mmBB; __m128i mmZeroData = _mm_setzero_si128(); INT64 res64[2]; mmResult = _mm_setzero_si128(); for(i = 0; i <= nSize - 16; i += 16) { mmA = _mm_loadu_si128((__m128i*) (pIn + i)); //load 16 pixels(pSmall[0:15]) mmAA = _mm_unpackhi_epi8(mmA, mmZeroData); //byte to short(pSmall[8:15]) mmResult2 = _mm_madd_epi16(mmAA, mmAA); //square sum's add(pSmall[8]^2 + pSmall[9]^2 ~ pSmall[14]^2 + pSmall[15]^2) mmAA = _mm_unpackhi_epi32(mmResult2, mmZeroData); //int to int64(pSmall[12]^2 + pSmall[13]^2, pSmall[14]^2 + pSmall[15]^2) mmBB = _mm_unpacklo_epi32(mmResult2, mmZeroData); //int to int64(pSmall[8]^2 + pSmall[9]^2, pSmall[10]^2 + pSmall[11]^2) mmResult = _mm_add_epi64(mmAA, mmResult); //sum(pSmall[12]^2 + pSmall[13]^2 + pSmall[14]^2 + pSmall[15]^2) mmResult = _mm_add_epi64(mmBB, mmResult); //sum(↑ + pSmall[8]^2 + pSmall[9]^2 + pSmall[10]^2 + pSmall[11]^2) mmAA = _mm_unpacklo_epi8(mmA, mmZeroData); //byte to short(pSmall[0:7]) mmResult2 = _mm_madd_epi16(mmAA, mmAA); //square sum's add(pSmall[0]^2 + pSmall[1]^2 ~ pSmall[6]^2 + pSmall[7]^2) mmAA = _mm_unpackhi_epi32(mmResult2, mmZeroData); //int to int64(pSmall[4]^2 + pSmall[5]^2, pSmall[6]^2 + pSmall[7]^2) mmBB = _mm_unpacklo_epi32(mmResult2, mmZeroData); //int to int64(pSmall[0]^2 + pSmall[1]^2, pSmall[2]^2 + pSmall[3]^2) mmResult = _mm_add_epi64(mmAA, mmResult); //sum(↑ + pSmall[4]^2 + pSmall[5]^2 + pSmall[6]^2 + pSmall[7]^2) mmResult = _mm_add_epi64(mmBB, mmResult); //sum(↑ + pSmall[0]^2 + pSmall[1]^2 + pSmall[2]^2 + pSmall[3]^2) } _mm_storeu_si128((__m128i*)res64, mmResult); sum = res64[0] + res64[1]; for( ; i < nSize; i++ ) { s += pIn[i] * pIn[i]; } return sum + s; } //GetSquareSumSmallImage와 동일하게 제곱의 합을 계산 //Review Image의 한 Line(Master Image Width만큼)의 제곱의 합을 계산하기 위해 사용 //Master Image Height만큼 합하면 Master Image Size의 Review Image의 제곱의 합을 계산할 수 있음 //Input // pIn : Image Buffer(Review Image) // nSize : Line Size(Master Image Width) //Return // Image Buffer의 Line Size만큼의 pixel 값의 제곱의 합 INT64 GetSquareSumBigLine(BYTE *pIn, int nSize) //GetSquareSumSmallImage와 동일 { if(pIn == NULL) return -1; int i, s = 0; INT64 sum = 0; __m128i mmResult, mmResult2; __m128i mmA; __m128i mmAA, mmBB; __m128i mmZeroData= _mm_setzero_si128(); INT64 res64[2]; mmResult = _mm_setzero_si128(); for(i = 0; i <= nSize - 16; i += 16) { mmA = _mm_loadu_si128((__m128i*) (pIn+ i)); mmAA = _mm_unpackhi_epi8(mmA, mmZeroData); mmResult2 = _mm_madd_epi16(mmAA, mmAA); mmAA = _mm_unpackhi_epi32(mmResult2, mmZeroData); mmBB = _mm_unpacklo_epi32(mmResult2, mmZeroData); mmResult = _mm_add_epi64(mmAA, mmResult); mmResult = _mm_add_epi64(mmBB, mmResult); mmAA = _mm_unpacklo_epi8(mmA, mmZeroData); mmResult2 = _mm_madd_epi16(mmAA, mmAA); mmAA = _mm_unpackhi_epi32(mmResult2, mmZeroData); mmBB = _mm_unpacklo_epi32(mmResult2, mmZeroData); mmResult = _mm_add_epi64(mmAA, mmResult); mmResult = _mm_add_epi64(mmBB, mmResult); } _mm_storeu_si128((__m128i*)res64, mmResult); sum = res64[0] + res64[1]; for( ; i < nSize; i++ ) { s += pIn[i] * pIn[i]; } return sum + s; } //2 Image의 pixel 값의 곱의 합을 계산 //2 Image의 Correlation을 계산하기 위해 두 Image의 각 pixel의 곱의 합이 필요함 //Input // pSmall : Small Image Buffer(Master Image) // pBig : Big Image Buffer(Review Image) // nSize : Small Image Size(Master Image Width * Height) //Return // Mastrer Image Size만큼의 Master Image와 Review Image의 Pixel 값의 곱의 합 INT64 GetMulSmallBig(BYTE *pSmall, BYTE *pBig, int nSize) { if(pSmall == NULL) return -1; if(pBig == NULL) return -1; int i, s = 0; INT64 sum = 0; __m128i mmResult, mmResult2; __m128i mmA, mmB; __m128i mmAA, mmBB; __m128i mmZeroData = _mm_setzero_si128(); mmResult = _mm_setzero_si128(); INT64 res64[2]; for(i = 0; i <= nSize - 16; i += 16) { mmA = _mm_loadu_si128((__m128i*) (pSmall + i)); //load 16 pixels(pSmall[0:15]) mmB = _mm_loadu_si128((__m128i*) (pBig + i)); //load 16 pixels(pBig[0:15]) mmAA = _mm_unpackhi_epi8(mmA, mmZeroData); //byte to short(pSmall[8:15]) mmBB = _mm_unpackhi_epi8(mmB, mmZeroData); //byte to short(pBig[8:15]) mmResult2 = _mm_madd_epi16(mmAA, mmBB); //Multiple sum's add(pSmall[8]*pBig[8] + pSmall[9]*pBig[9] ~ pSmall[14]*pBig[14] + pSmall[15]*pBig[15]) mmAA = _mm_unpackhi_epi32(mmResult2, mmZeroData); //int to int64(pSmall[12]*pBig[12] + pSmall[13]*pBig[13], pSmall[14]*pBig[14] + pSmall[15]*pBig[15]) mmBB = _mm_unpacklo_epi32(mmResult2, mmZeroData); //int to int64(pSmall[8]*pBig[8] + pSmall[9]*pBig[9], pSmall[10]*pBig[10] + pSmall[11]*pBig[11]) mmResult = _mm_add_epi64(mmAA, mmResult); //sum(pSmall[12]*pBig[12] + pSmall[13]*pBig[13], pSmall[14]*pBig[14] + pSmall[15]*pBig[15]) mmResult = _mm_add_epi64(mmBB, mmResult); //sum(↑ + pSmall[8]*pBig[8] + pSmall[9]*pBig[9], pSmall[10]*pBig[10] + pSmall[11]*pBig[11]) mmAA = _mm_unpacklo_epi8(mmA, mmZeroData); mmBB = _mm_unpacklo_epi8(mmB, mmZeroData); mmResult2 = _mm_madd_epi16(mmAA, mmBB); mmAA = _mm_unpackhi_epi32(mmResult2, mmZeroData); mmBB = _mm_unpacklo_epi32(mmResult2, mmZeroData); mmResult = _mm_add_epi64(mmAA, mmResult); mmResult = _mm_add_epi64(mmBB, mmResult); } _mm_storeu_si128((__m128i*)res64, mmResult); sum = res64[0] + res64[1]; for(; i < nSize; i++) { s += pSmall[i] * pBig[i]; } return sum + s; } //Matching 결과 Matching Score가 가장 높은 좌표를 찾음 //Input // pMatchResult : Matching Result를 각 좌표마다 저장한 array((Review Image Width - Master Image WIdth) * (Review Image Height - Master Image Height)) 크기 // nBigWidth : Big Image Width(Review Image) // nBigHeight : Big Image Height(Review Image) // nSmallWidth : Small Image Width(Master Image) // nSmallHeight : Small Image Height(Master Image) // MatchResult Array의 Size를 계산하기 위해 각 Image의 크기를 입력받음 //Output // x : Review Image 내에서 Matching 된 위치의 x좌표 // y : Review Image 내에서 Matching 된 위치의 y좌표 // s : Review Image 내에서 Matching 된 위치의 Matching Score void SetBestMatchResult(int &x, int &y, double &s, double *pMatchResult, int nBigWidth, int nBigHeight, int nSmallWidth, int nSmallHeight) { if(pMatchResult == NULL) { TRACE(_T("SetBestMatchResult : Match Result Array Is Not Allocated\n")); return; } int nWidth = nBigWidth - nSmallWidth + 1; int nHeight = nBigHeight - nSmallHeight + 1; int i, j; s = *pMatchResult; for(i = 0; i < nHeight; i++) //MatchResult 중 Max 값 탐색 { for(j = 0; j < nWidth; j++) { double dTempMatch = *(pMatchResult + i * nWidth + j); if(s < dTempMatch) { s = dTempMatch; x = j; y = i; } } } } //사용되지 않는 메소드 //Matching 결과 Matching Score가 가장 높은 좌표를 찾음 //정수 좌표의 Score(pMatchResult)를 이용하여 선형 보정을 통해 소수 좌표의 x, y 좌표를 찾음 //Input // pMatchResult : Matching Result를 각 좌표마다 저장한 array((Review Image Width - Master Image WIdth) * (Review Image Height - Master Image Height)) 크기 // nBigWidth : Big Image Width(Review Image) // nBigHeight : Big Image Height(Review Image) // nSmallWidth : Small Image Width(Master Image) // nSmallHeight : Small Image Height(Master Image) // MatchResult Array의 Size를 계산하기 위해 각 Image의 크기를 입력받음 //Output // dOffsetX : Review Image 내에서 Matching 된 위치의 x좌표 // dOffsetY : Review Image 내에서 Matching 된 위치의 y좌표 // dScore : Review Image 내에서 Matching 된 위치의 Matching Score void SetBestMatchResult(double *dOffsetX, double *dOffsetY, double *dScore, double *pMatchResult, int nBigWidth, int nBigHeight, int nSmallWidth, int nSmallHeight) { if(pMatchResult == NULL) { TRACE(_T("SetBestMatchResult : Match Result Array Is Not Allocated\n")); return; } if(dOffsetX == NULL || dOffsetY == NULL || dScore == NULL) { TRACE(_T("SetBestMatchResult : Output Value Is Not Allocated\n")); return; } int nWidth = nBigWidth - nSmallWidth + 1; int nHeight = nBigHeight - nSmallHeight + 1; double dBestMatch = *pMatchResult; int i, j; int xTemp = 0, yTemp = 0; double xBestMatch, yBestMatch; for(i = 0; i < nHeight; i++) //MatchResult 중 Max 값 탐색 { for(j = 0; j < nWidth; j++) { double dTempMatch = *(pMatchResult + i * nWidth + j); if(dBestMatch < dTempMatch) { dBestMatch = dTempMatch; xTemp = j; yTemp = i; } } } double dBestMatchP, dBestMatchN; if(xTemp == 0) { xBestMatch = xTemp; } else if(xTemp == nWidth - 1) { xBestMatch = xTemp; } else { dBestMatchP = *(pMatchResult + yTemp * nWidth + xTemp - 1); dBestMatchN = *(pMatchResult + yTemp * nWidth + xTemp + 1); if(dBestMatch == dBestMatchP) { xBestMatch = xTemp - 0.5; } else if(dBestMatch == dBestMatchN) { xBestMatch = xTemp + 0.5; } else if(dBestMatchP < dBestMatchN) { xBestMatch = xTemp + 0.5 - 0.5 * (dBestMatch - dBestMatchN) / (dBestMatch - dBestMatchP); } else { xBestMatch = xTemp - 0.5 + 0.5 / (dBestMatch - dBestMatchN) * (dBestMatch - dBestMatchP); } } if(yTemp == 0) { yBestMatch = yTemp; } else if(yTemp == nHeight - 1) { yBestMatch = yTemp; } else { dBestMatchP = *(pMatchResult + (yTemp - 1) * nWidth + xTemp); dBestMatchN = *(pMatchResult + (yTemp + 1) * nWidth + xTemp); if(dBestMatch == dBestMatchP) { yBestMatch = yTemp - 0.5; } else if(dBestMatch == dBestMatchN) { yBestMatch = yTemp + 0.5; } else if(dBestMatchP < dBestMatchN) { yBestMatch = yTemp + 0.5 - 0.5 * (dBestMatch - dBestMatchN) / (dBestMatch - dBestMatchP); } else { yBestMatch = yTemp - 0.5 + 0.5 / (dBestMatch - dBestMatchN) * (dBestMatch - dBestMatchP); } } *dOffsetX = xBestMatch - (nBigWidth - nSmallWidth) / 2; *dOffsetY = yBestMatch - (nBigHeight - nSmallHeight) / 2; *dScore = dBestMatch; } //Image를 복사하는 메소드. width가 widthBig -> widthSmall로 변경됨. //Review Image를 Master Image Width만큼 자르기 위해 사용 //Input // pIn : Input Image(Review Image) // nWidthSmall : Output Image의 Width(Master Image Width) // nWidthBig : Input Image의 Width(Review Image Width) // nHeightBig : Input Image의 Height(Review Image Height) //Output // pOut : Output Image(Master Image Width만큼 Crop된 Review Image) void CopyImage(BYTE *pOut, BYTE *pIn, int nWidthSmall, int nWidthBig, int nHeightBig) { if(pOut == NULL) { TRACE(_T("CopyImage : Output Is Not Allocated\n")); return; } if(pIn == NULL) { TRACE(_T("CopyImage : Input Is Not Allocated\n")); return; } BYTE *pOutTemp; BYTE *pInTemp; for(int y = 0; y < nHeightBig; y++) { pOutTemp = pOut + y * nWidthSmall; pInTemp = pIn + y * nWidthBig; memcpy(pOutTemp, pInTemp, sizeof(BYTE) * nWidthSmall); } } //Review Image와 Master Image를 Matching하여 Review Image 내 ROI를 설정함 //2D Matching은 속도가 오래 걸리기 때문에 Top, Bottom을 최대한 줄여서 하는 것이 좋음 //Side = Top의 경우 호출됨 //Matching Method는 Correlation 사용 //Input // pImage : Review Image(Gray Image) // nImageWidth : Review Image Width // nImageHeight : Review Image Height // pMaster : Master Image Buffer(Gray Image) // nMasterWidth : Master Image Width // nMasterHeight : Master Image Height //Output // rtMatch : Matching 결과 ROI //Return // Match 성공 여부 T/F // Matching Score 0.9 이상인 경우 TRUE(정확한 Score 기준은 추가 Test가 필요함) BOOL SecondMatch_Vertical(BYTE *pImage, int nImageWidth, int nImageHeight, BYTE *pMaster, int nMasterWidth, int nMasterHeight, CRect *rtMatch) { if(pImage == NULL) { TRACE(_T("SecondMatch_Vertical : Review Is Not Allocated\n")); return FALSE; } if(pMaster == NULL) { TRACE(_T("SecondMatch_Vertical : Master Is Not Allocated\n")); return FALSE; } if(rtMatch == NULL) { TRACE(_T("SecondMatch_Vertical : ROIRect Is Not Allocated\n")); return FALSE; } int x, y; int nMatchHeight = rtMatch->Height(); double *pMatchResult = NULL; pMatchResult = new double[(nImageWidth - nMasterWidth + 1) * (nMatchHeight - nMasterHeight + 1)]; //정수 단위 Match 수행 = Big - Small Size INT64 *pBigLineSqSum = NULL; pBigLineSqSum = new INT64[nMatchHeight]; //Big Image의 Line 단위 계산 = Big Height BYTE *pTempImage = NULL; pTempImage = new BYTE[nMasterWidth * (nMatchHeight + nImageWidth / nMasterWidth + 1)]; //Big Image의 Crop = Small Width * Big Height CopyImage(pTempImage, pImage + rtMatch->top * nImageWidth, nMasterWidth, nImageWidth, nMatchHeight); INT64 *ptBigLineSqSum = pBigLineSqSum; INT64 nSmallImageSqSum = GetSquareSumSmallImage(pMaster, nMasterWidth * nMasterHeight); //Small Image Square Sum double dSmallCorrelation = ((nSmallImageSqSum == 0) ? 1.7976931348623158e+308 : 1 / sqrt((double)nSmallImageSqSum)); //Normalize Factor BYTE *pBigLine; INT64 nBigLineSqSum; for(y = 0; y < nMatchHeight; y++) //y = Big height ( Big Image의 LineSqSum 계산 ) { pBigLine = pImage + nImageWidth * (y + rtMatch->top); nBigLineSqSum = GetSquareSumBigLine(pBigLine, nMasterWidth); //Big Image Line Square Sum(Small Image Width) pBigLineSqSum[y] = nBigLineSqSum; } //INT64 *pSmallBigImgMul = m_pSmallBigImgMul; //INT64 *pBigImgSqSum = m_pBigImgSqSum; INT64 nBigImageSqSum; for(x = 0; x < nImageWidth - nMasterWidth + 1; x++) //x = Big width - Small width ( Match Result 계산 ) { nBigImageSqSum = 0; BYTE *pImgPointer = pTempImage + x; if(x > 0) //이전 열 Data 제거, 다음 열 Data 추가 { BYTE *pTempImageIn = pImage + x + nMasterWidth - 1 + rtMatch->top * nImageWidth; //Big Image Line + Small Width(↑nBigLineSqSum에 포함되지 않은 다음 Pixel) BYTE *pTempImageOut = pImgPointer - 1; //Big Image Line - 1(↑nBigLineSqSum에 포함된 첫번째 Pixel) int nOutPixel = *pTempImageOut; pTempImageOut += nMasterWidth; for(y = 0; y < nMatchHeight; y++) //y = Big height ( Big Image의 LineSqSum 계산 ) { int nInPixel = *pTempImageIn; ptBigLineSqSum[y] += (nInPixel + nOutPixel) * (nInPixel - nOutPixel); //LineSqSum + InPixel^2 - OutPixel^2 nOutPixel = *pTempImageOut; //Big Image Line의 다음 행 *pTempImageOut = nInPixel; //pTempImage[x]에 nInPixel을 대입하여 순환식 구조로 사용 pTempImageIn += nImageWidth; //Big Image의 다음 행 pTempImageOut += nMasterWidth; //pTempImage의 다음 행 } } for(y = 0; y < nMasterHeight; y++) //y = Small height ( Big Image의 SqSum 계산(Small Image Size) ) { nBigImageSqSum += ptBigLineSqSum[y]; //Big Image(x, y) Square Sum(Small Image Size) } pImgPointer = pTempImage + x; //pTempImage는 Big Image의 Small Width Crop을 가지고 있음 for(y = 0; y < nMatchHeight - nMasterHeight + 1; y++) //y = Big height - Small height ( Match Result 계산 ) { INT64 nSmallBigImgMul = GetMulSmallBig(pMaster, pImgPointer, nMasterWidth * nMasterHeight); //Small Image와 Big Image의 Pixel의 곱 if(y > 0) //이전 행 Data 제거, 다음 행 Data 추가 { nBigImageSqSum -= ptBigLineSqSum[y - 1]; //nBigImageSqSum에 포함된 첫번째 Line Square Sum nBigImageSqSum += ptBigLineSqSum[y + nMasterHeight - 1]; //nBigImageSqSum에 포함되지 않은 다음 Line Square Sum } //pSmallBigImgMul[y] = nSmallBigImgMul; //Small Image * Big Image //pBigImgSqSum[y] = nBigImageSqSum; //Big Image Square Sum double dMatchResult = (double)nSmallBigImgMul * dSmallCorrelation / sqrt((double)nBigImageSqSum); //(Small * Big) / (sqrt(Small * Small) * sqrt(Big * Big)) pMatchResult[y * (nImageWidth - nMasterWidth + 1) + x] = dMatchResult; //↑ if(Small = Big) → (Small * Small) / sqrt(Small * Small)^2 = 1 //double dMatchResult = (double)pSmallBigImgMul[y] * dSmallCorrelation / sqrt((double)pBigImgSqSum[y]); //(Small * Big) / (sqrt(Small * Small) * sqrt(Big * Big)) //m_pMatchResult[y * (nImageWidth - nMasterWidth + 1) + x] = dMatchResult; //↑ if(Small = Big) → (Small * Small) / sqrt(Small * Small)^2 = 1 pImgPointer += nMasterWidth; //pTempImage의 다음 행 } } int left; int top; double score; SetBestMatchResult(left, top, score, pMatchResult, nImageWidth, nMatchHeight, nMasterWidth, nMasterHeight); if(score < 0.9) { if(pMatchResult) { delete [] pMatchResult; pMatchResult = NULL; } if(pBigLineSqSum) { delete [] pBigLineSqSum; pBigLineSqSum = NULL; } if(pTempImage) { delete [] pTempImage; pTempImage = NULL; } return FALSE; } else { rtMatch->right = left + nMasterWidth; rtMatch->left = left; rtMatch->bottom = top + rtMatch->top + nMasterHeight; rtMatch->top = top + rtMatch->top; if(pMatchResult) { delete [] pMatchResult; pMatchResult = NULL; } if(pBigLineSqSum) { delete [] pBigLineSqSum; pBigLineSqSum = NULL; } if(pTempImage) { delete [] pTempImage; pTempImage = NULL; } return TRUE; } } //Review Image와 Master Image를 Matching하여 Review Image 내 ROI를 설정함 //2D Matching은 속도가 오래 걸리기 때문에 Left, Right를 최대한 줄여서 하는 것이 좋음 //Side = Top의 경우 호출됨 //Matching Method는 Correlation 사용 //Input // pImage : Review Image(Gray Image) // nImageWidth : Review Image Width // nImageHeight : Review Image Height // pMaster : Master Image Buffer(Gray Image) // nMasterWidth : Master Image Width // nMasterHeight : Master Image Height //Output // rtMatch : Matching 결과 ROI //Return // Match 성공 여부 T/F // Matching Score 0.9 이상인 경우 TRUE(정확한 Score 기준은 추가 Test가 필요함) BOOL SecondMatch_Horizontal(BYTE *pImage, int nImageWidth, int nImageHeight, BYTE *pMaster, int nMasterWidth, int nMasterHeight, CRect *rtMatch) { int x, y; int nMatchWidth = rtMatch->Width(); double *pMatchResult = NULL; pMatchResult = new double[(nMatchWidth - nMasterWidth + 1) * (nImageHeight - nMasterHeight + 1)]; //정수 단위 Match 수행 = Big - Small Size INT64 *pBigLineSqSum = NULL; pBigLineSqSum = new INT64[nImageHeight]; //Big Image의 Line 단위 계산 = Big Height BYTE *pTempImage = NULL; pTempImage = new BYTE[nMasterWidth * (nImageHeight + nImageWidth / nMasterWidth + 1)]; //Big Image의 Crop = Small Width * Big Height CopyImage(pTempImage, pImage + rtMatch->left, nMasterWidth, nImageWidth, nImageHeight); INT64 *ptBigLineSqSum = pBigLineSqSum; INT64 nSmallImageSqSum = GetSquareSumSmallImage(pMaster, nMasterWidth * nMasterHeight); //Small Image Square Sum double dSmallCorrelation = ((nSmallImageSqSum == 0) ? 1.7976931348623158e+308 : 1 / sqrt((double)nSmallImageSqSum)); //Normalize Factor BYTE *pBigLine; INT64 nBigLineSqSum; for(y = 0; y < nImageHeight; y++) //y = Big height ( Big Image의 LineSqSum 계산 ) { pBigLine = pImage + nImageWidth * y + rtMatch->left; nBigLineSqSum = GetSquareSumBigLine(pBigLine, nMasterWidth); //Big Image Line Square Sum(Small Image Width) pBigLineSqSum[y] = nBigLineSqSum; } //INT64 *pSmallBigImgMul = m_pSmallBigImgMul; //INT64 *pBigImgSqSum = m_pBigImgSqSum; INT64 nBigImageSqSum; for(x = 0; x < nMatchWidth - nMasterWidth + 1; x++) //x = Big width - Small width ( Match Result 계산 ) { nBigImageSqSum = 0; BYTE *pImgPointer = pTempImage + x; if(x > 0) //이전 열 Data 제거, 다음 열 Data 추가 { BYTE *pTempImageIn = pImage + x + nMasterWidth - 1 + rtMatch->left; //Big Image Line + Small Width(↑nBigLineSqSum에 포함되지 않은 다음 Pixel) BYTE *pTempImageOut = pImgPointer - 1; //Big Image Line - 1(↑nBigLineSqSum에 포함된 첫번째 Pixel) int nOutPixel = *pTempImageOut; pTempImageOut += nMasterWidth; for(y = 0; y < nImageHeight; y++) //y = Big height ( Big Image의 LineSqSum 계산 ) { int nInPixel = *pTempImageIn; ptBigLineSqSum[y] += (nInPixel + nOutPixel) * (nInPixel - nOutPixel); //LineSqSum + InPixel^2 - OutPixel^2 nOutPixel = *pTempImageOut; //Big Image Line의 다음 행 *pTempImageOut = nInPixel; //pTempImage[x]에 nInPixel을 대입하여 순환식 구조로 사용 pTempImageIn += nImageWidth; //Big Image의 다음 행 pTempImageOut += nMasterWidth; //pTempImage의 다음 행 } } for(y = 0; y < nMasterHeight; y++) //y = Small height ( Big Image의 SqSum 계산(Small Image Size) ) { nBigImageSqSum += ptBigLineSqSum[y]; //Big Image(x, y) Square Sum(Small Image Size) } pImgPointer = pTempImage + x; //pTempImage는 Big Image의 Small Width Crop을 가지고 있음 for(y = 0; y < nImageHeight - nMasterHeight + 1; y++) //y = Big height - Small height ( Match Result 계산 ) { INT64 nSmallBigImgMul = GetMulSmallBig(pMaster, pImgPointer, nMasterWidth * nMasterHeight); //Small Image와 Big Image의 Pixel의 곱 if(y > 0) //이전 행 Data 제거, 다음 행 Data 추가 { nBigImageSqSum -= ptBigLineSqSum[y - 1]; //nBigImageSqSum에 포함된 첫번째 Line Square Sum nBigImageSqSum += ptBigLineSqSum[y + nMasterHeight - 1]; //nBigImageSqSum에 포함되지 않은 다음 Line Square Sum } //pSmallBigImgMul[y] = nSmallBigImgMul; //Small Image * Big Image //pBigImgSqSum[y] = nBigImageSqSum; //Big Image Square Sum double dMatchResult = (double)nSmallBigImgMul * dSmallCorrelation / sqrt((double)nBigImageSqSum); //(Small * Big) / (sqrt(Small * Small) * sqrt(Big * Big)) pMatchResult[y * (nMatchWidth - nMasterWidth + 1) + x] = dMatchResult; //↑ if(Small = Big) → (Small * Small) / sqrt(Small * Small)^2 = 1 //double dMatchResult = (double)pSmallBigImgMul[y] * dSmallCorrelation / sqrt((double)pBigImgSqSum[y]); //(Small * Big) / (sqrt(Small * Small) * sqrt(Big * Big)) //m_pMatchResult[y * (nImageWidth - nMasterWidth + 1) + x] = dMatchResult; //↑ if(Small = Big) → (Small * Small) / sqrt(Small * Small)^2 = 1 pImgPointer += nMasterWidth; //pTempImage의 다음 행 } } int left; int top; double score; SetBestMatchResult(left, top, score, pMatchResult, nMatchWidth, nImageHeight, nMasterWidth, nMasterHeight); if(score < 0.9) { if(pMatchResult) { delete [] pMatchResult; pMatchResult = NULL; } if(pBigLineSqSum) { delete [] pBigLineSqSum; pBigLineSqSum = NULL; } if(pTempImage) { delete [] pTempImage; pTempImage = NULL; } return FALSE; } else { rtMatch->right = left + nMasterWidth + rtMatch->left; rtMatch->left = left + rtMatch->left; rtMatch->bottom = top + nMasterHeight; rtMatch->top = top; if(pMatchResult) { delete [] pMatchResult; pMatchResult = NULL; } if(pBigLineSqSum) { delete [] pBigLineSqSum; pBigLineSqSum = NULL; } if(pTempImage) { delete [] pTempImage; pTempImage = NULL; } return TRUE; } } //검사Threshold가 몇개 설정되었는가 Check //Threshold 개수에 따라 아래와 같이 사용됨 //1개 : 모든 Line의 Threshold 통일 //2, 3개 : DAM1, DAM2가 각각 1개씩 사용 //4개 : 각 Line별 사용으로 나뉨 //Input // rParam : Linecheck_Method에 넘겨준 reflow parameter 정보 //Return // Threshold 정상 설정 여부 T/F BOOL CheckThresholdCount(reflowParam* rParam) { int countTh = 0; BOOL checkTh[4]; BOOL ret = TRUE; for(int i = 0; i < 4; i++) { checkTh[i] = FALSE; } if(rParam->nDamTh2 > 0){countTh++; checkTh[0] = TRUE;} if(rParam->nDamTh2_in > 0){countTh++; checkTh[1] = TRUE;} if(rParam->nDamTh1 > 0){countTh++; checkTh[2] = TRUE;} if(rParam->nDamTh1_in > 0){countTh++; checkTh[3] = TRUE;} if(countTh == 0) return FALSE; switch(countTh) { case 0 : ret = FALSE; break; case 1 : if(checkTh[0]) rParam->nDamTh1 = rParam->nDamTh1_in = rParam->nDamTh2_in = rParam->nDamTh2; if(checkTh[1]) rParam->nDamTh1 = rParam->nDamTh1_in = rParam->nDamTh2 = rParam->nDamTh2_in; if(checkTh[2]) rParam->nDamTh2 = rParam->nDamTh2_in = rParam->nDamTh1_in = rParam->nDamTh1; if(checkTh[3]) rParam->nDamTh2 = rParam->nDamTh2_in = rParam->nDamTh1 = rParam->nDamTh1_in; break; case 2 : //아이디어가.. if(checkTh[0] & checkTh[1]) { rParam->nDamTh1 = rParam->nDamTh2; rParam->nDamTh1_in = rParam->nDamTh2_in; } else if(checkTh[2] & checkTh[3]) { rParam->nDamTh2 = rParam->nDamTh1; rParam->nDamTh2_in = rParam->nDamTh1_in; } else { if(checkTh[0]) rParam->nDamTh2_in = rParam->nDamTh2; if(checkTh[1]) rParam->nDamTh2 = rParam->nDamTh2_in; if(checkTh[2]) rParam->nDamTh1_in = rParam->nDamTh1; if(checkTh[3]) rParam->nDamTh1 = rParam->nDamTh1_in; } break; case 3 : if(!checkTh[0]) rParam->nDamTh2 = rParam->nDamTh2_in; if(!checkTh[1]) rParam->nDamTh2_in = rParam->nDamTh2; if(!checkTh[2]) rParam->nDamTh1 = rParam->nDamTh1_in; if(!checkTh[3]) rParam->nDamTh1_in = rParam->nDamTh1; break; } return ret; } //검사에 필요한 Reflow Parameter가 정상적으로 Setting 되었는지 Check //Input // rParam : Linecheck_Method에 넘겨준 reflow parameter 정보 //Return // 정상 Setting 여부 T/F BOOL CheckSetting(reflowParam* rParam) { if(rParam == NULL) {TRACE(_T("Reflow Param Is Not Setted\n")); return FALSE;} BOOL ret = TRUE; if(rParam->pImageBuffer == NULL) {TRACE(_T("Review Image Not Loaded\n")); ret = FALSE;} if(rParam->nImageWidth <= 0) {TRACE(_T("Review Image Width Is Not Valid\n")); ret = FALSE;} if(rParam->nImageHeight <= 0) {TRACE(_T("Review Image Height Is Not Valid\n")); ret = FALSE;} if(rParam->nChannel <= 0 || rParam->nChannel > 4) {TRACE(_T("Review Image Channel Is Not Valid\n")); ret = FALSE;} if(rParam->nImageWidthStep <= 0 || rParam->nImageWidthStep < rParam->nImageWidth * rParam->nChannel) {TRACE(_T("Review Image WidthStep Is Not Valid\n")); ret = FALSE;} if(rParam->ROI_Rect == NULL) {TRACE(_T("ROI Area Is Not Set\n")); ret = FALSE;} if(rParam->nSide < 0 || rParam->nSide > 3) {TRACE(_T("Reflow Side Is Not Vaild\n")); ret = FALSE;} if(rParam->nDistance == NULL) {TRACE(_T("DAM Distances Is Not Set\n")); ret = FALSE;} if(rParam->pMasterBuffer == NULL) {TRACE(_T("Master Image Not Loaded\n")); ret = FALSE;} if(rParam->nMasterWidth <= 0) {TRACE(_T("Master Image Width Is Not Valid\n")); ret = FALSE;} if(rParam->nMasterHeight <= 0) {TRACE(_T("Master Image Height Is Not Valid\n")); ret = FALSE;} if(rParam->nMasterChannel <= 0 || rParam->nMasterChannel > 4) {TRACE(_T("Master Image Channel Is Not Valid\n")); ret = FALSE;} if(rParam->nMasterWidthStep <= 0 || rParam->nMasterWidthStep < rParam->nMasterWidth * rParam->nMasterChannel) {TRACE(_T("Master Image WidthStep Is Not Valid\n")); ret = FALSE;} //190216 최홍철 Threshold 4개로 분할 if(!CheckThresholdCount(rParam)) {TRACE(_T("Invalid Threshold\n")); ret = FALSE;} return ret; } // ////No Overflow 위치에 선을 그려 peak point의 위치를 보여줌 ////Side = Top일 때 호출되며, peak point에 해당하는 가로줄을 그림 ////Input //// pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 //// nImageWidth : Review Image Width. //// nImageHeight : Review Image Height. //// nChannel : Review Image Color Channel. //// nImageWidthStep : Review Image Buffer Width Size(Width * Channel + margin) //// boe_line : No overflow 판정된 DAM Line의 좌표 Array ////Output //// pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 //void Reflow_Line_Paint_Vertical(BYTE *pImageBuffer, int nImageWidth, int nImageHeight, int nChannel, int nImageWidthStep, int *boe_line) //{ // if(pImageBuffer == NULL) // { // TRACE(_T("Reflow_Line_Paint_Vertical : Review Image Is Not Loaded\n")); // return; // } // if(boe_line == NULL) // { // TRACE(_T("Reflow_Line_Paint_Vertical : Line Coordi Array Is Not Allocated\n")); // return; // } // // int nLineLength = 30; //30Pixel 단위로 표시선을 그림 // // int nSolidWidth = 20; // // if(nChannel == 1) //1 Channel(Gray Image)인 경우 // { // BYTE *tempWhite = NULL; // tempWhite = new BYTE[nLineLength]; // memset(tempWhite, 255, sizeof(BYTE) * nLineLength); //30Pixel 짜리 White Line 생성 // // for(int j = 0; j < 4; j++) // { // int nY = boe_line[j]; // if(nY <= 0) continue; //Overflow인 Line인 경우 Skip // for(int i = 0; i < nImageWidthStep - nLineLength * 2 * nChannel; i += nLineLength * 2 * nChannel) //30Pixel단위로 그리고 원래 Image 남겨두고를 반복 // { // for(int k = -nSolidWidth / 2; k < nSolidWidth / 2; k++) // { // //memcpy((pImageBuffer + (nY - 1) * nImageWidthStep + i), tempWhite, sizeof(BYTE) * nLineLength * nChannel); // memcpy((pImageBuffer + (nY + k) * nImageWidthStep + i), tempWhite, sizeof(BYTE) * nLineLength * nChannel); // //memcpy((pImageBuffer + (nY + 1) * nImageWidthStep + i), tempWhite, sizeof(BYTE) * nLineLength * nChannel); // } // } // } // // if(tempWhite) // { // delete [] tempWhite; // tempWhite = NULL; // } // } // else //3, 4Channel(Color Image)인 경우 // { // BYTE *tempWhite = NULL; // tempWhite = new BYTE[nLineLength * nChannel]; // memset(tempWhite, 0, sizeof(BYTE) * nLineLength * nChannel); // for(int i = 0; i < nLineLength; i++) // { // *(tempWhite + i * nChannel + 2) = 255; //30Pixel 짜리 Red Line 생성 // } // // for(int j = 0; j < 4; j++) // { // int nY = boe_line[j]; // if(nY <= 0) continue; // for(int i = 0; i < nImageWidthStep - nLineLength * 2 * nChannel; i += nLineLength * 2 * nChannel) //30Pixel단위로 그리고 원래 Image 남겨두고를 반복 // { // for(int k = -nSolidWidth / 2; k < nSolidWidth / 2; k++) // { // //memcpy((pImageBuffer + (nY - 1) * nImageWidthStep + i), tempWhite, sizeof(BYTE) * nLineLength * nChannel); // memcpy((pImageBuffer + (nY + k) * nImageWidthStep + i), tempWhite, sizeof(BYTE) * nLineLength * nChannel); // //memcpy((pImageBuffer + (nY + 1) * nImageWidthStep + i), tempWhite, sizeof(BYTE) * nLineLength * nChannel); // } // } // } // // if(tempWhite) // { // delete [] tempWhite; // tempWhite = NULL; // } // } //} // ////No Overflow 위치에 선을 그려 peak point의 위치를 보여줌 ////Side = Left, Right일 때 호출되며, peak point에 해당하는 세로줄을 그림 ////Input //// pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 //// nImageWidth : Review Image Width. //// nImageHeight : Review Image Height. //// nChannel : Review Image Color Channel. //// nImageWidthStep : Review Image Buffer Width Size(Width * Channel + margin) //// boe_line : No overflow 판정된 DAM Line의 좌표 Array ////Output //// pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 //void Reflow_Line_Paint_Horizontal(BYTE *pImageBuffer, int nImageWidth, int nImageHeight, int nChannel, int nImageWidthStep, int *boe_line) //{ // if(pImageBuffer == NULL) // { // TRACE(_T("Reflow_Line_Paint_Vertical : Review Image Is Not Loaded\n")); // return; // } // if(boe_line == NULL) // { // TRACE(_T("Reflow_Line_Paint_Vertical : Line Coordi Array Is Not Allocated\n")); // return; // } // // int nLineLength = 30; //30Pixel 단위로 표시선을 그림 // int nCount = 0; // BOOL bLine = TRUE; // // int nSolidWidth = 20; // // if(nChannel == 1) //1 Channel(Gray Image)인 경우 // { // for(int j = 0; j < 4; j++) // { // nCount = 0; // int nX = boe_line[j]; // if(nX <= 0) continue; //Overflow인 Line인 경우 Skip // for(int i = 0; i < nImageHeight; i++) // { // if(bLine) // { // for(int k = -nSolidWidth / 2; k < nSolidWidth / 2; k++) // { // //*(pImageBuffer + i * nImageWidthStep + (nX - 1) * nChannel) = 255; // *(pImageBuffer + i * nImageWidthStep + (nX + k) * nChannel) = 255; // //*(pImageBuffer + i * nImageWidthStep + (nX + 1) * nChannel) = 255; // } // } // // if(++nCount == nLineLength) //30Pixel단위로 그리고 원래 Image 남겨두고를 반복 // { // nCount = 0; // bLine = !bLine; // } // } // } // } // else //3, 4Channel(Color Image)인 경우 // { // for(int j = 0; j < 4; j++) // { // nCount = 0; // int nX = boe_line[j]; // if(nX <= 0) continue; //Overflow인 Line인 경우 Skip // for(int i = 0; i < nImageHeight; i ++) // { // if(bLine) // { // for(int k = -nSolidWidth / 2; k < nSolidWidth / 2; k++) // { // //*(pImageBuffer + i * nImageWidthStep + (nX - 1) * nChannel + 0) = 0; // //*(pImageBuffer + i * nImageWidthStep + (nX - 1) * nChannel + 1) = 0; // //*(pImageBuffer + i * nImageWidthStep + (nX - 1) * nChannel + 2) = 255; // *(pImageBuffer + i * nImageWidthStep + (nX + k) * nChannel + 0) = 0; // *(pImageBuffer + i * nImageWidthStep + (nX + k) * nChannel + 1) = 0; // *(pImageBuffer + i * nImageWidthStep + (nX + k) * nChannel + 2) = 255; // //*(pImageBuffer + i * nImageWidthStep + (nX + 1) * nChannel + 0) = 0; // //*(pImageBuffer + i * nImageWidthStep + (nX + 1) * nChannel + 1) = 0; // //*(pImageBuffer + i * nImageWidthStep + (nX + 1) * nChannel + 2) = 255; // } // } // // if(++nCount == nLineLength) //30Pixel단위로 그리고 원래 Image 남겨두고를 반복 // { // nCount = 0; // bLine = !bLine; // } // } // } // } //} //190214 최홍철 화살표 그리기 //No Overflow 위치에 화살표를 그려 peak point의 위치를 보여줌 //Side = Top일 때 호출되며, peak point의 Left 영역에 화살표를 그림 //Input // pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 // nImageWidth : Review Image Width. // nImageHeight : Review Image Height. // nChannel : Review Image Color Channel. // nImageWidthStep : Review Image Buffer Width Size(Width * Channel + margin) // boe_line : No overflow 판정된 DAM Line의 좌표 Array //Output // pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 void Reflow_Line_Paint_Vertical(BYTE *pImageBuffer, int nImageWidth, int nImageHeight, int nChannel, int nImageWidthStep, int *boe_line) { if(pImageBuffer == NULL) { TRACE(_T("Reflow_Line_Paint_Vertical : Review Image Is Not Loaded\n")); return; } if(boe_line == NULL) { TRACE(_T("Reflow_Line_Paint_Vertical : Line Coordi Array Is Not Allocated\n")); return; } const int nSize = 30; BYTE pWhite[nSize * nSize]; memset(pWhite, 0, nSize * nSize * sizeof(BYTE)); for(int i = 0; i < nSize / 2; i++) { for(int j = nSize / 4; j < nSize * 3 / 4; j++) { pWhite[j * nSize + i] = 255; } } for(int i = nSize / 2; i < nSize; i++) { for(int j = (i - nSize / 2); j < (nSize * 3 / 2 - i); j++) { pWhite[j * nSize + i] = 255; } } CRect rectArrow(0, -nSize / 2, nSize, nSize / 2); CRect rectImage(0, 0, nImageWidth, nImageHeight); for(int n = 0; n < 4; n++) { int nY = boe_line[n]; if(nY <= 0) continue; //Overflow인 Line인 경우 Skip CRect rectArrow2 = rectArrow; rectArrow2.OffsetRect(0, nY); CRect rectArrow3; rectArrow3.IntersectRect(rectArrow2, rectImage); int nXOffset = rectArrow2.Width() - rectArrow3.Width(); int nYOffset = rectArrow2.Height() - rectArrow3.Height(); for(int i = rectArrow3.top; i < rectArrow3.bottom; i++) //30Pixel단위로 그리고 원래 Image 남겨두고를 반복 { for(int j = rectArrow3.left; j < rectArrow3.right; j++) { BYTE temp = pWhite[(i - rectArrow3.top + nYOffset) * nSize + (j - rectArrow3.left + nXOffset)]; if(temp > 0) { *(pImageBuffer + i * nImageWidthStep + j * nChannel) = temp; for(int k = 1; k < nChannel; k++) { *(pImageBuffer + i * nImageWidthStep + j * nChannel + k) = 0; } } } } } } //No Overflow 위치에 화살표를 그려 peak point의 위치를 보여줌 //Side = Left, Right일 때 호출되며, peak point의 Top 영역에 화살표를 그림 //Input // pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 // nImageWidth : Review Image Width. // nImageHeight : Review Image Height. // nChannel : Review Image Color Channel. // nImageWidthStep : Review Image Buffer Width Size(Width * Channel + margin) // boe_line : No overflow 판정된 DAM Line의 좌표 Array //Output // pImageBuffer : Review Image(Color Image). reflowParam으로 전달 받은 image에 바로 그림 void Reflow_Line_Paint_Horizontal(BYTE *pImageBuffer, int nImageWidth, int nImageHeight, int nChannel, int nImageWidthStep, int *boe_line) { if(pImageBuffer == NULL) { TRACE(_T("Reflow_Line_Paint_Vertical : Review Image Is Not Loaded\n")); return; } if(boe_line == NULL) { TRACE(_T("Reflow_Line_Paint_Vertical : Line Coordi Array Is Not Allocated\n")); return; } const int nSize = 30; BYTE pWhite[nSize * nSize]; memset(pWhite, 0, nSize * nSize * sizeof(BYTE)); for(int i = 0; i < nSize / 2; i++) { for(int j = nSize / 4; j < nSize * 3 / 4; j++) { pWhite[i * nSize + j] = 255; } } for(int i = nSize / 2; i < nSize; i++) { for(int j = (i - nSize / 2); j < (nSize * 3 / 2 - i); j++) { pWhite[i * nSize + j] = 255; } } CRect rectArrow(-nSize / 2, 0, nSize / 2, nSize); CRect rectImage(0, 0, nImageWidth, nImageHeight); for(int j = 0; j < 4; j++) { int nX = boe_line[j]; if(nX <= 0) continue; //Overflow인 Line인 경우 Skip CRect rectArrow2 = rectArrow; rectArrow2.OffsetRect(nX, 0); CRect rectArrow3; rectArrow3.IntersectRect(rectArrow2, rectImage); int nXOffset = rectArrow2.Width() - rectArrow3.Width(); int nYOffset = rectArrow2.Height() - rectArrow3.Height(); for(int i = rectArrow3.top; i < rectArrow3.bottom; i++) //30Pixel단위로 그리고 원래 Image 남겨두고를 반복 { for(int j = rectArrow3.left; j < rectArrow3.right; j++) { BYTE temp = pWhite[(i - rectArrow3.top + nYOffset) * nSize + (j - rectArrow3.left + nXOffset)]; if(temp > 0) { *(pImageBuffer + i * nImageWidthStep + j * nChannel) = temp; for(int k = 1; k < nChannel; k++) { *(pImageBuffer + i * nImageWidthStep + j * nChannel + k) = 0; } } } } } } //Review Program에서 실제로 호출하는 Method //DAM Line을 분석해서 overflow 여부를 check하는 메소드 //Input // rParam : reflow 검사를 수행하기 위한 parameter. Image, threshold, ROI 등이 포함 // bSetMaster : Master Image가 Setting되었는지 여부 T/F. 제거할 필요가 있음 //Output // boe_line : no overflow 판정된 line의 좌표 정보. int[4] 크기가 필요함 //int Linecheck_Method(int* boe_line, reflowParam* rParam, BOOL bSetMaster) //{ // m_nLineCheckerLocalPeakPeriod=rParam->nPeakPeriod; // //#ifdef SAVE_PROJECTION_VALUE // CString temp(PROJECTION_DIR); // CreateDirectory(temp, NULL); //#endif // int ret = 0; // // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method : Line Coordi Array Is Not Allocated\n")); // return REFLOW_RESULT_OUTPUT_ARRAY_ERROR; // } // if(rParam == NULL) // { // TRACE(_T("Linecheck_Method : Reflow Parameter Is Not Allocated\n")); // return REFLOW_RESULT_REFLOWPARAM_SETTING_ERROR; // } // // if(!CheckSetting(rParam)) // { // TRACE(_T("Linecheck_Method : Reflow Parameter Is Invalid\n")); // return REFLOW_RESULT_REFLOWPARAM_SETTING_ERROR; // } // if(!bSetMaster) // { // TRACE(_T("Linecheck_Method : Master Setting Is Invalid\n")); // return REFLOW_RESULT_MATCHING_ERROR; // } // if(rParam->ROI_Rect->left < 0) rParam->ROI_Rect->left = 0; // if(rParam->ROI_Rect->right > rParam->nImageWidth - 1) rParam->ROI_Rect->right = rParam->nImageWidth - 1; // if(rParam->ROI_Rect->top < 0) rParam->ROI_Rect->top = 0; // if(rParam->ROI_Rect->bottom > rParam->nImageHeight - 1) rParam->ROI_Rect->bottom = rParam->nImageHeight - 1; // // // BYTE *pImage = NULL; //Review Image Gray 변환 // pImage = new BYTE[rParam->nImageWidth * rParam->nImageHeight]; // memset(pImage, 0, sizeof(BYTE)*rParam->nImageWidth * rParam->nImageHeight); // if(-1 == RGB2GRAY(pImage, rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep)) // { // if(pImage) // { // delete [] pImage; // pImage = NULL; // } // TRACE(_T("Linecheck_Method : RB2GRAY(Review Image) Fail\n")); // return REFLOW_RESULT_IMAGE_LOAD_ERROR; // } // // BOOL bMatch = FALSE; // // BYTE *pMaster = NULL; //Master Image Gray 변환 // pMaster = new BYTE[rParam->nMasterWidth * rParam->nMasterHeight]; // memset(pMaster, 0, sizeof(BYTE)*rParam->nMasterWidth * rParam->nMasterHeight); // if(-1 == RGB2GRAY(pMaster, rParam->pMasterBuffer, rParam->nMasterWidth, rParam->nMasterHeight, rParam->nMasterChannel, rParam->nMasterWidthStep)) // { // if(pImage) // { // delete [] pImage; // pImage = NULL; // } // if(pMaster) // { // delete [] pMaster; // pMaster = NULL; // } // TRACE(_T("Linecheck_Method : RB2GRAY(Master Image) Fail\n")); // return REFLOW_RESULT_IMAGE_LOAD_ERROR; // } // // switch(rParam->nSide) //Matching을 통한 ROI 영역 설정 // { // case CS_TOP : // bMatch = Match_Vertical(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // break; // case CS_LEFT : // case CS_RIGHT : // bMatch = Match_Horizontal(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // break; // } // // if(!bMatch) // { // //switch(rParam->nSide) // //{ // //case CS_TOP : // // bMatch = SecondMatch_Vertical(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // // break; // //case CS_LEFT : // //case CS_RIGHT : // // bMatch = SecondMatch_Horizontal(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // // break; // //} // //if(!bMatch) // //{ // if(pImage) // { // delete [] pImage; // pImage = NULL; // } // if(pMaster) // { // delete [] pMaster; // pMaster = NULL; // } // TRACE(_T("Linecheck_Method : Matching Fail\n")); // return REFLOW_RESULT_MATCHING_ERROR; // //} // } // // switch(rParam->nSide)//Review Image의 ROI 내에서 DAM을 탐색하여 overflow 여부 판정 // { // case CS_TOP : // ret = Linecheck_Method_Side0(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nDamTh2, rParam->nDamTh2_in, rParam->nDamTh1, rParam->nDamTh1_in, rParam->nDistance); // for(int i = 0; i < 4; i++)//ROI Start 좌표를 원점으로 좌표를 계산하기 때문에 ROI Start 좌표를 가산해줌 // { // if(boe_line[i] != 0) // { // boe_line[i] += rParam->ROI_Rect->top; // } // } // Reflow_Line_Paint_Vertical(rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep, boe_line); // break; // case CS_LEFT : // ret = Linecheck_Method_Side1(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nDamTh2, rParam->nDamTh2_in, rParam->nDamTh1, rParam->nDamTh1_in, rParam->nDistance); // for(int i = 0; i < 4; i++) // { // if(boe_line[i] != 0) // { // boe_line[i] += rParam->ROI_Rect->left; // } // } // Reflow_Line_Paint_Horizontal(rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep, boe_line); // break; // case CS_RIGHT : // ret = Linecheck_Method_Side2(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nDamTh2, rParam->nDamTh2_in, rParam->nDamTh1, rParam->nDamTh1_in, rParam->nDistance); // for(int i = 0; i < 4; i++) // { // if(boe_line[i] != 0) // { // boe_line[i] += rParam->ROI_Rect->left; // } // } // Reflow_Line_Paint_Horizontal(rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep, boe_line); // break; // default : // ret = REFLOW_RESULT_REFLOWPARAM_SETTING_ERROR; // Select Wrong Side // } // // if(pImage) // { // delete [] pImage; // pImage = NULL; // } // if(pMaster) // { // delete [] pMaster; // pMaster = NULL; // } // return 0; //} #define BTOS(x) (x ? "TRUE" : "") int Linecheck_Method_Side0(int* boe_line, BYTE* pImage, int nImageWidth, int nImageHeight, CRect* ROI_Rect, int thDam2, int thDam2_2, int thDam1, int thDam1_2, int *nDistance,reflowResult* result) { if(boe_line == NULL) { TRACE(_T("Linecheck_Method_Side0 : Line Coordi Array Is Not Allocated\n")); return REFLOW_RESULT_OUTPUT_ARRAY_ERROR; } if((nImageWidth == 0 && nImageHeight == 0) || pImage == NULL) { TRACE(_T("Linecheck_Method_Side0 : Review Image Is Not Loaded\n")); return REFLOW_RESULT_IMAGE_LOAD_ERROR; } if(ROI_Rect == NULL || ROI_Rect->IsRectEmpty()) { TRACE(_T("Linecheck_Method_Side0 : ROI Rect Is Not Allocated\n")); return REFLOW_RESULT_ROI_SETTING_ERROR; } if(nDistance == NULL) { TRACE(_T("Linecheck_Method_Side0 : DAM Position Array Is Not Allocated\n")); return REFLOW_RESULT_DAM_SETTING_ERROR; } if(ROI_Rect->left < 0) ROI_Rect->left = 0; if(ROI_Rect->right > nImageWidth - 1) ROI_Rect->right = nImageWidth - 1; if(ROI_Rect->top < 0) ROI_Rect->top = 0; if(ROI_Rect->bottom > nImageHeight - 1) ROI_Rect->bottom = nImageHeight - 1; if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return REFLOW_RESULT_ROI_SETTING_ERROR; // roi setting error int nMax = 0; for(int i = 0; i < 4; i++) { if(nMax < *(nDistance + i)) nMax = *(nDistance + i); } if(ROI_Rect->Height() < nMax) return REFLOW_RESULT_DAM_SETTING_ERROR; // roi length error int width; int *pProjection = NULL; int sumOfImage = 0; double avgOfImage = 0; int nGrayDiff[4] = {0, }; BOOL bLineComp[3] = {FALSE, }; width = ROI_Rect->bottom - ROI_Rect->top + 1; pProjection = new int[width + 1]; int state = 0; int temp_sum = 0; //int th = 10; int line_check = 0; bool opposite = false; memset(boe_line, 0, 4*sizeof(int)); for(int i = ROI_Rect->top; i <= ROI_Rect->bottom; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 { int sum = 0; for(int j = ROI_Rect->left; j <= ROI_Rect->right; j++) { sum += *(pImage + j + nImageWidth * i); } pProjection[i - ROI_Rect->top] = sum / (ROI_Rect->right - ROI_Rect->left + 1); sumOfImage += sum; } avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); int thNormalizeDam2 = thDam2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam2_2 = thDam2_2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam1 = thDam1 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam1_2 = thDam1_2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 char s[1024]; sprintf_s(s, 1023, "%s\\(Side0)Difference.txt", PROJECTION_DIR); BOOL bOpen = FALSE; #ifdef SAVE_PROJECTION_VALUE bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); #endif if(bOpen) { f.SeekToEnd(); sprintf_s(s, 1023, "%.5lf\t", avgOfImage); f.Write(s, (UINT)strlen(s)); } for(int i = 0; i < 4; i++) { int pos; #pragma region normalize factor int nMin = LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); int nDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - nMin; sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); if(bOpen) { f.Write(s, (UINT)strlen(s)); } #pragma endregion int nmMin,nmMax; if(i == 0) { //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam2_GrayMax =nmMax; result->nDam2_GrayMin =nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod * 2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod * 2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 result->nDam2_GrayDif = nNormalizeDiff; result->nDam2_GrayTH =thNormalizeDam2; //nNormalizeDiff *= 128 / avgOfImage; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam2 / 2) { boe_line[i] = pos; line_check++; result->nDam2 = TRUE; } } else if(i == 1) { //nGrayDiff[i] = LocalMaxima(pProjection, *(nDistance + i), width, LOCAL_PEAK_PERIOD * 2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, LOCAL_PEAK_PERIOD * 2); //if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalizeDam2_2, TRUE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 //{ // boe_line[i] = pos; // line_check++; //} nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam2_in_GrayMax =nmMax; result->nDam2_in_GrayMin =nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam2_in_GrayDif = nNormalizeDiff; result->nDam2_in_GrayTH =thNormalizeDam2_2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam2_2) { boe_line[i] = pos; line_check++; result->nDam2_in = TRUE; } } else if(i == 2) { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDAM1_GrayMax = nmMax; result->nDAM1_GrayMin = nmMin ; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam1_GrayDif = nNormalizeDiff; result->nDam1_GrayTH =thNormalizeDam1; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam1) { boe_line[i] = pos; line_check++; result->nDAM1 = TRUE; } } else { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam1_in_GrayMax= nmMax; result->nDam1_in_GrayMin= nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam1_in_GrayDif = nNormalizeDiff; result->nDam1_in_GrayTH =thNormalizeDam1_2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam1_2) { boe_line[i] = pos; line_check++; result->nDam1_in = TRUE; } } } //안쪽 Line 검출 여부를 활용하여 바깥쪽 Line 검출 정보 보정 #ifdef LINE_COMPENSATION for(int i = 3; i > 0; i--) { if(boe_line[i] > 0 && boe_line[i - 1] == 0) { bLineComp[i - 1] = TRUE; int nPos = 0; LocalMinima(pProjection, &nPos, *(nDistance + i - 1), width, m_nLineCheckerLocalPeakPeriod); boe_line[i - 1] = nPos; line_check++; } } #else //if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 //{ // boe_line[1] = *(nDistance + 1); // line_check++; //} #endif sprintf_s(s, 1023, "\r\n"); if(bOpen) { f.Write(s, (UINT)strlen(s)); f.Close(); } #ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 CFile file; char str[1024]; sprintf_s(str, 1023, "%s\\Horizontal_Projection_from(%d, %d)_to(%d, %d).csv", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) { sprintf_s(str, 1023, "Left,%d,Right,%d,Top,%d,Bottom,%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); file.Write(str, (UINT)strlen(str)); switch(line_check) { case 4 : sprintf_s(str, 1023, "NoReflow\r\n%d,%d,%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top, boe_line[3] + ROI_Rect->top); break; case 3 : sprintf_s(str, 1023, "DAM1Reflow\r\n%d,%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top); break; case 2 : sprintf_s(str, 1023, "DAM1Reflow\r\n%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top); break; default : sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->top); } file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Normalized Threshold,%3d,%3d,%3d,%3d\r\n", thNormalizeDam2, thNormalizeDam2_2, thNormalizeDam1, thNormalizeDam1_2); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Gray Difference,%3d,%3d,%3d,%3d\r\n", nGrayDiff[0], nGrayDiff[1], nGrayDiff[2], nGrayDiff[3]); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Line Compensation,%s,%s,%s\r\n", BTOS(bLineComp[0]), BTOS(bLineComp[1]), BTOS(bLineComp[2])); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Horizontal Projection,difference\r\n"); file.Write(str, (UINT)strlen(str)); for(int i = 0; i < width; i++) { sprintf_s(str, 1023, "%d,%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); file.Write(str, (UINT)strlen(str)); } file.Close(); } #endif if(pProjection) { delete [] pProjection; pProjection = NULL; } return line_check; } int Linecheck_Method_Side1(int* boe_line, BYTE* pImage, int nImageWidth, int nImageHeight, CRect* ROI_Rect, int thDam2, int thDam2_2, int thDam1, int thDam1_2, int *nDistance,reflowResult* result) { if(boe_line == NULL) { TRACE(_T("Linecheck_Method_Side1 : Line Coordi Array Is Not Allocated\n")); return REFLOW_RESULT_OUTPUT_ARRAY_ERROR; } if((nImageWidth == 0 && nImageHeight == 0) || pImage == NULL) { TRACE(_T("Linecheck_Method_Side1 : Review Image Is Not Loaded\n")); return REFLOW_RESULT_IMAGE_LOAD_ERROR; } if(ROI_Rect == NULL || ROI_Rect->IsRectEmpty()) { TRACE(_T("Linecheck_Method_Side1 : ROI Rect Is Not Allocated\n")); return REFLOW_RESULT_ROI_SETTING_ERROR; } if(nDistance == NULL) { TRACE(_T("Linecheck_Method_Side1 : DAM Position Array Is Not Allocated\n")); return REFLOW_RESULT_DAM_SETTING_ERROR; } if(ROI_Rect->left < 0) ROI_Rect->left = 0; if(ROI_Rect->right > nImageWidth - 1) ROI_Rect->right = nImageWidth - 1; if(ROI_Rect->top < 0) ROI_Rect->top = 0; if(ROI_Rect->bottom > nImageHeight - 1) ROI_Rect->bottom = nImageHeight - 1; if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return REFLOW_RESULT_ROI_SETTING_ERROR; // roi setting error int nMax = 0; for(int i = 0; i < 4; i++) { if(nMax < *(nDistance + i)) nMax = *(nDistance + i); } if(ROI_Rect->Width() < nMax) return REFLOW_RESULT_DAM_SETTING_ERROR; // roi length error int width; int *pProjection = NULL; int sumOfImage = 0; double avgOfImage = 0; int nGrayDiff[4] = {0, }; BOOL bLineComp[3] = {FALSE, }; width = ROI_Rect->right - ROI_Rect->left + 1; pProjection = new int[width + 1]; int state = 0; int temp_sum = 0; //int th = 10; int line_check = 0; bool opposite = false; memset(boe_line, 0, 4*sizeof(int)); for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 { int sum = 0; for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) { sum += *(pImage + j * nImageWidth + i); } pProjection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); sumOfImage += sum; } avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); int thNormalizeDam2 = thDam2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam2_2 = thDam2_2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam1 = thDam1 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam1_2 = thDam1_2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 char s[1024]; sprintf_s(s, 1023, "%s\\(Side1)Difference.txt", PROJECTION_DIR); BOOL bOpen = FALSE; #ifdef SAVE_PROJECTION_VALUE bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); #endif if(bOpen) { f.SeekToEnd(); sprintf_s(s, 1023, "%.5lf\t", avgOfImage); f.Write(s, (UINT)strlen(s)); } for(int i = 0; i < 4; i++) { int pos; #pragma region normalize factor int nMin = LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); int nDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - nMin; sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); if(bOpen) { f.Write(s, (UINT)strlen(s)); } #pragma endregion int nmMax,nmMin; if(i == 0) { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam2_GrayMax = nmMax; result->nDam2_GrayMin = nmMin; //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 //nNormalizeDiff *= 128 / avgOfImage; result->nDam2_GrayDif = nNormalizeDiff; result->nDam2_GrayTH =thNormalizeDam2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam2 / 2) { boe_line[i] = pos; line_check++; result->nDam2 = TRUE; } } else if(i == 1) { //nGrayDiff[i] = LocalMaxima(pProjection, *(nDistance + i), width, LOCAL_PEAK_PERIOD * 2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, LOCAL_PEAK_PERIOD * 2); //if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalizeDam2_2, TRUE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 //{ // boe_line[i] = pos; // line_check++; //} nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam2_in_GrayMax = nmMax; result->nDam2_in_GrayMin = nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam2_in_GrayDif = nNormalizeDiff; result->nDam2_in_GrayTH =thNormalizeDam2_2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam2_2) { boe_line[i] = pos; line_check++; result->nDam2_in= TRUE; } } else if(i == 2) { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDAM1_GrayMax = nmMax; result->nDAM1_GrayMin = nmMin ; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam1_GrayDif = nNormalizeDiff; result->nDam1_GrayTH =thNormalizeDam1; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam1) { boe_line[i] = pos; line_check++; result->nDAM1= TRUE; } } else { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam1_in_GrayMax= nmMax; result->nDam1_in_GrayMin= nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow result->nDam1_in_GrayDif = nNormalizeDiff; result->nDam1_in_GrayTH =thNormalizeDam1_2; //nNormalizeDiff *= 128 / avgOfImage; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam1_2) { boe_line[i] = pos; line_check++; result->nDam1_in = TRUE; } } } //안쪽 Line 검출 여부를 활용하여 바깥쪽 Line 검출 정보 보정 #ifdef LINE_COMPENSATION for(int i = 3; i > 0; i--) { if(boe_line[i] > 0 && boe_line[i - 1] == 0) { bLineComp[i - 1] = TRUE; int nPos = 0; LocalMinima(pProjection, &nPos, *(nDistance + i - 1), width, m_nLineCheckerLocalPeakPeriod); boe_line[i - 1] = nPos; line_check++; } } #else //if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 //{ // boe_line[1] = *(nDistance + 1); // line_check++; //} #endif sprintf_s(s, 1023, "\r\n"); if(bOpen) { f.Write(s, (UINT)strlen(s)); f.Close(); } #ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 CFile file; char str[1024]; sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).csv", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) { sprintf_s(str, 1023, "Left,%d,Right,%d,Top,%d,Bottom,%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); file.Write(str, (UINT)strlen(str)); switch(line_check) { case 4 : sprintf_s(str, 1023, "NoReflow\r\n%d,%d,%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); break; case 3 : sprintf_s(str, 1023, "DAM1Reflow\r\n%d,%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); break; case 2 : sprintf_s(str, 1023, "DAM1Reflow\r\n%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left); break; default : sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->left); } file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Normalized Threshold,%3d,%3d,%3d,%3d\r\n", thNormalizeDam2, thNormalizeDam2_2, thNormalizeDam1, thNormalizeDam1_2); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Gray Difference,%3d,%3d,%3d,%3d\r\n", nGrayDiff[0], nGrayDiff[1], nGrayDiff[2], nGrayDiff[3]); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Line Compensation,%s,%s,%s\r\n", BTOS(bLineComp[0]), BTOS(bLineComp[1]), BTOS(bLineComp[2])); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Vertical Projection,difference,lpf\r\n"); file.Write(str, (UINT)strlen(str)); for(int i = 0; i < width; i++) { sprintf_s(str, 1023, "%d,%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); file.Write(str, (UINT)strlen(str)); } file.Close(); } #endif if(pProjection) { delete [] pProjection; pProjection = NULL; } return line_check; } int Linecheck_Method_Side2(int* boe_line, BYTE* pImage, int nImageWidth, int nImageHeight, CRect* ROI_Rect, int thDam2, int thDam2_2, int thDam1, int thDam1_2, int *nDistance,reflowResult* result) { if(boe_line == NULL) { TRACE(_T("Linecheck_Method_Side2 : Line Coordi Array Is Not Allocated\n")); return REFLOW_RESULT_OUTPUT_ARRAY_ERROR; } if((nImageWidth == 0 && nImageHeight == 0) || pImage == NULL) { TRACE(_T("Linecheck_Method_Side2 : Review Image Is Not Loaded\n")); return REFLOW_RESULT_IMAGE_LOAD_ERROR; } if(ROI_Rect == NULL || ROI_Rect->IsRectEmpty()) { TRACE(_T("Linecheck_Method_Side2 : ROI Rect Is Not Allocated\n")); return REFLOW_RESULT_ROI_SETTING_ERROR; } if(nDistance == NULL) { TRACE(_T("Linecheck_Method_Side2 : DAM Position Array Is Not Allocated\n")); return REFLOW_RESULT_DAM_SETTING_ERROR; } if(ROI_Rect->left < 0) ROI_Rect->left = 0; if(ROI_Rect->right > nImageWidth - 1) ROI_Rect->right = nImageWidth - 1; if(ROI_Rect->top < 0) ROI_Rect->top = 0; if(ROI_Rect->bottom > nImageHeight - 1) ROI_Rect->bottom = nImageHeight - 1; if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return REFLOW_RESULT_ROI_SETTING_ERROR; // roi setting error int nMax = 0; for(int i = 0; i < 4; i++) { if(nMax < *(nDistance + i)) nMax = *(nDistance + i); } if(ROI_Rect->Width() < nMax) return REFLOW_RESULT_DAM_SETTING_ERROR; // roi length error int width; int *pProjection = NULL; int sumOfImage = 0; double avgOfImage = 0; int nGrayDiff[4] = {0, }; BOOL bLineComp[3] = {FALSE, }; width = ROI_Rect->right - ROI_Rect->left + 1; pProjection = new int[width + 1]; int state = 0; int temp_sum = 0; //int th = 10; int line_check = 0; bool opposite = false; memset(boe_line, 0, 4*sizeof(int)); for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 { int sum = 0; for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) { sum += *(pImage + j * nImageWidth + i); } pProjection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); sumOfImage += sum; } avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); int thNormalizeDam2 = thDam2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam2_2 = thDam2_2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam1 = thDam1 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 int thNormalizeDam1_2 = thDam1_2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized nThreshold 계산 CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 char s[1024]; sprintf_s(s, 1023, "%s\\(Side2)Difference.txt", PROJECTION_DIR); BOOL bOpen = FALSE; #ifdef SAVE_PROJECTION_VALUE bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); #endif if(bOpen) { f.SeekToEnd(); sprintf_s(s, 1023, "%.5lf\t", avgOfImage); f.Write(s, (UINT)strlen(s)); } for(int i = 0; i < 4; i++) { int pos; #pragma region normalize factor int nMin = LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); int nDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - nMin; sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); if(bOpen) { f.Write(s, (UINT)strlen(s)); } #pragma endregion int nmMax,nmMin; if(i == 0) { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam2_GrayMax = nmMax; result->nDam2_GrayMin = nmMin; //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 //nNormalizeDiff *= 128 / avgOfImage; result->nDam2_GrayDif = nNormalizeDiff; result->nDam2_GrayTH =thNormalizeDam2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam2 / 2) { boe_line[i] = pos; line_check++; result->nDam2 = TRUE; } } else if(i == 1) { //nGrayDiff[i] = LocalMaxima(pProjection, *(nDistance + i), width, LOCAL_PEAK_PERIOD * 2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, LOCAL_PEAK_PERIOD * 2); //if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalizeDam2_2, FALSE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 //{ // boe_line[i] = pos; // line_check++; //} nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam2_in_GrayMax = nmMax; result->nDam2_in_GrayMin = nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam2_in_GrayDif = nNormalizeDiff; result->nDam2_in_GrayTH =thNormalizeDam2_2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam2_2) { boe_line[i] = pos; line_check++; result->nDam2_in= TRUE; } } else if(i == 2) { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDAM1_GrayMax = nmMax; result->nDAM1_GrayMin = nmMin ; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam1_GrayDif = nNormalizeDiff; result->nDam1_GrayTH =thNormalizeDam1; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam1) { boe_line[i] = pos; line_check++; result->nDAM1 = TRUE; } } else { nmMax = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); nmMin =LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); result->nDam1_in_GrayMax= nmMax; result->nDam1_in_GrayMin= nmMin; int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod); //DAM1. LocalMaxima - LocalMinima가 Normalized nThreshold보다 큰 경우 no overflow //nNormalizeDiff *= 128 / avgOfImage; result->nDam1_in_GrayDif = nNormalizeDiff; result->nDam1_in_GrayTH =thNormalizeDam1_2; nGrayDiff[i] = nNormalizeDiff; if(nNormalizeDiff > thNormalizeDam1_2) { boe_line[i] = pos; line_check++; result->nDam1_in = TRUE; } } } //안쪽 Line 검출 여부를 활용하여 바깥쪽 Line 검출 정보 보정 #ifdef LINE_COMPENSATION for(int i = 3; i > 0; i--) { if(boe_line[i] > 0 && boe_line[i - 1] == 0) { bLineComp[i - 1] = TRUE; int nPos = 0; LocalMinima(pProjection, &nPos, *(nDistance + i - 1), width, m_nLineCheckerLocalPeakPeriod); boe_line[i - 1] = nPos; line_check++; } } #else //if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 //{ // boe_line[1] = *(nDistance + 1); // line_check++; //} #endif sprintf_s(s, 1023, "\r\n"); if(bOpen) { f.Write(s, (UINT)strlen(s)); f.Close(); } #ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 CFile file; char str[1024]; sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).csv", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) { sprintf_s(str, 1023, "Left,%d,Right,%d,Top,%d,Bottom,%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); file.Write(str, (UINT)strlen(str)); switch(line_check) { case 4 : sprintf_s(str, 1023, "NoReflow\r\n%d,%d,%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); break; case 3 : sprintf_s(str, 1023, "DAM1Reflow\r\n%d,%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); break; case 2 : sprintf_s(str, 1023, "DAM1Reflow\r\n%d,%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left); break; default : sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->left); } file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Normalized Threshold,%3d,%3d,%3d,%3d\r\n", thNormalizeDam2, thNormalizeDam2_2, thNormalizeDam1, thNormalizeDam1_2); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Gray Difference,%3d,%3d,%3d,%3d\r\n", nGrayDiff[0], nGrayDiff[1], nGrayDiff[2], nGrayDiff[3]); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Line Compensation,%s,%s,%s\r\n", BTOS(bLineComp[0]), BTOS(bLineComp[1]), BTOS(bLineComp[2])); file.Write(str, (UINT)strlen(str)); sprintf_s(str, 1023, "Vertical Projection,difference,lpf\r\n"); file.Write(str, (UINT)strlen(str)); for(int i = 0; i < width; i++) { sprintf_s(str, 1023, "%d,%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); file.Write(str, (UINT)strlen(str)); } file.Close(); } #endif if(pProjection) { delete [] pProjection; pProjection = NULL; } return line_check; } // // //int Linecheck_Method_Side0(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int th, int *nDistance) //{ // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method_Side0 : Line Coordi Array Is Not Allocated\n")); // return -5; // } // if((imageWidth == 0 && imageHeight == 0) || pImage == NULL) // { // TRACE(_T("Linecheck_Method_Side0 : Review Image Is Not Loaded\n")); // return -1; // } // // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // int nMax = max(*(nDistance + 0), max(*(nDistance + 1), max(*(nDistance + 2), *(nDistance + 3)))); // // if(ROI_Rect->Height() < nMax) return -3; // roi length error // // int width; // int *pProjection = NULL; // int sumOfImage = 0; // double avgOfImage = 0; // // width = ROI_Rect->bottom - ROI_Rect->top + 1; // pProjection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // // memset(boe_line, 0, 4*sizeof(int)); // // for(int i = ROI_Rect->top; i <= ROI_Rect->bottom; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 // { // int sum = 0; // for(int j = ROI_Rect->left; j <= ROI_Rect->right; j++) // { // sum += *(pImage + j + imageWidth * i); // } // pProjection[i - ROI_Rect->top] = sum / (ROI_Rect->right - ROI_Rect->left + 1); // sumOfImage += sum; // } // // avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); // int thNormalize = th * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // // CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 // char s[1024]; // sprintf_s(s, 1023, "%s\\(Side0)Difference.txt", PROJECTION_DIR); // BOOL bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // if(bOpen) // { // f.SeekToEnd(); // sprintf_s(s, 1023, "%.5lf\t", avgOfImage); // f.Write(s, (UINT)strlen(s)); // } // // for(int i = 0; i < 4; i++) // { //#pragma region normalize factor // int nMin = LocalMinima(pProjection, *(nDistance + i), width); // int nDiff = LocalMaxima(pProjection, *(nDistance + i), width) - nMin; // sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // } //#pragma endregion // int pos; // // if(i == 0) // { // //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod * 2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod * 2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalize / 2) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < thNormalize) //DAM2 바깥 Line. Line의 너비가 넓어 LocalMaxima를 찾을 수 없어 LocalMinima(Peak Low)를 단순 Gray로 비교 // //{ // // boe_line[i] = pos; // // line_check++; // //} // } // else if(i == 1) // { // if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalize, TRUE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 // { // boe_line[i] = pos; // line_check++; // } // } // else // { // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width) - LocalMinima(pProjection, &pos, *(nDistance + i), width); //DAM1. LocalMaxima - LocalMinima가 Normalized Threshold보다 큰 경우 no overflow // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalize) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < th2) // //{ // // //boe_line[line_check++] = *(nDistance + i); // // //boe_line[line_check++] = pos; // // boe_line[i] = pos; // // //line_check++; // // line_check |= (int)pow((double)2, i); // //} // } // } // // if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 // { // boe_line[1] = *(nDistance + 1); // line_check++; // } // // sprintf_s(s, 1023, "\r\n"); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // f.Close(); // } // //#ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Horizontal_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) // { // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 4 : // sprintf_s(str, 1023, "NoReflow\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top, boe_line[3] + ROI_Rect->top); // break; // case 3 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top); // break; // case 2 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top); // break; // default : // sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->top); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Horizontal Projection\tdifference\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); // //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); // } //#endif // // if(pProjection) // { // delete [] pProjection; // pProjection = NULL; // } // // return line_check; //} // //int Linecheck_Method_Side1(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int th, int *nDistance) //{ // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method_Side1 : Line Coordi Array Is Not Allocated\n")); // return -5; // } // if((imageWidth == 0 && imageHeight == 0) || pImage == NULL) // { // TRACE(_T("Linecheck_Method_Side1 : Review Image Is Not Loaded\n")); // return -1; // } // // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // int nMax = max(*(nDistance + 0), max(*(nDistance + 1), max(*(nDistance + 2), *(nDistance + 3)))); // // if(ROI_Rect->Width() < nMax) return -3; // roi length error // // int width; // int *pProjection = NULL; // int sumOfImage = 0; // double avgOfImage = 0; // // width = ROI_Rect->right - ROI_Rect->left + 1; // pProjection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // // memset(boe_line, 0, 4*sizeof(int)); // // for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 // { // int sum = 0; // for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) // { // sum += *(pImage + j * imageWidth + i); // } // pProjection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); // sumOfImage += sum; // } // // avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); // int thNormalize = th * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // // CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 // char s[1024]; // sprintf_s(s, 1023, "%s\\(Side1)Difference.txt", PROJECTION_DIR); // BOOL bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // if(bOpen) // { // f.SeekToEnd(); // sprintf_s(s, 1023, "%.5lf\t", avgOfImage); // f.Write(s, (UINT)strlen(s)); // } // // for(int i = 0; i < 4; i++) // { //#pragma region normalize factor // int nMin = LocalMinima(pProjection, *(nDistance + i), width); // int nDiff = LocalMaxima(pProjection, *(nDistance + i), width) - nMin; // sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // } //#pragma endregion // int pos; // // if(i == 0) // { // //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalize / 2) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < thNormalize) //DAM2 바깥 Line. Line의 너비가 넓어 LocalMaxima를 찾을 수 없어 LocalMinima(Peak Low)를 단순 Gray로 비교 // //{ // // boe_line[i] = pos; // // line_check++; // //} // } // else if(i == 1) // { // if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalize, TRUE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 // { // boe_line[i] = pos; // line_check++; // } // } // else // { // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width) - LocalMinima(pProjection, &pos, *(nDistance + i), width); //DAM1. LocalMaxima - LocalMinima가 Normalized Threshold보다 큰 경우 no overflow // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalize) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < th2) // //{ // // //boe_line[line_check++] = *(nDistance + i); // // //boe_line[line_check++] = pos; // // boe_line[i] = pos; // // //line_check++; // // line_check |= (int)pow((double)2, i); // //} // } // } // // if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 // { // boe_line[1] = *(nDistance + 1); // line_check++; // } // // sprintf_s(s, 1023, "\r\n"); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // f.Close(); // } // //#ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) // { // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 4 : // sprintf_s(str, 1023, "NoReflow\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); // break; // case 3 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); // break; // case 2 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left); // break; // default : // sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->left); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Vertical Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); // //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); // } //#endif // // if(pProjection) // { // delete [] pProjection; // pProjection = NULL; // } // // return line_check; //} //int Linecheck_Method_Side2(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int th, int *nDistance) //{ // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method_Side2 : Line Coordi Array Is Not Allocated\n")); // return -5; // } // if((imageWidth == 0 && imageHeight == 0) || pImage == NULL) // { // TRACE(_T("Linecheck_Method_Side2 : Review Image Is Not Loaded\n")); // return -1; // } // // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // int nMax = max(*(nDistance + 0), max(*(nDistance + 1), max(*(nDistance + 2), *(nDistance + 3)))); // // if(ROI_Rect->Width() < nMax) return -3; // roi length error // // int width; // int *pProjection = NULL; // int sumOfImage = 0; // double avgOfImage = 0; // // width = ROI_Rect->right - ROI_Rect->left + 1; // pProjection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // // memset(boe_line, 0, 4*sizeof(int)); // // for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 // { // int sum = 0; // for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) // { // sum += *(pImage + j * imageWidth + i); // } // pProjection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); // sumOfImage += sum; // } // // avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); // int thNormalize = th * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // // CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 // char s[1024]; // sprintf_s(s, 1023, "%s\\(Side2)Difference.txt", PROJECTION_DIR); // // BOOL bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // if(bOpen) // { // f.SeekToEnd(); // sprintf_s(s, 1023, "%.5lf\t", avgOfImage); // f.Write(s, (UINT)strlen(s)); // } // // for(int i = 0; i < 4; i++) // { //#pragma region normalize factor // int nMin = LocalMinima(pProjection, *(nDistance + i), width); // int nDiff = LocalMaxima(pProjection, *(nDistance + i), width) - nMin; // sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // } //#pragma endregion // int pos; // // if(i == 0) // { // //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalize / 2) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < thNormalize) //DAM2 바깥 Line. Line의 너비가 넓어 LocalMaxima를 찾을 수 없어 LocalMinima(Peak Low)를 단순 Gray로 비교 // //{ // // boe_line[i] = pos; // // line_check++; // //} // } // else if(i == 1) // { // if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalize, FALSE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 // { // boe_line[i] = pos; // line_check++; // } // } // else // { // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width) - LocalMinima(pProjection, &pos, *(nDistance + i), width); //DAM1. LocalMaxima - LocalMinima가 Normalized Threshold보다 큰 경우 no overflow // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalize) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < th2) // //{ // // //boe_line[line_check++] = *(nDistance + i); // // //boe_line[line_check++] = pos; // // boe_line[i] = pos; // // //line_check++; // // line_check |= (int)pow((double)2, i); // //} // } // } // // if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 // { // boe_line[1] = *(nDistance + 1); // line_check++; // } // // sprintf_s(s, 1023, "\r\n"); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // f.Close(); // } // //#ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) // { // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 4 : // sprintf_s(str, 1023, "NoReflow\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); // break; // case 3 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); // break; // case 2 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left); // break; // default : // sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->left); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Vertical Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); // //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); // } //#endif // // if(pProjection) // { // delete [] pProjection; // pProjection = NULL; // } // // return line_check; //} // //int Linecheck_Method_Side0(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int thDam2, int thDam1, int *nDistance,reflowResult* result) //{ // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method_Side0 : Line Coordi Array Is Not Allocated\n")); // return -5; // } // if((imageWidth == 0 && imageHeight == 0) || pImage == NULL) // { // TRACE(_T("Linecheck_Method_Side0 : Review Image Is Not Loaded\n")); // return -1; // } // // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // int nMax = max(*(nDistance + 0), max(*(nDistance + 1), max(*(nDistance + 2), *(nDistance + 3)))); // // if(ROI_Rect->Height() < nMax) return -3; // roi length error // // int width; // int *pProjection = NULL; // int sumOfImage = 0; // double avgOfImage = 0; // // width = ROI_Rect->bottom - ROI_Rect->top + 1; // pProjection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // // memset(boe_line, 0, 4*sizeof(int)); // // for(int i = ROI_Rect->top; i <= ROI_Rect->bottom; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 // { // int sum = 0; // for(int j = ROI_Rect->left; j <= ROI_Rect->right; j++) // { // sum += *(pImage + j + imageWidth * i); // } // pProjection[i - ROI_Rect->top] = sum / (ROI_Rect->right - ROI_Rect->left + 1); // sumOfImage += sum; // } // // avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); // int thNormalizeDam2 = thDam2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // int thNormalizeDam1 = thDam1 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // // CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 // char s[1024]; // sprintf_s(s, 1023, "%s\\(Side0)Difference.txt", PROJECTION_DIR); // BOOL bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // if(bOpen) // { // f.SeekToEnd(); // sprintf_s(s, 1023, "%.5lf\t", avgOfImage); // f.Write(s, (UINT)strlen(s)); // } // // for(int i = 0; i < 4; i++) // { //#pragma region normalize factor // int nMin = LocalMinima(pProjection, *(nDistance + i), width); // int nDiff = LocalMaxima(pProjection, *(nDistance + i), width) - nMin; // sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // } //#pragma endregion // int pos; // // if(i == 0) // { // //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod * 2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod * 2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalizeDam2 / 2) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < thNormalize) //DAM2 바깥 Line. Line의 너비가 넓어 LocalMaxima를 찾을 수 없어 LocalMinima(Peak Low)를 단순 Gray로 비교 // //{ // // boe_line[i] = pos; // // line_check++; // //} // } // else if(i == 1) // { // if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalizeDam2, TRUE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 // { // boe_line[i] = pos; // line_check++; // } // } // else // { // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width) - LocalMinima(pProjection, &pos, *(nDistance + i), width); //DAM1. LocalMaxima - LocalMinima가 Normalized Threshold보다 큰 경우 no overflow // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalizeDam1) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < th2) // //{ // // //boe_line[line_check++] = *(nDistance + i); // // //boe_line[line_check++] = pos; // // boe_line[i] = pos; // // //line_check++; // // line_check |= (int)pow((double)2, i); // //} // } // } // // if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 // { // boe_line[1] = *(nDistance + 1); // line_check++; // } // // sprintf_s(s, 1023, "\r\n"); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // f.Close(); // } // //#ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Horizontal_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) // { // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 4 : // sprintf_s(str, 1023, "NoReflow\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top, boe_line[3] + ROI_Rect->top); // break; // case 3 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top); // break; // case 2 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top); // break; // default : // sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->top); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Horizontal Projection\tdifference\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); // //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); // } //#endif // // if(pProjection) // { // delete [] pProjection; // pProjection = NULL; // } // // return line_check; //} // //int Linecheck_Method_Side1(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int thDam2, int thDam1, int *nDistance) //{ // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method_Side1 : Line Coordi Array Is Not Allocated\n")); // return -5; // } // if((imageWidth == 0 && imageHeight == 0) || pImage == NULL) // { // TRACE(_T("Linecheck_Method_Side1 : Review Image Is Not Loaded\n")); // return -1; // } // // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // int nMax = max(*(nDistance + 0), max(*(nDistance + 1), max(*(nDistance + 2), *(nDistance + 3)))); // // if(ROI_Rect->Width() < nMax) return -3; // roi length error // // int width; // int *pProjection = NULL; // int sumOfImage = 0; // double avgOfImage = 0; // // width = ROI_Rect->right - ROI_Rect->left + 1; // pProjection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // // memset(boe_line, 0, 4*sizeof(int)); // // for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 // { // int sum = 0; // for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) // { // sum += *(pImage + j * imageWidth + i); // } // pProjection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); // sumOfImage += sum; // } // // avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); // int thNormalizeDam2 = thDam2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // int thNormalizeDam1 = thDam1 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // // CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 // char s[1024]; // sprintf_s(s, 1023, "%s\\(Side1)Difference.txt", PROJECTION_DIR); // BOOL bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // if(bOpen) // { // f.SeekToEnd(); // sprintf_s(s, 1023, "%.5lf\t", avgOfImage); // f.Write(s, (UINT)strlen(s)); // } // // for(int i = 0; i < 4; i++) // { //#pragma region normalize factor // int nMin = LocalMinima(pProjection, *(nDistance + i), width); // int nDiff = LocalMaxima(pProjection, *(nDistance + i), width) - nMin; // sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // } //#pragma endregion // int pos; // // if(i == 0) // { // //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalizeDam2 / 2) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < thNormalize) //DAM2 바깥 Line. Line의 너비가 넓어 LocalMaxima를 찾을 수 없어 LocalMinima(Peak Low)를 단순 Gray로 비교 // //{ // // boe_line[i] = pos; // // line_check++; // //} // } // else if(i == 1) // { // if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalizeDam2, TRUE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 // { // boe_line[i] = pos; // line_check++; // } // } // else // { // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width) - LocalMinima(pProjection, &pos, *(nDistance + i), width); //DAM1. LocalMaxima - LocalMinima가 Normalized Threshold보다 큰 경우 no overflow // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalizeDam1) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < th2) // //{ // // //boe_line[line_check++] = *(nDistance + i); // // //boe_line[line_check++] = pos; // // boe_line[i] = pos; // // //line_check++; // // line_check |= (int)pow((double)2, i); // //} // } // } // // if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 // { // boe_line[1] = *(nDistance + 1); // line_check++; // } // // sprintf_s(s, 1023, "\r\n"); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // f.Close(); // } // //#ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) // { // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 4 : // sprintf_s(str, 1023, "NoReflow\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); // break; // case 3 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); // break; // case 2 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left); // break; // default : // sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->left); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Vertical Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); // //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); // } //#endif // // if(pProjection) // { // delete [] pProjection; // pProjection = NULL; // } // // return line_check; //} // //int Linecheck_Method_Side2(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int thDam2, int thDam1, int *nDistance) //{ // if(boe_line == NULL) // { // TRACE(_T("Linecheck_Method_Side2 : Line Coordi Array Is Not Allocated\n")); // return -5; // } // if((imageWidth == 0 && imageHeight == 0) || pImage == NULL) // { // TRACE(_T("Linecheck_Method_Side2 : Review Image Is Not Loaded\n")); // return -1; // } // // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // int nMax = max(*(nDistance + 0), max(*(nDistance + 1), max(*(nDistance + 2), *(nDistance + 3)))); // // if(ROI_Rect->Width() < nMax) return -3; // roi length error // // int width; // int *pProjection = NULL; // int sumOfImage = 0; // double avgOfImage = 0; // // width = ROI_Rect->right - ROI_Rect->left + 1; // pProjection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // // memset(boe_line, 0, 4*sizeof(int)); // // for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) //Projection Graph 계산 및 Image 전체 밝기 계산 // { // int sum = 0; // for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) // { // sum += *(pImage + j * imageWidth + i); // } // pProjection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); // sumOfImage += sum; // } // // avgOfImage = (double)sumOfImage / (ROI_Rect->Width() * ROI_Rect->Height()); // int thNormalizeDam2 = thDam2 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // int thNormalizeDam1 = thDam1 * avgOfImage / 128 + 0.5; //Image 전체 밝기를 이용하여 Normalized Threshold 계산 // // CFile f; //Image 전체 밝기와 DAM 위치(Peak Point)의 Minimum 값, Maximum과의 차를 text로 저장 // char s[1024]; // sprintf_s(s, 1023, "%s\\(Side2)Difference.txt", PROJECTION_DIR); // // BOOL bOpen = f.Open(CString(s), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite); // if(bOpen) // { // f.SeekToEnd(); // sprintf_s(s, 1023, "%.5lf\t", avgOfImage); // f.Write(s, (UINT)strlen(s)); // } // // for(int i = 0; i < 4; i++) // { //#pragma region normalize factor // int nMin = LocalMinima(pProjection, *(nDistance + i), width); // int nDiff = LocalMaxima(pProjection, *(nDistance + i), width) - nMin; // sprintf_s(s, 1023, "%d\t%d\t", nMin, nDiff); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // } //#pragma endregion // int pos; // // if(i == 0) // { // //190104 최홍철 단순 Gray 비교 → 탐색 범위 증가시여 Diff 비교 변경 // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2) - LocalMinima(pProjection, &pos, *(nDistance + i), width, m_nLineCheckerLocalPeakPeriod*2); //DAM2 바깥 Line. Line의 너비가 넓어 탐색 범위를 2배로 넓힘 // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalizeDam2 / 2) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < thNormalize) //DAM2 바깥 Line. Line의 너비가 넓어 LocalMaxima를 찾을 수 없어 LocalMinima(Peak Low)를 단순 Gray로 비교 // //{ // // boe_line[i] = pos; // // line_check++; // //} // } // else if(i == 1) // { // if(CheckTwoLines(pProjection, *(nDistance + i), width, thNormalizeDam2, FALSE, &pos)) //DAM2 안쪽 Line. overflow와 no overflow의 차이인 line 개수를 분석함 // { // boe_line[i] = pos; // line_check++; // } // } // else // { // int nNormalizeDiff = LocalMaxima(pProjection, *(nDistance + i), width) - LocalMinima(pProjection, &pos, *(nDistance + i), width); //DAM1. LocalMaxima - LocalMinima가 Normalized Threshold보다 큰 경우 no overflow // //nNormalizeDiff *= 128 / avgOfImage; // if(nNormalizeDiff > thNormalizeDam1) // { // boe_line[i] = pos; // line_check++; // } // //if(LocalMinima(pProjection, &pos, *(nDistance + i), width) < th2) // //{ // // //boe_line[line_check++] = *(nDistance + i); // // //boe_line[line_check++] = pos; // // boe_line[i] = pos; // // //line_check++; // // line_check |= (int)pow((double)2, i); // //} // } // } // // if(boe_line[1] == 0 && boe_line[2] > 0) //Focus 문제로 DAM2의 안쪽 Line이 검출되지 않았을 때 DAM1 바깥쪽 Line 검출 여부를 활용하여 보정 // { // boe_line[1] = *(nDistance + 1); // line_check++; // } // // sprintf_s(s, 1023, "\r\n"); // if(bOpen) // { // f.Write(s, (UINT)strlen(s)); // f.Close(); // } // //#ifdef SAVE_PROJECTION_VALUE //Reflow 판정, no overflow line 좌표, Projection Graph 등을 text로 출력 // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) // { // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 4 : // sprintf_s(str, 1023, "NoReflow\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); // break; // case 3 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); // break; // case 2 : // sprintf_s(str, 1023, "DAM1Reflow\r\n%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left); // break; // default : // sprintf_s(str, 1023, "DAM2Reflow\r\n%d\r\n\r\n", boe_line[0] + ROI_Rect->left); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Vertical Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\r\n", pProjection[i], pProjection[(i + 1) % width] - pProjection[i % width]); // //sprintf_s(str, 1023, "%d%d\r\n", i, pProjection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); // } //#endif // // if(pProjection) // { // delete [] pProjection; // pProjection = NULL; // } // // return line_check; //} //현재 알고리즘에서 비사용중인 메소드들 BYTE LocalMinima(int *pProjection, int x, int width) { int i = x - m_nLineCheckerLocalPeakPeriod / 2 ; if(i < 0) i = 0; BYTE local_minima = *(pProjection + i); for(; i < x + m_nLineCheckerLocalPeakPeriod / 2; i++) { if(i > width - 1) break; if(local_minima > *(pProjection + i)) local_minima = *(pProjection + i); } return local_minima; } int LocalMinimaAddr(int *pProjection, int x, int width) { int i = x - m_nLineCheckerLocalPeakPeriod / 2 ; if(i < 0) i = 0; BYTE local_minima = *(pProjection + i); int local_minima_addr = i; for(; i < x + m_nLineCheckerLocalPeakPeriod / 2; i++) { if(i > width - 1) break; if(local_minima > *(pProjection + i)) { local_minima = *(pProjection + i); local_minima_addr = i; } } return local_minima_addr; } BOOL CheckTwoLines(int *pDifference_lpf, int *pProjection, int x, int width, int threshold, BOOL bForward) { int i; int nSearchEnd; if(bForward) { //i = x - LOCAL_PEAK_PERIOD / 2; //nSearchEnd = x + LOCAL_PEAK_PERIOD * 9 / 2; i = x - m_nLineCheckerLocalPeakPeriod * 5 / 2; nSearchEnd = x + m_nLineCheckerLocalPeakPeriod * 5 / 2; } else { //i = x + LOCAL_PEAK_PERIOD / 2; //nSearchEnd = x - LOCAL_PEAK_PERIOD * 9 / 2; i = x + m_nLineCheckerLocalPeakPeriod * 5 / 2; nSearchEnd = x - m_nLineCheckerLocalPeakPeriod * 5 / 2; } if(i < 0) i = 0; if(nSearchEnd < 0) nSearchEnd = 0; if(i > width - 1) i = width - 1; if(nSearchEnd > width - 1) nSearchEnd = width - 1; int nPeakCount = 0; if(bForward) { BOOL bIncreaseSlope = (*(pDifference_lpf + i) >= 0); i++; for(; i < nSearchEnd; i++) { //if(!(bIncreaseSlope & (*(pDifference_lpf + i) >= 0))) if(bIncreaseSlope ^ (*(pDifference_lpf + i) >= 0)) { if(*(pProjection + i) < threshold) nPeakCount++; bIncreaseSlope = !bIncreaseSlope; } } } else { BOOL bIncreaseSlope = (*(pDifference_lpf + i) >= 0); i--; for(; i >= nSearchEnd; i--) { //if(!(bIncreaseSlope & (*(pDifference_lpf + i) >= 0))) if(bIncreaseSlope ^ (*(pDifference_lpf + i) >= 0)) { if(*(pProjection + i) < threshold) nPeakCount++; bIncreaseSlope = !bIncreaseSlope; } } } if(nPeakCount >= 2) { return TRUE; } return FALSE; } CString Reflow_Judge(int LineCheck) { CString ret; switch(LineCheck) { case 4 : ret.Format(_T("no Reflow")); break; case 3 : case 2 : ret.Format(_T("DAM#1 Reflow")); break; case -1 : ret.Format(_T("Image Load Error")); break; case -2 : ret.Format(_T("ROI Setting Error")); break; case -3 : ret.Format(_T("ROI Length Error")); break; case -4 : ret.Format(_T("Image Match Fail")); break; case -5: ret.Format(_T("Debug File Error")); break; default : ret.Format(_T("DAM#2 Reflow")); ; } return ret; } // //int BOE_Linecheck(int* boe_line, reflowParam* rParam, BOOL bSetMaster) //{ //#ifdef SAVE_PROJECTION_VALUE // CString temp(PROJECTION_DIR); // CreateDirectory(temp, NULL); //#endif // int ret = 0; // // if(rParam->ROI_Rect->left < 0) rParam->ROI_Rect->left = 0; // if(rParam->ROI_Rect->right > rParam->nImageWidth - 1) rParam->ROI_Rect->right = rParam->nImageWidth - 1; // if(rParam->ROI_Rect->top < 0) rParam->ROI_Rect->top = 0; // if(rParam->ROI_Rect->bottom > rParam->nImageHeight - 1) rParam->ROI_Rect->bottom = rParam->nImageHeight - 1; // // BYTE *pImage = new BYTE[rParam->nImageWidth * rParam->nImageHeight]; // memset(pImage, 0, sizeof(BYTE)*rParam->nImageWidth * rParam->nImageHeight); // if(-1 == RGB2GRAY(pImage, rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep)) // { // delete pImage; // pImage = NULL; // return -1; // } // // CRect *rtMatch = new CRect; // BOOL bMatch = FALSE; // BYTE *pMaster = NULL; // if(bSetMaster) // { // pMaster = new BYTE[rParam->nMasterWidth * rParam->nMasterHeight]; // memset(pMaster, 0, sizeof(BYTE)*rParam->nMasterWidth * rParam->nMasterHeight); // if(-1 == RGB2GRAY(pMaster, rParam->pMasterBuffer, rParam->nMasterWidth, rParam->nMasterHeight, rParam->nMasterChannel, rParam->nMasterWidthStep)) // { // delete pMaster; // pMaster = NULL; // return -1; // } // // switch(rParam->nSide) // { // case CS_TOP : // bMatch = Match_Vertical(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // break; // case CS_LEFT : // case CS_RIGHT : // bMatch = Match_Horizontal(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // break; // } // } // if(!bMatch) // { // *rtMatch = *rParam->ROI_Rect; // } // // switch(rParam->nSide) // { // case CS_TOP : // ret = BOE_Linecheck_Side0(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nBaseTh, rParam->nDamTh2, rParam->nDamTh1, rParam->nBaseline, rParam->nBaseDam2, rParam->nDam2Dist, rParam->nDam12Dist, rParam->nDam1Dist); // for(int i = 0; i < ret; i++) // { // boe_line[i] += rParam->ROI_Rect->top; // } // break; // case CS_LEFT : // ret = BOE_Linecheck_Side1(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nBaseTh, rParam->nDamTh2, rParam->nDamTh1, rParam->nBaseline, rParam->nBaseDam2, rParam->nDam2Dist, rParam->nDam12Dist, rParam->nDam1Dist); // for(int i = 0; i < ret; i++) // { // boe_line[i] += rParam->ROI_Rect->left; // } // break; // case CS_RIGHT : // ret = BOE_Linecheck_Side2(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nBaseTh, rParam->nDamTh2, rParam->nDamTh1, rParam->nBaseline, rParam->nBaseDam2, rParam->nDam2Dist, rParam->nDam12Dist, rParam->nDam1Dist); // for(int i = 0; i < ret; i++) // { // boe_line[i] += rParam->ROI_Rect->left; // } // break; // default : // ret = -5; // Select Wrong Side // } // // if(pImage) // delete pImage; // pImage = NULL; // if(pMaster) // delete pMaster; // pMaster = NULL; // if(rtMatch) // delete rtMatch; // rtMatch = NULL; // return ret; //} // //int BOE_Linecheck_Side0(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int th, int th2, int th3, int dist0, int dist1, int dist2, int dist3, int dist4) //{ // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(imageWidth == 0 && imageHeight == 0) return -1; // image not loaded // if(pImage == NULL) return -1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // if(ROI_Rect->Height() < dist0 + dist1 + dist2 + dist3 + dist4) return -3; // roi length error // // int width; // int *projection; // // width = ROI_Rect->bottom - ROI_Rect->top + 1; // projection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // int *difference_lpf = new int[width - 2]; // // memset(boe_line, 0, 6*sizeof(int)); // memset(difference_lpf, 0, (width-2)*sizeof(int)); // // for(int i = ROI_Rect->top; i <= ROI_Rect->bottom; i++) // { // int sum = 0; // for(int j = ROI_Rect->left; j <= ROI_Rect->right; j++) // { // sum += *(pImage + j + imageWidth * i); // } // projection[i - ROI_Rect->top] = sum / (ROI_Rect->right - ROI_Rect->left + 1); // // if(i - ROI_Rect->top - 3 >= 0) // difference_lpf[i - ROI_Rect->top - 3] = (projection[i - ROI_Rect->top] - projection[i - ROI_Rect->top - 3]) / 3; // } // // for(int i = 0; i < width - 3; i++) // { // //difference_lpf[i] = (projection[i + 3] - projection[i]) / 3; // // if(line_check > 5) continue; // else if(line_check < 2) // { // if(difference_lpf[i] > 0) // { // state++; // if(state > 5) state = 5; // opposite = false; // } // else if(difference_lpf[i] < 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // else if(line_check == 2) // { // if(difference_lpf[i] < 0) // { // state++; // if(state > 10) state = 10; // opposite = false; // } // else if(difference_lpf[i] > 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // else // { // if(difference_lpf[i] < 0) // { // state++; // if(state > 5) state = 5; // opposite = false; // } // else if(difference_lpf[i] > 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // // if(state < 0) // { // state = 0; // switch(line_check) // { // case 0 : // if(temp_sum > th) // { // boe_line[line_check++] = i; // //180510 BaseLine Count = 1 // if(dist0 == 0) // boe_line[line_check++] = i; // } // break; // case 1 : // if(temp_sum > th && (abs(i - boe_line[line_check - 1]) >= dist0 - 15) && (abs(i - boe_line[line_check - 1]) <= dist0 + 15)) // boe_line[line_check++] = i; // else if(temp_sum > th) // boe_line[line_check - 1] = i; // break; // case 2 : // if(-temp_sum > th && LocalMinima(projection, i, width) < th2 && (abs(i - boe_line[line_check - 1]) >= dist1 - 15) && (abs(i - boe_line[line_check - 1]) <= dist1 + 15)) // boe_line[line_check++] = i; // //else if(LocalMaxima(projection, i, width) - LocalMinima(projection, i, width) > th && (abs(i - boe_line[line_check - 1]) >= dist0 - 15) && (abs(i - boe_line[line_check - 1]) <= dist0 + 15)) // //{ // // boe_line[line_check - 2] = boe_line[line_check - 1]; // // boe_line[line_check - 1] = LocalMinimaAddr(projection, i, width); // //} // //else if(LocalMaxima(projection, i, width) - LocalMinima(projection, i, width) > th) // //{ // // boe_line[line_check - 2] = LocalMinimaAddr(projection, i, width); // // boe_line[line_check - 1] = 0; // // line_check = 1; // // //180510 BaseLine Count = 1 // // if(dist0 == 0) // // { // // line_check = 2; // // boe_line[line_check - 1] = boe_line[line_check - 2]; // // } // //} // break; // case 3 : //2 Lines... // if(LocalMinima(projection, i, width) < th2 && (abs(i - boe_line[line_check - 1]) >= dist2 - 15) && (abs(i - boe_line[line_check - 1])) <= dist2 + 15) // { // if(CheckTwoLines(difference_lpf, projection, i, width, th2, TRUE)) // boe_line[line_check++] = i; // } // break; // case 4 : // if(LocalMinima(projection, i, width) < th3 && (abs(i - boe_line[line_check - 1]) >= dist3 - 15) && (abs(i - boe_line[line_check - 1]) <= dist3 + 15)) // boe_line[line_check++] = i; // break; // case 5 : // if(LocalMinima(projection, i, width) < th3 && (abs(i - boe_line[line_check - 1]) >= dist4 - 15) && (abs(i - boe_line[line_check - 1]) <= dist4 + 15)) // boe_line[line_check++] = i; // break; // default : // continue; // } // temp_sum = 0; // } // else // { // if(!opposite) temp_sum += difference_lpf[i]; // } // } // //#ifdef SAVE_PROJECTION_VALUE // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Horizontal_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(! file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) return -1; // // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 6 : // sprintf_s(str, 1023, "A\r\n%d\t%d\t%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top, boe_line[3] + ROI_Rect->top, boe_line[4] + ROI_Rect->top, boe_line[5] + ROI_Rect->top); // break; // case 5 : // sprintf_s(str, 1023, "B\r\n%d\t%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top, boe_line[3] + ROI_Rect->top, boe_line[4] + ROI_Rect->top); // break; // case 4 : // sprintf_s(str, 1023, "C\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top, boe_line[3] + ROI_Rect->top); // break; // default : // sprintf_s(str, 1023, "D\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->top, boe_line[1] + ROI_Rect->top, boe_line[2] + ROI_Rect->top); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Horizontal Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\t%d\r\n", projection[i], projection[(i + 1) % width] - projection[i % width], difference_lpf[i % (width - 2)]); // //sprintf_s(str, 1023, "%d%d\r\n", i, projection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); //#endif // // free(projection); // free(difference_lpf); // // return line_check; //} // //int BOE_Linecheck_Side1(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int th, int th2, int th3, int dist0, int dist1, int dist2, int dist3, int dist4) //{ // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(imageWidth == 0 && imageHeight == 0) return -1; // image not loaded // if(pImage == NULL) return -1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // if(ROI_Rect->Width() < dist0 + dist1 + dist2 + dist3 + dist4) return -3; // roi length error // // int width; // int *projection; // // width = ROI_Rect->right - ROI_Rect->left + 1; // projection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // int *difference_lpf = new int[width - 2]; // // memset(boe_line, 0, 6*sizeof(int)); // memset(difference_lpf, 0, (width-2)*sizeof(int)); // // for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) // { // int sum = 0; // for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) // { // sum += *(pImage + j * imageWidth + i); // } // projection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); // // if(i - ROI_Rect->left - 3 >= 0) // difference_lpf[i - ROI_Rect->left - 3] = (projection[i - ROI_Rect->left] - projection[i - ROI_Rect->left - 3]) / 3; // } // // // for(int i = 0; i < width - 3; i++) // { // //difference_lpf[i] = (projection[i + 3] - projection[i]) / 3; // // if(line_check > 5) continue; // else if(line_check < 2) // { // if(difference_lpf[i] > 0) // { // state++; // if(state > 5) state = 5; // opposite = false; // } // else if(difference_lpf[i] < 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // else if(line_check == 2) // { // if(difference_lpf[i] < 0) // { // state++; // if(state > 10) state = 10; // opposite = false; // } // else if(difference_lpf[i] > 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // else // { // if(difference_lpf[i] < 0) // { // state++; // if(state > 5) state = 5; // opposite = false; // } // else if(difference_lpf[i] > 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // // if(state < 0) // { // state = 0; // switch(line_check) // { // case 0 : // if(temp_sum > th) // { // boe_line[line_check++] = i; // //180510 BaseLine Count = 1 // if(dist0 == 0) // boe_line[line_check++] = i; // } // break; // case 1 : // if(temp_sum > th && (abs(i - boe_line[line_check - 1]) >= dist0 - 15) && (abs(i - boe_line[line_check - 1]) <= dist0 + 15)) // boe_line[line_check++] = i; // else if(temp_sum > th) // boe_line[line_check - 1] = i; // break; // case 2 : // if(-temp_sum > th && LocalMinima(projection, i, width) < th2 && (abs(i - boe_line[line_check - 1]) >= dist1 - 15) && (abs(i - boe_line[line_check - 1]) <= dist1 + 15)) // boe_line[line_check++] = i; // //else if(LocalMaxima(projection, i, width) - LocalMinima(projection, i, width) > th && (abs(i - boe_line[line_check - 1]) >= dist0 - 15) && (abs(i - boe_line[line_check - 1]) <= dist0 + 15)) // //{ // // boe_line[line_check - 2] = boe_line[line_check - 1]; // // boe_line[line_check - 1] = LocalMinimaAddr(projection, i, width); // //} // //else if(LocalMaxima(projection, i, width) - LocalMinima(projection, i, width) > th) // //{ // // boe_line[line_check - 2] = LocalMinimaAddr(projection, i, width); // // boe_line[line_check - 1] = 0; // // line_check = 1; // // //180510 BaseLine Count = 1 // // if(dist0 == 0) // // { // // line_check = 2; // // boe_line[line_check - 1] = boe_line[line_check - 2]; // // } // //} // break; // case 3 : // if(LocalMinima(projection, i, width) < th2 && (abs(i - boe_line[line_check - 1]) >= dist2 - 15) && (abs(i - boe_line[line_check - 1])) <= dist2 + 15) // { // if(CheckTwoLines(difference_lpf, projection, i, width, th2, TRUE)) // boe_line[line_check++] = i; // } // break; // case 4 : // if(LocalMinima(projection, i, width) < th3 && (abs(i - boe_line[line_check - 1]) >= dist3 - 15) && (abs(i - boe_line[line_check - 1]) <= dist3 + 15)) // boe_line[line_check++] = i; // break; // case 5 : // if(LocalMinima(projection, i, width) < th3 && (abs(i - boe_line[line_check - 1]) >= dist4 - 15) && (abs(i - boe_line[line_check - 1]) <= dist4 + 15)) // boe_line[line_check++] = i; // break; // default : // continue; // } // temp_sum = 0; // } // else // { // if(!opposite) temp_sum += difference_lpf[i]; // } // } // //#ifdef SAVE_PROJECTION_VALUE // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(! file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) return -1; // // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 6 : // sprintf_s(str, 1023, "A\r\n%d\t%d\t%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left, boe_line[4] + ROI_Rect->left, boe_line[5] + ROI_Rect->left); // break; // case 5 : // sprintf_s(str, 1023, "B\r\n%d\t%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left, boe_line[4] + ROI_Rect->left); // break; // case 4 : // sprintf_s(str, 1023, "C\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); // break; // default : // sprintf_s(str, 1023, "D\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Vertical Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\t%d\r\n", projection[i], projection[(i + 1) % width] - projection[i % width], difference_lpf[i % (width - 2)]); // //sprintf_s(str, 1023, "%d%d\r\n", i, projection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); //#endif // // free(projection); // free(difference_lpf); // // return line_check; //} // //int BOE_Linecheck_Side2(int* boe_line, BYTE* pImage, int imageWidth, int imageHeight, CRect* ROI_Rect, int th, int th2, int th3, int dist0, int dist1, int dist2, int dist3, int dist4) //{ // if(ROI_Rect->left < 0) ROI_Rect->left = 0; // if(ROI_Rect->right > imageWidth - 1) ROI_Rect->right = imageWidth - 1; // if(ROI_Rect->top < 0) ROI_Rect->top = 0; // if(ROI_Rect->bottom > imageHeight - 1) ROI_Rect->bottom = imageHeight - 1; // // if(imageWidth == 0 && imageHeight == 0) return -1; // image not loaded // if(pImage == NULL) return -1; // // if(ROI_Rect->right < ROI_Rect->left + 1 || ROI_Rect->bottom < ROI_Rect->top + 1) return -2; // roi setting error // // if(ROI_Rect->Width() < dist0 + dist1 + dist2 + dist3 + dist4) return -3; // roi length error // // int width; // int *projection; // // width = ROI_Rect->right - ROI_Rect->left + 1; // projection = new int[width + 1]; // // int state = 0; // int temp_sum = 0; // //int th = 10; // int line_check = 0; // bool opposite = false; // int *difference_lpf = new int[width]; // // memset(boe_line, 0, 6*sizeof(int)); // memset(difference_lpf, 0, (width-2)*sizeof(int)); // // for(int i = ROI_Rect->left; i <= ROI_Rect->right; i++) // { // int sum = 0; // for(int j = ROI_Rect->top; j <= ROI_Rect->bottom; j++) // { // sum += *(pImage + j * imageWidth + i); // } // projection[i - ROI_Rect->left] = sum / (ROI_Rect->bottom - ROI_Rect->top + 1); // // if(i - ROI_Rect->left - 3 >= 0) // difference_lpf[i - ROI_Rect->left - 3] = (projection[i - ROI_Rect->left - 3] - projection[i - ROI_Rect->left]) / 3; // } // // for(int i = width - 1; i >= 3; i--) // { // //difference_lpf[i] = (projection[i - 3] - projection[i]) / 3; // // if(line_check > 5) continue; // else if(line_check < 2) // { // if(difference_lpf[i] > 0) // { // state++; // if(state > 5) state = 5; // opposite = false; // } // else if(difference_lpf[i] < 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // else if(line_check == 2) // { // if(difference_lpf[i] < 0) // { // state++; // if(state > 10) state = 10; // opposite = false; // } // else if(difference_lpf[i] > 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // else // { // if(difference_lpf[i] < 0) // { // state++; // if(state > 5) state = 5; // opposite = false; // } // else if(difference_lpf[i] > 0) // { // state--; // opposite = true; // } // else // { // state--; // if(state < 0) state = 0; // } // } // // if(state < 0) // { // state = 0; // switch(line_check) // { // case 0 : // if(temp_sum > th) // { // boe_line[line_check++] = i; // //180510 BaseLine Count = 1 // if(dist0 == 0) // boe_line[line_check++] = i; // } // break; // case 1 : // if(temp_sum > th && (abs(i - boe_line[line_check - 1]) >= dist0 - 15) && (abs(i - boe_line[line_check - 1]) <= dist0 + 15)) // boe_line[line_check++] = i; // else if(temp_sum > th) // boe_line[line_check - 1] = i; // break; // case 2 : // if(LocalMinima(projection, i, width) < th2 && (abs(i - boe_line[line_check - 1]) >= dist1 - 15) && (abs(i - boe_line[line_check - 1]) <= dist1 + 15)) // boe_line[line_check++] = i; // //else if(LocalMaxima(projection, i, width) - LocalMinima(projection, i, width) > th && (abs(i - boe_line[line_check - 1]) >= dist0 - 15) && (abs(i - boe_line[line_check - 1]) <= dist0 + 15)) // //{ // // boe_line[line_check - 2] = boe_line[line_check - 1]; // // boe_line[line_check - 1] = LocalMinimaAddr(projection, i, width); // //} // //else if(LocalMaxima(projection, i, width) - LocalMinima(projection, i, width) > th) // //{ // // boe_line[line_check - 2] = LocalMinimaAddr(projection, i, width); // // boe_line[line_check - 1] = 0; // // line_check = 1; // // //180510 BaseLine Count = 1 // // if(dist0 == 0) // // { // // line_check = 2; // // boe_line[line_check - 1] = boe_line[line_check - 2]; // // } // //} // break; // case 3 : // if(LocalMinima(projection, i, width) < th2 && (abs(i - boe_line[line_check - 1]) >= dist2 - 15) && (abs(i - boe_line[line_check - 1]) <= dist2 + 15)) // { // if(CheckTwoLines(difference_lpf, projection, i, width, th2, FALSE)) // boe_line[line_check++] = i; // } // break; // case 4 : // if(LocalMinima(projection, i, width) < th3 && (abs(i - boe_line[line_check - 1]) >= dist3 - 15) && (abs(i - boe_line[line_check - 1]) <= dist3 + 15)) // boe_line[line_check++] = i; // break; // case 5 : // if(LocalMinima(projection, i, width) < th3 && (abs(i - boe_line[line_check - 1]) >= dist4 - 15) && (abs(i - boe_line[line_check - 1]) <= dist4 + 15)) // boe_line[line_check++] = i; // break; // default : // continue; // } // temp_sum = 0; // } // else // { // if(!opposite) temp_sum += difference_lpf[i]; // //else temp_sum -= difference_lpf[i]; // } // } // //#ifdef SAVE_PROJECTION_VALUE // CFile file; // char str[1024]; // sprintf_s(str, 1023, "%s\\Vertical_Projection_from(%d, %d)_to(%d, %d).txt", PROJECTION_DIR, ROI_Rect->left, ROI_Rect->top, ROI_Rect->right, ROI_Rect->bottom); // // if(! file.Open(CString(str), CFile::modeCreate | CFile::modeWrite)) return -1; // // sprintf_s(str, 1023, "Left\t%d\tRight\t%d\tTop\t%d\tBottom\t%d\r\n", ROI_Rect->left, ROI_Rect->right, ROI_Rect->top, ROI_Rect->bottom); // file.Write(str, (UINT)strlen(str)); // // switch(line_check) // { // case 6 : // sprintf_s(str, 1023, "A\r\n%d\t%d\t%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left, boe_line[4] + ROI_Rect->left, boe_line[5] + ROI_Rect->left); // break; // case 5 : // sprintf_s(str, 1023, "B\r\n%d\t%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left, boe_line[4] + ROI_Rect->left); // break; // case 4 : // sprintf_s(str, 1023, "C\r\n%d\t%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left, boe_line[3] + ROI_Rect->left); // break; // default : // sprintf_s(str, 1023, "D\r\n%d\t%d\t%d\r\n\r\n", boe_line[0] + ROI_Rect->left, boe_line[1] + ROI_Rect->left, boe_line[2] + ROI_Rect->left); // } // file.Write(str, (UINT)strlen(str)); // // sprintf_s(str, 1023, "Vertical Projection\tdifference\tlpf\r\n"); // file.Write(str, (UINT)strlen(str)); // // for(int i = 0; i < width; i++) // { // sprintf_s(str, 1023, "%d\t%d\t%d\r\n", projection[i], projection[(i + 1) % width] - projection[i % width], difference_lpf[i % (width - 2)]); // //sprintf_s(str, 1023, "%d%d\r\n", i, projection[i]); // file.Write(str, (UINT)strlen(str)); // } // // file.Close(); //#endif // // free(projection); // free(difference_lpf); // // return line_check; //} reflowResult Linecheck_New_Method( int* boe_line, reflowParam *rParam, BOOL bSetMaster ) { m_nLineCheckerLocalPeakPeriod=rParam->nPeakPeriod; reflowResult result; #ifdef SAVE_PROJECTION_VALUE CString temp(PROJECTION_DIR); CreateDirectory(temp, NULL); #endif int ret = 0; if(boe_line == NULL) { TRACE(_T("Linecheck_Method : Line Coordi Array Is Not Allocated\n")); result.nErrorcode = REFLOW_RESULT_OUTPUT_ARRAY_ERROR; return result; } if(rParam == NULL) { TRACE(_T("Linecheck_Method : Reflow Parameter Is Not Allocated\n")); result.nErrorcode = REFLOW_RESULT_REFLOWPARAM_SETTING_ERROR; return result; } if(!CheckSetting(rParam)) { TRACE(_T("Linecheck_Method : Reflow Parameter Is Invalid\n")); result.nErrorcode = REFLOW_RESULT_REFLOWPARAM_SETTING_ERROR; return result; } if(!bSetMaster) { TRACE(_T("Linecheck_Method : Master Setting Is Invalid\n")); result.nErrorcode = REFLOW_RESULT_MATCHING_ERROR; return result; } if(rParam->ROI_Rect->left < 0) rParam->ROI_Rect->left = 0; if(rParam->ROI_Rect->right > rParam->nImageWidth - 1) rParam->ROI_Rect->right = rParam->nImageWidth - 1; if(rParam->ROI_Rect->top < 0) rParam->ROI_Rect->top = 0; if(rParam->ROI_Rect->bottom > rParam->nImageHeight - 1) rParam->ROI_Rect->bottom = rParam->nImageHeight - 1; BYTE *pImage = NULL; //Review Image Gray 변환 pImage = new BYTE[rParam->nImageWidth * rParam->nImageHeight]; memset(pImage, 0, sizeof(BYTE)*rParam->nImageWidth * rParam->nImageHeight); if(-1 == RGB2GRAY(pImage, rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep)) { if(pImage) { delete [] pImage; pImage = NULL; } TRACE(_T("Linecheck_Method : RB2GRAY(Review Image) Fail\n")); result.nErrorcode = REFLOW_RESULT_IMAGE_LOAD_ERROR; return result; } BOOL bMatch = FALSE; BYTE *pMaster = NULL; //Master Image Gray 변환 pMaster = new BYTE[rParam->nMasterWidth * rParam->nMasterHeight]; memset(pMaster, 0, sizeof(BYTE)*rParam->nMasterWidth * rParam->nMasterHeight); if(-1 == RGB2GRAY(pMaster, rParam->pMasterBuffer, rParam->nMasterWidth, rParam->nMasterHeight, rParam->nMasterChannel, rParam->nMasterWidthStep)) { if(pImage) { delete [] pImage; pImage = NULL; } if(pMaster) { delete [] pMaster; pMaster = NULL; } TRACE(_T("Linecheck_Method : RB2GRAY(Master Image) Fail\n")); result.nErrorcode = REFLOW_RESULT_IMAGE_LOAD_ERROR; return result; } switch(rParam->nSide) //Matching을 통한 ROI 영역 설정 { case CS_TOP : bMatch = Match_Vertical(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); break; case CS_LEFT : case CS_RIGHT : bMatch = Match_Horizontal(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); break; } if(!bMatch) { //switch(rParam->nSide) //{ //case CS_TOP : // bMatch = SecondMatch_Vertical(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // break; //case CS_LEFT : //case CS_RIGHT : // bMatch = SecondMatch_Horizontal(pImage, rParam->nImageWidth, rParam->nImageHeight, pMaster, rParam->nMasterWidth, rParam->nMasterHeight, rParam->ROI_Rect); // break; //} //if(!bMatch) //{ if(pImage) { delete [] pImage; pImage = NULL; } if(pMaster) { delete [] pMaster; pMaster = NULL; } TRACE(_T("Linecheck_Method : Matching Fail\n")); result.nErrorcode = REFLOW_RESULT_MATCHING_ERROR; return result; //} } switch(rParam->nSide)//Review Image의 ROI 내에서 DAM을 탐색하여 overflow 여부 판정 { case CS_TOP : result.nErrorcode = Linecheck_Method_Side0(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nDamTh2, rParam->nDamTh2_in, rParam->nDamTh1, rParam->nDamTh1_in, rParam->nDistance,&result); for(int i = 0; i < 4; i++)//ROI Start 좌표를 원점으로 좌표를 계산하기 때문에 ROI Start 좌표를 가산해줌 { if(boe_line[i] != 0) { boe_line[i] += rParam->ROI_Rect->top; } } Reflow_Line_Paint_Vertical(rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep, boe_line); break; case CS_LEFT : result.nErrorcode = Linecheck_Method_Side1(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nDamTh2, rParam->nDamTh2_in, rParam->nDamTh1, rParam->nDamTh1_in, rParam->nDistance,&result); for(int i = 0; i < 4; i++) { if(boe_line[i] != 0) { boe_line[i] += rParam->ROI_Rect->left; } } Reflow_Line_Paint_Horizontal(rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep, boe_line); break; case CS_RIGHT : result.nErrorcode = Linecheck_Method_Side2(boe_line, pImage, rParam->nImageWidth, rParam->nImageHeight, rParam->ROI_Rect, rParam->nDamTh2, rParam->nDamTh2_in,rParam->nDamTh1, rParam->nDamTh1_in, rParam->nDistance,&result); for(int i = 0; i < 4; i++) { if(boe_line[i] != 0) { boe_line[i] += rParam->ROI_Rect->left; } } Reflow_Line_Paint_Horizontal(rParam->pImageBuffer, rParam->nImageWidth, rParam->nImageHeight, rParam->nChannel, rParam->nImageWidthStep, boe_line); break; default : result.nErrorcode = REFLOW_RESULT_REFLOWPARAM_SETTING_ERROR; // Select Wrong Side } if(pImage) { delete [] pImage; pImage = NULL; } if(pMaster) { delete [] pMaster; pMaster = NULL; } return result; }