in sam2-cli/MainCommand.swift [48:99]
mutating func run() async throws {
// TODO: specify directory with loadable .mlpackages instead
let sam = try await SAM2.load()
print("Models loaded in: \(String(describing: sam.initializationTime))")
let targetSize = sam.inputSize
// Load the input image
guard let inputImage = CIImage(contentsOf: URL(filePath: input), options: [.colorSpace: NSNull()]) else {
print("Failed to load image.")
throw ExitCode(EXIT_FAILURE)
}
print("Original image size \(inputImage.extent)")
// Resize the image to match the model's expected input
let resizedImage = inputImage.resized(to: targetSize)
// Convert to a pixel buffer
guard let pixelBuffer = context.render(resizedImage, pixelFormat: kCVPixelFormatType_32ARGB) else {
print("Failed to create pixel buffer for input image.")
throw ExitCode(EXIT_FAILURE)
}
// Execute the model
let clock = ContinuousClock()
let start = clock.now
try await sam.getImageEncoding(from: pixelBuffer)
let duration = clock.now - start
print("Image encoding took \(duration.formatted(.units(allowed: [.seconds, .milliseconds])))")
let startMask = clock.now
let pointSequence = zip(points, types).map { point, type in
SAMPoint(coordinates:point, category:type.asCategory)
}
try await sam.getPromptEncoding(from: pointSequence, with: inputImage.extent.size)
guard let maskImage = try await sam.getMask(for: inputImage.extent.size) else {
throw ExitCode(EXIT_FAILURE)
}
let maskDuration = clock.now - startMask
print("Prompt encoding and mask generation took \(maskDuration.formatted(.units(allowed: [.seconds, .milliseconds])))")
// Write masks
if let mask = mask {
context.writePNG(maskImage, to: URL(filePath: mask))
}
// Overlay over original and save
guard let outputImage = maskImage.withAlpha(0.6)?.composited(over: inputImage) else {
print("Failed to blend mask.")
throw ExitCode(EXIT_FAILURE)
}
context.writePNG(outputImage, to: URL(filePath: output))
}