#include "StdAfx.h"
|
#include "AlignFinder.h"
|
#include "CHImageControls/CHImageProcess.h"
|
#include <tmmintrin.h>
|
#include <smmintrin.h>
|
#include "EdgeFind.h"
|
|
using namespace CHImageControls;
|
|
inline bool CompareMaxSize(SPixelBlob& a, SPixelBlob& b)
|
{
|
return (a.dMatchValue > b.dMatchValue);
|
}
|
|
CAlignFinder::CAlignFinder(int nIndex) : m_nIndex(nIndex)
|
{
|
Reset();
|
}
|
|
CAlignFinder::~CAlignFinder(void)
|
{
|
Reset();
|
}
|
|
void CAlignFinder::Reset()
|
{
|
ResetImages();
|
m_pTempImage = NULL;
|
m_findParam.Reset();
|
}
|
|
void CAlignFinder::ResetImages()
|
{
|
m_SourceImage.ReleaseImage();
|
m_EdgeImage.ReleaseImage();
|
m_ThresImage.ReleaseImage();
|
m_BlobImage.ReleaseImage();
|
m_ResultImage.ReleaseImage();
|
}
|
|
BOOL CAlignFinder::SaveSourceImage(const CString& strFilename)
|
{
|
return m_SourceImage.SaveImage(strFilename);
|
}
|
|
BOOL CAlignFinder::SaveEdgeImage(const CString& strFilename)
|
{
|
return m_EdgeImage.SaveImage(strFilename);
|
}
|
|
BOOL CAlignFinder::SaveThresholdImage(const CString& strFilename)
|
{
|
return m_ThresImage.SaveImage(strFilename);
|
}
|
|
BOOL CAlignFinder::SaveBlobImage(const CString& strFilename)
|
{
|
return m_BlobImage.SaveImage(strFilename);
|
}
|
|
BOOL CAlignFinder::SaveResultImage(const CString& strFilename)
|
{
|
return m_ResultImage.SaveImage(strFilename);
|
}
|
|
BOOL CAlignFinder::GetSourceImage(CCHImageData *pImageData)
|
{
|
return m_SourceImage.CopyImageTo(pImageData);
|
}
|
|
BOOL CAlignFinder::GetEdgeImage(CCHImageData *pImageData)
|
{
|
return m_EdgeImage.CopyImageTo(pImageData);
|
}
|
|
BOOL CAlignFinder::GetThresholdImage(CCHImageData *pImageData)
|
{
|
return m_ThresImage.CopyImageTo(pImageData);
|
}
|
|
BOOL CAlignFinder::GetBlobImage(CCHImageData *pImageData)
|
{
|
return m_BlobImage.CopyImageTo(pImageData);
|
}
|
|
BOOL CAlignFinder::GetResultImage(CCHImageData *pImageData)
|
{
|
return m_ResultImage.CopyImageTo(pImageData);
|
}
|
|
|
|
SAlignFindResult CAlignFinder::FindAlign(CCHImageData *pImageData, const SAlignFindParam& findParam, CCHImageData *pTempImage)
|
{
|
/////////////////////////////////////IMAGE LOAD FOR TEST !!!! /////////////////////
|
// CCHImageData *tempImage = new CCHImageData;
|
// tempImage->LoadImageW(_T("D:\\Align1.BMP"));
|
//
|
// m_pTempImage = pTempImage;
|
// m_findParam = findParam;
|
//
|
// return FindAlign(tempImage, pTempImage
|
|
m_pTempImage = pTempImage;
|
|
m_findParam = findParam;
|
|
return FindAlign(pImageData, pTempImage);
|
}
|
|
SAlignFindResult CAlignFinder::FindAlign(CCHImageData *pImageData, CCHImageData *pTempImage)
|
{
|
m_pTempImage = pTempImage;
|
//¾ó¶óÀÎ ÆÄÀεå
|
if (pImageData==NULL) return SAlignFindResult();
|
|
if (pImageData->GetImageExist()==FALSE) return SAlignFindResult();
|
|
|
|
if (pImageData->GetChannels()!=1) return SAlignFindResult();
|
else
|
{
|
int a = pImageData->GetChannels();
|
}
|
|
return FindAlign((BYTE*)pImageData->GetImageBuffer(), pImageData->GetWidth(), pImageData->GetHeight());
|
}
|
|
|
SAlignFindResult CAlignFinder::FindAlign(BYTE* pImage, int nWidth, int nHeight, const SAlignFindParam& findParam)
|
{
|
m_pTempImage = NULL;
|
|
m_findParam = findParam;
|
|
return FindAlign(pImage, nWidth, nHeight);
|
}
|
|
SAlignFindResult CAlignFinder::FindAlign(BYTE* pImage, int nWidth, int nHeight)
|
{
|
SAlignFindResult findResult;
|
if (pImage==NULL) return findResult;
|
|
ResetImages();
|
|
findResult.nResultCode = 0;
|
|
// step1. Áß°£°á°ú À̹ÌÁö »ý¼º
|
if (m_SourceImage.CreateImage(nWidth, nHeight)==FALSE) return findResult;
|
if (m_EdgeImage.CreateImage(nWidth, nHeight)==FALSE) return findResult;
|
memcpy(m_SourceImage.GetImageBuffer(), pImage, sizeof(BYTE)*nWidth*nHeight);
|
|
// step3. matching
|
if (FindAlignMatching(findResult)==1)
|
{
|
return findResult;
|
}
|
|
/*< LYW 20211013 - #3671 Delete Start >*/
|
// step2. edge find
|
// if (FindAlignEdge(findResult) == 1)
|
// {
|
// return findResult;
|
// }
|
/*< LYW 20211013 - #3671 Delete End >*/
|
|
|
return findResult;
|
}
|
|
int CAlignFinder::FindAlignMatching(SAlignFindResult& findResult)
|
{
|
findResult.nResultProcess = AlignProcess_Match;
|
|
if (m_findParam.bMatchProcess==FALSE)
|
{
|
return 0;
|
}
|
|
if (m_pTempImage==NULL)
|
{
|
findResult.nResultCode = AlignMatch_None;
|
return 0;
|
}
|
|
if (!m_pTempImage->GetImageExist())
|
{
|
findResult.nResultCode = AlignMatch_NoTemplate;
|
return 0;
|
}
|
|
if (m_pTempImage->GetChannels()!=1)
|
{
|
findResult.nResultCode = AlignMatch_NotOneChannels;
|
return 0;
|
}
|
|
double dResultX, dResultY;
|
CCHImageData resultImage;
|
if (CCHImageProcess::ImageMatching(&m_SourceImage, m_pTempImage,
|
dResultX, dResultY, findResult.dMatchValue, &resultImage)!=ResultSuccess)
|
{
|
findResult.nResultCode = AlignMatch_MatchFail;
|
return 0;
|
}
|
|
CCHImageData tempImage;
|
CCHImageProcess::ImageNormalize(&resultImage, &m_BlobImage, 0, 255);
|
|
/*< LYW 20211013 - #3671 Delete Start >*/
|
// if (findResult.dMatchValue < m_findParam.dMatchRate)
|
// {
|
// findResult.nResultCode = AlignMatch_LowScore;
|
// return 0;
|
// }
|
/*< LYW 20211013 - #3671 Delete End >*/
|
|
// step5. Make Result À̹ÌÁö
|
findResult.nResultCode = AlignMatch_Success;
|
double dHalfWidth = double(m_pTempImage->GetWidth()) / 2.0;
|
double dHalfHeight = double(m_pTempImage->GetHeight()) / 2.0;
|
findResult.dPosX = dResultX + dHalfWidth;
|
findResult.dPosY = dResultY + dHalfHeight;
|
|
if (m_SourceImage.CopyImageTo(&m_ResultImage))
|
{
|
m_ResultImage.DrawRectangle(CPoint((int)(dResultX+0.5), (int)(dResultY+0.5)), CPoint((int)(dResultX+m_pTempImage->GetWidth()+0.5), (int)(dResultY+m_pTempImage->GetHeight()+0.5)), RGB(255,255,255), 2);
|
}
|
|
/*< LYW 20211013 - #3671 ADD Start >*/
|
if (findResult.dMatchValue < m_findParam.dMatchRate)
|
{
|
findResult.nResultCode = AlignMatch_LowScore;
|
return 0;
|
}
|
/*< LYW 20211013 - #3671 ADD End >*/
|
return 1;
|
}
|
|
int CAlignFinder::FindAlignEdge(SAlignFindResult& findResult)
|
{
|
findResult.nResultProcess = AlignProcess_Edge;
|
|
if (m_findParam.bEdgeProcess==FALSE)
|
{
|
return AlignEdge_None;
|
}
|
|
// step1. Sobel Edge ¿¬»ê
|
int nWidth = m_SourceImage.GetWidth();
|
int nHeight = m_SourceImage.GetHeight();
|
|
if (ImageSobelEdge((BYTE*)m_SourceImage.GetImageBuffer(), (BYTE*)m_EdgeImage.GetImageBuffer(), nWidth, nHeight)!=1)
|
{
|
findResult.nResultCode = AlignEdge_EdgeFail;
|
return 0;
|
}
|
|
// step2. Binary Threshold ¿¬»ê
|
if (m_EdgeImage.CopyImageTo(&m_ThresImage)==FALSE)
|
{
|
findResult.nResultCode = AlignEdge_None;
|
return 0;
|
}
|
|
if (ImageThresholding((BYTE*)m_ThresImage.GetImageBuffer(), nWidth, nHeight, m_findParam.nEdgeThreshold)!=1)
|
{
|
findResult.nResultCode = AlignEdge_BinaryFail;
|
return 0;
|
}
|
|
// step3. Blob Analysis ¿¬»ê
|
if (m_ThresImage.CopyImageTo(&m_BlobImage)==FALSE)
|
{
|
findResult.nResultCode = AlignEdge_None;
|
return 0;
|
}
|
|
VectorPixelBlob pixelBlob;
|
if (ImageBlobAnalysis((BYTE*)m_BlobImage.GetImageBuffer(), nWidth, nHeight, pixelBlob,
|
m_findParam.nMergeRange, m_findParam.nAlignHeight, m_findParam.nAlignWidth)!=1)
|
{
|
findResult.nResultCode = AlignEdge_BlobFail;
|
return 0;
|
}
|
|
// step4. Blob Matching °ª °è»ê
|
//m_findParam.bMeasureThickness = 1; // Çü¸ñ¾¾ À̰ŠÁÖ¼® ²À°É¾î¿ä Edge Find ¾ÈµÇ¿ä
|
if (m_findParam.bMeasureThickness)
|
{
|
if (AlignMeasureThickness((BYTE*)m_BlobImage.GetImageBuffer(), nWidth, nHeight, pixelBlob, m_findParam)==0)
|
{
|
if(pixelBlob.size() > 0)
|
{
|
findResult.dMatchValue = pixelBlob[0].dMatchValue;
|
}
|
findResult.nResultCode = AlignEdge_BlobFail;
|
return 0;
|
}
|
}
|
|
findResult.dMatchValue = pixelBlob[0].dMatchValue;
|
if (findResult.dMatchValue<m_findParam.dEdgeRate)
|
{
|
findResult.nResultCode = AlignEdge_LowScore;
|
return 0;
|
}
|
|
// step5. Make Result À̹ÌÁö
|
findResult.nResultCode = AlignEdge_Success;
|
findResult.dPosX = pixelBlob[0].GetCenterX();
|
findResult.dPosY = pixelBlob[0].GetCenterY();
|
if (m_SourceImage.CopyImageTo(&m_ResultImage))
|
{
|
m_ResultImage.DrawRectangle(CPoint(pixelBlob[0].nLeft, pixelBlob[0].nTop), CPoint(pixelBlob[0].nRight, pixelBlob[0].nBottom), RGB(255,255,255), 2);
|
}
|
|
return 1;
|
}
|
|
int CAlignFinder::ImageSobelEdge(BYTE* pSrcImage, BYTE *pDstImage, int nWidth, int nHeight)
|
{
|
if (pSrcImage==NULL || pDstImage==NULL) return 0;
|
|
__m128i zeroData = _mm_setzero_si128();
|
__m128i currentData = _mm_setzero_si128();
|
__m128i sobelData = _mm_set1_epi16(2);
|
__m128i lowUnpack = _mm_setzero_si128(); // low unpack
|
__m128i highUnpack = _mm_setzero_si128(); // high unpack
|
__m128i multiData = _mm_setzero_si128();
|
__m128i TopKernel = _mm_setzero_si128();
|
__m128i BottomKernel = _mm_setzero_si128();
|
__m128i tempData = _mm_setzero_si128();
|
|
register BYTE *pSrcImageX, *pDstImageX;
|
register int nShiftOne, nShiftTwo;
|
register int nY0X2 = 2;
|
register int nY1X0 = nWidth;
|
register int nY1X2 = nWidth + 2;
|
register int nY2X0 = 2*nWidth;
|
register int nY2X2 = 2*nWidth + 2;
|
register int nLast = (nWidth % 8) ? 6: 2;
|
|
for (int y=0; y<nHeight-2; y++)
|
{
|
pSrcImageX = pSrcImage + (y*nWidth);
|
pDstImageX = pDstImage + ((y+1)*nWidth) + 1;
|
|
*(pDstImageX-1) = 0;
|
|
for (int x=0; x<nWidth; x+=8)
|
{
|
// [1] vertical kernel
|
|
// get pixel data (y+2,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X0));
|
tempData = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_unpackhi_epi8(currentData, zeroData); // high
|
|
nShiftOne = _mm_extract_epi16(highUnpack, 0);
|
nShiftTwo = _mm_extract_epi16(highUnpack, 1);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(tempData, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftOne, 7);
|
|
// mul * 2
|
multiData = _mm_mullo_epi16(highUnpack, sobelData);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(highUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftTwo, 7);
|
|
BottomKernel = _mm_add_epi16(tempData, multiData);
|
BottomKernel = _mm_add_epi16(BottomKernel, highUnpack); // top kernel value
|
|
// get pixel data (y,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX));
|
lowUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_unpackhi_epi8(currentData, zeroData); // high
|
|
nShiftOne = _mm_extract_epi16(highUnpack, 0);
|
nShiftTwo = _mm_extract_epi16(highUnpack, 1);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(lowUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftOne, 7);
|
|
// mul * 2
|
multiData = _mm_mullo_epi16(highUnpack, sobelData);
|
|
// left shift 2byte
|
highUnpack = _mm_srli_si128(highUnpack, 2);
|
highUnpack = _mm_insert_epi16(highUnpack, nShiftTwo, 7);
|
|
TopKernel = _mm_add_epi16(lowUnpack, multiData);
|
TopKernel = _mm_add_epi16(TopKernel, highUnpack); // top kernel value
|
|
TopKernel = _mm_sub_epi16(TopKernel, BottomKernel); // top + bottom
|
TopKernel = _mm_abs_epi16(TopKernel); // horizontal result
|
|
// lowUnpack, TopKernel, sobelData, currentData,
|
|
// [1] Horizontal kernel
|
// get pixel data (y+1,x)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X0));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_mullo_epi16(highUnpack, sobelData); // mul * 2
|
lowUnpack = _mm_add_epi16(lowUnpack, highUnpack); // add result
|
|
// get pixel data (y+2,x)
|
// currentData = _mm_loadu_si128((__m128i*)(pSrcImage+((y+2)*nWidth)+x));
|
// highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
lowUnpack = _mm_add_epi16(lowUnpack, tempData); // add result
|
|
// get pixel data (y,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY0X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
// get pixel data (y+1,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY1X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
highUnpack = _mm_mullo_epi16(highUnpack, sobelData); // mul * 2
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
// get pixel data (y+2,x+2)
|
currentData = _mm_loadu_si128((__m128i*)(pSrcImageX+nY2X2));
|
highUnpack = _mm_unpacklo_epi8(currentData, zeroData); // low
|
lowUnpack = _mm_sub_epi16(lowUnpack, highUnpack); // sub result
|
|
lowUnpack = _mm_abs_epi16(lowUnpack); // abs result
|
TopKernel = _mm_add_epi16(TopKernel, lowUnpack); // add horizontal + vertical
|
|
TopKernel = _mm_srai_epi16(TopKernel, 1); // shift right 1 <add>
|
|
TopKernel = _mm_packus_epi16(TopKernel, TopKernel); // last result
|
|
_mm_storel_epi64( (__m128i*)(pDstImageX), TopKernel);
|
|
pSrcImageX += 8;
|
pDstImageX += 8;
|
}
|
|
*(pDstImageX-nLast) = 0;
|
}
|
|
memset(pDstImage, 0, nWidth);
|
memset(pDstImage+((nHeight-1)*nWidth), 0, nWidth);
|
|
return 1;
|
}
|
|
int CAlignFinder::ImageThresholding(BYTE* pImage, int nWidth, int nHeight, int nThresValue)
|
{
|
if (pImage==NULL) return 0;
|
|
register BYTE *pBuffer = pImage;
|
|
__m128i _x80 = _mm_set1_epi8('\x80');
|
__m128i ThresData = _mm_set1_epi8(UCHAR(nThresValue)^0x80);
|
__m128i v0, v1;
|
|
register int i;
|
register int nTotalSize = nWidth*nHeight;
|
|
for(i=0; i<=nTotalSize-32; i+=32 )
|
{
|
v0 = _mm_loadu_si128( (const __m128i*)(pBuffer) );
|
v1 = _mm_loadu_si128( (const __m128i*)(pBuffer+16) );
|
v0 = _mm_cmpgt_epi8( _mm_xor_si128(v0, _x80), ThresData );
|
v1 = _mm_cmpgt_epi8( _mm_xor_si128(v1, _x80), ThresData );
|
_mm_storeu_si128( (__m128i*)(pBuffer), v0 );
|
_mm_storeu_si128( (__m128i*)(pBuffer+16), v1 );
|
pBuffer+=32;
|
}
|
|
for( ; i <=nTotalSize-8; i+=8 )
|
{
|
v0 = _mm_loadl_epi64( (const __m128i*)(pBuffer) );
|
v0 = _mm_cmpgt_epi8( _mm_xor_si128(v0, _x80), ThresData );
|
_mm_storel_epi64( (__m128i*)(pBuffer), v0 );
|
pBuffer+=8;
|
}
|
|
for (; i<nTotalSize; i++)
|
{
|
*(pBuffer++) = (*pBuffer>nThresValue) ? 255: 0;
|
}
|
|
return 1;
|
}
|
|
int CAlignFinder::ImageBlobAnalysis(BYTE *pImage, int nWidth, int nHeight, VectorPixelBlob& vectorBlob, int nBlob, int nAlignWidth, int nAlignHeight)
|
{
|
if (pImage==NULL) return 0;
|
|
int i, j, y, x;
|
|
// top & bottom margin
|
BYTE *pBuf1 = pImage;
|
BYTE *pBuf2 = pImage + (nHeight-1)*nWidth;
|
for (i=0; i<nBlob; i++)
|
{
|
memset(pBuf1, 0, sizeof(BYTE)*nWidth);
|
memset(pBuf2, 0, sizeof(BYTE)*nWidth);
|
pBuf1 += nWidth;
|
pBuf2 -= nWidth;
|
}
|
|
// left & right margin
|
pBuf1 = pImage;
|
for (i=0; i<nHeight; i++)
|
{
|
memset(pBuf1, 0, sizeof(BYTE)*nBlob);
|
memset(pBuf1+(nWidth-nBlob-1), 0, sizeof(BYTE)*nBlob);
|
pBuf1 += nWidth;
|
}
|
|
const int nWeightCount = 4;
|
double pWeight[nWeightCount] = {0.3, 0.3, 0.4, 0.0};
|
double pDistValue[nWeightCount];
|
double dAlignRatio = double(nAlignWidth)/float(nAlignHeight);
|
|
size_t nSize;
|
std::vector<CPoint> vectorPixel;
|
SPixelBlob pixelBlob;
|
register BYTE *pSrcImgY = pImage + (nBlob*nWidth) + nBlob;
|
register BYTE *pSrcImgX, *pSubX, *pSubY;
|
|
int nBlobMin = -nBlob;
|
int nBlobMax = nBlob+1;
|
|
for (i=nBlob; i<nHeight-nBlob; i++)
|
{
|
pSrcImgX = pSrcImgY;
|
for (j=nBlob; j<nWidth-nBlob; j++)
|
{
|
if (*pSrcImgX > 200)
|
{
|
*pSrcImgX = 128;
|
vectorPixel.push_back(CPoint(j, i));
|
|
// new pixel blob
|
pixelBlob.Reset();
|
|
while ((nSize=vectorPixel.size())>0)
|
{
|
x = vectorPixel[nSize-1].x;
|
y = vectorPixel[nSize-1].y;
|
|
// delete end point
|
vectorPixel.pop_back();
|
|
// add point to blob
|
pixelBlob.vectorPoint.push_back(CPoint(x, y));
|
|
// get current point
|
pSubY = pImage + ((y+nBlobMin)*nWidth) + (x+nBlobMin);
|
|
for (int sy=nBlobMin; sy<nBlobMax; sy++)
|
{
|
pSubX = pSubY;
|
for (int sx=nBlobMin; sx<nBlobMax; sx++)
|
{
|
if (*pSubX > 200)
|
{
|
*pSubX = 128;
|
vectorPixel.push_back(CPoint(x+sx, y+sy));
|
}
|
pSubX++;
|
}
|
pSubY += nWidth;
|
}
|
|
if (pixelBlob.nLeft>x) pixelBlob.nLeft = x;
|
if (pixelBlob.nRight<x) pixelBlob.nRight = x;
|
if (pixelBlob.nTop>y) pixelBlob.nTop = y;
|
if (pixelBlob.nBottom<y) pixelBlob.nBottom = y;
|
}
|
|
vectorPixel.clear();
|
|
// calculate blob match value
|
pDistValue[0] = double(nAlignWidth - pixelBlob.GetWidth()) / double(nAlignWidth); // width size
|
pDistValue[1] = double(nAlignHeight - pixelBlob.GetHeight()) / double(nAlignHeight); // height size
|
// (align_ratio - blob_ratio) / align_ratio
|
pDistValue[2] = ( dAlignRatio-(double(pixelBlob.GetWidth())/double(pixelBlob.GetHeight())) ) / dAlignRatio;
|
|
for (int i=0; i<nWeightCount; i++)
|
{
|
pDistValue[i] = (pDistValue[i] < 0.0) ? -pDistValue[i]: pDistValue[i]; // abs
|
pDistValue[i] = 1.0 - pDistValue[i]; // 1 - value
|
pDistValue[i] = (pDistValue[i] < 0.0) ? 0.0: pDistValue[i]; // min(0, value)
|
|
pixelBlob.dMatchValue += (pDistValue[i] * pWeight[i]);
|
}
|
|
vectorBlob.push_back(pixelBlob);
|
|
} // end if
|
pSrcImgX++;
|
} //end for j
|
pSrcImgY += nWidth;
|
}// end for i
|
|
if (vectorBlob.size()==0) return 0;
|
|
// sort blob max size
|
std::sort(vectorBlob.begin(), vectorBlob.end(), CompareMaxSize);
|
|
return 1;
|
}
|
|
SThicknessResult CAlignFinder::FindAlignMarkThickness(BYTE *pProcImg, int nWidth, int nHeight, CPoint ptResult, int nRefWidth, int nRefHeight)
|
{
|
SThicknessResult MeasureResult;
|
|
if(ptResult.x < nRefWidth / 2
|
|| ptResult.x > nWidth - nRefWidth / 2
|
|| ptResult.y < nRefHeight / 2
|
|| ptResult.y > nHeight - nRefHeight / 2)
|
return MeasureResult;
|
|
CRect rtROI;
|
const int nBaseWidth = nRefWidth / 9;
|
const int nBaseHeight = nRefHeight / 9;
|
|
//Left
|
rtROI.left = ptResult.x - nRefWidth / 2 + nBaseWidth;
|
rtROI.top = ptResult.y - nRefHeight / 2;
|
rtROI.right = rtROI.left + nBaseWidth;
|
rtROI.bottom = rtROI.top + nRefHeight;
|
|
MeasureResult.rtSizeL.left = rtROI.left;
|
MeasureResult.rtSizeL.right = rtROI.right;
|
MeasureResult.rtSizeL.top = CEdgeFind::ImageProjection_Vert(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
MeasureResult.rtSizeL.bottom = CEdgeFind::ImageProjection_Vert_R(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
|
//Right
|
rtROI.right = ptResult.x + nRefWidth / 2 - nBaseWidth;
|
rtROI.left = rtROI.right - nBaseWidth;
|
|
MeasureResult.rtSizeR.left = rtROI.left;
|
MeasureResult.rtSizeR.right = rtROI.right;
|
MeasureResult.rtSizeR.top = CEdgeFind::ImageProjection_Vert(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
MeasureResult.rtSizeR.bottom = CEdgeFind::ImageProjection_Vert_R(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
|
//top
|
rtROI.left = ptResult.x - nRefWidth / 2;
|
rtROI.top = ptResult.y - nRefHeight / 2 + nBaseHeight;
|
rtROI.right = rtROI.left + nRefWidth;
|
rtROI.bottom = rtROI.top + nBaseHeight;
|
|
MeasureResult.rtSizeT.top = rtROI.top;
|
MeasureResult.rtSizeT.bottom = rtROI.bottom;
|
MeasureResult.rtSizeT.left = CEdgeFind::ImageProjection(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
MeasureResult.rtSizeT.right = CEdgeFind::ImageProjection_R(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
|
//bottom
|
rtROI.bottom = ptResult.y + nRefHeight / 2 - nBaseHeight;
|
rtROI.top = rtROI.bottom - nBaseHeight;
|
|
MeasureResult.rtSizeB.top = rtROI.top;
|
MeasureResult.rtSizeB.bottom = rtROI.bottom;
|
MeasureResult.rtSizeB.left = CEdgeFind::ImageProjection(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
MeasureResult.rtSizeB.right = CEdgeFind::ImageProjection_R(pProcImg, nWidth, nHeight, rtROI, 100, 5, 1);
|
|
return MeasureResult;
|
}
|
|
int CAlignFinder::AlignMeasureThickness( BYTE *pImage, int nWidth, int nHeight, VectorPixelBlob& vectorBlob, const SAlignFindParam& sAlignFindParam )
|
{
|
int nLRThickness = sAlignFindParam.nEDThicknessLR;
|
int nTBThickness = sAlignFindParam.nEDThicknessTB;
|
int nThicknessRange = sAlignFindParam.nEDThicknessRange;
|
|
VectorPixelBlob vecResult;
|
|
for (VectorPixelBlobIt it=vectorBlob.begin(); it!=vectorBlob.end(); it++)
|
{
|
// check score
|
if (it->dMatchValue >= sAlignFindParam.dEdgeRate)
|
{
|
|
CPoint ptResult;
|
ptResult.x = it->GetCenterX();
|
ptResult.y = it->GetCenterY();
|
|
it->sThicknessResult = FindAlignMarkThickness(pImage, nWidth, nHeight, ptResult, it->GetWidth(), it->GetHeight());
|
|
int lh = it->sThicknessResult.rtSizeL.Height();
|
int rh = it->sThicknessResult.rtSizeR.Height();
|
int tw = it->sThicknessResult.rtSizeT.Width();
|
int bw = it->sThicknessResult.rtSizeB.Width();
|
if(it->sThicknessResult.IsAllSuccess() == FALSE
|
/* || it->sThicknessResult.rtSizeL.Height() > nLRThickness + nThicknessRange
|
|| it->sThicknessResult.rtSizeL.Height() < nLRThickness - nThicknessRange
|
|| it->sThicknessResult.rtSizeR.Height() > nLRThickness + nThicknessRange
|
|| it->sThicknessResult.rtSizeR.Height() < nLRThickness - nThicknessRange
|
|| it->sThicknessResult.rtSizeT.Width() > nTBThickness + nThicknessRange
|
|| it->sThicknessResult.rtSizeT.Width() < nTBThickness - nThicknessRange
|
|| it->sThicknessResult.rtSizeB.Width() > nTBThickness + nThicknessRange
|
|| it->sThicknessResult.rtSizeB.Width() < nTBThickness - nThicknessRange
|
*/
|
|| lh > nLRThickness + nThicknessRange
|
|| lh < nLRThickness - nThicknessRange
|
|| rh > nLRThickness + nThicknessRange
|
|| rh < nLRThickness - nThicknessRange
|
|| tw > nTBThickness + nThicknessRange
|
|| tw < nTBThickness - nThicknessRange
|
|| bw > nTBThickness + nThicknessRange
|
|| bw < nTBThickness - nThicknessRange
|
)
|
{
|
continue;
|
}
|
|
vecResult.push_back(*it);
|
}
|
}
|
|
vectorBlob = vecResult;
|
|
return (int)vectorBlob.size();
|
}
|