I am a newcomer to Swift and iOS development, so apologies upfront for this. I would like to ask for help around queuing and the UI (at least I think this is my problem!)
I am trying to enable the camera, via AVFoundation, in order to get a near real-time stream of images that I can pass on for CoreML analysis.
Currently, I am at the debugging / data learning stage. Essentially, I would like to take sample footage and save it all to an on-device CoreData [SQLite] database, that I can then analyse further offline. I can then learn from the results to fine tune / filter images / etc.
If I supply an individual image, the image model is able to provide descending order of “confidence” with up to 1000 rows. I recorded all this as part of the analysis by adding an extra counter integer to the [VNClassificationObservation] array and adding this to the CoreData database.
This doesn’t work with the stream from the camera. The counter doesnt seem to work, with everything having a counter value of 1000…
The tap gesture in viewDidLoad() function has also stopped working with these changes. I wonder if its related to the queuing stuff, as the text label doesnt properly reset either though I can see it updating for a millisecond or so...
func setupCameraSession() {
<<bunch of stuff to initialise devices, etc>>
cameraLayer = AVCaptureVideoPreviewLayer(session: cameraSession)
cameraLayer.frame = layer.frame
layer.addSublayer(cameraLayer)
cameraSession.startRunning()
cameraOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))
}
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
processCameraBuffer(sampleBuffer: sampleBuffer)
}
func processCameraBuffer(sampleBuffer: CMSampleBuffer) {
let coreMLModel = Inceptionv3()
if let model = try? VNCoreMLModel(for: coreMLModel.model) {
let request = VNCoreMLRequest(model: model, completionHandler: { (request, error) in
if let results = request.results as? [VNClassificationObservation] {
var counter = 1
for classification in results {
DispatchQueue.main.async(execute: {
let timestamp = NSDate().timeIntervalSince1970
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newItem = NSEntityDescription.insertNewObject(forEntityName: "Predictions", into: context)
newItem.setValue(classification.confidence, forKey: "confidence")
newItem.setValue(classification.identifier, forKey: "identifier")
newItem.setValue(counter, forKey: "index")
newItem.setValue(timestamp, forKey: "timestamp")
let confidence = String(format: "%.2f", classification.confidence * 100)
self.labelPrediction.text = "\(confidence)%"
do {
try context.save()
} catch {
print("CoreData Save error")
}
})
counter += 1
}
}
})
if let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
try? handler.perform([request])
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
imagePicker.delegate = self
if let imageIcon = UIImage(named: "icon_512") {
layer.contentsGravity = kCAGravityResizeAspect
layer.contents = imageIcon.cgImage
}
let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.releaseCamera))
viewCamera.addGestureRecognizer(tap)
}
I would like to understand more about the queuing process in order to achieve this, so that I can record every "confidence" row from the CoreML model and to always have the camera disable when the "tap" function is pressed (i.e. the screen is touched).
Thanks