0

我正在尝试使用vImageConvert_ARGB8888toPlanar8API 来提取 RGB 通道。假设以下是来自: httpsinputImage ://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

问题:0如果图像应该是纯白色(即所有像素值 = 255?),我怎么会得到像素值?

另请注意,如果我使用 Xcode 的模拟器运行上面的代码,我会得到不同数量的Pixel Val 0,但总数capacity仍然是2073600.

4

1 回答 1

1

这可能是因为缓冲区的实际行字节比图像宽(请参阅在捕获的图像序列中查找最清晰的图像中的创建浮点像素以在 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)")
            }
        }
于 2020-11-04T18:28:07.433 回答