#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& 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& 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; iheight; 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; iheight; i++) { for(int j=0; jwidth; 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; }