核心图像 CIPerspectiveTransform 过滤器:如何使用CIVector?
-
12-12-2019 - |
题
我很难在网上找到任何文档来清楚地解释如何正确实现 Core Image 的 CIPerspectiveTransform 过滤器。特别是,当设置 CIVector 值时 inputTopLeft
, inputTopRight
, inputBottomRight
, , 和 inputBottomLeft
, ,这些向量对图像做了什么?(即,这些向量如何扭曲我的图像背后的数学原理是什么?)
目前这是我正在使用的代码。它不会崩溃,但不显示图像:
CIImage *myCIImage = [[CIImage alloc] initWithImage:self.image];
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filter = [CIFilter filterWithName:@"CIPerspectiveTransform" keysAndValues:@"inputImage", myCIImage, @"inputTopLeft", [CIVector vectorWithX:118 Y:484], @"inputTopRight", [CIVector vectorWithX:646 Y:507], @"inputBottomRight", [CIVector vectorWithX:548 Y:140], @"inputBottomLeft", [CIVector vectorWithX:155 Y:153], nil];
CIImage *outputImage = [filter outputImage];
CGImageRef cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *transformedImage = [UIImage imageWithCGImage:cgimg];
[self setImage:transformedImage];
CGImageRelease(cgimg);
其他可能很重要的注意事项:
我的 UIImageView (75pts x 115 pts) 已经通过 awakeFromNib 初始化,并且已经有一个与其关联的图像 (151px x 235px)。
上面的代码是在UIImageView中实现的
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
功能。我希望能够根据屏幕坐标调整图像的视角,使图像看起来像是在 3D 空间中移动。此代码适用于 iPhone 应用程序。
同样,我认为我要问的问题是各种参数向量的作用,但我可能问错了问题。
下面的帖子非常相似,但询问的是为什么他的图像消失了,而不是如何使用 CIVectors 进行 CIPerspectiveTransform。它也没有受到多少关注,也许是因为它太笼统了:如何使用 CIPerspectiveTransform 过滤器
解决方案
正如我对链接问题的评论,CIPerspectiveTransform 是 自 iOS 5.1 起,在 Core Image 的 iOS 实现中不可用. 。这就是为什么你和另一个提问者没有看到任何图像的原因,因为很可能你的 CIFilter 为零。
如果您只想在图像上实现某种形式的透视,在 iOS 上有两种不同的快速方法可以实现此目的,正如我在 这个答案. 。一种是简单地使用 正确的 CATransform3D 类型 在 UIImageView 的图层上,但这仅对显示有用,对图像调整不起作用。
第二种方法是在 OpenGL ES 中使用适当的 3-D 变换矩阵来操作图像。正如我在上面链接的答案中指出的,我有 一个开源框架 包含了所有这些,其中的 FilterShowcase 示例有一个将透视应用于传入视频的示例。您可以轻松地将视频输入替换为图像,并在应用透视效果后从中抓取图像。
其他提示
太老了,但我敢打赌有人仍然会寻找这种过滤器:
以下函数将滤镜应用于图像并返回具有透视效果的相同图像,尝试创建具有透视效果的反射效果。(下图仅为示例,并非真实测试结果)
这是一个示例,因此您需要进行一些调整。目的是创建一个似乎反映“主要”图像的图像。
因此,我在视图中添加了两个图像视图,如图所示。增加了约束条件等。
然后在 func 中,您将看到坐标是硬编码的,因此返回的图像将完美匹配其容器(底部 UIImageView)。
func applyperspectiveTransform(imagen: UIImage) -> UIImage
{
var context = CIContext()
var outputImage = CIImage()
var newUIImage = UIImage()
let leftTop = CGPoint(x: self.ImgView.frame.origin.x, y: self.ImgReflection.frame.origin.y + self.ImgReflection.frame.size.height)
let leftBottom = CGPoint(x: self.ImgReflection.frame.origin.x, y: self.ImgView.frame.origin.y + self.ImgView.frame.size.height)
let rightTop = CGPoint(x: self.ImgView.frame.origin.x + self.ImgView.frame.size.width, y: self.ImgReflection.frame.origin.y + self.ImgReflection.frame.size.height)
let rightBottom = CGPoint(x: self.ImgReflection.frame.origin.x + self.ImgReflection.frame.size.width, y: self.ImgView.frame.origin.y + self.ImgView.frame.size.height)
let lT = CIVector(x: leftTop.x, y: leftTop.y)
let lB = CIVector(x: leftBottom.x, y: leftBottom.y)
let rT = CIVector(x: rightTop.x, y: rightTop.y)
let rB = CIVector(x: rightBottom.x, y: rightBottom.y)
let aCIImage = CIImage(image: imagen)
context = CIContext(options: nil);
let perspectiveTransform = CIFilter(name: "CIPerspectiveTransform")!
perspectiveTransform.setValue(lB,forKey: "inputTopLeft")
perspectiveTransform.setValue(rB,forKey: "inputTopRight")
perspectiveTransform.setValue(rT,forKey: "inputBottomRight")
perspectiveTransform.setValue(lT,forKey: "inputBottomLeft")
perspectiveTransform.setValue(aCIImage,forKey: kCIInputImageKey)
outputImage = perspectiveTransform.outputImage!
let cgimg = context.createCGImage(outputImage, from: outputImage.extent)
newUIImage = UIImage(cgImage: cgimg!)
return newUIImage
}
对于这个特定的效果(镜像),您可能需要添加更多效果,例如渐变、更改 alpha 等
快乐编码!希望能帮助到你
希望能帮助到你!