【问题标题】:RGB to Gray Scale yet pixel values seem wrongRGB 到灰度但像素值似乎错误
【发布时间】:2020-04-20 04:23:57
【问题描述】:

我有一个使用 tensorflow 2.0 / Keras 构建的模型。输入是具有 28x28 和 1 个通道的图像。该模型被保存并转换为 .tflite 并在我的 swift ios 应用程序中使用。不幸的是,当调用解释器时,我得到的预测与预期截然不同。当我进一步调查时,似乎我的图像准备可能是错误的。以下是我在将像素阵列输入模型之前采取的步骤。

  1. 加载图像。
  2. 将图像转换为灰度
  3. 通过除以 255 来归一化像素值。

1
252
255
253
255
255
255
253
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
253
255
253
254
253
255
254
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
248
255
253
255
255
248
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
253
255
255
252
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
250
254
255
248
253
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
251
255
255
254
253
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
250
255
255
255
255
248
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
253
255
251
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255

这是我的代码

let im =  UIImage(named: "dotsgray")!
let i = (im.pixelBufferGray(width: 28, height: 28))!
i.normalize()



extension UIImage {
  public func pixelBufferGray(width: Int, height: Int) -> CVPixelBuffer? {
        return pixelBuffer(width: width, height: height,
                           pixelFormatType: kCVPixelFormatType_OneComponent8,
                           colorSpace: CGColorSpaceCreateDeviceGray(),
                           alphaInfo: .none)
    }


    func pixelBuffer(width: Int, height: Int, pixelFormatType: OSType,
                     colorSpace: CGColorSpace, alphaInfo: CGImageAlphaInfo) -> CVPixelBuffer? {
        var maybePixelBuffer: CVPixelBuffer?
        let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
                     kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue]
        let status = CVPixelBufferCreate(kCFAllocatorDefault,
                                         width,
                                         height,
                                         pixelFormatType,
                                         attrs as CFDictionary,
                                         &maybePixelBuffer)

        guard status == kCVReturnSuccess, let pixelBuffer = maybePixelBuffer else {
            return nil
        }

        CVPixelBufferLockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
        let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer)

        guard let context = CGContext(data: pixelData,
                                      width: width,
                                      height: height,
                                      bitsPerComponent: 8,
                                      bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer),
                                      space: colorSpace,
                                      bitmapInfo: alphaInfo.rawValue)
            else {
                return nil
        }

        UIGraphicsPushContext(context)
        context.translateBy(x: 0, y: CGFloat(height))
        context.scaleBy(x: 1, y: -1)
        self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
        UIGraphicsPopContext()

        CVPixelBufferUnlockBaseAddress(pixelBuffer, CVPixelBufferLockFlags(rawValue: 0))
        return pixelBuffer
    }
}

extension CVPixelBuffer {

func normalize() {
  // 1
  let bytesPerRow = CVPixelBufferGetBytesPerRow(self)
  let totalBytes = CVPixelBufferGetDataSize(self)

  let width = bytesPerRow / MemoryLayout<UInt8>.size
  let height = totalBytes / bytesPerRow

  // 2
  CVPixelBufferLockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))

  // 3
  let floatBuffer = unsafeBitCast(
    CVPixelBufferGetBaseAddress(self),
    to: UnsafeMutablePointer<Double>.self)

  // 4
  var minPixel: Double = 1.0
  var maxPixel: Double = 0.0

  // 5
  for i in 0 ..< width * height {
    let pixel = floatBuffer[i]
    minPixel = min(pixel, minPixel)
    maxPixel = max(pixel, maxPixel)
  }

  // 6
  let range = maxPixel - minPixel

  // 7
  for i in 0 ..< width * height {
    let pixel = floatBuffer[i]
    floatBuffer[i] = (pixel - minPixel) / range
  }

  // 8
  CVPixelBufferUnlockBaseAddress(self, CVPixelBufferLockFlags(rawValue: 0))
}

【问题讨论】:

  • 检查CVPixelBufferGetBytesPerRow(pixelBuffer)的值
  • CVPixelBufferGetBytesPerRow(self) 为 64,CVPixelBufferGetDataSize(self) 为 1792
  • 您应该编写代码来执行 RGB -> 灰度转换并在不涉及像素缓冲区和 CoreVideo API 的情况下测试该逻辑。您需要同时处理色彩空间转换和伽玛。然后,一旦您的代码经过全面测试并且已知可以正常工作,请将该逻辑逐行应用于 CoreVideo 提供的像素。有关 RGB -> Grayscale 的详细信息,请参阅此问题(还提供源代码)stackoverflow.com/questions/53911662/…

标签: swift rgb pixel tensorflow2.0 grayscale


【解决方案1】:

您的normalize() 完全不符合您的目的。

它将基于Double 的像素缓冲区标准化为0.0...1.0,但您没有创建Double 的像素缓冲区。

当您为pixelFormatType 提供kCVPixelFormatType_OneComponent8 时,您的pixelBufferGray(width:height:) 会创建UInt8 的像素缓冲区。

删除i.normalize() 并检查像素缓冲区`。你会看到你所期望的。


您可能需要打包像素缓冲区,因为它只使用每个 64 字节行中的 28 个字节,但这是另一个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-22
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 2019-11-27
    • 2015-07-11
    • 2020-09-02
    • 1970-01-01
    相关资源
    最近更新 更多