|
#include "stdafx.h"
|
#include "LineChecker.h"
|
|
#include <cmath>
|
#include <emmintrin.h>
|
#include <tmmintrin.h>
|
|
#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;
|
}
|