IPSDK  4_1_0_2
IPSDK : Image Processing Software Development Kit
# [DocSampleImports]
import os
import sys, getopt
import PyIPSDK
import PyIPSDK.IPSDKIPLAdvancedMorphology as advmorpho
import PyIPSDK.IPSDKIPLBinarization as bin
import PyIPSDK.IPSDKIPLFiltering as filter
import PyIPSDK.IPSDKIPLIntensityTransform as itrans
import PyIPSDK.IPSDKIPLShapeSegmentation as shapesegmentation
# [DocSampleImports]
def readCmdArguments(argv):
# Default parameters values
imagesSamplePath = PyIPSDK.getIPSDKDirectory(PyIPSDK.eInternalDirectory.eID_Images)
inputImgPath = os.path.join(imagesSamplePath, "shapes.tif")
inputTemplatePathList = [os.path.join(imagesSamplePath, "Templates/templateSquare.tif"),
os.path.join(imagesSamplePath, "Templates/templateTriangle.tif"),
os.path.join(imagesSamplePath, "Templates/templateHexagon.tif"),
os.path.join(imagesSamplePath, "Templates/templateCircle.tif")]
tmpPath = PyIPSDK.getIPSDKDefaultDirectory(PyIPSDK.eDefaultExternalDirectory.eDED_Tmp)
outputImgPath = os.path.join(tmpPath, "shapeMatch.tif")
outputCsvResultPath = os.path.join(tmpPath, "shapeMatch.csv")
inputThresholdBinarization = 15
inputThresholdDistance = 0.2
inputStdDev = 1
try:
# Read the command line, the second argument is a string with all the possible options (short version)
# with a ':' if the option requires an argument and the third argument is the set of trings corresponding
# to the long versions of the program options
opts, args = getopt.getopt(argv,"hi:t:o:r:b:d:s:",
["inputImgFilePath=","inTemplatePathList=",
"inThresholdBinarization=","inThresholdDistance=","inStdDev=",
"outputImgFilePath=","outputCsvResultPath="])
except getopt.GetoptError:
print('<application_script_filename> [--inputImgFilePath <input_image_file_path>] [--inTemplatePathList <input_template_file_path_list>] [--inThresholdBinarization <input_binarization_threshold>] [--inThresholdDistance <input_distance_threshold>] [--inStdDev <input_blur_standard_deviation>] [--outputImgFilePath <output_image_file_path>] [--outputCsvResultPath <output_csv_file_path>]')
sys.exit(2)
# Parse the program options
for opt, arg in opts:
if opt == '-h':
print('<application_script_filename> [--inputImgFilePath <input_image_file_path>] [--outputImgFilePath <output_image_file_path>]')
sys.exit(0)
elif opt in ("-i", "--inputImgFilePath"):
inputImgPath = arg
elif opt in ("-t", "--inTemplatePathList"):
inputTemplatePathList = arg
elif opt in ("-b", "--inThresholdBinarization"):
inputThresholdBinarization = arg
elif opt in ("-d", "--inThresholdDistance"):
inputThresholdDistance = arg
elif opt in ("-s", "--inStdDev"):
inputStdDev = arg
elif opt in ("-o", "--outputImgFilePath"):
outputImgPath = arg
elif opt in ("-r", "--outputCsvResultPath"):
outputCsvResultPath = arg
return inputImgPath, inputTemplatePathList, outputImgPath, outputCsvResultPath, inputThresholdBinarization, inputThresholdDistance, inputStdDev
# [DocSampleWriteToCsvFct]
def writeToCsvFile(outputCsvResultPath, bestMatches, threshold):
file = open(outputCsvResultPath, "w")
file.write("Shape Index;Matched Template Index; Distance\n")
# For each shape (do not process the background)
nbTemplates = len(bestMatches[0])
for i in range(0, nbTemplates) :
file.write(str(i + 1) + ";")
# Test for a bad match
if (bestMatches[1][i] < threshold):
file.write(str(bestMatches[0][i]))
else:
file.write("Bad match according to threshold ( = " + str(threshold) + ")")
file.write(";" + str(bestMatches[1][i]) + "\n")
file.close()
# [DocSampleWriteToCsvFct]
def main(argv):
# [DocSampleDefineArguments]
# Retrieve program parameters
inputImgPath, inputTemplatePathList, outputImgPath, outputCsvResultPath, inputThresholdBinarization, inputThresholdDistance, stdDev = readCmdArguments(argv)
# [DocSampleDefineArguments]
# [DocSampleLoadImage]
# Opening of input image
inImg = PyIPSDK.loadTiffImageFile(inputImgPath)
# [DocSampleLoadImage]
# [DocSampleLoadTemplateImages]
# Loading all the template images and store them in a list
templateImgList = []
nbTemplates = len(inputTemplatePathList)
for i in range(0, nbTemplates):
templateImgList.append(PyIPSDK.loadTiffImageFile(inputTemplatePathList[i]))
# [DocSampleLoadTemplateImages]
# [DocSampleBlurImages]
# Blur the images if the standard deviation is strictly positive
if stdDev > 0:
filter.gaussianSmoothing2dImg(inImg, stdDev, stdDev, PyIPSDK.createGaussianCoverage(0.99, 2), inImg)
for i in range(0, nbTemplates):
filter.gaussianSmoothing2dImg(templateImgList[i], stdDev, stdDev, PyIPSDK.createGaussianCoverage(0.99, 2), templateImgList[i])
# [DocSampleBlurImages]
# [DocSampleExtractShape]
# Label contour extraction computation for the input image
binImg = bin.thresholdImg(inImg, inputThresholdBinarization, 255)
inLabelImg = advmorpho.connectedComponent2dImg(binImg)
imShape2dColl = shapesegmentation.labelShapeExtraction2d(inLabelImg)
# Label contour extraction computation for each template
templateShapesList = []
for i in range(0, nbTemplates):
binImg = bin.thresholdImg(templateImgList[i], inputThresholdBinarization, 255)
labelImg = advmorpho.connectedComponent2dImg(binImg)
templateShape2dColl = shapesegmentation.labelShapeExtraction2d(labelImg)
templateShapesList.append(templateShape2dColl)
# [DocSampleExtractShape]
# [DocSampleApplyOp]
matchesList = []
for i in range(0, nbTemplates):
# Match shape computation
matches = PyIPSDK.matchShapes(templateShapesList[i].getColl()[1], imShape2dColl, PyIPSDK.eSDT_Type3, False)
matchesList.append(matches)
# [DocSampleApplyOp]
# [DocSampleMatchTemplate]
# Declare and allocate the collection
# bestMatches is the collection of (_shapeHuDistance, _shapeIdx) structures
# where _shapeHuDistance is the minimum distance between a shape in the
# input image and the most similar template of index _shapeIdx
bestMatches = ([], [])
nbShapes = len(matchesList[0][0])
# Initialize the best matches for each templates
for shapeIdx in range(0, nbShapes) :
bestMatch = (-1, sys.float_info.max)
# For each template
for templateIdx in range(0, nbTemplates) :
# Check if we find a new minimum distance
matches = matchesList[templateIdx]
if (bestMatch[1] > matches[1][shapeIdx]) :
bestMatch = (templateIdx, matches[1][shapeIdx])
bestMatches[0].append(bestMatch[0])
bestMatches[1].append(bestMatch[1])
# Validate the match : if the distance is lower than the input threshold,
# then the algorithm considers that the match is correct, otherwise, it
# notes the match is unsatisfying by assigning the shape index to its
# maximum possible value
if (bestMatches[1][shapeIdx] >= inputThresholdDistance):
bestMatches[0][shapeIdx] = sys.maxsize
# [DocSampleMatchTemplate]
# [DocSampleGenerateOutputImage]
# Initialize the LUT
lut = PyIPSDK.createIntensityLUT(0, 1, [])
# Add the first value : the background is 0
lut.lookupTable.append(0)
# Add the other values
nbLabels = imShape2dColl.getSize()
for i in range(1, nbLabels) :
matchIndex = bestMatches[0][i - 1] + 1
if matchIndex < sys.maxsize:
lut.lookupTable.append(matchIndex)
else:
lut.lookupTable.append(0)
# Apply the LUT
matchImg = itrans.lutTransform2dImg(inLabelImg, lut);
# [DocSampleGenerateOutputImage]
# [DocSampleSaveOutputImage]
PyIPSDK.saveTiffImageFile(outputImgPath, matchImg)
# [DocSampleSaveOutputImage]
# [DocSampleSaveCsvResult]
# save the matching results to output csv file
writeToCsvFile(outputCsvResultPath, bestMatches, inputThresholdDistance)
# [DocSampleSaveCsvResult]
if __name__ == "__main__":
main(sys.argv[1:])