#include "StdAfx.h"
|
#include "HoleInspector.h"
|
|
|
CHoleInspector::CHoleInspector(void)
|
{
|
}
|
|
|
CHoleInspector::~CHoleInspector(void)
|
{
|
}
|
|
RetValue CHoleInspector::HoleInspect_TemplateMatching(int nThreshold, int nOffset, int nMinSize, IplImage* pTargetImage, IplImage* pTemplateImage, IplImage** pResultImage, std::vector<CRect>& vecDefectList, double& dMatRate, IplImage** pResultImageColor)
|
{
|
if(pTargetImage == NULL || pTemplateImage == NULL || pResultImage == NULL)
|
return Ret_ParamError;
|
|
if((pTargetImage->width < pTemplateImage->width) || (pTargetImage->height < pTemplateImage->height))
|
return Ret_ParamError;
|
|
|
if(*(pResultImage) != NULL)
|
cvReleaseImage(pResultImage);
|
|
if(pResultImageColor != NULL)
|
if(*(pResultImageColor) != NULL)
|
cvReleaseImage(pResultImageColor);
|
|
// 1. Template Matching
|
IplImage* C = cvCreateImage(cvSize(pTargetImage->width - pTemplateImage->width + 1, pTargetImage->height - pTemplateImage->height + 1), IPL_DEPTH_32F, 1);
|
|
CvPoint ptLeftTop;
|
double dMin;
|
double dMatchingRate;
|
|
cvMatchTemplate(pTargetImage, pTemplateImage, C, CV_TM_CCOEFF_NORMED);
|
cvMinMaxLoc(C, &dMin, &dMatchingRate, NULL, &ptLeftTop);
|
|
dMatRate = dMatchingRate;
|
|
cvReleaseImage(&C);
|
|
*(pResultImage) = cvCreateImage(cvSize(pTemplateImage->width, pTemplateImage->height), pTemplateImage->depth, pTemplateImage->nChannels);
|
cvZero(*(pResultImage));
|
|
if(pResultImageColor != NULL)
|
{
|
*(pResultImageColor) = cvCreateImage(cvSize(pTemplateImage->width, pTemplateImage->height), pTemplateImage->depth, 3);
|
cvZero(*(pResultImageColor));
|
}
|
|
// 2. Make Remove Ellipse Circle
|
IplImage* pEllipseRemove = cvCloneImage(*(pResultImage));
|
|
int nMaxOffsetX = pEllipseRemove->width/2;
|
int nMaxOffsetY = pEllipseRemove->height/2;
|
|
if(nMaxOffsetX < nMaxOffsetY && nMaxOffsetX < nOffset) nOffset = nMaxOffsetX;
|
else if(nMaxOffsetX > nMaxOffsetY && nMaxOffsetY < nOffset) nOffset = nMaxOffsetY;
|
|
cvEllipse(pEllipseRemove, cvPoint(pEllipseRemove->width/2, pEllipseRemove->height/2), cvSize(pEllipseRemove->width/2-nOffset, pEllipseRemove->height/2-nOffset), 0, 0, 360.0, cvScalar(255,255,255), -1, CV_AA);
|
|
// 3. Inspect
|
for(int i=0; i<(*pResultImage)->height; i++)
|
{
|
for(int j=0; j<(*pResultImage)->width; j++)
|
{
|
if(pEllipseRemove->imageData[i*pEllipseRemove->widthStep+j] != 0)
|
{
|
if(abs(pTemplateImage->imageData[i*pTemplateImage->widthStep+j] - pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)]) > nThreshold)
|
(*pResultImage)->imageData[i*(*pResultImage)->widthStep+j] = (BYTE) 255;
|
|
if(pResultImageColor != NULL)
|
{
|
(*pResultImageColor)->imageData[i*(*pResultImageColor)->widthStep+(j*(*pResultImageColor)->nChannels)] = pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)];
|
(*pResultImageColor)->imageData[i*(*pResultImageColor)->widthStep+(j*(*pResultImageColor)->nChannels)+1] = pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)];
|
(*pResultImageColor)->imageData[i*(*pResultImageColor)->widthStep+(j*(*pResultImageColor)->nChannels)+2] = pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)];
|
}
|
}
|
}
|
}
|
|
cvReleaseImage(&pEllipseRemove);
|
|
// 4. Blob Process
|
vecDefectList.clear();
|
|
CvSeq* contours = NULL;
|
CvMemStorage* storage = NULL;
|
|
IplImage* pBinImage = cvCloneImage((*pResultImage));
|
|
storage = cvCreateMemStorage(0);
|
cvFindContours(pBinImage, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0) );
|
cvReleaseImage(&pBinImage);
|
|
CvRect rtCv;
|
CRect rtDefect;
|
|
for(;contours!=0;contours=contours->h_next)
|
{
|
double dArea = cvContourArea(contours);
|
|
if(nMinSize < dArea)
|
{
|
rtCv = cvBoundingRect(contours);
|
|
rtDefect.left = rtCv.x;
|
rtDefect.right = rtDefect.left + rtCv.width;
|
|
rtDefect.top = rtCv.y;
|
rtDefect.bottom = rtDefect.top + rtCv.height;
|
|
vecDefectList.push_back(rtDefect);
|
|
}
|
}
|
cvReleaseMemStorage(&storage);
|
|
|
// Debug Image
|
if(pResultImageColor != NULL)
|
{
|
cvEllipse((*pResultImageColor), cvPoint((*pResultImageColor)->width/2, (*pResultImageColor)->height/2), cvSize((*pResultImageColor)->width/2, (*pResultImageColor)->height/2), 0, 0, 360.0, cvScalar(0,0,255), 1);
|
cvEllipse((*pResultImageColor), cvPoint((*pResultImageColor)->width/2, (*pResultImageColor)->height/2), cvSize((*pResultImageColor)->width/2-nOffset, (*pResultImageColor)->height/2-nOffset), 0, 0, 360.0, cvScalar(255,0,0), 1);
|
|
for(int i=0; i<(int)vecDefectList.size(); i++)
|
cvDrawRect((*pResultImageColor), cvPoint(vecDefectList[i].left, vecDefectList[i].top), cvPoint(vecDefectList[i].right, vecDefectList[i].bottom), cvScalar(0,255,0));
|
}
|
|
return Ret_Success;
|
}
|
|
RetValue CHoleInspector::HoleInspect_TemplateMatching(HOLE_INS_PARM* pParam, IplImage* pTargetImage, std::vector<CRect>& vecDefectList, CPoint& ptMatchingPos, IplImage** pResultImageColor/*=NULL*/)
|
{
|
if(pParam == NULL || pTargetImage == NULL)
|
return Ret_ParamError;
|
|
char str_filename[1024] = {};
|
|
#ifdef _UNICODE
|
int nSize = WideCharToMultiByte(CP_ACP, 0, pParam->m_strTemplatePath.GetBuffer(), -1, NULL, 0, NULL,NULL);
|
WideCharToMultiByte(CP_ACP, 0, pParam->m_strTemplatePath.GetBuffer(), -1, str_filename, nSize, NULL, NULL);
|
#else
|
sprintf_s(str_filename,sizeof(char)*pParam->m_strTemplatePath.GetLength(),"%s",(LPSTR)(LPCTSTR)pParam->m_strTemplatePath);
|
#endif
|
|
IplImage* pTemplateImage = cvLoadImage(str_filename, CV_LOAD_IMAGE_GRAYSCALE);
|
if(pTemplateImage == NULL)
|
return Ret_ParamError;
|
|
CRect rtMatchingArea;
|
|
if(IntersectRect(rtMatchingArea, CRect(0, 0, pTemplateImage->width, pTemplateImage->height), pParam->m_rtHoleArea) == FALSE)
|
{
|
cvReleaseImage(&pTemplateImage);
|
return Ret_ParamError;
|
}
|
|
IplImage* pHoleImage = cvCreateImage(cvSize(rtMatchingArea.Width(), rtMatchingArea.Height()), 8, 1);
|
|
for(int i=0; i<pHoleImage->height; i++)
|
memcpy(&pHoleImage->imageData[i*pHoleImage->widthStep], &pTemplateImage->imageData[((rtMatchingArea.top+i)*pTemplateImage->widthStep)+rtMatchingArea.left], pHoleImage->width);
|
|
cvReleaseImage(&pTemplateImage);
|
|
if((pTargetImage->width < pHoleImage->width) || (pTargetImage->height < pHoleImage->height))
|
{
|
cvReleaseImage(&pHoleImage);
|
return Ret_ParamError;
|
}
|
|
// 1. Template Matching
|
IplImage* C = cvCreateImage(cvSize(pTargetImage->width - pHoleImage->width + 1, pTargetImage->height - pHoleImage->height + 1), IPL_DEPTH_32F, 1);
|
|
CvPoint ptLeftTop;
|
double dMin;
|
double dMatchingRate;
|
|
cvMatchTemplate(pTargetImage, pHoleImage, C, CV_TM_CCOEFF_NORMED);
|
cvMinMaxLoc(C, &dMin, &dMatchingRate, NULL, &ptLeftTop);
|
cvReleaseImage(&C);
|
|
ptMatchingPos.x = ptLeftTop.x;
|
ptMatchingPos.y = ptLeftTop.y;
|
|
dMatchingRate = dMatchingRate * 100.0;
|
|
if(dMatchingRate < pParam->m_dMatRate)
|
{
|
vecDefectList.push_back(CRect(ptLeftTop.x, ptLeftTop.y, ptLeftTop.x+pHoleImage->width, ptLeftTop.y+pHoleImage->height));
|
cvReleaseImage(&pHoleImage);
|
return Ret_MatRateLimit;
|
}
|
|
|
IplImage* pBinImage = cvCreateImage(cvSize(pHoleImage->width, pHoleImage->height), pHoleImage->depth, pHoleImage->nChannels);
|
cvZero(pBinImage);
|
|
// Debug Image
|
if(pResultImageColor != NULL)
|
{
|
if(*(pResultImageColor) != NULL)
|
cvReleaseImage(pResultImageColor);
|
|
*(pResultImageColor) = cvCreateImage(cvSize(pHoleImage->width, pHoleImage->height), pHoleImage->depth, 3);
|
cvZero(*(pResultImageColor));
|
}
|
|
// 2. Make Remove Ellipse Circle
|
IplImage* pEllipseRemove = cvCloneImage(pBinImage);
|
|
int nMaxOffsetX = pEllipseRemove->width/2;
|
int nMaxOffsetY = pEllipseRemove->height/2;
|
|
int nOffset = 0;
|
if(nMaxOffsetX < nMaxOffsetY && nMaxOffsetX < pParam->m_nOffset) nOffset = nMaxOffsetX;
|
else if(nMaxOffsetX > nMaxOffsetY && nMaxOffsetY < pParam->m_nOffset) nOffset = nMaxOffsetY;
|
|
cvEllipse(pEllipseRemove, cvPoint(pEllipseRemove->width/2, pEllipseRemove->height/2), cvSize(pEllipseRemove->width/2-pParam->m_nOffset, pEllipseRemove->height/2-pParam->m_nOffset), 0, 0, 360.0, cvScalar(255,255,255), -1, CV_AA);
|
|
// 3. Inspect
|
for(int i=0; i<pBinImage->height; i++)
|
{
|
for(int j=0; j<pBinImage->width; j++)
|
{
|
if(pEllipseRemove->imageData[i*pEllipseRemove->widthStep+j] != 0)
|
{
|
if(abs(pHoleImage->imageData[i*pHoleImage->widthStep+j] - pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)]) > pParam->m_nThreshold)
|
pBinImage->imageData[(i*pBinImage->widthStep)+j] = (BYTE) 255;
|
|
if(pResultImageColor != NULL)
|
{
|
(*pResultImageColor)->imageData[i*(*pResultImageColor)->widthStep+(j*(*pResultImageColor)->nChannels)] = pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)];
|
(*pResultImageColor)->imageData[i*(*pResultImageColor)->widthStep+(j*(*pResultImageColor)->nChannels)+1] = pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)];
|
(*pResultImageColor)->imageData[i*(*pResultImageColor)->widthStep+(j*(*pResultImageColor)->nChannels)+2] = pTargetImage->imageData[(i+ptLeftTop.y)*pTargetImage->widthStep+(j+ptLeftTop.x)];
|
}
|
}
|
}
|
}
|
|
cvReleaseImage(&pEllipseRemove);
|
cvReleaseImage(&pHoleImage);
|
|
// 4. Blob Process
|
vecDefectList.clear();
|
|
CvSeq* contours = NULL;
|
CvMemStorage* storage = NULL;
|
|
storage = cvCreateMemStorage(0);
|
cvFindContours(pBinImage, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0) );
|
cvReleaseImage(&pBinImage);
|
|
CvRect rtCv;
|
CRect rtDefect;
|
|
for(;contours!=0;contours=contours->h_next)
|
{
|
double dArea = cvContourArea(contours);
|
|
if(pParam->m_nMinSize < dArea)
|
{
|
rtCv = cvBoundingRect(contours);
|
|
rtDefect.left = rtCv.x;
|
rtDefect.right = rtDefect.left + rtCv.width;
|
|
rtDefect.top = rtCv.y;
|
rtDefect.bottom = rtDefect.top + rtCv.height;
|
|
vecDefectList.push_back(rtDefect);
|
|
}
|
}
|
cvReleaseMemStorage(&storage);
|
|
|
// Debug Image
|
if(pResultImageColor != NULL)
|
{
|
cvEllipse((*pResultImageColor), cvPoint((*pResultImageColor)->width/2, (*pResultImageColor)->height/2), cvSize((*pResultImageColor)->width/2, (*pResultImageColor)->height/2), 0, 0, 360.0, cvScalar(0,0,255), 1);
|
cvEllipse((*pResultImageColor), cvPoint((*pResultImageColor)->width/2, (*pResultImageColor)->height/2), cvSize((*pResultImageColor)->width/2-nOffset, (*pResultImageColor)->height/2-nOffset), 0, 0, 360.0, cvScalar(255,0,0), 1);
|
|
for(int i=0; i<(int)vecDefectList.size(); i++)
|
cvDrawRect((*pResultImageColor), cvPoint(vecDefectList[i].left, vecDefectList[i].top), cvPoint(vecDefectList[i].right, vecDefectList[i].bottom), cvScalar(0,255,0));
|
}
|
|
return Ret_Success;
|
}
|