回答我自己的问题:
结果表明每个通道的结果像素代表它是该通道所代表的类的可能性。
换句话说就是找到某个位置的最大像素值。具有最高值的通道是类像素。
func getLabelsForImage() {
....
setup model here
....
guard let output = try? model.prediction(input: input) else {
fatalError("Could not generate model output.")
}
let channelCount = 10
// Ugly, I know. But works:
let colors = [NSColor.red.usingColorSpace(.sRGB)!, NSColor.blue.usingColorSpace(.sRGB)!, NSColor.green.usingColorSpace(.sRGB)!, NSColor.gray.usingColorSpace(.sRGB)!, NSColor.yellow.usingColorSpace(.sRGB)!, NSColor.purple.usingColorSpace(.sRGB)!, NSColor.cyan.usingColorSpace(.sRGB)!, NSColor.orange.usingColorSpace(.sRGB)!, NSColor.brown.usingColorSpace(.sRGB)!, NSColor.magenta.usingColorSpace(.sRGB)!]
// I don't know my min and max output, -64 and 64 seems to work OK for my data.
var firstData = output.toRawBytes(min: Float32(-64), max: Float32(64), channel: 0, axes: (0,1,2))!.bytes
var outputImageData:[UInt8] = []
for _ in 0..<firstData.count {
let r:UInt8 = UInt8(colors[0].redComponent * 255)
let g:UInt8 = UInt8(colors[0].greenComponent * 255)
let b:UInt8 = UInt8(colors[0].blueComponent * 255)
let a:UInt8 = UInt8(colors[0].alphaComponent * 255)
outputImageData.append(r)
outputImageData.append(g)
outputImageData.append(b)
outputImageData.append(a)
}
for i in 1..<channelCount {
let data = output.toRawBytes(min: Float32(-64), max: Float32(64), channel: i, axes: (0,1,2))!.bytes
for j in 0..<data.count {
if data[j] > firstData[j] {
firstData[j] = data[j]
let r:UInt8 = UInt8(colors[i].redComponent * 255)
let g:UInt8 = UInt8(colors[i].greenComponent * 255)
let b:UInt8 = UInt8(colors[i].blueComponent * 255)
let a:UInt8 = UInt8(colors[i].alphaComponent * 255)
outputImageData[j*4] = r
outputImageData[j*4+1] = g
outputImageData[j*4+2] = b
outputImageData[j*4+3] = a
}
}
}
let image = imageFromPixels(pixels: outputImageData, width: 512, height: 512)
image.writeJPG(toURL: labelURL.deletingLastPathComponent().appendingPathComponent("labels.jpg"))
}
// I found this function here: https://stackoverflow.com/questions/38590323/obtain-nsimage-from-pixel-array-problems-swift
func imageFromPixels(pixels: UnsafePointer<UInt8>, width: Int, height: Int)-> NSImage { //No need to pass another CGImage
let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo:CGBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
let bitsPerComponent = 8 //number of bits in UInt8
let bitsPerPixel = 4 * bitsPerComponent //ARGB uses 4 components
let bytesPerRow = bitsPerPixel * width / 8 // bitsPerRow / 8 (in some cases, you need some paddings)
let providerRef = CGDataProvider(
data: NSData(bytes: pixels, length: height * bytesPerRow) //Do not put `&` as pixels is already an `UnsafePointer`
)
let cgim = CGImage(
width: width,
height: height,
bitsPerComponent: bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: bytesPerRow, //->not bits
space: rgbColorSpace,
bitmapInfo: bitmapInfo,
provider: providerRef!,
decode: nil,
shouldInterpolate: true,
intent: CGColorRenderingIntent.defaultIntent
)
return NSImage(cgImage: cgim!, size: NSSize(width: width, height: height))
}