【问题标题】:In Swift, filter CIAreaMinMax provide incorrect output在 Swift 中,过滤器 CIAreaMinMax 提供不正确的输出
【发布时间】:2021-06-29 00:45:01
【问题描述】:

我正在使用过滤器CIAreaMinMax 从图像中获取最亮和最暗的颜色信息。

过滤器通常应该输出具有两个像素(最亮和最暗)的图像。但是,当我对包含两种相似颜色的图像实施此过滤器时,结果将不正确。结果不正确的症状是,两个像素的红色通道已经切换,但GB的值没有问题。

我使用的测试图片是here,一个png图片只包含两种颜色:

RGB(37,62,88), GRB(10,132,255).

经过代码处理后,会输出一个包含两个像素的png图片:

RGB(10,62,88), GRB(37,132,255).

下面是 swift playground 的测试代码:

import Cocoa
import CoreImage
import CoreGraphics

func saveImage(_ image: NSImage, atUrl url: URL) {
  let cgImage = image.cgImage(forProposedRect: nil, context: nil, hints: nil)!
  let newRep = NSBitmapImageRep(cgImage: cgImage)
  newRep.size = image.size
  let pngData = newRep.representation(using: .png, properties: [:])!
  try! pngData.write(to: url)
}

var sourceImage = CIImage.init(contentsOf: URL.init(fileURLWithPath: "/Users/ABC/Downloads/test.png"))!

let filter = CIFilter(name: "CIAreaMinMax")!
filter.setValue(sourceImage, forKey: kCIInputImageKey)
let civ = CIVector.init(x: sourceImage.extent.minX, y: sourceImage.extent.minY, z: sourceImage.extent.width, w: sourceImage.extent.height)
filter.setValue(civ, forKey: kCIInputExtentKey)

var filteredImage = filter.outputImage!
let context = CIContext(options: [.workingColorSpace: kCFNull!])

let filteredCGImageRef = context.createCGImage(
filteredImage,
from: filteredImage.extent)
let output = NSImage(cgImage: filteredCGImageRef!, size: NSSize.init(width: filteredImage.extent.width, height: filteredImage.extent.height))
saveImage(output, atUrl: URL.init(fileURLWithPath: "/Users/ABC/Downloads/output.png"))

【问题讨论】:

    标签: swift core-image cifilter


    【解决方案1】:

    来自文档(强调我的):

    计算图像中指定区域的每个组件最小值和最大值。

    这意味着最小像素的红色值将包含该区域所有像素中最小的红色值。其他频道也一样。所以红色值最小的像素的实际颜色不会被保留。

    【讨论】:

    • 感谢弗兰克的回答!那么你知道有什么现有的过滤器或函数可以达到我想要的结果吗?
    • 嗯,“最小和最大颜色”是相当宽松的术语。什么时候一种颜色比另一种颜色“小”?您可能需要一些亮度测量并找到它的最小值和最大值。但这真的取决于您的用例。
    【解决方案2】:

    这可以通过一些技巧来完成。

    1. 首先,获取您的图像并应用自定义 CIColorKernel 来放置亮度 在 alpha 通道中是这样的:
    kernel vec4 prepImage (__sample s, vec3 lumaWeights)
    {
        return vec4(s.rgb, dot(s.rgb, lumaWeights));
    }
    
    1. 对上图应用 CIAreaMinimumAlpha 滤镜。
    2. 将生成的 1x1 像素图像渲染到未预乘的 CIRenderDestination。

    【讨论】:

    • 不错!我们可以将 lumaWeights 生成放在过滤器中吗?
    • 如果您愿意,可以在内核中硬编码权重:
    猜你喜欢
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    相关资源
    最近更新 更多