diff --git a/3_runCntk.py b/3_runCntk.py index d811850..06f606d 100644 --- a/3_runCntk.py +++ b/3_runCntk.py @@ -1,68 +1,37 @@ -import os, sys, importlib -import shutil, time -import subprocess -import PARAMETERS -locals().update(importlib.import_module("PARAMETERS").__dict__) +from PARAMETERS import * +import numpy as np +import os, sys, pdb +#TODO: move all cntk imports (and hence also code) inside here and then remove from helpers.py + #################################### -# Parameters +# MAIN #################################### -print "classifier = " + classifier -cntkCmdStrPattern = "{0}/cntk.exe configFile={1}config.cntk currentDirectory={1}" +makeDirectory(modelDir) +print ("classifier = " + classifier) +print ("cntk_lr_per_image = " + str(cntk_lr_per_image)) - - -#################################### -# Main -#################################### -deleteAllFilesInDirectory(cntkFilesDir + "/tmp", None) -shutil.copy(os.path.join(cntkResourcesDir, "config.cntk"), cntkFilesDir) - -#generate cntk command string -cmdStr = cntkCmdStrPattern.format(cntkBinariesDir, cntkFilesDir, classifier) -cmdStr += " ImageH={} ImageW={}".format(cntk_padHeight, cntk_padWidth) -cmdStr += " NumLabels={0} NumTrainROIs={1} NumTestROIs={1}".format(len(classes), cntk_nrRois) -cmdStr += " TrainROIDim={} TrainROILabelDim={}".format(4*cntk_nrRois, cntk_nrRois * cntk_featureDimensions[classifier]) -cmdStr += " TestROIDim={} TestROILabelDim={}".format( 4*cntk_nrRois, cntk_nrRois * cntk_featureDimensions[classifier]) +# optionally retrain DNN +# if the classifier is svm, then simply return the 4096-floats penultimate layer as model +# otherwise add new output layer, retrain the DNN, and return this new model. if classifier == 'svm': - cmdStr += " [Train=[SGD=[maxEpochs=0]]]" #no need to train the network if just using it as featurizer - cmdStr += " [WriteTest=[outputNodeNames=(z.fcOut.h2.y)]]" - cmdStr += " [WriteTrain=[outputNodeNames=(z.fcOut.h2.y)]]" + boSkipTraining = True +else: + boSkipTraining = False +model = init_train_fast_rcnn(cntk_padHeight, cntk_padWidth, nrClasses, cntk_nrRois, cntk_mb_size, cntk_max_epochs, + cntk_lr_per_image, cntk_l2_reg_weight, cntk_momentum_time_constant, cntkFilesDir, boSkipTraining) -#run cntk -tstart = datetime.datetime.now() -os.environ['ACML_FMA'] = str(0) -print cmdStr -pid = subprocess.Popen(cmdStr, cwd = cntkFilesDir) #, creationflags=subprocess.CREATE_NEW_CONSOLE) -pid.wait() -print ("Time running cntk [s]: " + str((datetime.datetime.now() - tstart).total_seconds())) +# write model to disk +model_path = os.path.join(modelDir, "frcn_" + classifier + ".model") +print("Writing model to %s" % model_path) +model.save_model(model_path) -#delete model files written during cntk training -filenames = getFilesInDirectory(cntkFilesDir + "/tmp/", postfix = None) -for filename in filenames: - if filename.startswith('Fast-RCNN.'): - os.remove(cntkFilesDir + "/tmp/" + filename) -assert pid.returncode == 0, "ERROR: cntk ended with exit code {}".format(pid.returncode) - -#parse cntk output +# compute output of every image and write to disk image_sets = ["test", "train"] for image_set in image_sets: - print "Parsing CNTK output for image set: " + image_set - cntkImgsListPath = cntkFilesDir + image_set + ".txt" outParsedDir = cntkFilesDir + image_set + "_" + classifier + "_parsed/" - if classifier == 'svm': - cntkOutputPath = cntkFilesDir + image_set + ".z.fcOut.h2.y" - elif classifier == 'nn': - cntkOutputPath = cntkFilesDir + image_set + ".z" - else: - error - - #write cntk output for each image to separate file makeDirectory(outParsedDir) - parseCntkOutput(cntkImgsListPath, cntkOutputPath, outParsedDir, cntk_nrRois, cntk_featureDimensions[classifier], - saveCompressed = True, skipCheck = True) #, skip5Mod = 0) + run_fast_rcnn(model, image_set, cntk_padHeight, cntk_padWidth, nrClasses, cntk_nrRois, cntkFilesDir, outParsedDir) - #delete cntk output file which can be very large and are no longer needed - deleteFile(cntkOutputPath) -print "DONE." \ No newline at end of file +print("DONE.") \ No newline at end of file diff --git a/3_runCntk_brainscript.py b/3_runCntk_brainscript.py new file mode 100644 index 0000000..18c7a8d --- /dev/null +++ b/3_runCntk_brainscript.py @@ -0,0 +1,70 @@ +import os, sys, importlib +import shutil, time +import subprocess +import PARAMETERS +locals().update(importlib.import_module("PARAMETERS").__dict__) + + + +#################################### +# Parameters +#################################### +print("classifier = " + classifier) +cntkCmdStrPattern = "{0}/cntk.exe configFile={1}config.cntk currentDirectory={1}" + + + +#################################### +# Main +#################################### +deleteAllFilesInDirectory(cntkFilesDir + "/tmp", None) +shutil.copy(os.path.join(cntkResourcesDir, "config.cntk"), cntkFilesDir) + +#generate cntk command string +cmdStr = cntkCmdStrPattern.format(cntkBinariesDir, cntkFilesDir, classifier) +cmdStr += " ImageH={} ImageW={}".format(cntk_padHeight, cntk_padWidth) +cmdStr += " NumLabels={0} NumTrainROIs={1} NumTestROIs={1}".format(len(classes), cntk_nrRois) +cmdStr += " TrainROIDim={} TrainROILabelDim={}".format(4*cntk_nrRois, cntk_nrRois * cntk_featureDimensions[classifier]) +cmdStr += " TestROIDim={} TestROILabelDim={}".format( 4*cntk_nrRois, cntk_nrRois * cntk_featureDimensions[classifier]) +if classifier == 'svm': + cmdStr += " [Train=[SGD=[maxEpochs=0]]]" #no need to train the network if just using it as featurizer + cmdStr += " [WriteTest=[outputNodeNames=(z.fcOut.h2.y)]]" + cmdStr += " [WriteTrain=[outputNodeNames=(z.fcOut.h2.y)]]" + +#run cntk +tstart = datetime.datetime.now() +os.environ['ACML_FMA'] = str(0) +print(cmdStr) +pid = subprocess.Popen(cmdStr, cwd = cntkFilesDir) #, creationflags=subprocess.CREATE_NEW_CONSOLE) +pid.wait() +print ("Time running cntk [s]: " + str((datetime.datetime.now() - tstart).total_seconds())) + +#delete model files written during cntk training +filenames = getFilesInDirectory(cntkFilesDir + "/tmp/", postfix = None) +for filename in filenames: + if filename.startswith('Fast-RCNN.'): + os.remove(cntkFilesDir + "/tmp/" + filename) +assert pid.returncode == 0, "ERROR: cntk ended with exit code {}".format(pid.returncode) + +#parse cntk output +print("classifier = " + classifier) +image_sets = ["test", "train"] +for image_set in image_sets: + print("Parsing CNTK output for image set: " + image_set) + cntkImgsListPath = cntkFilesDir + image_set + ".txt" + outParsedDir = cntkFilesDir + image_set + "_" + classifier + "_parsed/" + if classifier == 'svm': + cntkOutputPath = cntkFilesDir + image_set + ".z.fcOut.h2.y" + elif classifier == 'nn': + cntkOutputPath = cntkFilesDir + image_set + ".z" + else: + error + + #write cntk output for each image to separate file + makeDirectory(outParsedDir) + parseCntkOutput(cntkImgsListPath, cntkOutputPath, outParsedDir, cntk_nrRois, cntk_featureDimensions[classifier], + saveCompressed = True, skipCheck = False) #, skip5Mod = 0) + + #delete cntk output file which can be very large and are no longer needed + deleteFile(cntkOutputPath) +print("DONE.") \ No newline at end of file diff --git a/6_scoreImage.py b/6_scoreImage.py new file mode 100644 index 0000000..7619706 --- /dev/null +++ b/6_scoreImage.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +import sys, os, importlib, random +import PARAMETERS +import json + +locals().update(importlib.import_module("PARAMETERS").__dict__) + +#################################### +# Parameters +#################################### +imgPath = r"C:\Users\pabuehle\Desktop\newImgs\WIN_20160803_11_48_26_Pro.jpg" +svm_experimentName = 'exp1' +classifier = 'nn' + +# no need to change these parameters +boAddSelectiveSearchROIs = True +boAddGridROIs = True +boFilterROIs = True +boUseNonMaximaSurpression = True + + +#################################### +# Mainpip +#################################### +# load cntk model +print("Loading DNN..") +tstart = datetime.datetime.now() +model_path = os.path.join(modelDir, "frcn_" + classifier + ".model") +model = load_model(model_path) +print("Time loading DNN [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) + +# load trained svm +if classifier == "svm": + print("Loading svm weights..") + tstart = datetime.datetime.now() + svmWeights, svmBias, svmFeatScale = loadSvm(trainedSvmDir, svm_experimentName) + print("Time loading svm [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) +else: + svmWeights, svmBias, svmFeatScale = (None, None, None) + +# compute ROIs +tstart = datetime.datetime.now() +imgOrig = imread(imgPath) +currRois = computeRois(imgOrig, boAddSelectiveSearchROIs, boAddGridROIs, boFilterROIs, ss_kvals, ss_minSize, + ss_max_merging_iterations, ss_nmsThreshold, + roi_minDimRel, roi_maxDimRel, roi_maxImgDim, roi_maxAspectRatio, roi_minNrPixelsRel, + roi_maxNrPixelsRel, grid_nrScales, grid_aspectRatios, grid_downscaleRatioPerIteration) +currRois = currRois[:cntk_nrRois] # only keep first cntk_nrRois rois +print("Time roi computation [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) + +# prepare DNN inputs +tstart = datetime.datetime.now() +imgPadded = imresizeAndPad(imgOrig, cntk_padWidth, cntk_padHeight) +_, _, roisCntk = getCntkInputs(imgPath, currRois, None, train_posOverlapThres, nrClasses, cntk_nrRois, cntk_padWidth, cntk_padHeight) +arguments = { + model.arguments[0]: [np.ascontiguousarray(np.array(imgPadded, dtype=np.float32).transpose(2, 0, 1))], # convert to CNTK's HWC format + model.arguments[1]: [np.array(roisCntk)] +} +print("Time cnkt input generation [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) + +# run DNN model +print("Running model..") +tstart = datetime.datetime.now() +dnnOutputs = model.eval(arguments)[0][0] +dnnOutputs = dnnOutputs[:len(currRois)] # remove the zero-padded rois +print("Time running model [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) + +# score all ROIs +tstart = datetime.datetime.now() +labels, scores = scoreRois(classifier, dnnOutputs, svmWeights, svmBias, svmFeatScale, len(classes), + decisionThreshold = vis_decisionThresholds[classifier]) +print("Time making prediction [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) + +# perform non-maxima surpression +tstart = datetime.datetime.now() +nmsKeepIndices = [] +if boUseNonMaximaSurpression: + nmsKeepIndices = applyNonMaximaSuppression(nmsThreshold, labels, scores, currRois) + print("Non-maxima surpression kept {:4} of {:4} rois (nmsThreshold={})".format( + len(nmsKeepIndices), len(labels), nmsThreshold)) +print("Time non-maxima surpression [ms]: " + str((datetime.datetime.now() - tstart).total_seconds() * 1000)) + +# visualize results +imgDebug = visualizeResults(imgPath, labels, scores, currRois, cntk_padWidth, cntk_padHeight, + classes, nmsKeepIndices, boDrawNegativeRois=False, boDrawNmsRejectedRois=False) +imshow(imgDebug, waitDuration=0, maxDim=800) +#imwrite(imgDebug, visualizationDir + "/" + classifier + "_" + str(imgIndex) + os.path.basename(imgPath)) + +# create json-encoded string of all detections +outDict = [{"label": str(l), "score": str(s), "left": str(r[0]), "top": str(r[1]), "right": str(r[2]), "bottom": str(r[3])} for l,s, r in zip(labels, scores, currRois)] +outJsonString = json.dumps(outDict) +print("Json-encoded detections: " + outJsonString[:120] + "...") + +print("DONE.") diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29