#include "StdAfx.h" #include "CHImageProcess.h" #include "CHDataFitting.h" #include "NCC.h" #include #include "OpenCV/cv.h" #include "OpenCV/highgui.h" using namespace CHImageControls; inline bool CompareAvgPeak(SDefectBlob& a, SDefectBlob& b) { return (a.GetAvgPeak() > b.GetAvgPeak()); } CCHImageProcess::CCHImageProcess(void) { } CCHImageProcess::~CCHImageProcess(void) { } int CCHImageProcess::ImageMinMax(CCHImageData* pSourceImage, double& dMinValue, double& dMaxValue) { if (pSourceImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; dMinValue = 0.0; dMaxValue = 0.0; cvMinMaxLoc(pSourceImage->GetIplImage(), &dMinValue, &dMaxValue, NULL, NULL, NULL); return ResultSuccess; } int CCHImageProcess::ImageAverage(CCHImageData* pSourceImage, double& dValue) { if (pSourceImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; CvScalar sValue = cvAvg(pSourceImage->m_pImageData); dValue = sValue.val[0]; return ResultSuccess; } int CCHImageProcess::ImageConvert(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nConvertCode) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; switch(nConvertCode) { case ConvertTypeGray2RGB: if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), 3)) return FALSE; cvCvtColor(pSourceImage->m_pImageData, pResultImage->m_pImageData, CV_GRAY2BGR); return ResultSuccess; case ConvertTypeRGB2Gray: if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), 1)) return FALSE; cvCvtColor(pSourceImage->m_pImageData, pResultImage->m_pImageData, CV_BGR2GRAY); return ResultSuccess; } return ResultImageNoExist; } int CCHImageProcess::ImageThreshold(CCHImageData* pSourceImage, CCHImageData* pResultImage, double dThresholdValue, double dMaxValue, int nThresholdType) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), 8, 1)) return ResultFail; cvThreshold(pSourceImage->m_pImageData, pResultImage->m_pImageData, dThresholdValue, dMaxValue, nThresholdType); return ResultSuccess; } int CCHImageProcess::ImageResize(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nNewWidth, int nNewHeight, int nInterpolation) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; BOOL bNotAlloc = TRUE; bNotAlloc = bNotAlloc & (nNewWidth==pResultImage->GetWidth()); bNotAlloc = bNotAlloc & (nNewHeight==pResultImage->GetHeight()); bNotAlloc = bNotAlloc & (pSourceImage->GetDepth()==pResultImage->GetDepth()); bNotAlloc = bNotAlloc & (pSourceImage->GetChannels()==pResultImage->GetChannels()); if (bNotAlloc==FALSE) { if (!pResultImage->CreateImage(nNewWidth, nNewHeight, pSourceImage->GetDepth(), pSourceImage->GetChannels())) { return ResultFail; } } cvResize(pSourceImage->m_pImageData, pResultImage->m_pImageData, nInterpolation); return ResultSuccess; } int CCHImageProcess::ImageResize(CCHImageData* pSourceImage, CCHImageData* pResultImage, double dScale, int nInterpolation) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; int nNewWidth = int(double(pSourceImage->GetWidth()) * dScale); int nNewHeight = int(double(pSourceImage->GetHeight()) * dScale); if (!pResultImage->CreateImage(nNewWidth, nNewHeight, pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultFail; cvResize(pSourceImage->m_pImageData, pResultImage->m_pImageData, nInterpolation); return ResultSuccess; } int CCHImageProcess::ImageFlip(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nFlipMode) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvFlip(pSourceImage->m_pImageData, pResultImage->m_pImageData, nFlipMode); return ResultSuccess; } int CCHImageProcess::ImageErode(CCHImageData* pSourceImage, CCHImageData* pResultImage, IplConvKernel* pElement, int nIterations) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvErode(pSourceImage->m_pImageData, pResultImage->m_pImageData, pElement, nIterations); return ResultSuccess; } int CCHImageProcess::ImageDilate(CCHImageData* pSourceImage, CCHImageData* pResultImage, IplConvKernel* pElement, int nIterations) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvDilate(pSourceImage->m_pImageData, pResultImage->m_pImageData, pElement, nIterations); return ResultSuccess; } int CCHImageProcess::ImageOpening(CCHImageData* pSourceImage, CCHImageData* pResultImage, IplConvKernel* pElement, int nIterations) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvMorphologyEx(pSourceImage->m_pImageData, pResultImage->m_pImageData, pElement, pElement, CV_MOP_OPEN, nIterations); return ResultSuccess; } int CCHImageProcess::ImageClosing(CCHImageData* pSourceImage, CCHImageData* pResultImage, IplConvKernel* pElement, int nIterations) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvMorphologyEx(pSourceImage->m_pImageData, pResultImage->m_pImageData, pElement, pElement, CV_MOP_CLOSE, nIterations); return ResultSuccess; } int CCHImageProcess::ImageRotate(CCHImageData* pSourceImage, CCHImageData* pResultImage, double dAngle, int nFlag, UCHAR nValue ) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; CvMat *pRotationMatrix = cvCreateMat(2, 3, CV_32FC1); CvPoint2D32f centerPos; centerPos.x = float(pSourceImage->GetWidth())/2.f; centerPos.y = float(pSourceImage->GetHeight())/2.f; cv2DRotationMatrix(centerPos, dAngle, 1.0, pRotationMatrix); CvScalar fillval=cvScalarAll(nValue); cvWarpAffine(pSourceImage->m_pImageData, pResultImage->m_pImageData, pRotationMatrix, nFlag, fillval); cvReleaseMat(&pRotationMatrix); return ResultSuccess; } int CCHImageProcess::ImageRotate(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nRotateType) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; int nSrcWidth = pSourceImage->GetWidth(); int nSrcHeight = pSourceImage->GetHeight(); if (!pResultImage->CreateImage(nSrcHeight, nSrcWidth, pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvTranspose(pSourceImage->m_pImageData, pResultImage->m_pImageData); switch(nRotateType) { case RotateTypeRight: cvFlip(pResultImage->m_pImageData, NULL, 1); break; case RotateTypeLeft: cvFlip(pResultImage->m_pImageData, NULL, 0); break; default: return ResultImageNoExist; } return ResultSuccess; } int CCHImageProcess::ImageSmooth(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nSmoothType, int nSize1, int nSize2, double dSigma1, double dSigma2) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; cvSmooth(pSourceImage->m_pImageData, pResultImage->m_pImageData, nSmoothType, nSize1, nSize2, dSigma1, dSigma2); return ResultSuccess; } int CCHImageProcess::ImageNormalize(CCHImageData* pSourceImage, CCHImageData* pResultImage, double dMin, double dMax, int nType) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; CCHImageData tmpImage; if (!tmpImage.CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, pSourceImage->GetChannels())) return ResultImageNoExist; cvNormalize(pSourceImage->m_pImageData, tmpImage.m_pImageData, dMin, dMax, nType); if (!pResultImage->CreateImage(tmpImage.GetWidth(), tmpImage.GetHeight(), IPL_DEPTH_8U, tmpImage.GetChannels())) return ResultImageNoExist; cvCvtScaleAbs(tmpImage.m_pImageData, pResultImage->m_pImageData); return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, CCHImageData* pResultImage, int nMethod) { if (pSourceImage==NULL || pTemplateImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist() || !pTemplateImage->GetImageExist()) return ResultImageNoExist; if (pResultImage==NULL) return ResultImageNoExist; int nSrcWidth = pSourceImage->GetWidth(); int nSrcHeight = pSourceImage->GetHeight(); int nTmpWidth = pTemplateImage->GetWidth(); int nTmpHeight = pTemplateImage->GetHeight(); int nWidth = nSrcWidth - nTmpWidth + 1; int nHeight = nSrcHeight - nTmpHeight + 1; if (nWidth<1 || nHeight<1) return FALSE; if (!pResultImage->CreateImage(nWidth, nHeight, IPL_DEPTH_32F, 1)) return ResultImageNoExist; cvMatchTemplate(pSourceImage->m_pImageData, pTemplateImage->m_pImageData, pResultImage->m_pImageData, nMethod); return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, CRect& rtROIRegion, CCHImageData* pResultImage, int nMethod) { if (pSourceImage==NULL || pTemplateImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist() || !pTemplateImage->GetImageExist()) return ResultImageNoExist; int nTmpWidth = pTemplateImage->GetWidth() / 2; int nTmpHeight = pTemplateImage->GetHeight() / 2; rtROIRegion.left = (rtROIRegion.left<0) ? 0: rtROIRegion.left; rtROIRegion.top = (rtROIRegion.top<0) ? 0: rtROIRegion.top; rtROIRegion.right = (rtROIRegion.right>pSourceImage->GetWidth()) ? pSourceImage->GetWidth(): rtROIRegion.right; rtROIRegion.bottom = (rtROIRegion.bottom>pSourceImage->GetHeight()) ? pSourceImage->GetHeight(): rtROIRegion.bottom; if (rtROIRegion.Width() < pTemplateImage->GetWidth() || rtROIRegion.Height() < pTemplateImage->GetHeight()) { return ResultImageNoExist; } CvRect orgROI = cvGetImageROI(pSourceImage->m_pImageData); cvSetImageROI(pSourceImage->m_pImageData, cvRect(rtROIRegion.left, rtROIRegion.top, rtROIRegion.Width(), rtROIRegion.Height())); int nSrcWidth = rtROIRegion.Width(); int nSrcHeight = rtROIRegion.Height(); nTmpWidth = pTemplateImage->GetWidth(); nTmpHeight = pTemplateImage->GetHeight(); int nWidth = nSrcWidth - nTmpWidth + 1; int nHeight = nSrcHeight - nTmpHeight + 1; if (nWidth<1 || nHeight<1) return ResultImageNoExist; if (!pResultImage->CreateImage(nWidth, nHeight, IPL_DEPTH_32F, 1)) return ResultImageNoExist; cvMatchTemplate(pSourceImage->m_pImageData, pTemplateImage->m_pImageData, pResultImage->m_pImageData, nMethod); cvSetImageROI(pSourceImage->m_pImageData, orgROI); rtROIRegion = rtROIRegion; return ResultSuccess; } void GetBestPosition(int nMethod, CCHImageData *pResult, int& nResultX, int& nResultY, double& dResultValue) { double dMinValue = 0.0; double dMaxValue = 0.0; CvPoint ptMinPos; CvPoint ptMaxPos; cvMinMaxLoc(pResult->GetIplImage(), &dMinValue, &dMaxValue, &ptMinPos, &ptMaxPos, NULL); switch(nMethod) { case CV_TM_SQDIFF: nResultX = ptMinPos.x; nResultY = ptMinPos.y; dResultValue = dMinValue; break; case CV_TM_SQDIFF_NORMED: nResultX = ptMinPos.x; nResultY = ptMinPos.y; dResultValue = dMinValue; break; case CV_TM_CCORR: nResultX = ptMaxPos.x; nResultY = ptMaxPos.y; dResultValue = dMaxValue; break; case CV_TM_CCORR_NORMED: nResultX = ptMaxPos.x; nResultY = ptMaxPos.y; dResultValue = dMaxValue; break; case CV_TM_CCOEFF: nResultX = ptMaxPos.x; nResultY = ptMaxPos.y; dResultValue = dMaxValue; break; case CV_TM_CCOEFF_NORMED: nResultX = ptMaxPos.x; nResultY = ptMaxPos.y; dResultValue = dMaxValue; break; } } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, int& nResultX, int& nResultY, double& dResultValue, int nMethod) { CCHImageData resultImage; nResultX = nResultY = 0; dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, &resultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; GetBestPosition(nMethod, &resultImage, nResultX, nResultY, dResultValue); resultImage.ReleaseImage(); return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, int& nResultX, int& nResultY, double& dResultValue, CCHImageData* pResultImage, int nMethod) { nResultX = nResultY = 0; dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, pResultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; GetBestPosition(nMethod, pResultImage, nResultX, nResultY, dResultValue); return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, CRect& rtROIRegion, int& nResultX, int& nResultY, double& dResultValue, int nMethod) { CCHImageData resultImage; nResultX = nResultY = 0; dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, rtROIRegion, &resultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; GetBestPosition(nMethod, &resultImage, nResultX, nResultY, dResultValue); resultImage.ReleaseImage(); return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, CRect& rtROIRegion, int& nResultX, int& nResultY, double& dResultValue, CCHImageData* pResultImage, int nMethod) { nResultX = nResultY = 0; dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, rtROIRegion, pResultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; GetBestPosition(nMethod, pResultImage, nResultX, nResultY, dResultValue); return ResultSuccess; } typedef std::vector VectorDouble; typedef std::vector::iterator VectorDoubleIt; BOOL CalculatePosition(int nSubPixel, CCHImageData *pResult, int nResultX, int nResultY, double& dResultX, double& dResultY, double& dResultValue) { int nWidth = pResult->GetWidth(); int nHeight = pResult->GetHeight(); // check result if (nResultX<1 || nResultX>(nWidth-2)) { dResultX = nResultX; dResultY = nResultY; return TRUE; } if (nResultY<1 || nResultY>(nHeight-2)) { dResultX = nResultX; dResultY = nResultY; return TRUE; } // result image pointer float *pResultBuffer = (float*) pResult->GetImageBuffer(); int nWidthStep = pResult->GetWidthStep() / 4; double vectorX[3] = { -1, 0, 1 }; double vectorY[3] = { 0, 0, 0 }; // x axis vectorY[0] = pResultBuffer[(nResultY*nWidthStep)+(nResultX-1)]; vectorY[1] = dResultValue; vectorY[2] = pResultBuffer[(nResultY*nWidthStep)+(nResultX+1)]; double vectorResultX[3] = { 0, 0, 0 }; if (CCHDataFitting::PolynomialFitting(vectorX, vectorY, 3, vectorResultX, 2)!=1) { return FALSE; } // y axis vectorY[0] = pResultBuffer[((nResultY-1)*nWidthStep)+nResultX]; vectorY[1] = dResultValue; vectorY[2] = pResultBuffer[((nResultY+1)*nWidthStep)+nResultX]; double vectorResultY[3] = { 0, 0, 0 }; if (CCHDataFitting::PolynomialFitting(vectorX, vectorY, 3, vectorResultY, 2)<1) { return FALSE; } dResultX = (nResultX-1) + (-1.0 * vectorResultX[1]) / (2.0 * vectorResultX[2]); dResultY = (nResultY-1) + (-1.0 * vectorResultY[1]) / (2.0 * vectorResultY[2]); dResultValue = -1.0 * ( ( (vectorResultX[1]*vectorResultX[1]) - (4.0 * vectorResultX[2] * vectorResultX[0]) ) / (4.0 * vectorResultX[2]) ); dResultValue += -1.0 * ( ( (vectorResultY[1]*vectorResultY[1]) - (4.0 * vectorResultY[2] * vectorResultY[0]) ) / (4.0 * vectorResultY[2]) ); dResultValue /= 2.0; return TRUE; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, double& dResultX, double& dResultY, double& dResultValue, int nMethod, int nSubPixel) { CCHImageData resultImage; dResultX = dResultY = dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, &resultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; int nResultX, nResultY; GetBestPosition(nMethod, &resultImage, nResultX, nResultY, dResultValue); if (!CalculatePosition(nSubPixel, &resultImage, nResultX, nResultY, dResultX, dResultY, dResultValue)) return ResultFail; return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, double& dResultX, double& dResultY, double& dResultValue, CCHImageData* pResultImage, int nMethod, int nSubPixel) { dResultX = dResultY = dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, pResultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; int nResultX, nResultY; GetBestPosition(nMethod, pResultImage, nResultX, nResultY, dResultValue); if (!CalculatePosition(nSubPixel, pResultImage, nResultX, nResultY, dResultX, dResultY, dResultValue)) return ResultFail; return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, CRect& rtROIRegion, double& dResultX, double& dResultY, double& dResultValue, int nMethod, int nSubPixel) { CCHImageData resultImage; dResultX = dResultY = dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, rtROIRegion, &resultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; int nResultX, nResultY; GetBestPosition(nMethod, &resultImage, nResultX, nResultY, dResultValue); if (!CalculatePosition(nSubPixel, &resultImage, nResultX, nResultY, dResultX, dResultY, dResultValue)) return ResultFail; return ResultSuccess; } int CCHImageProcess::ImageMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, CRect& rtROIRegion, double& dResultX, double& dResultY, double& dResultValue, CCHImageData* pResultImage, int nMethod, int nSubPixel) { dResultX = dResultY = dResultValue = 0.0; int nResultCode = ImageMatching(pSourceImage, pTemplateImage, rtROIRegion, pResultImage, nMethod); if (nResultCode!=ResultSuccess) return nResultCode; int nResultX, nResultY; GetBestPosition(nMethod, pResultImage, nResultX, nResultY, dResultValue); if (!CalculatePosition(nSubPixel, pResultImage, nResultX, nResultY, dResultX, dResultY, dResultValue)) return ResultFail; return ResultSuccess; } int CCHImageProcess::ImageLocalConvolution(CCHImageData* pSourceImage, CCHImageData* pVertImage, CCHImageData* pHoriImage, int nPitchX, int nPitchY, int& nPosX, int& nPosY) { nPosX = nPosY = -1; if (pSourceImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; CvRect orgROI = cvGetImageROI(pSourceImage->m_pImageData); CCHImageData bandImage, *pProcImage = pSourceImage; if (pSourceImage->GetChannels()!=1) { if (!pSourceImage->GetBandImage(BandTypeGray, &bandImage)) return ResultImageNoExist; pProcImage = &bandImage; } int nWidth = pProcImage->GetWidth(); int nHeight = pProcImage->GetHeight(); int nHalfWidth = nWidth / 2; int nHalfHeight = nHeight / 2; CCHImageData tempResult; double dMinValue; CvScalar scalar; if (pVertImage!=NULL && nPitchX>0) { nPosX = -1; CCHImageData vertImg; double dMinValue = DBL_MAX; pProcImage->GetSubImage(nHalfWidth, 0, nHalfWidth, nHeight, &vertImg); tempResult.ReleaseImage(); tempResult.CreateImage(nHalfWidth, nHeight); for (int i=0; im_pImageData, cvRect(i, 0, nHalfWidth, nHeight)); cvAbsDiff(pProcImage->m_pImageData, vertImg.m_pImageData, tempResult.m_pImageData); scalar = cvAvg(tempResult.m_pImageData); if (dMinValue>scalar.val[0]) { nPosX = i; dMinValue = scalar.val[0]; tempResult.CopyImageTo(pVertImage); } } } if (pHoriImage!=NULL && nPitchY>0) { nPosY = -1; CCHImageData horiImg; dMinValue = DBL_MAX; pProcImage->GetSubImage(0, nHalfHeight, nWidth, nHalfHeight, &horiImg); tempResult.ReleaseImage(); tempResult.CreateImage(nWidth, nHalfHeight); for (int i=0; im_pImageData, cvRect(0, i, nWidth, nHalfHeight)); cvAbsDiff(pProcImage->m_pImageData, horiImg.m_pImageData, tempResult.m_pImageData); scalar = cvAvg(tempResult.m_pImageData); if (dMinValue>scalar.val[0]) { nPosY = i; dMinValue = scalar.val[0]; tempResult.CopyImageTo(pHoriImage); } } } cvSetImageROI(pSourceImage->m_pImageData, orgROI); if (pVertImage==NULL && pHoriImage==NULL) ResultImageNoExist; return ResultSuccess; // CCHImageProcess::ImageThreshold(&vertResult, &vertThres, nThres, 255, CV_THRESH_BINARY); // CCHImageProcess::ImageThreshold(&horiResult, &horiThres, nThres, 255, CV_THRESH_BINARY); // // left top // cvSetImageROI(vertResult.m_pImageData, cvRect(0, 0, nHalfWidth, nHalfHeight)); // top // cvSetImageROI(horiResult.m_pImageData, cvRect(0, 0, nHalfWidth, nHalfHeight)); // left // cvSetImageROI(pResultImage->m_pImageData, cvRect(0, 0, nHalfWidth, nHalfHeight)); // cvAnd(vertResult.m_pImageData, horiResult.m_pImageData, pResultImage->m_pImageData); // // // left bottom // cvSetImageROI(vertResult.m_pImageData, cvRect(0, nHalfHeight, nHalfWidth, nHalfHeight)); // bottom // cvSetImageROI(horiResult.m_pImageData, cvRect(0, 0, nHalfWidth, nHalfHeight)); // left // cvSetImageROI(pResultImage->m_pImageData, cvRect(0, nHalfHeight, nHalfWidth, nHalfHeight)); // cvAnd(vertResult.m_pImageData, horiResult.m_pImageData, pResultImage->m_pImageData); // // // right top // cvSetImageROI(vertResult.m_pImageData, cvRect(0, 0, nHalfWidth, nHalfHeight)); // top // cvSetImageROI(horiResult.m_pImageData, cvRect(nHalfWidth, 0, nHalfWidth, nHalfHeight)); // right // cvSetImageROI(pResultImage->m_pImageData, cvRect(nHalfWidth, 0, nHalfWidth, nHalfHeight)); // cvAnd(vertResult.m_pImageData, horiResult.m_pImageData, pResultImage->m_pImageData); // // // right bottom // cvSetImageROI(vertResult.m_pImageData, cvRect(0, nHalfHeight, nHalfWidth, nHalfHeight)); // bottom // cvSetImageROI(horiResult.m_pImageData, cvRect(nHalfWidth, 0, nHalfWidth, nHalfHeight)); // right // cvSetImageROI(pResultImage->m_pImageData, cvRect(nHalfWidth, nHalfHeight, nHalfWidth, nHalfHeight)); // cvAnd(vertResult.m_pImageData, horiResult.m_pImageData, pResultImage->m_pImageData); // // cvSetImageROI(vertResult.m_pImageData, cvRect(0, 0, nHalfWidth, nHeight)); // cvSetImageROI(horiResult.m_pImageData, cvRect(0, 0, nWidth, nHalfHeight)); // cvSetImageROI(pResultImage->m_pImageData, cvRect(0, 0, nWidth, nHeight)); // cvSetImageROI(pSourceImage->m_pImageData, orgROI); // vertThres.SaveImage(_T("d:\\vertImage.bmp")); // horiThres.SaveImage(_T("d:\\horiImage.bmp")); //pResultImage->SaveImage(_T("d:\\resultImage.bmp")); return ResultSuccess; } int CCHImageProcess::ImageIntegral(CCHImageData* pSourceImage, CCHImageData* pResultImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; int nWidth = pSourceImage->GetWidth(); int nHeight = pSourceImage->GetHeight(); if (!pResultImage->CreateImage(nWidth, nHeight, IPL_DEPTH_32S, 1)) return ResultImageNoExist; BYTE* image = (BYTE*)pSourceImage->GetImageBuffer(); int* integral = (int*)pResultImage->GetImageBuffer(); int nSum = 0; for(int xs=0; xsGetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; int nWidth = pSourceImage->GetWidth(); int nHeight = pSourceImage->GetHeight(); int nWidthStep = pSourceImage->GetWidthStep(); if (!pResultImage->CreateImage(nWidth, nHeight, 8, 1)) return ResultImageNoExist; pResultImage->ClearImage(0); int nKernelW = nKernelSizeW / 2; int nKernelH = nKernelSizeH / 2; int nDivValue = nKernelSizeW * nKernelSizeH; int *pIntImage = new int[nWidth*nHeight]; BYTE *pSrc = (BYTE*) pSourceImage->GetImageBuffer(); BYTE *pRes = (BYTE*) pResultImage->GetImageBuffer(); int *pInt = pIntImage; Get_Sum_Map(pSrc, pInt, nWidth, nHeight); pSrc += ((nKernelH+1)*nWidthStep) + (nKernelW+1); pRes += ((nKernelH+1)*nWidthStep) + (nKernelW+1); int nKernelWLength = (nKernelW*2)+1; int nKernelHLength = ((nKernelH*2+1)*nWidth); int nYIdx=0; int nValue; BYTE *pResult, *pSource; int *pLeftTop, *pLeftBottom, *pRightTop, *pRightBottom; for (int i=(nKernelH+1); iGetWidth(); int nHeight = pImageData->GetHeight(); int nCenterX = nWidth/2; int nCenterY = nHeight/2; ptResult = CPoint(nCenterX, nCenterY); // vertical x, horizontal y int nPosX, nPosY; CCHImageData vertImage, horiImage; CCHImageData *pVertImage = (nPitchX<1) ? NULL: &vertImage; CCHImageData *pHoriImage = (nPitchY<1) ? NULL: &horiImage; if (CCHImageProcess::ImageLocalConvolution(pImageData, pVertImage, pHoriImage, nPitchX, nPitchY, nPosX, nPosY)!=1) { return 0; } VectorDefectBlob resultDefectBlob; // vertical x (peak °ªÀÌ Á¦ÀÏÅ« blob n°³) if (pVertImage && nPosX>-1) { VectorDefectBlob vertDefectBlob; int nLocalWidth = pVertImage->GetWidth(); int nLocalHeight = pVertImage->GetHeight(); int nDefectCount = ImageBlobAnalysis4FindDefect((BYTE*)pVertImage->GetImageBuffer(), nLocalWidth, nLocalHeight, nThreshold, nBlobMargin, nPosX, 0, vertDefectBlob); for (int i=0; i-1) { VectorDefectBlob horiDefectBlob; int nLocalWidth = pHoriImage->GetWidth(); int nLocalHeight = pHoriImage->GetHeight(); int nDefectCount = ImageBlobAnalysis4FindDefect((BYTE*)pHoriImage->GetImageBuffer(), nLocalWidth, nLocalHeight, nThreshold, nBlobMargin, 0, nPosY, horiDefectBlob); for (int i=0; iGetCenterX()-nCenterX)*(it->GetCenterX()-nCenterX) + (it->GetCenterY()-nCenterY)*(it->GetCenterY()-nCenterY); if (dMinDistance > dTempDistance) { ptResult.x = it->GetCenterX(); ptResult.y = it->GetCenterY(); dMinDistance = dTempDistance; } } return 1; } int CCHImageProcess::ImageBlobAnalysis4FindDefect(BYTE *pImage, int nWidth, int nHeight, int nThreshold, int nBlobMargin, int nStartX, int nStartY, VectorDefectBlob& vectorBlob) { 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 vectorPixel; SDefectBlob pixelBlob; register BYTE *pSrcImgY = pImage + (nBlobMargin*nWidth) + nBlobMargin; register BYTE *pSrcImgX, *pSubX, *pSubY; int nBlobMin = -nBlobMargin; int nBlobMax = nBlobMargin+1; for (i=nBlobMargin; i=nThreshold && *pSrcImgX!=255) { // new pixel blob pixelBlob.Reset(); pixelBlob.nPeak += *pSrcImgX; // add peak pixelBlob.nCount++; *pSrcImgX = 255; vectorPixel.push_back(CPoint(j, i)); 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= nThreshold && *pSubX!=255) { pixelBlob.nPeak += *pSubX; // add peak pixelBlob.nCount++; *pSubX = 255; vectorPixel.push_back(CPoint(x+sx, y+sy)); } pSubX++; } pSubY += nWidth; } if (pixelBlob.nLeft>x) pixelBlob.nLeft = x; if (pixelBlob.nRighty) pixelBlob.nTop = y; if (pixelBlob.nBottomGetImageExist()) return ResultImageNoExist; CCHImageData bandImage, *pProcImage = pSourceImage; if (pSourceImage->GetChannels()!=1) { if (!pSourceImage->GetBandImage(BandTypeGray, &bandImage)) return ResultImageNoExist; pProcImage = &bandImage; } int nWidth = pProcImage->GetWidth(); int nHeight = pProcImage->GetHeight(); if (!pResultImage->CreateImage(nWidth, nHeight, IPL_DEPTH_16S, 1)) return ResultImageNoExist; int nSubStartX, nSubStartY; switch(nKernelX) { case 2: nSubStartX = 0; break; case 3: nSubStartX = 1; break; case 4: nSubStartX = 2; break; case 5: nSubStartX = 2; break; default: return -1; } switch(nKernelY) { case 2: nSubStartY = 0; break; case 3: nSubStartY = 1; break; case 4: nSubStartY = 2; break; case 5: nSubStartY = 2; break; default: return -1; } BYTE *pImage = (BYTE*) pProcImage->GetImageBuffer(); short *pResult = (short*) pResultImage->GetImageBuffer(); int nStep = pResultImage->GetWidthStep() / 2; BYTE *pImageY = pImage + (nTop*nWidth) + (nLeft); short *pResultY = pResult + (nTop*nWidth) + nLeft; BYTE *pImageX, *pSubY, *pSubX; short *pResultX; static int nStartPos = (nSubStartY*nWidth) + nSubStartX; __m128i MinThresData = _mm_set1_epi16(-(nThres*nKernelX*nKernelY)); __m128i MaxThresData = _mm_set1_epi16((nThres*nKernelX*nKernelY)); __m128i ZeroData = _mm_setzero_si128(); __m128i CurrentData = _mm_setzero_si128(); __m128i DirMaskLow = _mm_setzero_si128(); __m128i DirMaskHigh = _mm_setzero_si128(); __m128i ResultLow = _mm_setzero_si128(); __m128i ResultHigh = _mm_setzero_si128(); __m128i LeftResultLow = _mm_setzero_si128(); __m128i LeftResultHigh = _mm_setzero_si128(); __m128i RightResultLow = _mm_setzero_si128(); __m128i RightResultHigh = _mm_setzero_si128(); __m128i TempData = _mm_setzero_si128(); for (int y=nTop; y 16bit] TempData = _mm_unpackhi_epi8(CurrentData, ZeroData); // high ResultHigh = _mm_add_epi16(ResultHigh, TempData); // high TempData = _mm_unpacklo_epi8(CurrentData, ZeroData); // low ResultLow = _mm_add_epi16(ResultLow, TempData); // low // get left pitch image [8bit x 16ea] CurrentData = _mm_loadu_si128((__m128i*)(pSubX-nPitch)); // unpack and add[8bit => 16bit] TempData = _mm_unpackhi_epi8(CurrentData, ZeroData); // high LeftResultHigh = _mm_add_epi16(LeftResultHigh, TempData); // high TempData = _mm_unpacklo_epi8(CurrentData, ZeroData); // low LeftResultLow = _mm_add_epi16(LeftResultLow, TempData); // low // get right pitch image [8bit x 16ea] CurrentData = _mm_loadu_si128((__m128i*)(pSubX+nPitch)); // unpack and add[8bit => 16bit] TempData = _mm_unpackhi_epi8(CurrentData, ZeroData); // high RightResultHigh = _mm_add_epi16(RightResultHigh, TempData); // high TempData = _mm_unpacklo_epi8(CurrentData, ZeroData); // low RightResultLow = _mm_add_epi16(RightResultLow, TempData); // low pSubX++; } pSubY += nWidth; } // (current - left) LeftResultHigh = _mm_sub_epi16(ResultHigh, LeftResultHigh); LeftResultLow = _mm_sub_epi16(ResultLow, LeftResultLow); // (current - right) RightResultHigh = _mm_sub_epi16(ResultHigh, RightResultHigh); RightResultLow = _mm_sub_epi16(ResultLow, RightResultLow); // compare left LeftResultHigh = _mm_or_si128(_mm_cmplt_epi16(LeftResultHigh, MinThresData), _mm_cmpgt_epi16(LeftResultHigh, MaxThresData)); LeftResultLow = _mm_or_si128(_mm_cmplt_epi16(LeftResultLow, MinThresData), _mm_cmpgt_epi16(LeftResultLow, MaxThresData)); // compare right RightResultHigh = _mm_or_si128(_mm_cmplt_epi16(RightResultHigh, MinThresData), _mm_cmpgt_epi16(RightResultHigh, MaxThresData)); RightResultLow = _mm_or_si128(_mm_cmplt_epi16(RightResultLow, MinThresData), _mm_cmpgt_epi16(RightResultLow, MaxThresData)); // left & right (pair) ResultHigh = _mm_and_si128(RightResultHigh, LeftResultHigh); ResultLow = _mm_and_si128(RightResultLow, LeftResultLow); // result save _mm_storeu_si128((__m128i*)(pResultX), ResultLow); _mm_storeu_si128((__m128i*)(pResultX+8), ResultHigh); pImageX += 16; pResultX += 16; } pImageY += nWidth; pResultY += nStep; } return ResultSuccess; } int CCHImageProcess::ImageFastMatching(CCHImageData* pSourceImage, CCHImageData* pTemplateImage, int& nResultX, int& nResultY, double& dResultValue) { if (pSourceImage==NULL || pTemplateImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist() || !pTemplateImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1 || pTemplateImage->GetChannels()!=1) return ResultImageNoExist; unsigned char* pSrcBuffer = (unsigned char*) pSourceImage->GetImageBuffer(); int nSrcWidth = pSourceImage->GetWidth(); int nSrcHeight = pSourceImage->GetHeight(); unsigned char* pTmpBuffer = (unsigned char*) pTemplateImage->GetImageBuffer(); int nTmpWidth = pTemplateImage->GetWidth(); int nTmpHeight = pTemplateImage->GetHeight(); int xx,yy; double NCC_value = Adaptive_WUS(pSrcBuffer, nSrcWidth, nSrcHeight, pTmpBuffer, nTmpWidth, nTmpHeight, xx, yy); nResultX = xx; nResultY = yy; dResultValue = NCC_value; return ResultSuccess; } int CCHImageProcess::ImageDCT(CCHImageData* pSourceImage, CCHImageData* pResultImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultFail; IplImage *source = cvCreateImage(cvGetSize(pSourceImage->m_pImageData), IPL_DEPTH_32F, 1); IplImage *freq = cvCreateImage(cvGetSize(pSourceImage->m_pImageData), IPL_DEPTH_32F, 1); //cvConvertScale(pSourceImage->m_pImageData, source, 1, 0); cvNormalize(pSourceImage->m_pImageData, source, 255, 0); cvShowImage("src1", source); cvDCT(source, freq, CV_DXT_FORWARD); cvNormalize(freq, pResultImage->m_pImageData, 0, 255, CV_MINMAX); cvReleaseImage(&source); cvReleaseImage(&freq); return ResultSuccess; } int CCHImageProcess::ImageInvertDCT(CCHImageData* pSourceImage, CCHImageData* pResultImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultFail; cvDCT(pSourceImage->m_pImageData, pResultImage->m_pImageData, CV_DXT_INVERSE); return ResultSuccess; } int CCHImageProcess::ImageEqualizeHist(CCHImageData* pSourceImage, CCHImageData* pResultImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultFail; cvEqualizeHist(pSourceImage->m_pImageData, pResultImage->m_pImageData); return ResultSuccess; } int CCHImageProcess::ImagePreCornerDetect(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nApertureSize) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; IplImage *tmpImage = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_32F, 1); cvPreCornerDetect(pSourceImage->m_pImageData, tmpImage, nApertureSize); cvConvertScaleAbs(tmpImage, pResultImage->m_pImageData, 255, 0); cvReleaseImage(&tmpImage); return ResultSuccess; } int CCHImageProcess::ImageCanny(CCHImageData* pSourceImage, CCHImageData* pResultImage, double dThreshold1, double dThreshold2, int nApertureSize) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; cvCanny(pSourceImage->m_pImageData, pResultImage->m_pImageData, dThreshold1, dThreshold2, nApertureSize); return ResultSuccess; } int CCHImageProcess::ImageAdd( CCHImageData* pAImage, CCHImageData* pBImage, CCHImageData* pCImage ) { if (pAImage==NULL || pBImage==NULL || pCImage==NULL) return ResultImageNULL; if (!pAImage->GetImageExist()) return ResultImageNoExist; if (!pBImage->GetImageExist()) return ResultImageNoExist; if (!pCImage->CreateImage(pAImage->GetWidth(), pAImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; cvAddWeighted(pAImage->m_pImageData, 0.5, pBImage->m_pImageData, 0.5, 0.0, pCImage->m_pImageData); return ResultSuccess; } int CCHImageProcess::ImageAnd(CCHImageData* pSourceImage, CCHImageData* pMaskImage, CCHImageData* pResultImage) { if (pSourceImage==NULL || pResultImage==NULL || pMaskImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; cvAnd(pSourceImage->m_pImageData, pResultImage->m_pImageData, pMaskImage->m_pImageData); return ResultSuccess; } int CCHImageProcess::ImageHoughLines2(CCHImageData* pSourceImage, int nMethod, double dRho, double dTheta, int nThreshold, double dParam1, double dParam2, VectorLineData& vectorLineData) { if (pSourceImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* lines = 0; lines = cvHoughLines2( pSourceImage->m_pImageData, storage, nMethod, dRho, dTheta, nThreshold, dParam1, dParam2); for (int i=0; itotal; i++) { CvPoint *line = (CvPoint*) cvGetSeqElem(lines, i); CLineData lineData(line[0].x, line[0].y, line[1].x, line[1].y); vectorLineData.push_back(lineData); } cvReleaseMemStorage(&storage); return ResultSuccess; } int CCHImageProcess::ImageHoughCircles(CCHImageData* pSourceImage, int nMethod, double dDp, double dMinDist, double dParam1, double dParam2, int nMinRadius, int nMaxRadius, VectorCircleData& vectorCircleData) { if (pSourceImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (pSourceImage->GetChannels()!=1) return ResultImageNoExist; CvMemStorage* storage = cvCreateMemStorage(0); CvSeq *circles = cvHoughCircles(pSourceImage->m_pImageData, storage, nMethod, dDp, dMinDist, dParam1, dParam2, nMinRadius, nMaxRadius); CCircleData circleData; for (int i= 0; i < circles->total; i++) { float *p = (float *) cvGetSeqElem (circles, i); circleData.dCenterX = p[0]; circleData.dCenterY = p[1]; circleData.dRadius = p[2]; vectorCircleData.push_back(circleData); } cvReleaseMemStorage(&storage); return ResultSuccess; } int CCHImageProcess::ImageSobel(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nXOrder, int nYOrder, int nApertureSize) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; // only x if (nXOrder!=0 && nYOrder==0) { IplImage *tempImage = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_16S, 1); cvSobel(pSourceImage->m_pImageData, tempImage, nXOrder, 0, nApertureSize); cvConvertScaleAbs(tempImage, pResultImage->m_pImageData); cvReleaseImage(&tempImage); return ResultSuccess; } // only y if (nXOrder==0 && nYOrder!=0) { IplImage *tempImage = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_16S, 1); cvSobel(pSourceImage->m_pImageData, tempImage, 0, nYOrder, nApertureSize); cvConvertScaleAbs(tempImage, pResultImage->m_pImageData); cvReleaseImage(&tempImage); return ResultSuccess; } // x & y IplImage *xImage = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_8U, 1); IplImage *yImage = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_8U, 1); IplImage *tempImage = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_16S, 1); cvSobel(pSourceImage->m_pImageData, tempImage, nXOrder, 0, nApertureSize); cvConvertScaleAbs(tempImage, xImage, 0.5, 0); cvSobel(pSourceImage->m_pImageData, tempImage, 0, nYOrder, nApertureSize); cvConvertScaleAbs(tempImage, yImage, 0.5, 0); cvAdd(xImage, yImage, pResultImage->m_pImageData); cvReleaseImage(&xImage); cvReleaseImage(&yImage); cvReleaseImage(&tempImage); return ResultSuccess; } int CCHImageProcess::ImageSobel(CCHImageData* pSourceImage, CCHImageData* pXImage, CCHImageData* pYImage, int nApertureSize) { if (pSourceImage==NULL || pXImage==NULL || pYImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pXImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; if (!pYImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), IPL_DEPTH_8U, 1)) return ResultFail; IplImage *tmpImage1 = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_16S, 1); IplImage *tmpImage2 = cvCreateImage(cvSize(pSourceImage->GetWidth(), pSourceImage->GetHeight()), IPL_DEPTH_16S, 1); cvSobel(pSourceImage->m_pImageData, tmpImage2, 1, 0, nApertureSize); cvConvertScaleAbs(tmpImage2, pXImage->m_pImageData, 1, 0); cvSobel(pSourceImage->m_pImageData, tmpImage1, 0, 1, nApertureSize); cvConvertScaleAbs(tmpImage1, pYImage->m_pImageData, 1, 0); cvReleaseImage(&tmpImage1); cvReleaseImage(&tmpImage2); return ResultSuccess; } int CCHImageProcess::ImageAdaptiveThreshold(CCHImageData* pSourceImage, CCHImageData* pResultImage, double dMaxValue, int nMethodType, int nThresholdType, int nBlockSize, double dParam1) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), 8, 1)) return ResultFail; cvAdaptiveThreshold(pSourceImage->m_pImageData, pResultImage->m_pImageData, dMaxValue, nMethodType, nThresholdType, nBlockSize, dParam1); return ResultSuccess; } int GS_optimal_power(int num) { int result = 0; int tmp_num = num; while(tmp_num >= 2) { tmp_num = tmp_num >> 1; result++; } int powers = (int) pow(2.0, result); return (num != powers) ? (powers<<1): num; } int GS_check_power(int num) { int optimal_num = GS_optimal_power( num ); return (optimal_num == num) ? 0: -1; } int GS_check_log2N(int width, int height) { int width_log2N = GS_check_power( height ); int height_log2N = GS_check_power( height ); if (height_log2N == -1) return -1; if (width_log2N == -1) return -1; return 0; } IplImage *GS_forward_FFT2D(IplImage *src_image) { if (src_image==NULL) return NULL; int width = src_image->width; int height = src_image->height; if (src_image->nChannels!=1) return NULL; int checked = GS_check_log2N(width, height); if (checked==-1) return NULL; IplImage *spatial = cvCreateImage(cvGetSize(src_image), IPL_DEPTH_32F, 2); IplImage *real = cvCreateImage(cvGetSize(src_image), IPL_DEPTH_32F, 1); IplImage *imag = cvCreateImage(cvGetSize(src_image), IPL_DEPTH_32F, 1); IplImage *freq = cvCreateImage(cvGetSize(src_image), IPL_DEPTH_32F, 2); cvConvertScale(src_image, real, 1, 0); cvSetZero(imag); cvCvtPlaneToPix(real, imag, NULL, NULL, spatial); cvFFT(spatial, freq, CV_DXT_FORWARD); cvReleaseImage(&spatial); cvReleaseImage(&real); cvReleaseImage(&imag); return freq; } double GS_log(double x, double y) { return log(1 + sqrt(x*x + y*y)); } IplImage *GS_create_FFT_image(IplImage *freq, int method) { int i, j; double tmp; if (freq==NULL) return NULL; if (freq->nChannels!=2) return NULL; int width = freq->width; int height = freq->height; int checked = GS_check_log2N(width, height); if (checked==-1) return NULL; IplImage *real = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *imag = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); cvCvtPixToPlane(freq, real, imag, NULL, NULL); IplImage *norm = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); for (i=0; iimageData; cvMinMaxLoc(imag, &min_val, &max_val); cvNormalize(imag, test_normal, 0.0, 255.0, CV_MINMAX); cvCvtScaleAbs(test_normal, test_save); pValue = (float*) real->imageData; IplImage *dst_freq_image = cvCreateImage(cvGetSize(freq), IPL_DEPTH_8U, 1); IplImage *temp = cvCreateImage(cvGetSize(freq), IPL_DEPTH_8U, 1); cvNormalize(norm, temp, 0.0, 255.0, CV_MINMAX); cvCvtScaleAbs(temp, dst_freq_image); cvReleaseImage(&temp); if (method==0) return dst_freq_image; IplImage *dst_freq_center_image = cvCreateImage(cvGetSize(freq), IPL_DEPTH_8U, 1); for (i=0; i 4 cvSetReal2D(dst_freq_center_image, i+height/2 - 1, j+width/2 - 1, cvGetReal2D(dst_freq_image, i, j)); // 2 => 3 cvSetReal2D(dst_freq_center_image, i+height/2 - 1, j, cvGetReal2D(dst_freq_image, i, j+width/2 -1)); // 3 => 2 cvSetReal2D(dst_freq_center_image, i, j+width/2 - 1, cvGetReal2D(dst_freq_image, i+height/2-1, j)); // 4 => 1 cvSetReal2D(dst_freq_center_image, i, j, cvGetReal2D(dst_freq_image, i+height/2-1, j+width/2-1)); } } cvReleaseImage(&dst_freq_image); cvReleaseImage(&norm); cvReleaseImage(&real); cvReleaseImage(&imag); return dst_freq_center_image; } IplImage *GS_pre_zero_padding(IplImage *src_image) { int width = src_image->width; int height = src_image->height; if (src_image->nChannels!=1) return NULL; int pz_width = GS_optimal_power(width); int pz_height = GS_optimal_power(height); if (pz_height < pz_width) pz_height = pz_width; else pz_width = pz_height; CvSize pz_size = cvSize(pz_width, pz_height); IplImage *pz_src_image = cvCreateImage(pz_size, IPL_DEPTH_8U, 1); cvZero(pz_src_image); cvSetImageROI(pz_src_image, cvRect(0, 0, width, height)); cvCopy(src_image, pz_src_image); cvResetImageROI(pz_src_image); return pz_src_image; } IplImage *GS_post_zero_padding(IplImage *pz_src_image, int width, int height) { CvSize size = cvSize(width, height); IplImage *dst_image = cvCreateImage(size, IPL_DEPTH_8U, 1); cvSetImageROI(pz_src_image, cvRect(0, 0, width, height)); cvCopy(pz_src_image, dst_image); cvResetImageROI(pz_src_image); return dst_image; } int CCHImageProcess::ImageFFT(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nFlags, CCHImageData* pNormalImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; pResultImage->m_pImageData = GS_forward_FFT2D(GS_pre_zero_padding(pSourceImage->m_pImageData)); if (pResultImage->m_pImageData==NULL) return ResultImageNoExist; if (pNormalImage==NULL) return ResultSuccess; pNormalImage->m_pImageData = GS_create_FFT_image(pResultImage->m_pImageData, nFlags); if (pNormalImage->m_pImageData==NULL) return ResultImageNoExist; return ResultSuccess; } IplImage *GS_inverse_FFT2D(IplImage *freq) { if (freq==NULL) return NULL; if (freq->nChannels!=2) return NULL; int width = freq->width; int height = freq->height; int checked = GS_check_log2N(width, height); if (checked==-1) return NULL; IplImage *spatial = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 2); IplImage *real = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *imag = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *dst_image = cvCreateImage(cvGetSize(freq), IPL_DEPTH_8U, 1); cvFFT(freq, spatial, CV_DXT_INVERSE_SCALE); cvCvtPixToPlane(spatial, real, imag, NULL, NULL); cvConvertScale(real, dst_image, 1, 0); cvReleaseImage(&spatial); cvReleaseImage(&real); cvReleaseImage(&imag); return dst_image; } int CCHImageProcess::ImageInverseFFT(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nWidth, int nHeight) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; pResultImage->m_pImageData = GS_post_zero_padding(GS_inverse_FFT2D(pSourceImage->m_pImageData), nWidth, nHeight); if (pResultImage->m_pImageData==NULL) return ResultImageNoExist; return ResultSuccess; } IplImage *BW_Lowpass_Filter(IplImage *freq, int D0, int N) { int i, j; int temp_h, temp_w; double sqrt_value, h_2powers, w_2powers, norm; double var, real_var, imag_var; if (freq==NULL) return NULL; if (freq->nChannels!=2) return NULL; IplImage *lowpass_real = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *lowpass_imag = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *freq_real = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *freq_imag = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); cvCvtPixToPlane(freq, freq_real, freq_imag, NULL, NULL); int width = freq->width; int height = freq->height; int half_width = width/2; int half_height = height/2; for (i=0; i=half_height) temp_h = i - half_height; else temp_h = i + half_height; for (j=0; j=half_width) temp_w = j - half_width; else temp_w = j + half_width; w_2powers = (temp_w-half_width) * (temp_w - half_width); h_2powers = (temp_h-half_height) * (temp_h - half_height); norm = (double) (h_2powers + w_2powers); sqrt_value = sqrt(norm); var = 1.0 / (1.0 + pow((sqrt_value/(double)D0), 2*N)); real_var = cvGetReal2D(freq_real, i, j) * var; imag_var = cvGetReal2D(freq_imag, i, j) * var; cvSetReal2D(lowpass_real, i, j, real_var); cvSetReal2D(lowpass_imag, i, j, imag_var); } } IplImage *lowpass_freq = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 2); cvCvtPlaneToPix(lowpass_real, lowpass_imag, NULL, NULL, lowpass_freq); cvReleaseImage(&freq_real); cvReleaseImage(&freq_imag); cvReleaseImage(&lowpass_real); cvReleaseImage(&lowpass_imag); return lowpass_freq; } IplImage *BW_Highpass_Filter(IplImage *freq, int D0, int N) { int i, j; int temp_h, temp_w; double sqrt_value, h_2powers, w_2powers, norm; double var, real_var, imag_var; if (freq==NULL) return NULL; if (freq->nChannels!=2) return NULL; IplImage *highpass_real = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *highpass_imag = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *freq_real = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); IplImage *freq_imag = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 1); cvCvtPixToPlane(freq, freq_real, freq_imag, NULL, NULL); int width = freq->width; int height = freq->height; int half_width = width/2; int half_height = height/2; for (i=0; i=half_height) temp_h = i - half_height; else temp_h = i + half_height; for (j=0; j=half_width) temp_w = j - half_width; else temp_w = j + half_width; w_2powers = (temp_w-half_width) * (temp_w - half_width); h_2powers = (temp_h-half_height) * (temp_h - half_height); norm = (double) (h_2powers + w_2powers); sqrt_value = sqrt(norm); var = 1.0 / (1.0 + pow(((double)D0/sqrt_value), 2*N)); real_var = cvGetReal2D(freq_real, i, j) * var; imag_var = cvGetReal2D(freq_imag, i, j) * var; cvSetReal2D(highpass_real, i, j, real_var); cvSetReal2D(highpass_imag, i, j, imag_var); } } IplImage *highpass_freq = cvCreateImage(cvGetSize(freq), IPL_DEPTH_32F, 2); cvCvtPlaneToPix(highpass_real, highpass_imag, NULL, NULL, highpass_freq); cvReleaseImage(&freq_real); cvReleaseImage(&freq_imag); cvReleaseImage(&highpass_real); cvReleaseImage(&highpass_imag); return highpass_freq; } int CCHImageProcess::ImageHighPassFilter(CCHImageData* pSourceImage, CCHImageData* pResultImage, int D0, int N, int nFlags, CCHImageData *pNormalImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; pResultImage->m_pImageData = GS_forward_FFT2D(GS_pre_zero_padding(pSourceImage->m_pImageData)); if (pResultImage->m_pImageData==NULL) return ResultImageNoExist; IplImage* high_pass = BW_Highpass_Filter(pResultImage->m_pImageData, D0, N); if (high_pass==NULL) return ResultImageNoExist; if (pNormalImage==NULL) { cvReleaseImage(&high_pass); return ResultSuccess; } pNormalImage->m_pImageData = GS_create_FFT_image(high_pass, nFlags); if (pNormalImage->m_pImageData==NULL) return ResultImageNoExist; if (pNormalImage->m_pImageData==NULL) { cvReleaseImage(&high_pass); return ResultImageNoExist; } cvReleaseImage(&high_pass); return ResultSuccess; } int CCHImageProcess::ImageLowPassFilter(CCHImageData* pSourceImage, CCHImageData* pResultImage, int D0, int N, int nFlags, CCHImageData *pNormalImage) { if (pSourceImage==NULL || pResultImage==NULL) return ResultImageNULL; if (!pSourceImage->GetImageExist()) return ResultImageNoExist; pResultImage->m_pImageData = GS_forward_FFT2D(GS_pre_zero_padding(pSourceImage->m_pImageData)); if (pResultImage->m_pImageData==NULL) return ResultImageNoExist; IplImage* low_pass = BW_Lowpass_Filter(pResultImage->m_pImageData, D0, N); if (low_pass==NULL) return ResultImageNoExist; if (pNormalImage==NULL) { cvReleaseImage(&low_pass); return ResultSuccess; } pNormalImage->m_pImageData = GS_post_zero_padding(GS_inverse_FFT2D(low_pass), low_pass->width, low_pass->height); if (pNormalImage->m_pImageData==NULL) return ResultImageNoExist; if (pNormalImage->m_pImageData==NULL) { cvReleaseImage(&low_pass); return ResultImageNoExist; } cvReleaseImage(&low_pass); return ResultSuccess; } BOOL CCHImageProcess::CalculateLagrange(VectorDouble& vectorX, VectorDouble& vectorY, ListPolynomial& listPolynomial) { if (vectorX.size()<2) return FALSE; if (vectorX.size()!=vectorY.size()) return FALSE; int n = (int)vectorX.size(); int i, j; int sign; double coef, temp; for (i=0; inDegree == pNewPoly->nDegree) { // ÇöÀç ³ëµå¿Í Â÷¼ö °°À¸¸é ÇöÀç ³ëµå¿¡ °è¼ö¸¦ ´õÇϰí, »ý¼º³ëµå´Â »èÁ¦ÇÑ´Ù. pCurrent->dCoef += pNewPoly->dCoef; delete pNewPoly; bAdded = TRUE; break; } else if (pCurrent->nDegree < pNewPoly->nDegree) { // ÇöÀç ¾Õ¿¡ »ðÀÔÇÑ´Ù. listPolynomial.push_front(pNewPoly); bAdded = TRUE; break; } } // ¾Õ¿¡¼­ Ãß°¡°¡ ¾ÈµÇ¾úÀ¸¸é, ¸ÇµÚ¿¡ »ðÀÔÇÑ´Ù. if (!bAdded) { listPolynomial.push_back(pNewPoly); return; } } int CCHImageProcess::MatrixSolve(double *A, double* B, double* X, int nSize, int nMethod) { CvMat a = cvMat( nSize, nSize, CV_64FC1, A ); CvMat b = cvMat( nSize, 1, CV_64FC1, B ); CvMat x = cvMat( nSize, 1, CV_64FC1, X ); int nValue = cvSolve(&a, &b, &x, nMethod); return nValue; } int CCHImageProcess::ImageFindLineInfo(CCHImageData *pSource, float rho, float theta, int threshold, int lineLength, int lineGap, VectorLineData& vectorLine, int linesMax) { if (pSource==NULL) return ResultImageNULL; if (!pSource->GetImageExist()) return ResultImageNoExist; if (pSource->GetChannels()!=1) return ResultImageNoExist; int nWidth = pSource->GetWidth(); int nHeight = pSource->GetHeight(); int nWidthStep = pSource->GetWidthStep(); // point list CvSeq* seq; CvSeqWriter writer; cv::MemStorage storage(cvCreateMemStorage(0)); float ang; int r, n, count; float irho = 1 / rho; CvRNG rng = cvRNG(-1); int numangle = cvRound(CV_PI / theta); int numrho = cvRound(((nWidth + nHeight) * 2 + 1) / rho); // alloc memory BYTE *pMask = new BYTE[nWidth*nHeight]; float *pAccum = new float[numangle*numrho]; memset(pAccum, 0, sizeof(float)*numangle*numrho); float *pTrigtab = new float[numangle*2]; // step 0. calculate angle lookup table for(ang=0, n=0; nGetImageBuffer(); BYTE *pMaskY = pMask; BYTE *pSourceX, *pMaskX; cvStartWriteSeq( CV_32SC2, sizeof(CvSeq), sizeof(CvPoint), storage, &writer ); CvPoint pt; for(pt.y=0, count=0; pt.ytotal; // step 2. process all the points in random order for( ; count>0; count--) { // choose random point out of the remaining ones int idx = cvRandInt(&rng) % count; float max_val = float(threshold-1); int max_n = 0; CvPoint* pt = (CvPoint*)cvGetSeqElem(seq, idx); CvPoint line_end[2] = {{0,0}, {0,0}}; float a, b; int i, j, k, x0, y0, dx0, dy0, xflag; int good_line; const int shift = 16; float* adata = pAccum; // save pos i = pt->y; j = pt->x; // "remove" it by overriding it with the last element (save last element value to current element) *pt = *(CvPoint*)cvGetSeqElem( seq, count-1 ); // check if it has been excluded already (i.e. belongs to some other line) if(!pMask[i*nWidth + j]) { continue; } // update accumulator, find the most probable line for(n=0; nfabs(b)) { xflag = 1; dx0 = a > 0 ? 1 : -1; dy0 = cvRound( b*(1 << shift)/fabs(a) ); y0 = (y0 << shift) + (1 << (shift-1)); } else { xflag = 0; dy0 = b > 0 ? 1 : -1; dx0 = cvRound( a*(1 << shift)/fabs(b) ); x0 = (x0 << shift) + (1 << (shift-1)); } for(k=0; k<2; k++) { int gap = 0, x = x0, y = y0, dx = dx0, dy = dy0; if(k>0) { dx = -dx, dy = -dy; } // walk along the line using fixed-point arithmetics, // stop at the image border or in case of too big gap for( ;; x+=dx, y+=dy) { BYTE* pCurMask; int i1, j1; if(xflag) { j1 = x; i1 = y >> shift; } else { j1 = x >> shift; i1 = y; } if(j1<0 || j1>=nWidth || i1<0 || i1>=nHeight) { break; } pCurMask = pMask + i1*nWidth + j1; // for each non-zero point: // update line end, // clear the mask element // reset the gap if(*pCurMask) { gap = 0; line_end[k].y = i1; line_end[k].x = j1; } else if(++gap>lineGap) { break; } } } good_line = abs(line_end[1].x - line_end[0].x) >= lineLength || abs(line_end[1].y - line_end[0].y) >= lineLength; for(k=0; k<2; k++) { int x = x0, y = y0, dx = dx0, dy = dy0; if( k > 0 ) { dx = -dx, dy = -dy; } // walk along the line using fixed-point arithmetics, // stop at the image border or in case of too big gap for( ;; x+=dx, y+=dy) { BYTE* pCurMask; int i1, j1; if(xflag) { j1 = x; i1 = y >> shift; } else { j1 = x >> shift; i1 = y; } pCurMask = pMask + i1*nWidth + j1; // for each non-zero point: // update line end, // clear the mask element // reset the gap if(*pCurMask) { if(good_line) { adata = pAccum; for( n = 0; n < numangle; n++, adata += numrho ) { r = cvRound( j1 * ttab[n*2] + i1 * ttab[n*2+1] ); r += (numrho - 1) / 2; adata[r]--; } } *pCurMask = 0; } if(i1 == line_end[k].y && j1 == line_end[k].x) { break; } } } if(good_line) { vectorLine.push_back(CLineData(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y)); if(int(vectorLine.size())>=linesMax) { break; } } } // end for delete [] pMask; delete [] pAccum; delete [] pTrigtab; return ResultSuccess; } void MultipleMaxLoc( const IplImage& image, CvPoint** locations, int numMaxima) { // initialize input variable locations *locations = new CvPoint[numMaxima]; // create array for tracking maxima double *maxima = new double[numMaxima]; memset(maxima, 0, sizeof(double)*numMaxima); // extract the raw data for analysis float* data; int step; CvSize size; cvGetRawData( &image, ( uchar** )&data, &step, &size ); step /= sizeof( data[0] ); for( int y = 0; y < size.height; y++, data += step ) { for( int x = 0; x < size.width; x++ ) { // insert the data value into the array if it is greater than any of the // other array values, and bump the other values below it, down for( int j = 0; j < numMaxima; j++ ) { if( data[x] > maxima[j] ) { // move the maxima down for( int k = numMaxima - 1; k > j; k-- ) { maxima[k] = maxima[k-1]; ( *locations )[k] = ( *locations )[k-1]; } // insert the value maxima[j] = ( double )data[x]; ( *locations )[j].x = x; ( *locations )[j].y = y; break; } } } } delete [] maxima; } /* int CCHImageProcess::FastMatchTemplate(const IplImage& source, const IplImage& target, std::vector* foundPointsList, std::vector* confidencesList, int matchPercentage, BOOL findMultipleTargets, int numMaxima, int numDownPyrs, int searchExpansion) { // make sure that the template image is smaller than the source if( target.width > source.width || target.height > source.height ) { return 0; } if( source.depth != target.depth ) { return 0; } if( source.nChannels != target.nChannels ) { return 0; } CvSize sourceSize = cvGetSize( &source ); CvSize targetSize = cvGetSize( &target ); int depth = source.depth; int numChannels = source.nChannels; // create copies of the images to modify IplImage* copyOfSource = cvCloneImage( &source ); IplImage* copyOfTarget = cvCloneImage( &target ); // down pyramid the images for( int ii = 0; ii < numDownPyrs; ii++ ) { // start with the source image sourceSize.width /= 2; sourceSize.height /= 2; IplImage* smallSource = NULL; smallSource = cvCreateImage( sourceSize, depth, numChannels ); cvPyrDown( copyOfSource, smallSource, CV_GAUSSIAN_5x5 ); // prepare for next loop, if any cvReleaseImage( ©OfSource ); copyOfSource = cvCloneImage( smallSource ); cvReleaseImage( &smallSource ); // next, do the target targetSize.width /= 2; targetSize.height /= 2; IplImage* smallTarget = NULL; smallTarget = cvCreateImage( targetSize, depth, numChannels ); cvPyrDown( copyOfTarget, smallTarget, CV_GAUSSIAN_5x5 ); // prepare for next loop, if any cvReleaseImage( ©OfTarget ); copyOfTarget = cvCloneImage( smallTarget ); cvReleaseImage( &smallTarget ); } // perform the match on the shrunken images CvSize smallTargetSize = cvGetSize( copyOfTarget ); CvSize smallSourceSize = cvGetSize( copyOfSource ); CvSize resultSize; resultSize.width = smallSourceSize.width - smallTargetSize.width + 1; resultSize.height = smallSourceSize.height - smallTargetSize.height + 1; IplImage* result = cvCreateImage(resultSize, IPL_DEPTH_32F, 1); cvMatchTemplate( copyOfSource, copyOfTarget, result, CV_TM_CCOEFF_NORMED); // release memory we don't need anymore cvReleaseImage( ©OfSource ); cvReleaseImage( ©OfTarget ); // find the top match locations CvPoint* locations = NULL; MultipleMaxLoc(*result, &locations, numMaxima); cvReleaseImage(&result); // search the large images at the returned locations sourceSize = cvGetSize( &source ); targetSize = cvGetSize( &target ); // create a copy of the source in order to adjust its ROI for searching IplImage* searchImage = cvCloneImage( &source ); for( int currMax = 0; currMax < numMaxima; currMax++ ) { // transform the point to its corresponding point in the larger image locations[currMax].x *= ( int )pow( double(2), double(numDownPyrs) ); locations[currMax].y *= ( int )pow( double(2), double(numDownPyrs) ); locations[currMax].x += targetSize.width / 2; locations[currMax].y += targetSize.height / 2; const CvPoint& searchPoint = locations[currMax]; // if we are searching for multiple targets and we have found a target or // multiple targets, we don't want to search in the same location(s) again if( findMultipleTargets && !foundPointsList->empty() ) { BOOL thisTargetFound = FALSE; int numPoints = (int)foundPointsList->size(); for( int currPoint = 0; currPoint < numPoints; currPoint++ ) { const CvPoint& foundPoint = ( *foundPointsList )[currPoint]; if( abs( searchPoint.x - foundPoint.x ) <= searchExpansion * 2 && abs( searchPoint.y - foundPoint.y ) <= searchExpansion * 2 ) { thisTargetFound = TRUE; break; } } // if the current target has been found, continue onto the next point if( thisTargetFound ) { continue; } } // set the source image's ROI to slightly larger than the target image, // centred at the current point CvRect searchRoi; searchRoi.x = searchPoint.x - ( target.width ) / 2 - searchExpansion; searchRoi.y = searchPoint.y - ( target.height ) / 2 - searchExpansion; searchRoi.width = target.width + searchExpansion * 2; searchRoi.height = target.height + searchExpansion * 2; // make sure ROI doesn't extend outside of image if( searchRoi.x < 0 ) { searchRoi.x = 0; } if( searchRoi.y < 0 ) { searchRoi.y = 0; } if( ( searchRoi.x + searchRoi.width ) > ( sourceSize.width - 1 ) ) { int numPixelsOver = ( searchRoi.x + searchRoi.width ) - ( sourceSize.width - 1 ); searchRoi.width -= numPixelsOver; } if( ( searchRoi.y + searchRoi.height ) > ( sourceSize.height - 1 ) ) { int numPixelsOver = ( searchRoi.y + searchRoi.height ) - ( sourceSize.height - 1 ); searchRoi.height -= numPixelsOver; } cvSetImageROI( searchImage, searchRoi ); // perform the search on the large images resultSize.width = searchRoi.width - target.width + 1; resultSize.height = searchRoi.height - target.height + 1; result = cvCreateImage( resultSize, IPL_DEPTH_32F, 1 ); cvMatchTemplate( searchImage, &target, result, CV_TM_CCOEFF_NORMED ); cvResetImageROI( searchImage ); // find the best match location double minValue, maxValue; CvPoint minLoc, maxLoc; cvMinMaxLoc( result, &minValue, &maxValue, &minLoc, &maxLoc ); maxValue *= 100; // transform point back to original image maxLoc.x += searchRoi.x + target.width / 2; maxLoc.y += searchRoi.y + target.height / 2; cvReleaseImage( &result ); if( maxValue >= matchPercentage ) { // add the point to the list foundPointsList->push_back( maxLoc ); confidencesList->push_back( maxValue ); // if we are only looking for a single target, we have found it, so we // can return if( !findMultipleTargets ) { break; } } } if( foundPointsList->empty() ) { printf( "\nTarget was not found to required confidence of %d.\n", matchPercentage); } delete [] locations; cvReleaseImage( &searchImage ); return ResultSuccess; } */ BOOL CCHImageProcess::ImageSmooth_HybridMedianFilter(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nFilterSize) { if (pSourceImage==NULL || pResultImage==NULL) return FALSE; if (!pSourceImage->GetImageExist()) return FALSE; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; pResultImage->ClearImage(0); pSourceImage->CopyImageTo(pResultImage); int *pMedianArray, *pTempArray; int nTempArrayIdx, nMedianArrayIdx; int x, y, nWidth, nHeight, nWidthStep, nMiddleOfFilter, nFilterRowIdx, nFilterColIdx, nValue, nMiddleIdx, nRow; pTempArray = new int[nFilterSize * 2]; pMedianArray = new int[3]; nWidth = pSourceImage->GetWidth(); nHeight = pSourceImage->GetHeight(); nWidthStep = pSourceImage->GetWidthStep(); nMiddleOfFilter = nFilterSize / 2; BYTE* pSrc = (BYTE*) pSourceImage->GetImageBuffer(); BYTE* pDst = (BYTE*) pResultImage->GetImageBuffer(); BYTE* pTempLine = NULL; BYTE** pFilterLine = NULL; pFilterLine = new BYTE*[nFilterSize]; for(nFilterColIdx = 0; nFilterColIdx < nFilterSize; nFilterColIdx++) { if(nFilterColIdx == 0) { pFilterLine[nFilterColIdx] = &pSrc[0]; } else { pFilterLine[nFilterColIdx] = pFilterLine[nFilterColIdx - 1] + nWidthStep; } } for(y = nMiddleOfFilter; y < nHeight - nMiddleOfFilter; y++) { for(x = nMiddleOfFilter; x < nWidth - nMiddleOfFilter; x++) { //1. X¹æÇâ nRow = x - nMiddleOfFilter; nTempArrayIdx = 0; nMedianArrayIdx = 0; ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2); ZeroMemory(pMedianArray, sizeof(int) * 3); for(nFilterColIdx = 0; nFilterColIdx < nFilterSize; nFilterColIdx++) { nValue = pFilterLine[nFilterColIdx][nRow + nFilterColIdx]; pTempArray[nTempArrayIdx++] = nValue; nValue = pFilterLine[nFilterColIdx][nRow + nFilterSize - 1 - nFilterColIdx]; pTempArray[nTempArrayIdx++] = nValue; } QuickSort(pTempArray, 0, nTempArrayIdx - 1); nMiddleIdx = nTempArrayIdx / 2; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //2. £«¹æÇâ nTempArrayIdx = 0; ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2); for(nFilterColIdx = 0; nFilterColIdx < nFilterSize; nFilterColIdx++) { if(nFilterColIdx == nMiddleOfFilter) { for(nFilterRowIdx = 0; nFilterRowIdx < nFilterSize; nFilterRowIdx++) { nValue = pFilterLine[nFilterColIdx][nRow + nFilterRowIdx]; pTempArray[nTempArrayIdx++] = nValue; } } else { nValue = pFilterLine[nFilterColIdx][nRow + nMiddleOfFilter]; pTempArray[nTempArrayIdx++] = nValue; } } QuickSort(pTempArray, 0, nTempArrayIdx - 1); nMiddleIdx = nTempArrayIdx / 2; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //3. ÇöÀç Æ÷ÀÎÆ® nValue = pFilterLine[nMiddleOfFilter][x]; pMedianArray[nMedianArrayIdx++] = nValue; //4. Áß°£°ª ÃßÃâ QuickSort(pMedianArray, 0, nMedianArrayIdx - 1); nMiddleIdx = nMedianArrayIdx / 2; nValue = pMedianArray[nMiddleIdx]; pDst[y * nWidthStep + x] = nValue; } for(nFilterColIdx = 0; nFilterColIdx < nFilterSize; nFilterColIdx++) { if(nFilterColIdx == nFilterSize - 1) { pFilterLine[nFilterColIdx] = pFilterLine[nFilterColIdx] + nWidthStep; } else { pFilterLine[nFilterColIdx] = pFilterLine[nFilterColIdx + 1]; } } } delete[] pTempArray; delete[] pMedianArray; delete[] pFilterLine; return TRUE; } BOOL CCHImageProcess::ImageSmooth_HybridMedianFilter2(CCHImageData* pSourceImage, CCHImageData* pResultImage, int nFilterSize) { if (pSourceImage==NULL || pResultImage==NULL) return FALSE; if (!pSourceImage->GetImageExist()) return FALSE; if (!pResultImage->CreateImage(pSourceImage->GetWidth(), pSourceImage->GetHeight(), pSourceImage->GetDepth(), pSourceImage->GetChannels())) return ResultImageNoExist; pResultImage->ClearImage(0); int nMiddleIdx, nMedianArrayIdx; int i, x, y, nWidth, nHeight, nWidthStep, nMiddleOfFilter, nValue; int *pKernelX, *pKernelY, *pKernelDial1, *pKernelDial2, *pMedianArray, *pTempArray; nWidth = pSourceImage->GetWidth(); nHeight = pSourceImage->GetHeight(); nWidthStep = pSourceImage->GetWidthStep(); nMiddleOfFilter = nFilterSize / 2; BYTE* pSrcY = (BYTE*) pSourceImage->GetImageBuffer(); BYTE* pRetY = (BYTE*) pResultImage->GetImageBuffer() + (nMiddleOfFilter * nWidthStep) + nMiddleOfFilter; BYTE *pRetX, *pSrcX; pKernelX = new int[nFilterSize]; pKernelY = new int[nFilterSize]; pKernelDial1 = new int[nFilterSize]; pKernelDial2 = new int[nFilterSize]; pTempArray = new int[nFilterSize * 2]; pMedianArray = new int[3]; BYTE *pX, *pY, *pD1, *pD2; int nPitchX = nWidthStep * nMiddleOfFilter; int nPitchD1 = nWidthStep + 1; int nPitchD2 = nWidthStep - 1; BYTE* pKernelValue = new BYTE[nFilterSize * nFilterSize]; for(y = nMiddleOfFilter; y < nHeight - nMiddleOfFilter; y++) { pSrcX = pSrcY; pRetX = pRetY; for(x = nMiddleOfFilter; x < nWidth - nMiddleOfFilter; x++) { pX = pSrcX + nPitchX; pY = pSrcX + nMiddleOfFilter; pD1 = pSrcX; pD2 = pSrcX + nFilterSize - 1; for(i = 0; i < nFilterSize; i++) { pKernelX[i] = *pX; pKernelY[i] = *pY; pKernelDial1[i] = *pD1; pKernelDial2[i] = *pD2; pX++; pY += nWidthStep; pD1 += nPitchD1; pD2 += nPitchD2; } //1. X¹æÇâ nMedianArrayIdx = 0; ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2 - 1); ZeroMemory(pMedianArray, sizeof(int) * 3); memcpy(pTempArray, pKernelDial1, sizeof(int) * nFilterSize); memcpy(pTempArray + nFilterSize, pKernelDial2, sizeof(int) * nMiddleOfFilter); memcpy(pTempArray + nFilterSize + nMiddleOfFilter, pKernelDial2 + nMiddleOfFilter + 1, sizeof(int) * nMiddleOfFilter); QuickSort(pTempArray, 0, nFilterSize * 2 - 2); nMiddleIdx = nFilterSize - 1; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //2. £«¹æÇâ ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2 - 1); memcpy(pTempArray, pKernelX, sizeof(int) * nFilterSize); memcpy(pTempArray + nFilterSize, pKernelY, sizeof(int) * nMiddleOfFilter); memcpy(pTempArray + nFilterSize + nMiddleOfFilter, pKernelY + nMiddleOfFilter + 1, sizeof(int) * nMiddleOfFilter); QuickSort(pTempArray, 0, nFilterSize * 2 - 2); nMiddleIdx = nFilterSize - 1; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //3. ÇöÀç Æ÷ÀÎÆ® nValue = pKernelX[nMiddleOfFilter]; pMedianArray[nMedianArrayIdx++] = nValue; //4. Áß°£°ª ÃßÃâ QuickSort(pMedianArray, 0, nMedianArrayIdx - 1); nMiddleIdx = nMedianArrayIdx / 2; nValue = pMedianArray[nMiddleIdx]; *pRetX = nValue; pSrcX++; pRetX++; } /*for(x = nMiddleOfFilter; x < nWidth - nMiddleOfFilter; x++) { nIdx = 0; pSubY = pSrcX; ZeroMemory(pKernelX, sizeof(int) * nFilterSize); ZeroMemory(pKernelY, sizeof(int) * nFilterSize); ZeroMemory(pKernelDial1, sizeof(int) * nFilterSize); ZeroMemory(pKernelDial2, sizeof(int) * nFilterSize); for(i = 0; i < nFilterSize; i++) { pKernelX[i] = pSrcX[(nWidthStep * nMiddleOfFilter) + i]; pKernelY[i] = pSrcX[(nWidthStep * i) + nMiddleOfFilter]; pKernelDial1[i] = pSrcX[(nWidthStep * i) + i]; pKernelDial2[i] = pSrcX[(nWidthStep * i) + (nFilterSize - i - 1)]; } //1. X¹æÇâ nMedianArrayIdx = 0; ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2 - 1); ZeroMemory(pMedianArray, sizeof(int) * 3); memcpy(pTempArray, pKernelDial1, sizeof(int) * nFilterSize); memcpy(pTempArray + nFilterSize, pKernelDial2, sizeof(int) * nMiddleOfFilter); memcpy(pTempArray + nFilterSize + nMiddleOfFilter, pKernelDial2 + nMiddleOfFilter + 1, sizeof(int) * nMiddleOfFilter); QuickSort(pTempArray, 0, nFilterSize * 2 - 2); nMiddleIdx = nFilterSize - 1; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //2. £«¹æÇâ ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2 - 1); memcpy(pTempArray, pKernelX, sizeof(int) * nFilterSize); memcpy(pTempArray + nFilterSize, pKernelY, sizeof(int) * nMiddleOfFilter); memcpy(pTempArray + nFilterSize + nMiddleOfFilter, pKernelY + nMiddleOfFilter + 1, sizeof(int) * nMiddleOfFilter); QuickSort(pTempArray, 0, nFilterSize * 2 - 2); nMiddleIdx = nFilterSize - 1; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //3. ÇöÀç Æ÷ÀÎÆ® nValue = pKernelX[nMiddleOfFilter]; pMedianArray[nMedianArrayIdx++] = nValue; //4. Áß°£°ª ÃßÃâ QuickSort(pMedianArray, 0, nMedianArrayIdx - 1); nMiddleIdx = nMedianArrayIdx / 2; nValue = pMedianArray[nMiddleIdx]; // for(i = 0; i < nFilterSize; i++) // { // pSubX = pSubY; // // for(j = 0; j < nFilterSize; j++) // { // pKernelValue[nIdx++] = *pSubX++; // } // // pSubY += nWidthStep; // } // // nValue = GetHybridMedianFilterValue(pKernelValue, nFilterSize); *pRetX = nValue; pSrcX++; pRetX++; }*/ pSrcY += nWidthStep; pRetY += nWidthStep; } delete[] pKernelX; delete[] pKernelY; delete[] pKernelDial1; delete[] pKernelDial2; delete[] pTempArray; delete[] pMedianArray; delete[] pKernelValue; return TRUE; } int CCHImageProcess::GetHybridMedianFilterValue(BYTE* pKernelValue, int nFilterSize) { int *pMedianArray, *pTempArray; int i, j, nIdx, nValue, nMiddleOfFilter, nMiddleIdx, nTempArrayIdx, nMedianArrayIdx; pTempArray = new int[nFilterSize * 2]; ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2); pMedianArray = new int[3]; ZeroMemory(pMedianArray, sizeof(int) * 3); //1. X¹æÇâ nTempArrayIdx = 0; nMedianArrayIdx = 0; nMiddleOfFilter = nFilterSize / 2; for(i = 0; i < nFilterSize; i++) { nIdx = i * nFilterSize + i; nValue = pKernelValue[nIdx]; pTempArray[nTempArrayIdx++] = nValue; if(i != nMiddleOfFilter) { nIdx = (i + 1) * nFilterSize - (i + 1); nValue = pKernelValue[nIdx]; pTempArray[nTempArrayIdx++] = nValue; } } QuickSort(pTempArray, 0, nTempArrayIdx - 1); nMiddleIdx = nTempArrayIdx / 2; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //2. £«¹æÇâ nTempArrayIdx = 0; ZeroMemory(pTempArray, sizeof(int) * nFilterSize * 2); for(i = 0; i < nFilterSize; i++) { if(i == nMiddleOfFilter) { nIdx = i * nFilterSize; for(j = 0; j < nFilterSize; j++) { nValue = pKernelValue[nIdx++]; pTempArray[nTempArrayIdx++] = nValue; } } else { nIdx = i * nFilterSize + nMiddleOfFilter; nValue = pKernelValue[nIdx]; pTempArray[nTempArrayIdx++] = nValue; } } QuickSort(pTempArray, 0, nTempArrayIdx - 1); nMiddleIdx = nTempArrayIdx / 2; nValue = pTempArray[nMiddleIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //3. ÇöÀç Æ÷ÀÎÆ® nIdx = nMiddleOfFilter * nFilterSize + nMiddleOfFilter; nValue = pKernelValue[nIdx]; pMedianArray[nMedianArrayIdx++] = nValue; //4. Áß°£°ª ÃßÃâ QuickSort(pMedianArray, 0, nMedianArrayIdx - 1); nMiddleIdx = nMedianArrayIdx / 2; nValue = pMedianArray[nMiddleIdx]; delete[] pTempArray; delete[] pMedianArray; return nValue; } template inline T limit(const T& value) { return ( (value > 255) ? 255 : ((value < 0) ? 0 : value) ); } //ºñµî¹æ¼º È®»ê ÇÊÅÍ void CCHImageProcess::ImageDiffusion(BYTE *pBuffer, int w, int h, int iter, float lambda, float k) { register int i, x, y; float k2 = k * k; float gradn, grads, grade, gradw; float gcn, gcs, gce, gcw; float tmp; // ¿¬»êÀ»½Ç¼öÇüÀ¸·ÎÇϱâÀ§ÇÏ¿©½Ç¼öÇü2Â÷¿ø¹è¿­µ¿Àû»ý¼º float** cpy = new float*[h]; for( i = 0 ; i < h ; i++ ) { cpy[i] = new float[w]; memset(cpy[i], 0, sizeof(float)*w); } float** buf = new float*[h]; for( i = 0 ; i < h ; i++ ) { buf[i] = new float[w]; memset(buf[i], 0, sizeof(float)*w); } // ÀԷ¿µ»óÀÇÁ¤º¸¸¦º¹»ç BYTE *pImg = pBuffer; for( y = 0 ; y < h ; y++ ) for( x = 0 ; x < w ; x++ ) { cpy[y][x] = buf[y][x] = (float)*pImg++; } for( i = 0 ; i < iter ; i++ ) { for( y = 1 ; y < h-1 ; y++ ) for( x = 1 ; x < w-1 ; x++ ) { tmp = cpy[y][x]; gradn = cpy[y-1][x ] - tmp; grads = cpy[y+1][x ] - tmp; grade = cpy[y ][x-1] - tmp; gradw = cpy[y ][x+1] - tmp; gcn = gradn / (1.0f + gradn*gradn/k2); gcs = grads / (1.0f + grads*grads/k2); gce = grade / (1.0f + grade*grade/k2); gcw = gradw / (1.0f + gradw*gradw/k2); buf[y][x] = cpy[y][x] + lambda*(gcn + gcs + gce + gcw); } // ¹öÆÛº¹»ç for( y = 0 ; y < h ; y++ ) memcpy(cpy[y], buf[y], sizeof(float)*w); } // ÀԷ¿µ»óÀǰª°»½Å pImg = pBuffer; for( y = 0 ; y < h ; y++ ) for( x = 0 ; x < w ; x++ ) { *pImg++ = (BYTE)limit(buf[y][x] + 0.5f); } // µ¿ÀûÇÒ´çÇѸ޸ð¸®ÇØÁ¦ for( i = 0 ; i < h ; i++ ) { delete [] buf[i]; delete [] cpy[i]; } delete [] buf; delete [] cpy; } void CCHImageProcess::Swap(int* pA, int* pB) { int nTemp = *pA; *pA = *pB; *pB = nTemp; } void CCHImageProcess::QuickSort(int* nArr, int nStart, int nEnd) { int nPivot = nArr[nStart]; int nLeft = nStart + 1; int nRight = nEnd; // °³¼ö°¡ Àû¾î¼­ ãÀ» °ÍÀÌ ¾ø´Â°¡? if( nEnd - nStart <= 0 ) { return; } while(1) { // Left¸¦ ã´Â´Ù. for(; nLeft <= nEnd; nLeft++) { if(nPivot < nArr[nLeft]) { break; } } // Right¸¦ ã´Â´Ù. for(; nRight > nStart; nRight--) { if(nPivot > nArr[nRight]) { break; } } // ¹Ù²ã¾ßÇÒ »óȲÀ̶ó¸é ¹Ù²Û´Ù. if(nLeft <= nEnd && nRight > nStart && nLeft < nRight) { Swap(&nArr[nLeft], &nArr[nRight]); continue; } // Left, Right°¡ ¸ðµÎ ¹üÀ§ ¹ÛÀ¸·Î ³ª°¬´Ù¸é ¹è¿­ ¾ÈÀÇ ¼ýÀÚ´Â ¸ðµÎ °°Àº ¼ýÀÚ´Ù. if(nRight <= nStart && nLeft > nEnd) { return; } // Á¶°ÇÀÌ µÈ´Ù¸é ¿ÞÂÊ Array¸¦ Recursive·Î µ¹¸°´Ù. if(nRight > nStart) { // Pivot°ú Right¸¦ ¹Ù²Û´Ù. Swap(&nArr[nStart], &nArr[nRight]); QuickSort(nArr, nStart, nRight); } // ¿À¸¥ÂÊ Array´Â Áö±ÝÀÇ ÇÔ¼ö¸¦ Àç»ç¿ë. nStart = nRight + 1; nPivot = nArr[nStart]; nLeft = nStart + 1; nRight = nEnd; // °³¼ö°¡ Àû¾î¼­ ãÀ» °ÍÀÌ ¾ø´Â°¡? if(nEnd - nStart <= 0) { return; } } }