2016-12-01 1 views
0

전 프레임을 캡처 할 때 프레임을 캡처 할 때 CCW가 90도 회전합니다. CGContext에서 캡쳐 된 이미지를 회전시키고 싶습니다 (Core Graphic을 읽는 것이 다른 프레임 워크보다 훨씬 빠르기 때문에).CGContext의 Samplebuffer에서 캡처 한 프레임을 회전

여기 내 코드입니다 :

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!) 
} 

답변

1

검색하고 기사를 읽고 많은 후, 나는 AVCaptureConnection 클래스 안에 내 해결책을 발견! 캡쳐 기능 안에서 다음 샘플 코드로 버퍼 내에서 프레임을 회전 시키려면 연결을 요청하면됩니다 !!

if connection.isVideoOrientationSupported 
{ 
    connection.videoOrientation = .portrait 
} 
    if connection.isVideoMirroringSupported 
{ 
    connection.isVideoMirrored = true 
} 

그게 전부입니다!

1

실제로 어떤 각도로든 버퍼를 실제로 회전하는 방법을 검색하는 사람은 여기에서 수행 할 수 있습니다. 기능 (AVCaptureConnection *) 연결 및 적용 :

CVPixelBufferRef pixBuf = CMSampleBufferGetImageBuffer(sampleBuffer); 
RotatePixelBufferToAngle(pixBuf, radians(45.0)); 

captureOutput에

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 didOutputSampleBuffer : (CMSampleBufferRef) sampleBuffer fromConnection 파일의 상단이 추가 45.0 - 원하는 각도입니다.

이 옵션은 회전 할뿐만 아니라 이미지를 채워서 이미지를 채 웁니다 ons (Aspect Fill과 같은 종류). scalingFact을 수정하여 배율을 끌 수 있습니다.

관련 문제