问题描述
我使用过滤器 CIAreaMinMax
从图像中获取最亮和最暗的颜色信息。
通常,过滤器应输出具有两个像素(最亮和最暗)的图像。但是,当我将此过滤器应用于包含两种相似颜色的图像时,结果将不正确。结果不正确的症状是,两个像素的红色通道已经切换,但G
和B
值没有问题。
RGB(37,62,88)
,GRB(10,132,255)
。
RGB(10,88)
,GRB(37,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"))
解决方法
来自文档(强调我的):
计算图像中指定区域的每个组件最小值和最大值。
这意味着最小像素的红色值将包含该区域所有像素中最小的红色值。其他频道也一样。所以不会保留红色值最小的像素的实际颜色。
,这可以通过一些技巧来完成。
- 首先,拍摄您的图像并应用一个自定义 CIColorKernel,该 CIColorKernel 将 luma 在像这样的 alpha 通道中:
kernel vec4 prepImage (__sample s,vec3 lumaWeights)
{
return vec4(s.rgb,dot(s.rgb,lumaWeights));
}
- 对上图应用 CIAreaMinimumAlpha 过滤器。
- 将生成的 1x1 像素图像渲染到未预乘的 CIRenderDestination。