Swift : 将字节数组转换为 CIImage
Swift : Convert byte array into CIImage
我正在寻找一种将字节数组转换为 CIIimage 的方法,以便我可以将其输入 ML 模型进行分类。我正在使用 REST HTTP 服务器,我将 POST 请求发送到服务器,并将有效负载作为图像。服务器接收到的图像字节需要处理并转换为 MAC OS 的 CIImage 格式,以便可以将其馈送到接受类型 VNImageRequestHandler(ciImage: <ciimage>)
请求的 ML 模型中。
有人可以在 swift 中举个例子吗?
VNImageRequestHandler : NSObject
let data = Data(bytes)
let imgHandler = VNImageRequestHandler(ciImage: data)
上面的数据变量需要类型化为 CIImage
类型。
在 HTTP 服务器端,我正在接收这样的图像字节:
imageData = request.body.bytes
使用此方法将字节数组转换为 CGImage。您必须确保您的字节是 rgba 32 位像素原始字节。
func byteArrayToCGImage(raw: UnsafeMutablePointer<UInt8>, // Your byte array
w: Int, // your image's width
h: Int // your image's height
) -> CGImage! {
// 4 bytes(rgba channels) for each pixel
let bytesPerPixel: Int = 4
// (8 bits per each channel)
let bitsPerComponent: Int = 8
let bitsPerPixel = bytesPerPixel * bitsPerComponent;
// channels in each row (width)
let bytesPerRow: Int = w * bytesPerPixel;
let cfData = CFDataCreate(nil, raw, w * h * bytesPerPixel)
let cgDataProvider = CGDataProvider.init(data: cfData!)!
let deviceColorSpace = CGColorSpaceCreateDeviceRGB()
let image: CGImage! = CGImage.init(width: w,
height: h,
bitsPerComponent: bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: bytesPerRow,
space: deviceColorSpace,
bitmapInfo: [],
provider: cgDataProvider,
decode: nil,
shouldInterpolate: true,
intent: CGColorRenderingIntent.defaultIntent)
return image;
}
使用这个方法,你可以像这样转换成CIImage。
let cgimage = byteArrayToCGImage(raw: <#Pointer to Your byte array#> ,
w: <#your image's width#>,
h: <#your image's height#>)
if cgimage != nil {
let ciImage = CIImage.init(cgImage: cgimage)
}
根据评论,您的数据可能是 RGB 原始字节而不是 RGBA。在这种情况下,您将必须分配新的缓冲区,手动为每个 alpha 通道放置 255,然后将该缓冲区传递给方法。
更新了 32 位 RGB 到 32 位 RGBA 的转换
func convertTo32bitsRGBA(from32bitsRGB pointer: UnsafeMutablePointer<UInt8>!,
width: Int,
height: Int) -> UnsafeMutablePointer<UInt8> {
let pixelCount = width * height
let memorySize = pixelCount * 4
let newBuffer = malloc(memorySize).bindMemory(to: UInt8.self, capacity: width * height)
var i = 0;
while(i < pixelCount) {
let oldBufferIndex = i * 3;
let newBufferIndex = i * 4;
// red channel
newBuffer.advanced(by: newBufferIndex).pointee = pointer.advanced(by: oldBufferIndex).pointee
// green channel
newBuffer.advanced(by: newBufferIndex + 1).pointee = pointer.advanced(by: oldBufferIndex + 1).pointee
// blue channel
newBuffer.advanced(by: newBufferIndex + 2).pointee = pointer.advanced(by: oldBufferIndex + 2).pointee
// alpha channel
newBuffer.advanced(by: newBufferIndex + 3).pointee = 0xff;
// &+ is used for little performance gain
i = i &+ 1;
}
return newBuffer;
}
您可以使用您的 rgb 图像缓冲区调用转换器方法,如下所示
let newImageBuffer = convertTo32bitsRGBA(from32bitsRGB: <#Your RGB image buffer#>,
width: <#Your image pixel row count or width#>,
height: <#Your image pixel column count or height#>)
但请记住,就像在 C、C++ 或 Objective-C 中一样,您有责任释放此方法返回的内存分配。这些是内存不受编译器管理的指针。
你可以用简单的功能释放。
newImageBuffer.deallocate();
解除分配后,您不得访问解除分配的内存。如果你这样做,你会得到 BAD_ACCESS_EXC
(Bad access exception by OS throwed for accessing memory you do not owned)。
我正在寻找一种将字节数组转换为 CIIimage 的方法,以便我可以将其输入 ML 模型进行分类。我正在使用 REST HTTP 服务器,我将 POST 请求发送到服务器,并将有效负载作为图像。服务器接收到的图像字节需要处理并转换为 MAC OS 的 CIImage 格式,以便可以将其馈送到接受类型 VNImageRequestHandler(ciImage: <ciimage>)
请求的 ML 模型中。
有人可以在 swift 中举个例子吗?
VNImageRequestHandler : NSObject
let data = Data(bytes)
let imgHandler = VNImageRequestHandler(ciImage: data)
上面的数据变量需要类型化为 CIImage
类型。
在 HTTP 服务器端,我正在接收这样的图像字节:
imageData = request.body.bytes
使用此方法将字节数组转换为 CGImage。您必须确保您的字节是 rgba 32 位像素原始字节。
func byteArrayToCGImage(raw: UnsafeMutablePointer<UInt8>, // Your byte array
w: Int, // your image's width
h: Int // your image's height
) -> CGImage! {
// 4 bytes(rgba channels) for each pixel
let bytesPerPixel: Int = 4
// (8 bits per each channel)
let bitsPerComponent: Int = 8
let bitsPerPixel = bytesPerPixel * bitsPerComponent;
// channels in each row (width)
let bytesPerRow: Int = w * bytesPerPixel;
let cfData = CFDataCreate(nil, raw, w * h * bytesPerPixel)
let cgDataProvider = CGDataProvider.init(data: cfData!)!
let deviceColorSpace = CGColorSpaceCreateDeviceRGB()
let image: CGImage! = CGImage.init(width: w,
height: h,
bitsPerComponent: bitsPerComponent,
bitsPerPixel: bitsPerPixel,
bytesPerRow: bytesPerRow,
space: deviceColorSpace,
bitmapInfo: [],
provider: cgDataProvider,
decode: nil,
shouldInterpolate: true,
intent: CGColorRenderingIntent.defaultIntent)
return image;
}
使用这个方法,你可以像这样转换成CIImage。
let cgimage = byteArrayToCGImage(raw: <#Pointer to Your byte array#> ,
w: <#your image's width#>,
h: <#your image's height#>)
if cgimage != nil {
let ciImage = CIImage.init(cgImage: cgimage)
}
根据评论,您的数据可能是 RGB 原始字节而不是 RGBA。在这种情况下,您将必须分配新的缓冲区,手动为每个 alpha 通道放置 255,然后将该缓冲区传递给方法。
更新了 32 位 RGB 到 32 位 RGBA 的转换
func convertTo32bitsRGBA(from32bitsRGB pointer: UnsafeMutablePointer<UInt8>!,
width: Int,
height: Int) -> UnsafeMutablePointer<UInt8> {
let pixelCount = width * height
let memorySize = pixelCount * 4
let newBuffer = malloc(memorySize).bindMemory(to: UInt8.self, capacity: width * height)
var i = 0;
while(i < pixelCount) {
let oldBufferIndex = i * 3;
let newBufferIndex = i * 4;
// red channel
newBuffer.advanced(by: newBufferIndex).pointee = pointer.advanced(by: oldBufferIndex).pointee
// green channel
newBuffer.advanced(by: newBufferIndex + 1).pointee = pointer.advanced(by: oldBufferIndex + 1).pointee
// blue channel
newBuffer.advanced(by: newBufferIndex + 2).pointee = pointer.advanced(by: oldBufferIndex + 2).pointee
// alpha channel
newBuffer.advanced(by: newBufferIndex + 3).pointee = 0xff;
// &+ is used for little performance gain
i = i &+ 1;
}
return newBuffer;
}
您可以使用您的 rgb 图像缓冲区调用转换器方法,如下所示
let newImageBuffer = convertTo32bitsRGBA(from32bitsRGB: <#Your RGB image buffer#>,
width: <#Your image pixel row count or width#>,
height: <#Your image pixel column count or height#>)
但请记住,就像在 C、C++ 或 Objective-C 中一样,您有责任释放此方法返回的内存分配。这些是内存不受编译器管理的指针。
你可以用简单的功能释放。
newImageBuffer.deallocate();
解除分配后,您不得访问解除分配的内存。如果你这样做,你会得到 BAD_ACCESS_EXC
(Bad access exception by OS throwed for accessing memory you do not owned)。