In this episode we take the captured image and run the perspective correction filter on it in order to turn a skewed rect back into a flat rectangle. We then display the image on the screen for a few seconds as a preview mechanism.
Episode Links Episode 147 - Core Image Filters Core Image Filter Reference Perspective Correction private func perspectiveCorrect(_ image: CIImage, rectFeature: CIRectangleFeature) -> CIImage? { let perspectiveFilter = CIFilter(name: kCIPerspectiveCorrection)! perspectiveFilter.setValue(image, forKey: kCIInputImageKey) let corners = [ (rectFeature.topLeft, "inputTopLeft"), (rectFeature.topRight, "inputTopRight"), (rectFeature.bottomRight, "inputBottomRight"), (rectFeature.bottomLeft, "inputBottomLeft"), ] for (point, key) in corners { let vector = CIVector(cgPoint: point) perspectiveFilter.setValue(vector, forKey: key) } guard let correctedImage = perspectiveFilter.outputImage else { return nil } return correctedImage } Displaying the image on screen private func displayImage(ciImage: CIImage) { guard let cgImage = ciContext.createCGImage(ciImage, from: ciImage.extent) else { fatalError() } let image = UIImage(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up) let imageView = UIImageView(image: image) imageView.frame = view.bounds imageView.backgroundColor = UIColor(white: 0, alpha: 0.8) imageView.contentMode = .scaleAspectFit imageView.alpha = 0 view.addSubview(imageView) UIView.animate(withDuration: 0.3) { imageView.alpha = 1 } DispatchQueue.main.asyncAfter(deadline: .now() + 2) { UIView.animate(withDuration: 0.3, animations: { imageView.alpha = 0 }, completion: { completed in imageView.removeFromSuperview() self.detectRectangles = true }) } } Fixing the rotation of the image Running the application, we can see that if we capture the image, it is displayed in a rotated fashion. To fix this, we can chain another filter to our perspective correction method in order to rotate the image to the proper orientation. let extent = correctedImage.extent let transformFilter = CIFilter(name: kCIAffineTransform)! /*----* | | *----*/ var transform = CGAffineTransform(translationX: extent.midX, y: -extent.midY) transform = transform.rotated(by: -.pi/2) transform = transform.translatedBy(x: -extent.midX, y: extent.midY) transformFilter.setValue(correctedImage, forKey: kCIInputImageKey) transformFilter.setValue(transform, forKey: kCIInputTransformKey) return transformFilter.outputImage