使用Core Image在Swift中复制cv::warpAffine

4
我会尝试在Swift中使用Core Image来复制一种面部对齐算法。然而,我已经无法在Swift中复制来自opencv的简单warpAffine。
Python代码:
print(M) #M is a matrix calculated using some face detection code
print("let transform = CGAffineTransform(a: {0[0][0]}, b: {0[1][0]}, c: {0[0][1]}, d: {0[1][1]}, tx: {0[0][2]}, ty: {0[1][2]})".format(M))
warped = cv2.warpAffine(img,M,(image_size[1],image_size[0]), borderValue = 0.0) #warped is the correctly aligned image, image_size is 112,112

我的 Swift 版本:

import UIKit
import CoreImage

let ctx = CIContext()
let image = UIImage(named: "lg.jpg")
let ciimage = CIImage(image: image!)
let transform = CGAffineTransform(a: 0.390825773796, b: -0.0333640808264, c: 0.0333640808264, d: 0.390825773796, tx: -53.8777275485, ty: -23.0859985227)
let aligned = ciimage?.transformed(by: transform)
let size = aligned!.extent
let center = CGPoint(x: size.midX, y: size.midY)
let cropRect = CGRect(x: center.x-56, y: center.y-56, width: 112, height: 112)
let cropped = aligned!.cropped(to: cropRect)

使用 swift 版本(cropped)所给出的图像向左旋转了几度,并且裁剪过度向下。我已经尝试重新排序变换参数,因为我猜想这就是我的错误之处。但根据opencv文档CGAffineTransform文档的说法,参数应该是正确的。

你使用了哪个 CIFilter?它不在你的代码中,我也不确定为什么你将其标记为 [core-image]。如果是因为你可以在 CIImage 上调用某些东西...那为什么?如果你没有使用过滤器或内核 - 我认为你可能会使用 - 那为什么不只是使用一个实际的图像(无论是 UIImage 还是 CGImage)呢? - user7014451
因为这将实际在一系列 CoreML 请求中被实现。由于 CoreML 喜欢 CVPixelBuffers,所以我不想先将其转换为 UIImage 以节省开销。我只是在 playground 中使用 UIImage 进行测试对齐。 - gallileo
我认为是一个很好的理由。因此,如果Core Image具有CIDetection(iOS 11之前)和CoreML和Vision,则在代码方面您要做什么? - user7014451
@dfd 不太明白你的问题,但是想法是进行离线人脸识别(因此iOS 11之前的版本不适用)。我以前做过这个,但是面部对齐是使用Objective-C中的OpenCV完成的。我想为了性能和编译的便利性将那部分重写为纯Swift。然而,我已经卡在了执行与Python中面部对齐相同的仿射变换上。 - gallileo
1个回答

0

很遗憾,我无法使用CoreImage复制它。但是我已经成功地使用UIImage实现了它:

extension UIImage {
    func transformed(by transform: CGAffineTransform, size: CGSize) -> UIImage {
        UIGraphicsBeginImageContext(size)
        let c = UIGraphicsGetCurrentContext()
        let orig = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
        c?.concatenate(transform)
        self.draw(in: orig)
        let result = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return result!
    }
}

虽然这种方法可以工作,但是在我的使用场景中,将CIImage转换为UIImage再转回来的速度太慢了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接