My app uses the Vision framework to find images that are visually similar. Before WWDC23, this code worked predictably to request image observations and compare images:
private func observe(cgImage: CGImage?) -> VNFeaturePrintObservation? {
var returnVal: VNFeaturePrintObservation? = nil
guard let cgImage = cgImage else {return returnVal}
let imageRequestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
let request = VNGenerateImageFeaturePrintRequest()
request.usesCPUOnly = true
do {
try imageRequestHandler.perform([request])
returnVal = request.results?.first as? VNFeaturePrintObservation
} catch {
}
return returnVal
}
func similarity(to compareAsset: Asset) -> Float {
var dist = Float.infinity
if let obs = self.observation, let compareObs = compareAsset.observation {
try? obs.computeDistance(&dist, to: compareObs)
}
return dist
}
In the new frameworks, there is a new VNGenerateImageFeaturePrintRequestRevision value, and observations made with different request revisions can't be compared. If you try, you get an error:
Error Domain=com.apple.vis Code=12 "The revision of the observations do not match" UserInfo={NSLocalizedDescription=The revision of the observations do not match}.
The docs state that by explicitly setting the new VNGenerateImageFeaturePrintRequestRevision property on my requests, I can force the request to use a particular version. But I've updated the above code to do this, but explicitly setting the revision of my request doesn't work, and my app still gets tons of errors about mismatched request revisions. Here's the updated code:
private func observe(cgImage: CGImage?) -> VNFeaturePrintObservation? {
var returnVal: VNFeaturePrintObservation? = nil
guard let cgImage = cgImage else {return returnVal}
let imageRequestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])
let request = VNGenerateImageFeaturePrintRequest()
if #available(iOS 17.0, *) {
request.revision = VNGenerateImageFeaturePrintRequestRevision2
} else {
request.revision = VNGenerateImageFeaturePrintRequestRevision1
}
request.usesCPUOnly = true
do {
try imageRequestHandler.perform([request])
returnVal = request.results?.first as? VNFeaturePrintObservation
} catch {
print("\(type(of: self)) :: \(#function) :: error in observation request \(error)")
}
return returnVal
}
func similarity(to compareAsset: Asset) -> Float {
var dist = Float.infinity
if let obs = self.observation, let compareObs = compareAsset.observation {
do {
try obs.computeDistance(&dist, to: compareObs)
} catch {
print("\(type(of: self)) :: \(#function) :: error in simvalue \(error)")
if (error as NSError).code == 12 {
let revision = obs.requestRevision
let compareRevision = compareObs.requestRevision
print("\(type(of: self)) :: \(#function) :: simValue req mismatch \(revision) \(compareRevision)")
}
}
}
return dist
}
This breaks my app, and I can't figure out how to reliably force requests to the revision number I need. What am I doing wrong here? Will this behavior sort itself out as the SDK evolves?
Thanks y'all