在 iOS 上使用核心图像对图片进行二值化
Binarize Picture with Core Image on iOS
我想知道是否可以使用 Core Image 将图像二值化(仅转换为黑白图像)?
我是用 OpenCV 和 GPUImage 制作的,但如果可能的话,我更希望它使用 Apple Core Image
是的。您至少有两个选择,CIPhotoEffectMono 或小型自定义 CIColorKernel。
CIPhotoEffectMono:
func createMonoImage(image:UIImage) -> UIImage {
let filter = CIFilter(name: "CIPhotoEffectMono")
filter!.setValue(CIImage(image: image), forKey: "inputImage")
let outputImage = filter!.outputImage
let cgimg = ciCtx.createCGImage(outputImage!, from: (outputImage?.extent)!)
return UIImage(cgImage: cgimg!)
}
请注意,我写得很快,您可能需要为 nil returns.
收紧一些东西
CIColorKernel:
FadeToBW GLSL(0.0因子全彩,1.0因子无色):
kernel vec4 fadeToBW(__sample s, float factor) {
vec3 lum = vec3(0.299,0.587,0.114);
vec3 bw = vec3(dot(s.rgb,lum));
vec3 pixel = s.rgb + (bw - s.rgb) * factor;
return vec4(pixel,s.a);
}
下面的代码将其作为名为 FadeToBW.cikernel 的文件打开。您还可以 post 将其作为字符串直接进入 openKernelFile
调用。
Swift代码:
func createMonoImage(image:UIImage, inputColorFade:NSNumber) -> UIImage {
let ciKernel = CIColorKernel(string: openKernelFile("FadeToBW"))
let extent = image.extent
let arguments = [image, inputColorFade]
let outputImage = ciKernel.applyWithExtent(extent, arguments: arguments)
let cgimg = ciCtx.createCGImage(outputImage!, from: (outputImage?.extent)!)
return UIImage(cgImage: cgimg!)
}
再次,增加一些警卫等
您可以为此使用 MetalPerformanceShaders。和 CIImageProcessingKernel。
https://developer.apple.com/documentation/coreimage/ciimageprocessorkernel
这里是class需要的代码。
class ThresholdImageProcessorKernel: CIImageProcessorKernel {
static let device = MTLCreateSystemDefaultDevice()
override class func process(with inputs: [CIImageProcessorInput]?, arguments: [String : Any]?, output: CIImageProcessorOutput) throws {
guard
let device = device,
let commandBuffer = output.metalCommandBuffer,
let input = inputs?.first,
let sourceTexture = input.metalTexture,
let destinationTexture = output.metalTexture,
let thresholdValue = arguments?["thresholdValue"] as? Float else {
return
}
let threshold = MPSImageThresholdBinary(
device: device,
thresholdValue: thresholdValue,
maximumValue: 1.0,
linearGrayColorTransform: nil)
threshold.encode(
commandBuffer: commandBuffer,
sourceTexture: sourceTexture,
destinationTexture: destinationTexture)
}
}
这是您可以使用它的方式:
let context = CIContext(options: nil)
if let binaryCIImage = try? ThresholdImageProcessorKernel.apply(
withExtent: croppedCIImage.extent,
inputs: [croppedCIImage],
arguments: ["thresholdValue": Float(0.2)]) {
if let cgImage = context.createCGImage(binaryCIImage, from: binary.extent) {
DispatchQueue.main.async {
let resultingImage = UIImage(cgImage: cgImage)
if resultingImage.size.width > 100 {
print("Received an image \(resultingImage.size)")
}
}
}
}
我成功地使用 CIPhotoEffectMono 或等效方法将其转换为灰度,然后使用具有高得离谱的 inputContrast 数字(我使用了 10000)的 CIColorControls。这有效地使它变成黑色和白色,从而二值化。对于那些不想弄乱自定义内核的人很有用。
此外,您可以使用像 Apple 的“色度键”过滤器这样的示例,它使用 Hue 进行过滤,但您无需查看 Hue,只需给出对数据进行二值化的规则(即:何时将 RGB 全部设置为 1.0以及何时设置为 0.0)。
https://developer.apple.com/documentation/coreimage/applying_a_chroma_key_effect
从 Google 搜索中找到此线程,我想我会提到从 iOS 14 和 OSX 11.0 开始,CoreImage 包括 CIColorThreshold
和 CIColorThresholdOtsu
filters(后者使用Otsu的方法从图像直方图计算阈值)
参见:
let outputImage = inputImage.applyingFilter("CIColorMonochrome",
parameters: [kCIInputColorKey: CIColor.white])
如果您想使用 250 个 CIFilters 中的每一个,请查看此应用:https://apps.apple.com/us/app/filter-magic/id1594986951
我想知道是否可以使用 Core Image 将图像二值化(仅转换为黑白图像)?
我是用 OpenCV 和 GPUImage 制作的,但如果可能的话,我更希望它使用 Apple Core Image
是的。您至少有两个选择,CIPhotoEffectMono 或小型自定义 CIColorKernel。
CIPhotoEffectMono:
func createMonoImage(image:UIImage) -> UIImage {
let filter = CIFilter(name: "CIPhotoEffectMono")
filter!.setValue(CIImage(image: image), forKey: "inputImage")
let outputImage = filter!.outputImage
let cgimg = ciCtx.createCGImage(outputImage!, from: (outputImage?.extent)!)
return UIImage(cgImage: cgimg!)
}
请注意,我写得很快,您可能需要为 nil returns.
收紧一些东西CIColorKernel:
FadeToBW GLSL(0.0因子全彩,1.0因子无色):
kernel vec4 fadeToBW(__sample s, float factor) {
vec3 lum = vec3(0.299,0.587,0.114);
vec3 bw = vec3(dot(s.rgb,lum));
vec3 pixel = s.rgb + (bw - s.rgb) * factor;
return vec4(pixel,s.a);
}
下面的代码将其作为名为 FadeToBW.cikernel 的文件打开。您还可以 post 将其作为字符串直接进入 openKernelFile
调用。
Swift代码:
func createMonoImage(image:UIImage, inputColorFade:NSNumber) -> UIImage {
let ciKernel = CIColorKernel(string: openKernelFile("FadeToBW"))
let extent = image.extent
let arguments = [image, inputColorFade]
let outputImage = ciKernel.applyWithExtent(extent, arguments: arguments)
let cgimg = ciCtx.createCGImage(outputImage!, from: (outputImage?.extent)!)
return UIImage(cgImage: cgimg!)
}
再次,增加一些警卫等
您可以为此使用 MetalPerformanceShaders。和 CIImageProcessingKernel。 https://developer.apple.com/documentation/coreimage/ciimageprocessorkernel
这里是class需要的代码。
class ThresholdImageProcessorKernel: CIImageProcessorKernel {
static let device = MTLCreateSystemDefaultDevice()
override class func process(with inputs: [CIImageProcessorInput]?, arguments: [String : Any]?, output: CIImageProcessorOutput) throws {
guard
let device = device,
let commandBuffer = output.metalCommandBuffer,
let input = inputs?.first,
let sourceTexture = input.metalTexture,
let destinationTexture = output.metalTexture,
let thresholdValue = arguments?["thresholdValue"] as? Float else {
return
}
let threshold = MPSImageThresholdBinary(
device: device,
thresholdValue: thresholdValue,
maximumValue: 1.0,
linearGrayColorTransform: nil)
threshold.encode(
commandBuffer: commandBuffer,
sourceTexture: sourceTexture,
destinationTexture: destinationTexture)
}
}
这是您可以使用它的方式:
let context = CIContext(options: nil)
if let binaryCIImage = try? ThresholdImageProcessorKernel.apply(
withExtent: croppedCIImage.extent,
inputs: [croppedCIImage],
arguments: ["thresholdValue": Float(0.2)]) {
if let cgImage = context.createCGImage(binaryCIImage, from: binary.extent) {
DispatchQueue.main.async {
let resultingImage = UIImage(cgImage: cgImage)
if resultingImage.size.width > 100 {
print("Received an image \(resultingImage.size)")
}
}
}
}
我成功地使用 CIPhotoEffectMono 或等效方法将其转换为灰度,然后使用具有高得离谱的 inputContrast 数字(我使用了 10000)的 CIColorControls。这有效地使它变成黑色和白色,从而二值化。对于那些不想弄乱自定义内核的人很有用。
此外,您可以使用像 Apple 的“色度键”过滤器这样的示例,它使用 Hue 进行过滤,但您无需查看 Hue,只需给出对数据进行二值化的规则(即:何时将 RGB 全部设置为 1.0以及何时设置为 0.0)。
https://developer.apple.com/documentation/coreimage/applying_a_chroma_key_effect
从 Google 搜索中找到此线程,我想我会提到从 iOS 14 和 OSX 11.0 开始,CoreImage 包括 CIColorThreshold
和 CIColorThresholdOtsu
filters(后者使用Otsu的方法从图像直方图计算阈值)
参见:
let outputImage = inputImage.applyingFilter("CIColorMonochrome",
parameters: [kCIInputColorKey: CIColor.white])
如果您想使用 250 个 CIFilters 中的每一个,请查看此应用:https://apps.apple.com/us/app/filter-magic/id1594986951