Skip to content

Commit

Permalink
ADAT - Updates & improvements (#1315)
Browse files Browse the repository at this point in the history
* Resize - Updates

* APP - Inference fix

* Cleanup

* APP - Cleanup

* Add Stats

* Cleanup & updates
  • Loading branch information
kiritigowda committed Mar 28, 2024
1 parent 70e0af7 commit 67f2a65
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 31 deletions.
2 changes: 1 addition & 1 deletion amd_openvx_extensions/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ elseif(AMDRPP_FOUND AND ("${BACKEND}" STREQUAL "CPU" OR NOT(GPU_SUPPORT)))
add_subdirectory(amd_rpp)
message("-- ${Green}AMD ROCm Performance Primitives -- amd_rpp module added with CPU only backend support${ColourReset}")
else()
message("-- ${Red}WARNING:AMD RPP Not Found -- OpenVX Extension amd_rpp module excluded${ColourReset}")
message("-- ${Red}WARNING: AMD RPP Not Found -- OpenVX Extension amd_rpp module excluded${ColourReset}")
endif()

if(OpenCV_FOUND)
Expand Down
Binary file modified apps/mivisionx_inference_analyzer/data/images/MIVisionX-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 9 additions & 5 deletions apps/mivisionx_inference_analyzer/inference_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def initUI(self):
self.image_lineEdit.textChanged.connect(self.checkInput)
self.image_lineEdit.textChanged.connect(self.checkInput)
self.close_pushButton.clicked.connect(self.closeEvent)
self.file_lineEdit.setPlaceholderText("File Directory [required]")
self.file_lineEdit.setPlaceholderText("File Directory for NNEF / Model File for CAFFE/ONNX [required]")
self.name_lineEdit.setPlaceholderText("Model Name [required]")
self.idims_lineEdit.setPlaceholderText("c,h,w [required]")
self.odims_lineEdit.setPlaceholderText("c,h,w [required]")
Expand All @@ -61,22 +61,26 @@ def browseFile(self):
if self.format_comboBox.currentText() == 'nnef':
self.file_lineEdit.setText(QtWidgets.QFileDialog.getExistingDirectory(self, 'Open Folder', './'))
else:
self.file_lineEdit.setText(QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', '*'))
filename, _filter = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './')
self.file_lineEdit.setText(filename)

def browseOutput(self):
self.output_lineEdit.setText(QtWidgets.QFileDialog.getExistingDirectory(self, 'Open Folder', './'))

def browseLabel(self):
self.label_lineEdit.setText(QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', '*.txt'))
filename, _filter = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', filter="Text files (*.txt)")
self.label_lineEdit.setText(filename)

def browseImage(self):
self.image_lineEdit.setText(QtWidgets.QFileDialog.getExistingDirectory(self, 'Open Folder', './'))

def browseVal(self):
self.val_lineEdit.setText(QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', '*.txt'))
filename, _filter = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', filter="Text files (*.txt)")
self.val_lineEdit.setText(filename)

def browseHier(self):
self.hier_lineEdit.setText(QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', '*.csv'))
filename, _filter = QtWidgets.QFileDialog.getOpenFileName(self, 'Open File', './', '*.csv')
self.hier_lineEdit.setText(filename)

def readSetupFile(self):
setupDir = '~/.mivisionx-inference-analyzer'
Expand Down
83 changes: 58 additions & 25 deletions apps/mivisionx_inference_analyzer/mivisionx_inference_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__copyright__ = "Copyright 2019 - 2024, AMD MIVisionX"
__credits__ = ["Mike Schmit; Hansel Yang; Lakshmi Kumar;"]
__license__ = "MIT"
__version__ = "1.0"
__version__ = "1.1"
__maintainer__ = "Kiriti Nagesh Gowda"
__email__ = "[email protected]"
__status__ = "Shipping"
Expand All @@ -15,6 +15,7 @@
import cv2
import time
import numpy
import statistics
import numpy as np
from numpy.ctypeslib import ndpointer
from inference_control import inference_control
Expand All @@ -31,6 +32,11 @@
(0,128,255), # Top4
(255,102,102), # Top5
]
# error check calls
def ERROR_CHECK(call):
status = call
if(status != 0):
exit(status)

# AMD Neural Net python wrapper
class AnnAPI:
Expand All @@ -54,7 +60,7 @@ def __init__(self,library):
self.annRunInference = self.lib.annRunInference
self.annRunInference.restype = ctypes.c_int
self.annRunInference.argtypes = [ctypes.c_void_p, ctypes.c_int]
print('OK: AnnAPI found "' + self.annQueryInference().decode("utf-8") + '" as configuration in ' + library)
print('OK: AMD VX NN API found "' + self.annQueryInference().decode("utf-8") + '" as configuration in ' + library)

# classifier definition
class annieObjectWrapper():
Expand Down Expand Up @@ -85,15 +91,15 @@ def runInference(self, img, out):
# copy input f32 to inference input
status = self.api.annCopyToInferenceInput(self.hdl, np.ascontiguousarray(img_t, dtype=np.float32), (img.shape[0]*img.shape[1]*3*4), 0)
if(status):
print('ERROR: annCopyToInferenceInput Failed ')
print('ERROR: AMD VX NN CopyToInferenceInput Failed ')
# run inference
status = self.api.annRunInference(self.hdl, 1)
if(status):
print('ERROR: annRunInference Failed ')
print('ERROR: AMD VX NN RunInference Failed ')
# copy output f32
status = self.api.annCopyFromInferenceOutput(self.hdl, np.ascontiguousarray(out, dtype=np.float32), out.nbytes)
if(status):
print('ERROR: annCopyFromInferenceOutput Failed ')
print('ERROR: AMD VX NN CopyFromInferenceOutput Failed ')
return out

def classify(self, img):
Expand Down Expand Up @@ -260,13 +266,13 @@ def processClassificationOutput(inputImage, modelName, modelOutput):
print("\nMIVisionX Inference Analyzer\n")
# replace old model or throw error
if(replaceModel == 'yes'):
os.system('rm -rf '+modelDir)
ERROR_CHECK(os.system('rm -rf '+modelDir))
elif(os.path.exists(modelDir)):
print("OK: Model exists")

else:
print("\nMIVisionX Inference Analyzer Created\n")
os.system('(cd ; mkdir .mivisionx-inference-analyzer)')
ERROR_CHECK(os.system('(cd ; mkdir .mivisionx-inference-analyzer)'))

# Setup Text File for Demo
if (not os.path.isfile(analyzerDir + "/setupFile.txt")):
Expand All @@ -291,7 +297,7 @@ def processClassificationOutput(inputImage, modelName, modelOutput):
delModelName = data[0].split(';')[1]
delmodelPath = analyzerDir + '/' + delModelName + '_dir'
if(os.path.exists(delmodelPath)):
os.system('rm -rf ' + delmodelPath)
ERROR_CHECK(os.system('rm -rf ' + delmodelPath))
with open(analyzerDir + "/setupFile.txt", "w") as fout:
fout.writelines(data[1:])
with open(analyzerDir + "/setupFile.txt", "a") as fappend:
Expand All @@ -300,36 +306,36 @@ def processClassificationOutput(inputImage, modelName, modelOutput):

# Compile Model and generate python .so files
if (replaceModel == 'yes' or not os.path.exists(modelDir)):
os.system('mkdir '+modelDir)
ERROR_CHECK(os.system('mkdir '+modelDir))
if(os.path.exists(modelDir)):
# convert to NNIR
if(modelFormat == 'caffe'):
os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/caffe_to_nnir.py '+trainedModel+' nnir-files --input-dims 1,'+modelInputDims+' )')
ERROR_CHECK(os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/caffe_to_nnir.py '+trainedModel+' nnir-files --input-dims 1,'+modelInputDims+' )'))
elif(modelFormat == 'onnx'):
os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/onnx_to_nnir.py '+trainedModel+' nnir-files --input-dims 1,'+modelInputDims+' )')
ERROR_CHECK(os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/onnx_to_nnir.py '+trainedModel+' nnir-files --input-dims 1,'+modelInputDims+' )'))
elif(modelFormat == 'nnef'):
os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/nnef_to_nnir.py '+trainedModel+' nnir-files )')
ERROR_CHECK(os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/nnef_to_nnir.py '+trainedModel+' nnir-files )'))
else:
print("ERROR: Neural Network Format Not supported, use caffe/onnx/nnef in arugment --model_format")
quit()
# convert the model to FP16
if(FP16inference):
os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/nnir_update.py --convert-fp16 1 --fuse-ops 1 nnir-files nnir-files)')
ERROR_CHECK(os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/nnir_update.py --convert-fp16 1 --fuse-ops 1 nnir-files nnir-files)'))
print("\nModel Quantized to FP16\n")
# convert to openvx
if(os.path.exists(nnirDir)):
os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/nnir_to_openvx.py nnir-files openvx-files)')
ERROR_CHECK(os.system('(cd '+modelDir+'; python3 '+modelCompilerPath+'/nnir_to_openvx.py nnir-files openvx-files)'))
else:
print("ERROR: Converting Pre-Trained model to NNIR Failed")
quit()

# build model
if(os.path.exists(openvxDir)):
os.system('mkdir '+modelBuildDir)
ERROR_CHECK(os.system('mkdir '+modelBuildDir))
else:
print("ERROR: Converting NNIR to OpenVX Failed")
quit()
os.system('(cd '+modelBuildDir+'; cmake ../openvx-files; make; ./anntest ../openvx-files/weights.bin )')
ERROR_CHECK(os.system('(cd '+modelBuildDir+'; cmake ../openvx-files; make; ./anntest ../openvx-files/weights.bin )'))
print("\nSUCCESS: Converting Pre-Trained model to MIVisionX Runtime successful\n")

#else:
Expand Down Expand Up @@ -381,6 +387,9 @@ def processClassificationOutput(inputImage, modelName, modelOutput):

# process images
correctTop5 = 0; correctTop1 = 0; wrong = 0; noGroundTruth = 0
totalTimeForInference = 0
totalCorners = 0
listOfCorners = []
for x in range(totalImages):
imageFileName,grountTruth = imageValidation[x].split(' ')
groundTruthIndex = int(grountTruth)
Expand All @@ -393,26 +402,44 @@ def processClassificationOutput(inputImage, modelName, modelOutput):
start = time.time()
frame = cv2.imread(imageFile)
end = time.time()
totalTimeForInference += ((end - start)*1000)
if(verbosePrint):
print('%30s' % 'Read Image in ', str((end - start)*1000), 'ms')

# image complexity detection
start = time.time()
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,2,3,0.04)
numCorners = np.sum(dst > 0.01 * dst.max())
listOfCorners.append(numCorners)
totalCorners += numCorners
end = time.time()
if(verbosePrint):
print('%30s' % 'Image complexity detection in ', str((end - start)*1000), 'ms')

# resize and process frame
start = time.time()
resizedFrame = cv2.resize(frame, (w_i,h_i))
if(numCorners <= 3500):
resizedFrame = cv2.resize(frame, (w_i,h_i), interpolation = cv2.INTER_LINEAR)
else:
resizedFrame = cv2.resize(frame, (w_i,h_i), interpolation = cv2.INTER_AREA)
RGBframe = cv2.cvtColor(resizedFrame, cv2.COLOR_BGR2RGB)
if(inputAdd != '' or inputMultiply != ''):
pFrame = np.zeros(RGBframe.shape).astype('float32')
for i in range(RGBframe.shape[2]):
pFrame[:,:,i] = RGBframe.copy()[:,:,i] * Mx[i] + Ax[i]
RGBframe = pFrame
end = time.time()
totalTimeForInference += ((end - start)*1000)
if(verbosePrint):
print('%30s' % 'Input pre-processed in ', str((end - start)*1000), 'ms')

# run inference
start = time.time()
output = classifier.classify(RGBframe)
end = time.time()
totalTimeForInference += ((end - start)*1000)
if(verbosePrint):
print('%30s' % 'Executed Model in ', str((end - start)*1000), 'ms')

Expand All @@ -427,7 +454,7 @@ def processClassificationOutput(inputImage, modelName, modelOutput):
cv2.imshow(windowResult, resultImage)
end = time.time()
if(verbosePrint):
print('%30s' % 'Processed display in ', str((end - start)*1000), 'ms\n')
print('%30s' % 'Processed display in ', str((end - start)*1000), 'ms')

# write image results to a file
start = time.time()
Expand Down Expand Up @@ -504,6 +531,7 @@ def processClassificationOutput(inputImage, modelName, modelOutput):
end = time.time()
if(verbosePrint):
print('%30s' % 'Progress image created in ', str((end - start)*1000), 'ms')
print('%30s' % 'Images Processed: ', str(x), '\n\n')

# exit on ESC
key = cv2.waitKey(2)
Expand All @@ -512,22 +540,27 @@ def processClassificationOutput(inputImage, modelName, modelOutput):

# Inference Analyzer Successful
print("\nSUCCESS: Images Inferenced with the Model\n")
timePerInference = float (totalTimeForInference / totalImages)
print('%30s' % 'Time per image Inference ', str(timePerInference), 'ms')
avgCornersPerImage = float(totalCorners / totalImages )
print('%30s' % 'Avg number of corners per image: ', str(avgCornersPerImage))
print('%30s' % 'Mean number of corners per image: ', str(statistics.mean(listOfCorners)))
cv2.destroyWindow(windowInput)
cv2.destroyWindow(windowResult)

# Create ADAT folder and file
print("\nADAT tool called to create the analysis toolkit\n")
if(not os.path.exists(adatOutputDir)):
os.system('mkdir ' + adatOutputDir)
ERROR_CHECK(os.system('mkdir -p ' + adatOutputDir))

if(hierarchy == ''):
os.system('python '+ADATPath+'/generate-visualization.py --inference_results '+finalImageResultsFile+
' --image_dir '+inputImageDir+' --label '+labelText+' --model_name '+modelName+' --output_dir '+adatOutputDir+' --output_name '+modelName+'-ADAT')
ERROR_CHECK(os.system('python '+ADATPath+'/generate-visualization.py --inference_results '+finalImageResultsFile+
' --image_dir '+inputImageDir+' --label '+labelText+' --model_name '+modelName+' --output_dir '+adatOutputDir+' --output_name '+modelName+'-ADAT'))
else:
os.system('python '+ADATPath+'/generate-visualization.py --inference_results '+finalImageResultsFile+
' --image_dir '+inputImageDir+' --label '+labelText+' --hierarchy '+hierarchyText+' --model_name '+modelName+' --output_dir '+adatOutputDir+' --output_name '+modelName+'-ADAT')
ERROR_CHECK(os.system('python '+ADATPath+'/generate-visualization.py --inference_results '+finalImageResultsFile+
' --image_dir '+inputImageDir+' --label '+labelText+' --hierarchy '+hierarchyText+' --model_name '+modelName+' --output_dir '+adatOutputDir+' --output_name '+modelName+'-ADAT'))
print("\nSUCCESS: Image Analysis Toolkit Created\n")
print("Press ESC to exit or close progess window\n")
print("Press ESC to exit or close progress window\n")

# Wait to quit
while True:
Expand All @@ -539,4 +572,4 @@ def processClassificationOutput(inputImage, modelName, modelOutput):
break

outputHTMLFile = os.path.expanduser(adatOutputDir+'/'+modelName+'-ADAT-toolKit/index.html')
os.system('firefox '+outputHTMLFile)
ERROR_CHECK(os.system('firefox '+outputHTMLFile))

0 comments on commit 67f2a65

Please sign in to comment.