#include <mil.h>
#include <math.h>
#include "defectdetectionprocfunc.h"
void Remap8BitImage(MIL_ID MilSrcImage,
MIL_ID MilDestImage,
MIL_INT StartIndex,
MIL_INT EndIndex,
MIL_DOUBLE MinValue,
MIL_DOUBLE MaxValue)
{
MIL_ID MilSystem = MbufInquire(MilSrcImage, M_OWNER_SYSTEM, M_NULL);
MIL_ID MilLut = MbufAlloc1d(MilSystem, 256, 32+M_FLOAT, M_LUT, M_NULL);
MgenLutRamp(MilLut, 0, MinValue, StartIndex, MinValue);
MgenLutRamp(MilLut, StartIndex, MinValue, EndIndex, MaxValue);
MgenLutRamp(MilLut, EndIndex, MaxValue, 255, MaxValue);
MimLutMap(MilSrcImage, MilDestImage, MilLut);
MbufFree(MilLut);
}
void CreateGradientMaskImage(MIL_ID MilTemplateImage,
MIL_ID MilTemplateLumImage,
MIL_DOUBLE GradientSmoothness,
MIL_ID *MilGradientMaskImagePtr,
MIL_ID *MilGradientLumMaskImagePtr)
{
MIL_ID MilSystem = MbufInquire(MilTemplateLumImage, M_OWNER_SYSTEM, M_NULL);
MIL_INT TemplateSizeX = MbufInquire(MilTemplateLumImage, M_SIZE_X, M_NULL);
MIL_INT TemplateSizeY = MbufInquire(MilTemplateLumImage, M_SIZE_Y, M_NULL);
MIL_ID MilGradientMaskColorImage = MbufAllocColor(MilSystem, 3, TemplateSizeX, TemplateSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC, M_NULL);
MIL_ID MilGradientLumMaskImage = MbufAlloc2d(MilSystem, TemplateSizeX, TemplateSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC, M_NULL);
MIL_ID MilGradientMaskImage = MbufAlloc2d(MilSystem, TemplateSizeX, TemplateSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC, M_NULL);
MimConvolve(MilTemplateLumImage, MilGradientLumMaskImage, M_SHEN_FILTER(M_EDGE_DETECT, GradientSmoothness));
MimConvolve(MilTemplateImage, MilGradientMaskColorImage, M_SHEN_FILTER(M_EDGE_DETECT, GradientSmoothness));
MIL_ID MilGradientTotal = MbufAlloc2d(MilSystem, TemplateSizeX, TemplateSizeY, 32+M_UNSIGNED, M_IMAGE+M_PROC, M_NULL);
MIL_ID MilGradientSquare = MbufAlloc2d(MilSystem, TemplateSizeX, TemplateSizeY, 16+M_UNSIGNED, M_IMAGE+M_PROC, M_NULL);
MbufClear(MilGradientTotal, 0);
for(MIL_INT BandIdx = 0; BandIdx < 3; BandIdx++)
{
MIL_ID MilGradientBand = MbufChildColor(MilGradientMaskColorImage, M_RED << BandIdx, M_NULL);
MimArith(MilGradientBand, M_NULL, MilGradientSquare, M_SQUARE);
MimArith(MilGradientTotal, MilGradientSquare, MilGradientTotal, M_ADD);
MbufFree(MilGradientBand);
}
MimArith(MilGradientTotal, M_NULL, MilGradientMaskImage, M_SQUARE_ROOT);
static const MIL_INT MaxColorGradient = (MIL_INT)sqrt(127.0*127.0*3.0);
Remap8BitImage(MilGradientMaskImage, MilGradientMaskImage, 0, MaxColorGradient, 0, 255);
Remap8BitImage(MilGradientLumMaskImage, MilGradientLumMaskImage, 0, 127, 0, 255);
if(MilGradientMaskImagePtr != M_NULL)
*MilGradientMaskImagePtr = MilGradientMaskImage;
else
MbufFree(MilGradientMaskImage);
if(MilGradientLumMaskImagePtr != M_NULL)
*MilGradientLumMaskImagePtr = MilGradientLumMaskImage;
else
MbufFree(MilGradientLumMaskImage);
MbufFree(MilGradientTotal);
MbufFree(MilGradientSquare);
MbufFree(MilGradientMaskColorImage);
}
bool DefineModelAndFixture(MIL_ID MilTemplateLumImage,
MIL_ID MilModContext,
MIL_ID MilFixturingOffset,
MIL_DOUBLE ModelOffsetX,
MIL_DOUBLE ModelOffsetY,
MIL_DOUBLE ModelSizeX,
MIL_DOUBLE ModelSizeY)
{
if(MmodInquire(MilModContext, M_CONTEXT, M_NUMBER_MODELS + M_TYPE_MIL_INT, M_NULL))
MmodDefine(MilModContext, M_DELETE, M_ALL, M_DEFAULT, M_DEFAULT, M_DEFAULT, M_DEFAULT);
MmodDefine(MilModContext, M_IMAGE, MilTemplateLumImage, ModelOffsetX, ModelOffsetY, ModelSizeX, ModelSizeY);
MIL_INT NbModelEdges = MmodInquire(MilModContext, 0, M_NUMBER_OF_CHAINED_EDGELS, M_NULL);
if (NbModelEdges == 0)
{
MosPrintf(MIL_TEXT("Invalid template image. The resulting model is empty.\n\n"));
return false;
}
MmodControl(MilModContext, 0, M_NUMBER, M_ALL);
MmodPreprocess(MilModContext, M_DEFAULT);
McalFixture(M_NULL, MilFixturingOffset, M_LEARN_OFFSET, M_MODEL_MOD, MilModContext, 0, M_DEFAULT, M_DEFAULT, M_DEFAULT);
return true;
}
MIL_INT FindModel(MIL_ID MilModContext,
MIL_ID MilTargetImage,
MIL_ID MilModResult)
{
MmodFind(MilModContext, MilTargetImage, MilModResult);
MIL_INT NbOfOccurrences;
MmodGetResult(MilModResult, M_GENERAL, M_NUMBER+M_TYPE_MIL_INT, &NbOfOccurrences);
return NbOfOccurrences;
}
void AlignImageBasedOnFixture(MIL_ID MilSrcImage,
MIL_ID MilDestImage,
MIL_ID MilFixturingOffset,
MIL_ID MilFixtureProvider,
MIL_INT ResultType,
MIL_INT OccurenceIdx)
{
McalFixture(MilSrcImage, MilFixturingOffset, M_MOVE_RELATIVE, ResultType, MilFixtureProvider, OccurenceIdx, M_DEFAULT, M_DEFAULT, M_DEFAULT);
McalTransformImage(MilSrcImage, MilDestImage, M_DEFAULT, M_BILINEAR+M_OVERSCAN_CLEAR, M_DEFAULT, M_WARP_IMAGE+M_USE_DESTINATION_CALIBRATION);
}
MIL_INT ExtractDefects(MIL_ID MilDifferenceGrayImage,
MIL_ID MilBlobResult,
MIL_ID MilBlobFeatureList,
MIL_DOUBLE TriangleLowerCutoff,
MIL_DOUBLE TriangleUpperCutoff,
MIL_DOUBLE BinCumulativeValue,
MIL_DOUBLE NormalVariation,
MIL_DOUBLE FixedDiffThreshold,
MIL_INT CleanMorphSize,
const BinarizationMethod BinMethod)
{
MIL_ID MilSystem = MbufInquire(MilDifferenceGrayImage, M_OWNER_SYSTEM, M_NULL);
MIL_INT ImageSizeX = MbufInquire(MilDifferenceGrayImage, M_SIZE_X, M_NULL);
MIL_INT ImageSizeY = MbufInquire(MilDifferenceGrayImage, M_SIZE_Y, M_NULL);
MIL_ID MilInspectionBinImage = MbufAlloc2d(MilSystem, ImageSizeX, ImageSizeY, 1+M_UNSIGNED, M_IMAGE+M_PROC, M_NULL);
MIL_INT BinValue;
switch(BinMethod)
{
case enCumulHistPercentage:
BinValue = MimBinarize(MilDifferenceGrayImage, M_NULL, M_PERCENTILE_VALUE, BinCumulativeValue, M_NULL);
break;
case enTriangleBisection:
NormalVariation = (MIL_DOUBLE) MimBinarize(MilDifferenceGrayImage, M_NULL, M_TRIANGLE_BISECTION_BRIGHT, TriangleLowerCutoff, TriangleUpperCutoff);
case enFixed:
BinValue = (MIL_INT) (((NormalVariation + FixedDiffThreshold) > 255) ? 255 : (NormalVariation + FixedDiffThreshold));
break;
case enBiModal:
default:
BinValue = MimBinarize(MilDifferenceGrayImage, M_NULL, M_BIMODAL, M_NULL, M_NULL);
break;
}
MimBinarize(MilDifferenceGrayImage, MilInspectionBinImage, M_FIXED + M_GREATER_OR_EQUAL, (MIL_DOUBLE) BinValue, M_NULL);
MimOpen(MilInspectionBinImage, MilInspectionBinImage, CleanMorphSize, M_BINARY);
MblobCalculate(MilInspectionBinImage, M_NULL, MilBlobFeatureList, MilBlobResult);
MbufFree(MilInspectionBinImage);
return BinValue;
}
void ExtractDifferences(MIL_ID MilTemplateImage,
MIL_ID MilTemplateLumImage,
MIL_ID MilTemplateGradientMask,
MIL_ID MilTemplateLumGradientMask,
MIL_ID MilWarpedTarget,
MIL_ID MilDifferenceGrayImage,
MIL_ID MilStructElement,
const DifferenceExtractionMethod DiffExtractMethod)
{
MIL_ID MilSystem = MbufInquire(MilDifferenceGrayImage, M_OWNER_SYSTEM, M_NULL);
MIL_INT ImageSizeX = MbufInquire(MilDifferenceGrayImage, M_SIZE_X, M_NULL);
MIL_INT ImageSizeY = MbufInquire(MilDifferenceGrayImage, M_SIZE_Y, M_NULL);
MIL_ID MilWarpedTargetLum = M_NULL;
if(DiffExtractMethod != enColDistance)
{
if(MbufInquire(MilWarpedTarget, M_SIZE_BAND, M_NULL) == 3)
{
MbufAlloc2d(MilSystem, ImageSizeX, ImageSizeY, 8+M_UNSIGNED, M_IMAGE+M_PROC, &MilWarpedTargetLum);
MimConvert(MilWarpedTarget, MilWarpedTargetLum, M_RGB_TO_L);
}
else
MilWarpedTargetLum = MilWarpedTarget;
}
switch(DiffExtractMethod)
{
case enAbsoluteDiff:
MimArith(MilTemplateLumImage, MilWarpedTargetLum, MilDifferenceGrayImage, M_SUB_ABS);
break;
case enColDistance:
McolDistance(MilTemplateImage, MilWarpedTarget, MilDifferenceGrayImage, M_NULL, M_DEFAULT, M_EUCLIDEAN, M_NO_NORMALIZE, M_DEFAULT);
break;
case enTopHat:
MimMorphic(MilWarpedTargetLum, MilDifferenceGrayImage, MilStructElement, M_TOP_HAT, 1, M_GRAYSCALE);
break;
case enBottomHat:
default:
MimMorphic(MilWarpedTargetLum, MilDifferenceGrayImage, MilStructElement, M_BOTTOM_HAT, 1, M_GRAYSCALE);
break;
}
MimArith(MilDifferenceGrayImage, DiffExtractMethod == enColDistance ? MilTemplateGradientMask : MilTemplateLumGradientMask, MilDifferenceGrayImage, M_SUB+M_SATURATION);
if(MilWarpedTargetLum && MilWarpedTargetLum != MilWarpedTarget)
MbufFree(MilWarpedTargetLum);
}