【问题标题】:Scale image in CVImageBuffer在 CVImageBuffer 中缩放图像
【发布时间】:2019-12-11 03:01:00
【问题描述】:

我有一个任务 - 缩小从相机拍摄的图像。我需要它来对较小版本的图像进行繁重的操作,这将帮助我节省一些处理能力。

我决定从Accelerate 选择vImage_Buffer。这是我的代码,其中包含一些 cmets,只是为了清楚地了解那里的内容:

        guard let imgBuffer = CMSampleBufferGetImageBuffer(buffer) else {
            return
        }


        CVPixelBufferLockBaseAddress(imgBuffer, CVPixelBufferLockFlags(rawValue: 0))

        // create vImage_Buffer out of CVImageBuffer
        var inBuff: vImage_Buffer = vImage_Buffer()
        inBuff.width = UInt(CVPixelBufferGetWidth(imgBuffer))
        inBuff.height = UInt(CVPixelBufferGetHeight(imgBuffer))
        inBuff.rowBytes = CVPixelBufferGetBytesPerRow(imgBuffer)
        inBuff.data = CVPixelBufferGetBaseAddress(imgBuffer)

        // bring down the size at half
        let new_width: UInt = inBuff.width/2
        let new_height: UInt = inBuff.height/2

        // create output buffer where scaled image is supposed to be
        var outBuff: vImage_Buffer = vImage_Buffer()
        outBuff.data = UnsafeMutableRawPointer.allocate(byteCount: Int(new_width * new_height * 4), alignment: MemoryLayout<UInt>.size)
        outBuff.width = new_width
        outBuff.height = new_height
        outBuff.rowBytes = Int(new_width * 4)

        // perform scale
        let err = vImageScale_ARGB8888(&inBuff, &outBuff, nil, 0)
        if err != kvImageNoError {
            print("Wrong!")
        }

        // I guess I need to unlock buffer at this point, right?
        CVPixelBufferUnlockBaseAddress(imgBuffer, CVPixelBufferLockFlags(rawValue: 0))

        // create CVImageBuffer
        let options = [kCVPixelBufferCGImageCompatibilityKey: true,
                       kCVPixelBufferCGBitmapContextCompatibilityKey: true,
                       kCVPixelBufferWidthKey: new_width,
                       kCVPixelBufferHeightKey: new_height] as CFDictionary

        var newPixelBuffer: CVImageBuffer?
        let status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
                                                  Int(new_width), Int(new_height),
                                                  kCVPixelFormatType_32BGRA, &outBuff, Int(new_width * 4),
                                                  nil, nil, options, &newPixelBuffer)

        if status == kCVReturnError {
            print("Wrong again!")
        }

        // create CIImage from CVImageBuffer and UIImage from CIImage just to see how scale went
        let ciImg = CIImage(cvImageBuffer: newPixelBuffer!)
        let img = UIImage(ciImage: ciImg)
        delegate?.testSmallImage(img)

似乎所有操作都在没有任何错误的情况下执行,我想检查缩放是如何进行的,所以我试图在缩放缓冲区之外创建新的UIImage。但是,当我尝试使用UIImageView 显示图像时,出现EXC_BAD_ACCESS 错误。当我尝试保存全新的UIImage 时,一切正常,但Documents 目录中没有文件出现。你能指出我在这里到底做错了什么吗?谢谢!

【问题讨论】:

标签: ios swift image-processing core-video vimage


【解决方案1】:

这是 Swift 上的代码 sn-p 调整 CMSampleBuffer 的大小:

    private func scale(_ sampleBuffer: CMSampleBuffer) -> CVImageBuffer?
    {
        guard let imgBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return nil
        }

        CVPixelBufferLockBaseAddress(imgBuffer, CVPixelBufferLockFlags(rawValue: 0))

        // create vImage_Buffer out of CVImageBuffer
        var inBuff: vImage_Buffer = vImage_Buffer()
        inBuff.width = UInt(CVPixelBufferGetWidth(imgBuffer))
        inBuff.height = UInt(CVPixelBufferGetHeight(imgBuffer))
        inBuff.rowBytes = CVPixelBufferGetBytesPerRow(imgBuffer)
        inBuff.data = CVPixelBufferGetBaseAddress(imgBuffer)

        // perform scale
        var err = vImageScale_ARGB8888(&inBuff, &scaleBuffer, nil, 0)
        if err != kvImageNoError {
            print("Can't scale a buffer")
            return nil
        }
        CVPixelBufferUnlockBaseAddress(imgBuffer, CVPixelBufferLockFlags(rawValue: 0))

        var newBuffer: CVPixelBuffer?
        let attributes : [NSObject:AnyObject] = [
            kCVPixelBufferCGImageCompatibilityKey : true as AnyObject,
            kCVPixelBufferCGBitmapContextCompatibilityKey : true as AnyObject
        ]

        let status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
                                                  Int(scaleBuffer.width), Int(scaleBuffer.height),
                                                  kCVPixelFormatType_32BGRA, scaleBuffer.data,
                                                  Int(scaleBuffer.width) * 4,
                                                  nil, nil,
                                                  attributes as CFDictionary?, &newBuffer)

        guard status == kCVReturnSuccess, let b = newBuffer else {
            print("Can't create new CVPixelBuffer")
            return nil
        }

        return b
    }

这是scaleBuffer 的定义,它在规模操作中充当目标。我不需要每个比例都创建它,所以我只做一次:

        scaleBuffer.data = UnsafeMutableRawPointer.allocate(byteCount: Int(new_width * new_height * 4), alignment: MemoryLayout<UInt>.size)
        scaleBuffer.width = vImagePixelCount(new_width)
        scaleBuffer.height = vImagePixelCount(new_height)
        scaleBuffer.rowBytes = Int(new_width * 4)

【讨论】:

    猜你喜欢
    • 2013-05-29
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 2011-01-16
    • 2019-03-04
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多