我正在使用AVCaptureVideoDataOutput
和AVCaptureAudioDataOutput
录制视频和音频,并且在captureOutput:didOutputSampleBuffer:fromConnection:
委托方法中,我想在我从视频中收到的每个样本缓冲区上绘制文字连接。文本随着每一帧(它是一个秒表标签)而变化,我希望将其记录在捕获的视频数据之上。
到目前为止,这是我能够提出的:
//1.
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
//2.
UIImage *textImage = [self createTextImage];
CIImage *maskImage = [CIImage imageWithCGImage:textImage.CGImage];
//3.
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSDictionary *options = [NSDictionary dictionaryWithObject:(__bridge id)colorSpace forKey:kCIImageColorSpace];
CIImage *inputImage = [CIImage imageWithCVPixelBuffer:pixelBuffer options:options];
//4.
CIFilter *filter = [CIFilter filterWithName:@"CIBlendWithMask"];
[filter setValue:inputImage forKey:@"inputImage"];
[filter setValue:maskImage forKey:@"inputMaskImage"];
CIImage *outputImage = [filter outputImage];
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
//5.
[self.renderContext render:outputImage toCVPixelBuffer:pixelBuffer bounds:[outputImage extent] colorSpace:CGColorSpaceCreateDeviceRGB()];
//6.
[self.pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:timestamp];
createTextImage
所做的。我能够验证这一步是否有效;我保存了一张图像,并将文字绘制到我的照片中。CIBlendWithMask
创建了一个CIFilter,将输入图像设置为从原始像素缓冲区创建的图像,输入掩码设置为CIImage
从图像上绘制的文本。CIContext
预先使用[CIContext contextWithOptions:nil];
创建。{/ li>
pixelBufferAdaptor
。在录制结束时保存的视频没有可见的变化,即没有在像素缓冲区上绘制蒙版图像。
任何人都知道我在哪里错了?我已经坚持了几天,任何帮助都会如此受到赞赏。
编辑:
- (UIImage *)createTextImage {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height), NO, 1.0);
NSMutableAttributedString *timeStamp = [[NSMutableAttributedString alloc]initWithString:self.timeLabel.text attributes:@{NSForegroundColorAttributeName:self.timeLabel.textColor, NSFontAttributeName: self.timeLabel.font}];
NSMutableAttributedString *countDownString = [[NSMutableAttributedString alloc]initWithString:self.cDownLabel.text attributes:@{NSForegroundColorAttributeName:self.cDownLabel.textColor, NSFontAttributeName:self.cDownLabel.font}];
[timeStamp drawAtPoint:self.timeLabel.center];
[countDownString drawAtPoint:self.view.center];
UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return blank;
}
答案 0 :(得分:4)
你想要如下吗?
您应该使用CIBlendWithMask
,而不是CISourceOverCompositing
,请尝试:
//4.
CIFilter *filter = [CIFilter filterWithName:@"CISourceOverCompositing"];
[filter setValue:maskImage forKey:kCIInputImageKey];
[filter setValue:inputImage forKey:kCIInputBackgroundImageKey];
CIImage *outputImage = [filter outputImage];
答案 1 :(得分:1)
您还可以使用CoreGraphics
和CoreText
直接在现有CVPixelBufferRef
上绘制(如果它是RGBA)(如果是YUV则在副本上)。我在这个答案中有一些示例代码:https://stackoverflow.com/a/46524831/48125
答案 2 :(得分:1)
我向Apple DTS询问了同样的问题,因为我的所有方法都运行得非常慢或做得很奇怪,他们发给我了这个:
这让我很快就找到了工作解决方案!你可以使用CIFilters完全绕过CVPixelBuffer,恕我直言更易于使用。因此,如果您实际上并不需要使用CVPixelBuffer,那么这种方法将很快成为您的新朋友。
将源图像和图像与我为每个帧生成的文本合成的CIFilter的组合起到了作用。
我希望这有助于其他人!
答案 3 :(得分:0)
Bannings答案的快速版本。
let combinedFilter = CIFilter(name: "CISourceOverCompositing")!
combinedFilter.setValue(maskImage.oriented(.left), forKey: "inputImage")
combinedFilter.setValue(inputImage, forKey: "inputBackgroundImage")
let outputImage = combinedFilter.outputImage!
let tmpcontext = CIContext(options: nil)
tmpcontext.render(outputImage, to: pixelBuffer, bounds: outputImage.extent, colorSpace: CGColorSpaceCreateDeviceRGB())