问题描述
我正在尝试使用vImageConvert_ARGB8888toPlanar8
API提取RGB通道。假设以下inputimage
是来自https://www.solidbackgrounds.com/images/1080x1920/1080x1920-white-solid-color-background.jpg
这是我的代码:
let inputimage = #imageLiteral(resourceName: "1080x1920-white-solid-color-background.jpg")
guard let sourceCGImage = inputimage.cgImage,let sourceImageFormat = vImage_CGImageFormat(cgImage: sourceCGImage),var sourceImageBuffer = try? vImage_Buffer(cgImage: sourceCGImage,format: sourceImageFormat) else {
fatalError()
}
let componentCount = sourceImageFormat.componentCount
var argbSourcePlanarBuffers: [vImage_Buffer] = (0..<componentCount).map { _ in
let bitsPerPixel = UInt32(8)
guard let buffer = try? vImage_Buffer(width: Int(sourceImageBuffer.width),height: Int(sourceImageBuffer.height),bitsPerPixel: bitsPerPixel) else {
fatalError("Error creating planar buffers.")
}
return buffer
}
vImageConvert_ARGB8888toPlanar8(&sourceImageBuffer,&argbSourcePlanarBuffers[0],// R
&argbSourcePlanarBuffers[1],// G
&argbSourcePlanarBuffers[2],// B
&argbSourcePlanarBuffers[3],// A
vImage_Flags(kvImageNoFlags))
print("Image H: \(sourceCGImage.height),W: \(sourceCGImage.width)")
let capacity = sourceCGImage.width * sourceCGImage.height
print("capacity: \(capacity)")
// Repeat the following code for other 3 channels
let channelDataPtrR = argbSourcePlanarBuffers[0].data.bindMemory(to: Pixel_8.self,capacity: capacity)
let channelRawDataR = UnsafeBufferPointer(start: channelDataPtrR,count: capacity)
let channelDataR = Array(channelRawDataR)
var histogramR = [Double](repeating: 0.0,count: 255 + 1)
channelDataR.map { histogramR[Int($0)] += 1.0 }
print("histogramR:")
for (i,px) in histogramR.enumerated() {
if px > 0.0 {
print("Pixel Val \(i): \(px)")
}
}
这就是我得到的:
Image H: 1920,W: 1080
capacity: 2073600
histogramR:
Pixel Val 0: 129600.0
Pixel Val 255: 1944000.0
histogramG:
Pixel Val 0: 129600.0
Pixel Val 255: 1944000.0
histogramB:
Pixel Val 0: 129600.0
Pixel Val 255: 1944000.0
histogramA:
Pixel Val 0: 129600.0
Pixel Val 255: 1944000.0
问题:如果图像应该是纯白色(即所有像素值= 255?),我怎么得到像素值0
还要注意,如果我使用Xcode的模拟器运行上面的代码,我得到的Pixel Val 0
数量会有所不同,但是总的capacity
仍然是2073600
。 / p>
解决方法
这可能是因为缓冲区的实际行字节比图像宽(请参见Finding the Sharpest Image in a Sequence of Captured Images中的创建浮点像素以在vDSP中使用 ,以获取行字节如何扩展的说明。超出图像的边界框)。
如果您使用Specifying Histograms with vImage中的代码,则应获得期望的值:
var histogramBinZero = [vImagePixelCount](repeating: 0,count: 256)
var histogramBinOne = [vImagePixelCount](repeating: 0,count: 256)
var histogramBinTwo = [vImagePixelCount](repeating: 0,count: 256)
var histogramBinThree = [vImagePixelCount](repeating: 0,count: 256)
histogramBinZero.withUnsafeMutableBufferPointer { zeroPtr in
histogramBinOne.withUnsafeMutableBufferPointer { onePtr in
histogramBinTwo.withUnsafeMutableBufferPointer { twoPtr in
histogramBinThree.withUnsafeMutableBufferPointer { threePtr in
var histogramBins = [zeroPtr.baseAddress,onePtr.baseAddress,twoPtr.baseAddress,threePtr.baseAddress]
histogramBins.withUnsafeMutableBufferPointer { histogramBinsPtr in
let error = vImageHistogramCalculation_ARGB8888(&sourceImageBuffer,histogramBinsPtr.baseAddress!,vImage_Flags(kvImageNoFlags))
guard error == kvImageNoError else {
fatalError("Error calculating histogram: \(error)")
}
}
}
}
}
}
for (i,px) in histogramBinTwo.enumerated() {
if px > 0 {
print("Pixel Val \(i): \(px)")
}
}