MlModel prediction returns nil - swift

I converted an ONNX model to mlmodel and I'm unable to use the prediction function.
here is my model's input and output:
[enter image description here][1]
[1]: https://i.stack.imgur.com/6mY4H.png
i'm initializing the model and the input like this:
var model: dont_touch_model!
var modelInputVector = try! MLMultiArray(shape: [1,1,13], dataType: MLMultiArrayDataType.float32)
I fill the vector with motion data like this:
modelInputVector[[0, 0, 0] as [NSNumber]] = deviceMotion.userAcceleration.x as NSNumber
modelInputVector[[0, 0, 1] as [NSNumber]] = deviceMotion.userAcceleration.y as NSNumber
modelInputVector[[0, 0, 2] as [NSNumber]] = deviceMotion.userAcceleration.z as NSNumber
I try to execute a prediction:
let modelInput = dont_touch_modelInput(sequenceinput: modelInputVector)
var modelOutput = try! model.prediction(input: modelInput)
and I get this error message:
"Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"
can someone please help?

Related

Convert AVAudioPCMBuffer into MLMultiArray and get prediction from CoreML model

I try to send AVAudioPCMBuffer into a coreML model and get the output from it. Input of the model is MultiArray (Float32 0 × 64 × 0) and output is MultiArray (Float32 0 × 0 × 36).
inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
let buff = buffer.floatChannelData?.pointee
let config = MLModelConfiguration()
let hafiz = try! asr_hafiz(configuration: config)
if let buff = buff {
let mlData = try! MLMultiArray(dataPointer: buff, shape: [0,64,0], dataType: .float32, strides: [0,64,0])
let input = asr_hafizInput(audio_signal: mlData)
let options = MLPredictionOptions()
let output = try! hafiz.model.prediction(from: input, options: options)
} else {
print("buff is nil")
}
}
I tried to convert AVAudioPCMBuffer into MLMultiArray model accepts the input but when prediction method is called I get the following error
2022-05-14 12:18:02.842630+0300 VoiceRecognitionTest[7329:5846863] [espresso] [Espresso::handle_ex_plan] exception=Espresso exception: "Invalid state": Null output blobs [Exception from Layer: 1: Conv_0]
2022-05-14 12:18:02.842686+0300 VoiceRecognitionTest[7329:5846863] [coreml] Error computing NN outputs -1
2022-05-14 12:18:02.842722+0300 VoiceRecognitionTest[7329:5846863] [coreml] Failure in -executePlan:error:.
VoiceRecognitionTest/ViewController.swift:252: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.apple.CoreML Code=0 "Error computing NN outputs." UserInfo={NSLocalizedDescription=Error computing NN outputs.}

How to initialise a multi-dimensional MLMultiArray

I'm hosting a CoreML model that takes a MLMultiArray of rank 4 as its input:
My input data is as follows:
let inputArray: [[[Float]]]
But I can't figure out how to initialise the MLMultiArray from it. Here are some attempts:
MLMultiArray(inputArray) // error: No exact matches in call to initializer
let multiArray = try! MLMultiArray(shape: [0, 128, 128, 1], dataType: .float32)
multiArray[0,1] = inputArray[0] // Cannot assign value of type '[[Float]]' to subscript of type 'NSNumber'
memset(multiArray.dataPointer, 0, 128*128) // EXC_BAD_ACCESS (code=1, address=0x0)
How do you initialise such a MLMultiArray?
Initialising it as
let input = try! MLMultiArray(shape: [1, 128, 128, 1], dataType: .float64)
is correct (note that I edited the input shape in coremltools).
The populating should be as follows:
for batchIndex in 0..<inputArray.count {
for heightIndex in 0..<inputArray[0].count {
for widthIndex in 0..<inputArray[0][0].count {
input[[batchIndex, heightIndex, widthIndex, 0] as [NSNumber]] = (inputArray[batchIndex][heightIndex][widthIndex]) as NSNumber
}
}
}

Unwrapping issue with AXUIElementCopyAttributeValue in Mac OS

I'm trying to copy some information regarding an accessibility window option. Unfortunately, I can't resolve an error that's caused by the AXUIElementCopyAttributeValue method, despite passing in what appears to be all the correct types as parameters.
Code:
for entry in windowList! as Array {
let ownerName: String = entry.object(forKey: kCGWindowName) as? String ?? "N/A"
let ownerPID: Int = entry.object(forKey: kCGWindowOwnerPID) as? Int ?? 0
let pid = Int32(ownerPID)
//3. Get AXUIElement using PID
let windowAccessibilityElem : AXUIElement = AXUIElementCreateApplication(pid)
print(windowAccessibilityElem)
var position : CFTypeRef? = nil
/****
* This line throws the error
****/
let res : AXError = AXUIElementCopyAttributeValue(windowAccessibilityElem, kAXPositionAttribute as CFString, position as! UnsafeMutablePointer<CFTypeRef?>)
print("res is: \(res)")
...
I'm new to Swift, yet I've read and re-read the documentation on optionals and it really isn't apparent what unexpected value is being passed in- I think it has to do with the position variable, but from what I see I should be passing in the reference correctly. Any help would be apprediated.
You have to assign the pointer to the variable with the in-out operator &
var position : CFTypeRef?
let res : AXError = AXUIElementCopyAttributeValue(windowAccessibilityElem,
kAXPositionAttribute as CFString,
&position)
res contains the error on failure.
position contains the position on success.
In the documentation an in-out parameter is indicated by On return, ...

How do you initialize NSXMLDocument with an XML string in Swift?

I'm trying to acquire values from an xml string, but being new to Swift I can't figure out how to initialize the NSXMLDocument object. I'm trying:
var xmlString:String = "<?xml version=\"1.0\"><results><item1><name>Something</name><price>10.99</price></item1></results>"
var xml:NSXMLDocument = NSXMLDocument(xmlString)
I'm getting the error "Cannot find an overload for 'init' that accepts the supplied arguments". I've tried converting the string to NSData but I end up with the same error:
var nsData:NSData = xmlString.dataUsingEncoding(NSUTF8StringEncoding)
var xml:NSXMLDocument = NSXMLDocument(nsData)
NSXMLDocument doesn't contain an initializer than only takes a string as a parameter. There is initWithXMLString:options:error: though, which should solve your problem. Something like:
let xmlString = "<?xml version=\"1.0\"><results><item1><name>Something</name><price>10.99</price></item1></results>"
var error: NSError?
let xml = NSXMLDocument(XMLString: xmlString, options: 0, error: &error)

How to correctly initialize an UnsafePointer in Swift?

I'm trying to use CTFontCreatePathForGlyph(font: CTFont?, glyph: CGGlyph, transform: CConstPointer<CGAffineTransform>):
let myFont = CTFontCreateWithName("Helvetica", 12, nil)
let myGlyph = CTFontGetGlyphWithName(myFont, "a")
let myTransform = CGAffineTransformIdentity
But how do I correctly pass myTransform to CTFontCreatePathForGlyph?
I've tried creating a myTransformPointer to pass to the function like so:
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer().initialize(newvalue: myTransform)
but I get this error:
Playground execution failed: error: <REPL>:20:76: error: '()' is not convertible to 'UnsafePointer<CGAffineTransform>'
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer().initialize(newvalue: myTransform)
so then I tried explicitly naming the type:
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer<CGAffineTransform>().initialize(newvalue: myTransform)
and then I get a different error:
Playground execution failed: error: <REPL>:20:95: error: could not find an overload for 'init' that accepts the supplied arguments
var myTransformPointer: UnsafePointer<CGAffineTransform> = UnsafePointer<CGAffineTransform>().initialize(newvalue: myTransform)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The auto-complete suggests this should work?
The simplest solution is using withUnsafePointer function:
let myFont = CTFontCreateWithName("Helvetica", 12, nil)
let myGlyph = CTFontGetGlyphWithName(myFont, "a")
var myTransform = CGAffineTransformIdentity
var path = withUnsafePointer(&myTransform) { (pointer: UnsafePointer<CGAffineTransform>) -> (CGPath) in
return CTFontCreatePathForGlyph(myFont, myGlyph, pointer)
}
The initialize is not a constructor. You would have to alloc a new memory using UnsafePointer<T>.alloc, then initialize and then dealloc. Function withUnsafePointer does that all for you.
Note that myTransform cannot be a constant (var not let) otherwise you cannot use it for an inout param (&myTransform).