我正在使用前置摄像头,当我捕捉到帧时,它们会逆时针旋转90度。我想在CGContext中旋转捕获的图像(因为我读取Core Graphic比其他框架快得多)。
这是我的代码:
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0))
let width = CVPixelBufferGetWidthOfPlane(imageBuffer!, 0)
let height = CVPixelBufferGetHeightOfPlane(imageBuffer!, 0)
let bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer!, 0)
let lumaBuffer = CVPixelBufferGetBaseAddressOfPlane(imageBuffer!, 0)
let grayColorSpace = CGColorSpaceCreateDeviceGray()
let context = CGContext(data: lumaBuffer,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: bytesPerRow,
space: grayColorSpace,
bitmapInfo: CGImageAlphaInfo.none.rawValue);
let transform1 = CGAffineTransform(rotationAngle: CGFloat(M_PI_2))
context!.concatenate(transform1)
//context!.rotate(by: CGFloat(M_PI_2)) // also not working!
let dstImage = context!.makeImage()
detect(image: dstImage!)
}
答案 0 :(得分:2)
对于任何搜索如何以任何角度实际旋转缓冲区的人来说,这是如何做到的。将其添加到文件顶部:
static double radians (double degrees) {return degrees * M_PI/180;}
static double ScalingFactorForAngle(double angle, CGSize originalSize) {
double oriWidth = originalSize.height;
double oriHeight = originalSize.width;
double horizontalSpace = fabs( oriWidth*cos(angle) ) + fabs( oriHeight*sin(angle) );
double scalingFactor = oriWidth / horizontalSpace ;
return scalingFactor;
}
CGColorSpaceRef rgbColorSpace = NULL;
CIContext *context = nil;
CIImage *ci_originalImage = nil;
CIImage *ci_transformedImage = nil;
CIImage *ci_userTempImage = nil;
static inline void RotatePixelBufferToAngle(CVPixelBufferRef thePixelBuffer, double theAngle) {
@autoreleasepool {
if (context==nil) {
rgbColorSpace = CGColorSpaceCreateDeviceRGB();
context = [CIContext contextWithOptions:@{kCIContextWorkingColorSpace: (__bridge id)rgbColorSpace,
kCIContextOutputColorSpace : (__bridge id)rgbColorSpace}];
}
long int w = CVPixelBufferGetWidth(thePixelBuffer);
long int h = CVPixelBufferGetHeight(thePixelBuffer);
ci_originalImage = [CIImage imageWithCVPixelBuffer:thePixelBuffer];
ci_userTempImage = [ci_originalImage imageByApplyingTransform:CGAffineTransformMakeScale(0.6, 0.6)];
// CGImageRef UICG_image = [context createCGImage:ci_userTempImage fromRect:[ci_userTempImage extent]];
double angle = theAngle;
angle = angle+M_PI;
double scalingFact = ScalingFactorForAngle(angle, CGSizeMake(w, h));
CGAffineTransform transform = CGAffineTransformMakeTranslation(w/2.0, h/2.0);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformTranslate(transform, -w/2.0, -h/2.0);
//rotate it by applying a transform
ci_transformedImage = [ci_originalImage imageByApplyingTransform:transform];
CVPixelBufferLockBaseAddress(thePixelBuffer, 0);
CGRect extentR = [ci_transformedImage extent];
CGPoint centerP = CGPointMake(extentR.size.width/2.0+extentR.origin.x,
extentR.size.height/2.0+extentR.origin.y);
CGSize scaledSize = CGSizeMake(w*scalingFact, h*scalingFact);
CGRect cropRect = CGRectMake(centerP.x-scaledSize.width/2.0, centerP.y-scaledSize.height/2.0,
scaledSize.width, scaledSize.height);
CGImageRef cg_img = [context createCGImage:ci_transformedImage fromRect:cropRect];
ci_transformedImage = [CIImage imageWithCGImage:cg_img];
ci_transformedImage = [ci_transformedImage imageByApplyingTransform:CGAffineTransformMakeScale(1.0/scalingFact, 1.0/scalingFact)];
[context render:ci_transformedImage toCVPixelBuffer:thePixelBuffer bounds:CGRectMake(0, 0, w, h) colorSpace:NULL];
CGImageRelease(cg_img);
CVPixelBufferUnlockBaseAddress(thePixelBuffer, 0);
}
}
转到captureOutput: captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 并应用函数:
CVPixelBufferRef pixBuf = CMSampleBufferGetImageBuffer(sampleBuffer);
RotatePixelBufferToAngle(pixBuf, radians(45.0));
其中 45.0 - 是所需的角度
请注意,这不仅可以旋转,还可以缩放图像,使其填充视频尺寸(类似于Aspect Fill)。您可以通过修改 scalingFact 变量来关闭缩放。
答案 1 :(得分:0)
如果您使用的方法:
- (void)captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection*)connection
您可以更改缓冲区的方向以获得正确的图像,这里有一个示例:
UIInterfaceOrientation iOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(iOrientation == UIInterfaceOrientationLandscapeLeft){
[connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
}
else{
[connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
}
希望它有所帮助。