在 iOS OpenCV 相机中将相机预览旋转到人像
Posted
技术标签:
【中文标题】在 iOS OpenCV 相机中将相机预览旋转到人像【英文标题】:Rotate camera preview to Portrait in iOS OpenCV Camera 【发布时间】:2016-01-05 20:29:16 【问题描述】:我刚打算在我的 ios 应用中使用 openCV。
我创建了相机预览,但它以横向模式显示,但方向不正确。我不知道如何以正确的方向旋转相机意味着如果手机是纵向的,那么相机应该以纵向模式打开..
有什么解决办法吗?
【问题讨论】:
【参考方案1】:如果你使用的是CvVideoCameraDelegate,那么在viewDidLoad方法中初始化相机参数后添加如下代码。
self->videoCamera.rotateVideo = YES;
【讨论】:
【参考方案2】:您没有具体说明相关窗口是视图还是图层,或者是实时视频还是保存到文件中。您也没有指定视频是通过 OpenCV 录制的,还是通过其他方式录制的。
因此,我为每个意外事件都包含了代码 sn-ps;如果您熟悉 OpenCV 和 iOS 视图编程的基础知识,那么应该很清楚您应该使用什么(在我的情况下,顺便说一下,我使用了所有这些):
- (void)viewDidLayoutSubviews
[super viewDidLayoutSubviews];
switch ([UIDevice currentDevice].orientation)
case UIDeviceOrientationPortraitUpsideDown:
self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
break;
case UIDeviceOrientationLandscapeLeft:
self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationLandscapeLeft;
break;
case UIDeviceOrientationLandscapeRight:
self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationLandscapeRight;
break;
default:
self.videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
break;
[self refresh];
- (void)processImage:(cv::Mat &)mat
if (self.videoCamera.running)
switch (self.videoCamera.defaultAVCaptureVideoOrientation)
case AVCaptureVideoOrientationLandscapeLeft:
case AVCaptureVideoOrientationLandscapeRight:
// The landscape video is captured upside-down.
// Rotate it by 180 degrees.
cv::flip(mat, mat, -1);
break;
default:
break;
- (void)convertBlendSrcMatToWidth:(int)dstW height:(int)dstH
double dstAspectRatio = dstW / (double)dstH;
int srcW = originalBlendSrcMat.cols;
int srcH = originalBlendSrcMat.rows;
double srcAspectRatio = srcW / (double)srcH;
cv::Mat subMat;
if (srcAspectRatio < dstAspectRatio)
int subMatH = (int)(srcW / dstAspectRatio);
int startRow = (srcH - subMatH) / 2;
int endRow = startRow + subMatH;
subMat = originalBlendSrcMat.rowRange(startRow, endRow);
else
int subMatW = (int)(srcH * dstAspectRatio);
int startCol = (srcW - subMatW) / 2;
int endCol = startCol + subMatW;
subMat = originalBlendSrcMat.colRange(startCol, endCol);
cv::resize(subMat, convertedBlendSrcMat, cv::Size(dstW, dstH), 0.0, 0.0, cv::INTER_LANCZOS4);
- (int)imageWidth
AVCaptureVideoDataOutput *output = [self.captureSession.outputs lastObject];
NSDictionary *videoSettings = [output videoSettings];
int videoWidth = [[videoSettings objectForKey:@"Width"] intValue];
return videoWidth;
- (int)imageHeight
AVCaptureVideoDataOutput *output = [self.captureSession.outputs lastObject];
NSDictionary *videoSettings = [output videoSettings];
int videoHeight = [[videoSettings objectForKey:@"Height"] intValue];
return videoHeight;
- (void)updateSize
// Do nothing.
- (void)layoutPreviewLayer
if (self.parentView != nil)
// Center the video preview.
self.customPreviewLayer.position = CGPointMake(0.5 * self.parentView.frame.size.width, 0.5 * self.parentView.frame.size.height);
// Find the video's aspect ratio.
CGFloat videoAspectRatio = self.imageWidth / (CGFloat)self.imageHeight;
// Scale the video preview while maintaining its aspect ratio.
CGFloat boundsW;
CGFloat boundsH;
if (self.imageHeight > self.imageWidth)
if (self.letterboxPreview)
boundsH = self.parentView.frame.size.height;
boundsW = boundsH * videoAspectRatio;
else
boundsW = self.parentView.frame.size.width;
boundsH = boundsW / videoAspectRatio;
else
if (self.letterboxPreview)
boundsW = self.parentView.frame.size.width;
boundsH = boundsW / videoAspectRatio;
else
boundsH = self.parentView.frame.size.height;
boundsW = boundsH * videoAspectRatio;
self.customPreviewLayer.bounds = CGRectMake(0.0, 0.0, boundsW, boundsH);
- (void)processImage:(cv::Mat &)mat
if (self.videoCamera.running)
switch (self.videoCamera.defaultAVCaptureVideoOrientation)
case AVCaptureVideoOrientationLandscapeLeft:
case AVCaptureVideoOrientationLandscapeRight:
// The landscape video is captured upside-down.
// Rotate it by 180 degrees.
cv::flip(mat, mat, -1);
break;
default:
break;
- (void)convertBlendSrcMatToWidth:(int)dstW height:(int)dstH
double dstAspectRatio = dstW / (double)dstH;
int srcW = originalBlendSrcMat.cols;
int srcH = originalBlendSrcMat.rows;
double srcAspectRatio = srcW / (double)srcH;
cv::Mat subMat;
if (srcAspectRatio < dstAspectRatio)
int subMatH = (int)(srcW / dstAspectRatio);
int startRow = (srcH - subMatH) / 2;
int endRow = startRow + subMatH;
subMat = originalBlendSrcMat.rowRange(startRow, endRow);
else
int subMatW = (int)(srcH * dstAspectRatio);
int startCol = (srcW - subMatW) / 2;
int endCol = startCol + subMatW;
subMat = originalBlendSrcMat.colRange(startCol, endCol);
cv::resize(subMat, convertedBlendSrcMat, cv::Size(dstW, dstH), 0.0, 0.0, cv::INTER_LANCZOS4);
- (int)imageWidth
AVCaptureVideoDataOutput *output = [self.captureSession.outputs lastObject];
NSDictionary *videoSettings = [output videoSettings];
int videoWidth = [[videoSettings objectForKey:@"Width"] intValue];
return videoWidth;
- (int)imageHeight
AVCaptureVideoDataOutput *output = [self.captureSession.outputs lastObject];
NSDictionary *videoSettings = [output videoSettings];
int videoHeight = [[videoSettings objectForKey:@"Height"] intValue];
return videoHeight;
- (void)updateSize
// Do nothing.
- (void)layoutPreviewLayer
if (self.parentView != nil)
// Center the video preview.
self.customPreviewLayer.position = CGPointMake(0.5 * self.parentView.frame.size.width, 0.5 * self.parentView.frame.size.height);
// Find the video's aspect ratio.
CGFloat videoAspectRatio = self.imageWidth / (CGFloat)self.imageHeight;
// Scale the video preview while maintaining its aspect ratio.
CGFloat boundsW;
CGFloat boundsH;
if (self.imageHeight > self.imageWidth)
if (self.letterboxPreview)
boundsH = self.parentView.frame.size.height;
boundsW = boundsH * videoAspectRatio;
else
boundsW = self.parentView.frame.size.width;
boundsH = boundsW / videoAspectRatio;
else
if (self.letterboxPreview)
boundsW = self.parentView.frame.size.width;
boundsH = boundsW / videoAspectRatio;
else
boundsH = self.parentView.frame.size.height;
boundsW = boundsH * videoAspectRatio;
self.customPreviewLayer.bounds = CGRectMake(0.0, 0.0, boundsW, boundsH);
这里有很多东西,你必须知道把它放在哪里。如果你不明白,请告诉我。
【讨论】:
以上是关于在 iOS OpenCV 相机中将相机预览旋转到人像的主要内容,如果未能解决你的问题,请参考以下文章
如何在surfaceview中将Android相机更改为人像?
Android:在方向更改时保留相机预览,而其他视图可以旋转