gpt4 book ai didi

ios - 将捕获的图像精确裁剪为 AVCaptureVideoPreviewLayer 中的外观

转载 作者:技术小花猫 更新时间:2023-10-29 10:21:00 27 4
gpt4 key购买 nike

我有一个使用 AV Foundation 的照片应用程序。我已经使用占据屏幕上半部分的 AVCaptureVideoPreviewLayer 设置了一个预览层。因此,当用户尝试拍照时,他们只能看到屏幕的上半部分。

效果很好,但是当用户实际拍摄照片并且我尝试将照片设置为图层的内容时,图像失真了。我做了研究,意识到我需要裁剪图像。

我想做的就是裁剪完整的捕获图像,这样剩下的就是用户最初在屏幕上半部分看到的内容。

我已经能够完成此操作,但我是通过输入手动 CGRect 值来完成此操作的,但它看起来仍然不完美。必须有一种更简单的方法来做到这一点。

在过去的 2 天里,我确实浏览了 stack overflow 上所有关于裁剪图像的帖子,但没有任何效果。

必须有一种方法以编程方式裁剪捕获的图像,以便最终图像与预览层中最初看到的完全一致。

这是我的 viewDidLoad 实现:

- (void)viewDidLoad
{
[super viewDidLoad];

AVCaptureSession *session =[[AVCaptureSession alloc]init];
[session setSessionPreset:AVCaptureSessionPresetPhoto];

AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

NSError *error = [[NSError alloc]init];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];

if([session canAddInput:deviceInput])
[session addInput:deviceInput];

CALayer *rootLayer = [[self view]layer];
[rootLayer setMasksToBounds:YES];

_previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
[_previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height/2)];
[_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

[rootLayer insertSublayer:_previewLayer atIndex:0];

_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
[session addOutput:_stillImageOutput];

[session startRunning];
}

下面是当用户按下按钮拍摄照片时运行的代码:

-(IBAction)stillImageCapture {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in _stillImageOutput.connections){
for (AVCaptureInputPort *port in [connection inputPorts]){
if ([[port mediaType] isEqual:AVMediaTypeVideo]){
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}

NSLog(@"about to request a capture from: %@", _stillImageOutput);

[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if(imageDataSampleBuffer) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

UIImage *image = [[UIImage alloc]initWithData:imageData];
CALayer *subLayer = [CALayer layer];
subLayer.frame = _previewLayer.frame;
image = [self rotate:image andOrientation:image.imageOrientation];

//Below is the crop that is sort of working for me, but as you can see I am manually entering in values and just guessing and it still does not look perfect.
CGRect cropRect = CGRectMake(0, 650, 3000, 2000);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);

subLayer.contents = (id)[UIImage imageWithCGImage:imageRef].CGImage;
subLayer.frame = _previewLayer.frame;

[_previewLayer addSublayer:subLayer];
}
}];
}

最佳答案

看看 AVCaptureVideoPreviewLayer

-(CGRect)metadataOutputRectOfInterestForRect:(CGRect)layerRect

此方法可让您轻松地将图层的可见 CGRect 转换为实际的相机输出。

一个警告:物理摄像头不是“顶面朝上”安装的,而是顺时针旋转 90 度。 (因此,如果您按住 iPhone - 右侧的主页按钮,相机实际上是顶部朝上的)。

请记住这一点,您必须转换上述方法提供的 CGRect,以准确裁剪图像以显示屏幕上的内容。

例子:

CGRect visibleLayerFrame = THE ACTUAL VISIBLE AREA IN THE LAYER FRAME
CGRect metaRect = [self.previewView.layer metadataOutputRectOfInterestForRect:visibleLayerFrame];


CGSize originalSize = [originalImage size];

if (UIInterfaceOrientationIsPortrait(_snapInterfaceOrientation)) {
// For portrait images, swap the size of the image, because
// here the output image is actually rotated relative to what you see on screen.

CGFloat temp = originalSize.width;
originalSize.width = originalSize.height;
originalSize.height = temp;
}


// metaRect is fractional, that's why we multiply here

CGRect cropRect;

cropRect.origin.x = metaRect.origin.x * originalSize.width;
cropRect.origin.y = metaRect.origin.y * originalSize.height;
cropRect.size.width = metaRect.size.width * originalSize.width;
cropRect.size.height = metaRect.size.height * originalSize.height;

cropRect = CGRectIntegral(cropRect);

这可能有点令人困惑,但让我真正理解它的是:

按住设备的“Home Button right” -> 你会看到 x 轴实际上位于 iPhone 的“高度”,而 y 轴位于 iPhone 的“宽度”。这就是为什么对于肖像图像,您必须交换尺寸 ;)

关于ios - 将捕获的图像精确裁剪为 AVCaptureVideoPreviewLayer 中的外观,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21924255/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com