vImageHistogramCalculation_Planar8 中的不同通道如何使用直方图
How does a histogram work for the different channels in vImageHistogramCalculation_Planar8
我正在尝试计算 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 图像缓冲区中 Y 通道的直方图。当我使用 vImageHistogramCalculation_Planar8 时,我只传递对单个直方图的引用。
我如何知道正在使用哪个通道创建直方图?如果我想阅读所有频道,我该怎么办?
也欢迎对代码示例的批评。
extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ captureOutput: AVCaptureOutput!,
didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,
from connection: AVCaptureConnection!) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
let height = CVPixelBufferGetHeight(imageBuffer)
let width = CVPixelBufferGetWidth(imageBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
let pixelBuffer = CVPixelBufferGetBaseAddress(imageBuffer)
// let format = CVPixelBufferGetPixelFormatType(imageBuffer)
// print("format: \(format)")
///kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v'
var vBuffer = vImage_Buffer()
vBuffer.data = pixelBuffer
vBuffer.rowBytes = bytesPerRow
vBuffer.width = vImagePixelCount(width)
vBuffer.height = vImagePixelCount(height)
let luma = [UInt](repeating: 0, count: 256)
let lumaHist = UnsafeMutablePointer<vImagePixelCount>(mutating: luma)
vImageHistogramCalculation_Planar8(&vBuffer, lumaHist, UInt32(kvImageNoFlags))
CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
}
}
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
是平面格式,所有平面都编码到缓冲区中。 vImage
平面函数一次只能在一个平面上工作。
上面的代码正在计算三个平面上的直方图,但被视为一个大平面,这可能不是您想要的。
可以使用这些函数访问 Y
平面的基地址和每行字节数:
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0)
let pixelBuffer = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)
平面索引取决于缓冲区格式。这个名字通常会给你一个提示。这是 YpCbCr
所以 Y
平面应该是第一个,在索引 0
.
根据header,CVPixelBufferGetBaseAddress将return:
For chunky buffers, this will return a pointer to the pixel at
0,0 in the buffer.
For planar buffers this will return a pointer to a PlanarComponentInfo struct
(defined in QuickTime).
因此,如果为真,则它不会同时计算所有三个通道的直方图。它正在计算 PlanarComponentInfo 结构的更没用的直方图,并且可能会崩溃。
要读取所有通道,您可以使用上面 Sparga 的回答中描述的接口(CVPixelBufferGetBytesPerRowOfPlane(imageBuffer,1) 和 CVPixelBufferGetBaseAddressOfPlane(imageBuffer,1)) 获取第二个平面,然后做一半的 ARGB 直方图宽度色度图像并将偶数直方图和奇数直方图相加。请注意,因为这是 420,所以色度平面的高度和宽度与亮度平面不同。
我还会向 apple 提交错误报告,要求 vImageHistogramCalculation_RG88 处理双平面色度数据。
我正在尝试计算 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 图像缓冲区中 Y 通道的直方图。当我使用 vImageHistogramCalculation_Planar8 时,我只传递对单个直方图的引用。
我如何知道正在使用哪个通道创建直方图?如果我想阅读所有频道,我该怎么办?
也欢迎对代码示例的批评。
extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ captureOutput: AVCaptureOutput!,
didOutputSampleBuffer sampleBuffer: CMSampleBuffer!,
from connection: AVCaptureConnection!) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
CVPixelBufferLockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
let height = CVPixelBufferGetHeight(imageBuffer)
let width = CVPixelBufferGetWidth(imageBuffer)
let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
let pixelBuffer = CVPixelBufferGetBaseAddress(imageBuffer)
// let format = CVPixelBufferGetPixelFormatType(imageBuffer)
// print("format: \(format)")
///kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange = '420v'
var vBuffer = vImage_Buffer()
vBuffer.data = pixelBuffer
vBuffer.rowBytes = bytesPerRow
vBuffer.width = vImagePixelCount(width)
vBuffer.height = vImagePixelCount(height)
let luma = [UInt](repeating: 0, count: 256)
let lumaHist = UnsafeMutablePointer<vImagePixelCount>(mutating: luma)
vImageHistogramCalculation_Planar8(&vBuffer, lumaHist, UInt32(kvImageNoFlags))
CVPixelBufferUnlockBaseAddress(imageBuffer, CVPixelBufferLockFlags(rawValue: 0))
}
}
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
是平面格式,所有平面都编码到缓冲区中。 vImage
平面函数一次只能在一个平面上工作。
上面的代码正在计算三个平面上的直方图,但被视为一个大平面,这可能不是您想要的。
可以使用这些函数访问 Y
平面的基地址和每行字节数:
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0)
let pixelBuffer = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0)
平面索引取决于缓冲区格式。这个名字通常会给你一个提示。这是 YpCbCr
所以 Y
平面应该是第一个,在索引 0
.
根据header,CVPixelBufferGetBaseAddress将return:
For chunky buffers, this will return a pointer to the pixel at
0,0 in the buffer.
For planar buffers this will return a pointer to a PlanarComponentInfo struct
(defined in QuickTime).
因此,如果为真,则它不会同时计算所有三个通道的直方图。它正在计算 PlanarComponentInfo 结构的更没用的直方图,并且可能会崩溃。
要读取所有通道,您可以使用上面 Sparga 的回答中描述的接口(CVPixelBufferGetBytesPerRowOfPlane(imageBuffer,1) 和 CVPixelBufferGetBaseAddressOfPlane(imageBuffer,1)) 获取第二个平面,然后做一半的 ARGB 直方图宽度色度图像并将偶数直方图和奇数直方图相加。请注意,因为这是 420,所以色度平面的高度和宽度与亮度平面不同。
我还会向 apple 提交错误报告,要求 vImageHistogramCalculation_RG88 处理双平面色度数据。