簡體   English   中英

在Swift中從相機裁剪圖像,而無需移動到另一個ViewController

[英]Crop Image from Camera in Swift without move to another ViewController

我在CameraViewController中有一個圖像疊加層:

描述 我想從這個紅色方塊內獲取圖像。 我不想移動到另一個視圖控制器來設置CropViewController,裁剪應在此Controller內部完成。

后面的這段代碼幾乎可以正常工作,問題是從相機生成的圖像是1080x1920,self.cropView.bounds是(0,0,185,120),當然它不代表用於拍攝圖像的相同比例

extension UIImage {
    func crop(rect: CGRect) -> UIImage {
        var rect = rect
        rect.origin.x*=self.scale
        rect.origin.y*=self.scale
        rect.size.width*=self.scale
        rect.size.height*=self.scale

        let imageRef = self.cgImage!.cropping(to: rect)
        let image = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
        return image
    }
}

您始終可以使用Core Image濾鏡調用CIPerspectiveCorrection直觀地裁剪四邊形(四邊形-不必是矩形)中的任何圖像。

假設您有一個imageView框架,其寬度為414 x 716高度,圖像的尺寸為1600寬度x 900高度。 (您使用的是.aspectFit的內容模式,對嗎?)假設您要裁剪一個4角的角形狀-在imageView的(X,Y)坐標中-為(50,50),(75,75) ,(100,300)和(25,200)。 請注意,我以左上角(TL,右上角(TR),右下角(BR),左下角(BL)的順序列出這些點。另外請注意,這不是一個直截了當的矩形。

您需要做的就是這個。 (1)將UIImage轉換為CIImage,其中“范圍”是UIImage大小,(2)將那些UIImageView坐標轉換為CIImage坐標,(3)將它們和CIImage傳遞到CIPerspectiveCorrection過濾器中進行裁剪,以及(4)渲染將CIImage輸出到UIImageView中。

以下是我放在一起的一些代碼。 有用。 邊緣也有些粗糙,但希望您能理解。

class ViewController: UIViewController {

    let uiTL = CGPoint(x: 50, y: 50)
    let uiTR = CGPoint(x: 75, y: 75)
    let uiBL = CGPoint(x: 100, y: 300)
    let uiBR = CGPoint(x: 25, y: 200)

    var ciImage:CIImage!
    var ctx:CIContext!

    @IBOutlet weak var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        ctx = CIContext(options: nil)
        ciImage = CIImage(image: imageView.image!)
    }

    override func viewWillLayoutSubviews() {
        let ciTL = createVector(createScaledPoint(uiTL))
        let ciTR = createVector(createScaledPoint(uiTR))
        let ciBR = createVector(createScaledPoint(uiBR))
        let ciBL = createVector(createScaledPoint(uiBL))
        imageView.image = doPerspectiveCorrection(CIImage(image: imageView.image!)!,
                                                  context: ctx,
                                                  topLeft: ciTL,
                                                  topRight: ciTR,
                                                  bottomRight: ciBR,
                                                  bottomLeft: ciBL)
    }
    func doPerspectiveCorrection(
        _ image:CIImage,
        context:CIContext,
        topLeft:AnyObject,
        topRight:AnyObject,
        bottomRight:AnyObject,
        bottomLeft:AnyObject)
        -> UIImage {
            let filter = CIFilter(name: "CIPerspectiveCorrection")
            filter?.setValue(topLeft, forKey: "inputTopLeft")
            filter?.setValue(topRight, forKey: "inputTopRight")
            filter?.setValue(bottomRight, forKey: "inputBottomRight")
            filter?.setValue(bottomLeft, forKey: "inputBottomLeft")
            filter!.setValue(image, forKey: kCIInputImageKey)
            let cgImage = context.createCGImage((filter?.outputImage)!, from: (filter?.outputImage!.extent)!)
            return UIImage(cgImage: cgImage!)
    }

    func createScaledPoint(_ pt:CGPoint) -> CGPoint {
        let x = (pt.x / imageView.frame.width) * ciImage.extent.width
        let y = (pt.y / imageView.frame.height) * ciImage.extent.height
        return CGPoint(x: x, y: y)
    }
    func createVector(_ point:CGPoint) -> CIVector {
        return CIVector(x: point.x, y: ciImage.extent.height - point.y)
    }
    func createPoint(_ vector:CGPoint) -> CGPoint {
        return CGPoint(x: vector.x, y: ciImage.extent.height - vector.y)
    }

}

編輯:我把這里放在這里來解釋事情。 希望這不會違反站點規則。 我們兩個人交換了項目,發問者的代碼出現問題,零回報正在發生。 首先,這是更正后的代碼,應該在cropImage()函數中:

let ciTL = createVector(createScaledPoint(topLeft, overlay: cameraView, image: image), image: image)
let ciTR = createVector(createScaledPoint(topRight, overlay: cameraView, image: image), image: image)
let ciBR = createVector(createScaledPoint(bottomRight, overlay: cameraView, image: image), image: image)
let ciBL = createVector(createScaledPoint(bottomLeft, overlay: cameraView, image: image), image: image)

問題在於最后兩行,它們是通過將bottomLeft傳遞到應該為bottomRight的位置來進行轉置的,反之亦然。 (容易犯的錯誤,我也做到了!)

一些說明可幫助使用CIPerspectiveCorrection(以及使用CIVectors的其他過濾器)的人員。

  • (1)CIVector可以有-從我認為2到幾乎無限數量的組件。 這取決於過濾器。 在這種情況下,有兩個分量(X,Y)。 足夠簡單,但有一個問題是4個CIVector在CIImage范圍內描述了4個點,其原點位於左下角而不是左上角。

  • (2)請注意,我沒有說四邊形。 實際上,您可以擁有一個類似“圖8”的形狀,其中“右下”點位於“左下”點的左邊! 這將導致兩側相互交叉的形狀。

  • (3)重要的是所有四個點都位於CIImage范圍內。 如果沒有,則返回值為nil的過濾器作為其輸出圖像。

對於那些以前沒有使用過CIImage過濾器的人,請注意最后一點-過濾器將不會執行,直到您要求outputImage為止。 您可以實例化一個,填寫參數,將其鏈接,無論如何。 您甚至可以在過濾器名稱(或其任何鍵)中輸入錯誤。 在您的代碼要求filter.outputImage之前,什么都不會發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM