Para clasificar una imagen, puede utilizar el Video marco para preparar la imagen para la clasificación.
Importe el marco de Vision colocando la declaración de importación justo debajo del UIKit
importar por encima de la declaración de clase:
import Vision
Usarás algo llamado VNCoreMLRequest
que utilizará un ejemplo del modelo Core ML para la clasificación de imágenes.
Aplicar el siguiente código debajo del viewDidLoad(:)
, lea los comentarios en línea con atención:
lazy var classificationRequest: VNCoreMLRequest = {
do {
// Instantiate the Core ML model
let model = try VNCoreMLModel(for: ProductImageClassifier_1(configuration: MLModelConfiguration()).model)
// Create a VNCoreMLRequest passing in the model and starting the classification process in the completionHandler.
let request = VNCoreMLRequest(model: model, completionHandler: { [weak self] request, error in
self?.processClassifications(for: request, error: error)
})
// Crop and scale the image
request.imageCropAndScaleOption = .centerCrop
return request
} catch {
fatalError("Failed to load Vision ML model: (error)")
}
}()
Entonces desea aplicar un método para cumplir con las solicitudes.
Agrega un método llamado updateClassifications(for:)
:
/// - Tag: PerformRequests
func updateClassifications(for image: UIImage) {
// show the loading indicator
self.showFioriLoadingIndicator("Finding similar products...")
// make sure the orientation of the image is passed in the CGImagePropertyOrientation to set the orientation of the image
let orientation = CGImagePropertyOrientation(image.imageOrientation)
// Create a CIImage as needed by the model for classification. If that fails throw a fatalError.
guard let ciImage = CIImage(image: image) else { fatalError("Unable to create (CIImage.self) from (image).") }
// Dispatch to the Global queue to asynchronously perform the classification request.
DispatchQueue.global(qos: .userInitiated).async {
let handler = VNImageRequestHandler(ciImage: ciImage, orientation: orientation)
do {
try handler.perform([self.classificationRequest])
} catch {
/*
This handler catches general image processing errors. The `classificationRequest`'s
completion handler `processClassifications(_:error:)` catches errors specific
to processing that request.
*/
print("Failed to perform classification.n(error.localizedDescription)")
}
}
}
En este momento, el código anterior sumará errores de tiempo. Necesitas una extensión CGImagePropertyOrientation
para orientación UIImage
hacia CGImagePropertyOrientation
.
Crea una nueva clase Swift con el nombre CGImagePropertyOrientation+UIImageOrientation
sa Navegador de proyectos.
En esa clase de extensión, reemplace el código con las siguientes líneas:
import UIKit
import ImageIO
extension CGImagePropertyOrientation {
init(_ orientation: UIImage.Orientation) {
switch orientation {
case .up: self = .up
case .upMirrored: self = .upMirrored
case .down: self = .down
case .downMirrored: self = .downMirrored
case .left: self = .left
case .leftMirrored: self = .leftMirrored
case .right: self = .right
case .rightMirrored: self = .rightMirrored
@unknown default:
fatalError()
}
}
}
Vuelve al ProductClassificationTableViewController.swift
clasificación y aplicación de un método que procesa la clasificación de la imagen. Este método obtendrá los productos de acuerdo con el resultado de la clasificación.
Aplicar el siguiente método directamente debajo updateClassifications(for:)
y lea los comentarios en línea con atención:
/// - Tag: ProcessClassifications
func processClassifications(for request: VNRequest, error: Error?) {
// Use the main dispatch queue
DispatchQueue.main.async {
// Check if the results are nil and display the error in an Alert Dialogue
guard let results = request.results else {
self.logger.error("Unable to classify image.", error: error)
AlertHelper.displayAlert(with: "Unable to classify image.", error: error, viewController: self)
return
}
// The `results` will always be `VNClassificationObservation`s, as specified by the Core ML model in this project.
let classifications = results as! [VNClassificationObservation]
if classifications.isEmpty {
AlertHelper.displayAlert(with: "Couldn't recognize the image", error: nil, viewController: self)
} else {
// Retrieve top classifications ranked by confidence.
let topClassifications = classifications.prefix(2)
let categoryNames = topClassifications.map { classification in
return String(classification.identifier)
}
// Safe unwrap the first classification, because that will be the category with the highest confidence.
guard let category = categoryNames.first else {
AlertHelper.displayAlert(with: "Unable to identify product category", error: nil, viewController: self)
self.logger.error("Something went wrong. Please check the classification code.")
return
}
// Set the Navigation Bar's title to the classified category
self.navigationItem.title = category
// Define a DataQuery to only fetch the products matching the classified product category
let query = DataQuery().filter(Product.categoryName == category)
// Fetch the products matching the defined query
self.dataService?.fetchProducts(matching: query) { [weak self] result, error in
if let error = error {
AlertHelper.displayAlert(with: "Failed to load list of products!", error: error, viewController: self!)
self?.logger.error("Failed to load list of products!", error: error)
return
}
// Hide the loading indicator
self?.hideFioriLoadingIndicator()
self?.products = result!
// You will display the product images as well, for that reason create a new array containing the picture urls.
self?.productImageURLs = result!.map { $0.pictureUrl ?? "" }
self?.tableView.reloadData()
}
}
}
}
Pon el productImageURLs
propiedades debajo de las propiedades de la matriz de productos arriba en la clase:
private var productImageURLs = [String]()
El último paso sería llamar al updateClassifications(for:)
método dentro del viewDidLoad(_:)
método como la última línea de código:
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 80
tableView.rowHeight = UITableView.automaticDimension
tableView.register(FUIObjectTableViewCell.self, forCellReuseIdentifier: FUIObjectTableViewCell.reuseIdentifier)
updateClassifications(for: image)
}
Eso es todo lo que tiene que hacer para clasificar una imagen con Vision y un modelo Core ML previamente entrenado.
Continúe con el tutorial para implementar la visualización de productos en la vista de tabla.