Как обрезать изображение по координатам VNRecognizedObjectObservation в Swift?

Мне нужно обрезать UIImage из признанных VNRecognizedObjectObservation и VNImageRectForNormalizedRect. Я пробовал много способов обрезки изображений, но ничего не работает, только один метод был близок, но не совсем обрезан, другие возвращали черное изображение (или не в прямом).

@IBOutlet weak var recognitionImageView: UIImageView!
var chosenImage: UIImage?
private var bufferSize: CGSize = .zero
func handleClassifications(request: VNRequest, error: Error?) {
        DispatchQueue.main.async { [weak self] in

            guard let self = self, let predictions = request.results as? [VNRecognizedObjectObservation] else { return }

            let objectBounds = VNImageRectForNormalizedRect(predictions.first!.boundingBox, Int(self.bufferSize.width), Int(self.bufferSize.height))

            let img = self.chosenImage!.cropped(rect: objectBounds)
            self.recognitionImageView.image = img 


        }

    }

Средство выбора изображений

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

        picker.dismiss(animated: true)

        guard let selectedImage = info[.originalImage] as? UIImage
            else {
                fatalError("")
        }

        chosenImage = selectedImage
        recognitionImageView.image = selectedImage

        let heightInPoints = selectedImage.size.height
        let heightInPixels = heightInPoints * selectedImage.scale
        let widthInPoints = selectedImage.size.width
        let widthInPixels = widthInPoints * selectedImage.scale

        bufferSize.height = heightInPixels
        bufferSize.width = widthInPixels

        updateClassifications(for: selectedImage)

    }

Обрезка изображения, но большинство проверенных решений возвращают черный экран или неправильное изображение

private func cropImage(object: VNDetectedObjectObservation) -> CGImage? {
        let objectBounds = VNImageRectForNormalizedRect(object.boundingBox, Int(self.bufferSize.width), Int(self.bufferSize.height))

        let width = objectBounds.width * CGFloat(self.detectable!.width)
           let height = objectBounds.height * CGFloat(self.detectable!.height)
           let x = objectBounds.origin.x * CGFloat(self.detectable!.width)
           let y = (1 - objectBounds.origin.y) * CGFloat(self.detectable!.height) - height

           let croppingRect = CGRect(x: x, y: y, width: width, height: height)
           let image = self.detectable!.cropping(to: croppingRect)
           return image
       }

    private func CropImage( image:UIImage , cropRect:CGRect) -> UIImage
    {
        UIGraphicsBeginImageContextWithOptions(cropRect.size, false, 0);
        let context = UIGraphicsGetCurrentContext();

        context?.translateBy(x: 0.0, y: image.size.height);
        context?.scaleBy(x: 1.0, y: -1.0);
        context?.draw(image.cgImage!, in: CGRect(x:0, y:0, width:image.size.width, height:image.size.height), byTiling: false);
        context?.clip(to: [cropRect]);

        let croppedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return croppedImage!;
    }

    func cropImage(imageToCrop:UIImage, toRect rect:CGRect) -> UIImage{

        let imageRef:CGImage = imageToCrop.cgImage!.cropping(to: rect)!
        let cropped:UIImage = UIImage(cgImage:imageRef)
        return cropped
    }
    func CGRectMake(_ x: CGFloat, _ y: CGFloat, _ width: CGFloat, _ height: CGFloat) -> CGRect {
        return CGRect(x: x, y: y, width: width, height: height)
    }

    func cropImage2(image: UIImage, rect: CGRect, scale: CGFloat) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: rect.size.width / scale, height: rect.size.height / scale), true, 0.0)
        image.draw(at: CGPoint(x: -rect.origin.x / scale, y: -rect.origin.y / scale))
        let croppedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return croppedImage
    }

Это расширение близко к тому, что мне нужно, но иногда оно возвращает неправильное изображение. Я знаю, что это неправильно, потому что у меня boundingBoxView с блоками распознавания

func cropped(rect: CGRect) -> UIImage? {

            let rad: (Double) -> CGFloat = { deg in
                return CGFloat(deg / 180.0 * .pi)
            }
            var rectTransform: CGAffineTransform
            switch imageOrientation {
            case .left:
                let rotation = CGAffineTransform(rotationAngle: rad(90))
                rectTransform = rotation.translatedBy(x: 0, y: -size.height)
            case .right:
                let rotation = CGAffineTransform(rotationAngle: rad(-90))
                rectTransform = rotation.translatedBy(x: -size.width, y: 0)
            case .down:
                let rotation = CGAffineTransform(rotationAngle: rad(-180))
                rectTransform = rotation.translatedBy(x: -size.width, y: -size.height)
            default:
                rectTransform = .identity
            }

            rectTransform = rectTransform.scaledBy(x: scale, y: scale)
            let transformedRect = rect.applying(rectTransform)

            let imageRef = cgImage!.cropping(to: transformedRect)!
            let result = UIImage(cgImage: imageRef, scale: scale, orientation: imageOrientation)
            return result
        }

0 ответов

Другие вопросы по тегам