【发布时间】:2019-12-21 20:34:29
【问题描述】:
CIEdges(以及其他 CIFilters)在设备和 iOS 版本之间的工作方式不再一致。所以我决定用卷积滤波器找到边缘。成功:我可以得到一个很好的黑白蒙版图像,并让渐变或纯色显示出来:
问题是,我想不出一个可变调整线条粗细的好方法。我尝试的一种方法是减少源图像的版本,并在黑白相机图像的顶部应用卷积和放大。那种作品,但线条看起来锯齿状和粗糙。有任何想法吗?这是我的代码:
func sketch(with ciImage: CIImage) -> CIImage {
var sourceCore = ciImage
var convolutionValue_A:CGFloat = -0.0925937220454216
var convolutionValue_B:CGFloat = -0.4166666567325592
var convolutionValue_C:CGFloat = -1.8518532514572144
var convolutionValue_D:CGFloat = 0.23148006200790405
var convolutionValue_E:CGFloat = 4.5833334922790527
var convolutionValue_F:CGFloat = 14.166666984558105
var brightnessVal:CGFloat = 1.1041666269302368
var contrastVal:CGFloat = 3.0555555820465088
// radially symmetrical convolution weights:
var weightsArr: [CGFloat] = [
convolutionValue_A, convolutionValue_A, convolutionValue_B, convolutionValue_B, convolutionValue_B, convolutionValue_A, convolutionValue_A,
convolutionValue_A, convolutionValue_B, convolutionValue_C, convolutionValue_C, convolutionValue_C, convolutionValue_B, convolutionValue_A,
convolutionValue_B, convolutionValue_C, convolutionValue_D, convolutionValue_E, convolutionValue_D, convolutionValue_C, convolutionValue_B,
convolutionValue_B, convolutionValue_C, convolutionValue_E, convolutionValue_F, convolutionValue_E, convolutionValue_C, convolutionValue_B,
convolutionValue_B, convolutionValue_C, convolutionValue_D, convolutionValue_E, convolutionValue_D, convolutionValue_C, convolutionValue_B,
convolutionValue_A, convolutionValue_B, convolutionValue_C, convolutionValue_C, convolutionValue_C, convolutionValue_B, convolutionValue_A,
convolutionValue_A, convolutionValue_A, convolutionValue_B, convolutionValue_B, convolutionValue_B, convolutionValue_A, convolutionValue_A
]
let inputWeights:CIVector = CIVector(values: weightsArr, count: weightsArr.count)
sourceCore = sourceCore
.applyingFilter("CIColorControls", parameters: [kCIInputImageKey: sourceCore,
kCIInputSaturationKey: 0.0,
kCIInputBrightnessKey: brightnessVal,
kCIInputContrastKey: contrastVal])
// transforms image to only show edges in black and white
sourceCore = sourceCore
.applyingFilter("CIConvolution7X7", parameters: [kCIInputImageKey: sourceCore,
let whiteCIColor = CIColor.white
let whiteColor = CIImage(color: whiteCIColor).cropped(to: ciImage.extent)
// for some reason, I need to blend the black and white mask with the color white.
// either CIColorDodgeBlendMode or CILinearDodgeBlendMode seems to work fine here:
sourceCore = sourceCore
.applyingFilter("CIColorDodgeBlendMode", parameters: [kCIInputImageKey: sourceCore,
kCIInputBackgroundImageKey: whiteColor])
kCIInputWeightsKey: inputWeights]).cropped(to: sourceCore.extent)
// give camera image a black and white Noir effect
var ciImage = ciImage
.applyingFilter("CIPhotoEffectNoir", parameters: [kCIInputImageKey: ciImage])
// make solid color
let color = CIColor(red: 0.819, green: 0.309, blue: 0.309)
let colFilter = CIFilter(name: "CIConstantColorGenerator")!
colFilter.setValue(color, forKey: kCIInputColorKey)
var solidColor = colFilter.value(forKey: "outputImage") as! CIImage
solidColor = solidColor.cropped(to: ciImage.extent)
// color is shown through outlines correctly,
// and image is black and white
sourceCore = sourceCore
.applyingFilter("CIBlendWithMask", parameters: [
kCIInputImageKey: ciImage, // black and white image
kCIInputBackgroundImageKey: solidColor, // solid color
kCIInputMaskImageKey:sourceCore]) // edge work image
ciImage = sourceCore
return ciImage
}
【问题讨论】:
-
FWIW,我在创建具有圆角半径的蒙版并为其添加边缘时遇到了同样的问题,所有这些都使用 CIImages。我认为(完全不确定)部分原因是抗锯齿和像素。也许您可以尝试稍微模糊边缘线?
-
模糊是我考虑过并尝试过的一种方法,如果我可以使用某些阈值将颜色值四舍五入为黑色并向下舍入为白色,这可能是一个解决方案。 CIColorClamp 几乎是我正在寻找的,除了增加你匹配的值小于一定数量,如果超过一定数量则减少值。除非我理解错了,否则我不能使用它。
-
当我第一次阅读你的问题时,我想到了这个问题,它就是答案——我认为它没有帮助,但它可能会给你一个想法......stackoverflow.com/questions/45927329/cifilter-combination
-
哦,是的,我以前见过这个问题。谢谢,这是我所追求的,但程度更高。
-
祝你好运。如果我正确阅读了您想要的内容(没有锯齿的较厚边缘),我认为掩蔽和模糊的组合可能会更好。如果您找到满意的东西,请发布它 - 我很乐意支持它(并可能合并它)。