将检测到的矩形从纵向CIImage转换为横向CIImage

时间:2017-03-24 05:19:35

标签: objective-c image cidetector

我正在修改找到的代码here。在代码中,我们使用AVCaptureSession从手机摄像头捕获视频,并使用CIDetector检测图像源中的矩形。 Feed的图像为640x842(iphone5为纵向)。然后我们对图像进行叠加,这样用户就可以看到检测到的矩形(实际上它大部分时间都是梯形)。

当用户按下UI上的按钮时,我们从视频中捕获图像并在这个较大的图像(3264x2448)上重新运行矩形检测,如您所见,它是横向的。然后,我们对检测到的矩形进行透视变换并在图像上进行裁剪。

这项工作非常顺利,但我所遇到的问题是,在5个中,有1个捕获较大图像上检测到的矩形与从较小图像检测到的(并呈现给用户)的矩形不同。即使我只是在检测到手机(相对)静止时捕获,但最终图像并不代表用户期望的矩形。

为了解决这个问题,我的想法是使用最初捕获的矩形的坐标,并将它们转换为捕获的静止图像上的矩形。这就是我挣扎的地方。

我用检测到的矩形尝试了这个:

CGFloat radians = -90 * (M_PI/180);
CGAffineTransform rotation = CGAffineTransformMakeRotation(radians);

CGRect rect = CGRectMake(detectedRect.bounds.origin.x, detectedRect.bounds.origin.y, detectedRect.bounds.size.width, detectedRect.bounds.size.height);

CGRect rotatedRect = CGRectApplyAffineTransform(rect, rotation);

所以给出了一个检测到的矩形:

TopLeft:88.213425,632.31329 TopRight:545.59302,632.15546 BottomRight:575.57819,369.22321 BottomLeft:49.973862,369.40466

我现在有这个旋转的矩形:

origin =(x = 369.223206,y = -575.578186) size =(宽度= 263.090088,身高= 525.604309)

如何将较小的纵向图像中的旋转矩形坐标转换为3264x2448图像的坐标?

修改 Duh ..阅读我自己的方法意识到用梯形创建一个矩形不会解决我的问题!

支持代码检测矩形等...

// In this method we detect a rect from the video feed and overlay

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);

    CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer];

   // image is 640x852 on iphone5

    NSArray *rects = [[CIDetector detectorOfType:CIDetectorTypeRectangle context:nil options:@{CIDetectorAccuracy : CIDetectorAccuracyHigh}] featuresInImage:image];

    CIRectangleFeature *detectedRect = rects[0]; 

    // draw overlay on image code....
}

这是如何获得静止图像的摘要版本:

// code block to handle output from AVCaptureStillImageOutput
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
     {
         NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
         CIImage *enhancedImage = [[CIImage alloc] initWithData:imageData options:@{kCIImageColorSpace:[NSNull null]}];
             imageData = nil;

         CIRectangleFeature *rectangleFeature = [self getDetectedRect:[[self highAccuracyRectangleDetector] featuresInImage:enhancedImage]];

         if (rectangleFeature) {
             enhancedImage = [self   correctPerspectiveForImage:enhancedImage withTopLeft:rectangleFeature.topLeft andTopRight:rectangleFeature.topRight andBottomRight:rectangleFeature.bottomRight andBottomLeft:rectangleFeature.bottomLeft];
         }
    }

谢谢。

1 个答案:

答案 0 :(得分:0)

我在做这种事情时遇到了同样的问题。我已经通过在swift中执行以下代码解决了这个问题。看看它是否可以帮到你。

 if let videoConnection = stillImageOutput.connection(withMediaType: AVMediaTypeVideo) {
            stillImageOutput.captureStillImageAsynchronously(from: videoConnection) {
                (imageDataSampleBuffer, error) -> Void in
                let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
                var img = UIImage(data: imageData!)!

                let outputRect = self.previewLayer?.metadataOutputRectOfInterest(for: (self.previewLayer?.bounds)!)
                let takenCGImage = img.cgImage
                let width = (takenCGImage?.width)!
                let height = (takenCGImage?.height)!
                let cropRect = CGRect(x: (outputRect?.origin.x)! * CGFloat(width), y: (outputRect?.origin.y)! * CGFloat(height), width: (outputRect?.size.width)! * CGFloat(width), height: (outputRect?.size.height)! * CGFloat(height))
                let cropCGImage = takenCGImage!.cropping(to: cropRect)
                img = UIImage(cgImage: cropCGImage!, scale: 1, orientation: img.imageOrientation)

                let cropViewController = TOCropViewController(image: self.cropToBounds(image: img))
                cropViewController.delegate = self
                self.navigationController?.pushViewController(cropViewController, animated: true)
            }
        }