在 iOS 中设置 AVCaptureDevice 输出的灰度

2023-11-21

我想在我的应用程序中实现自定义相机。所以,我正在使用创建这个相机AVCaptureDevice.

现在我只想在我的自定义相机中显示灰色输出。所以我试图使用这个setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains: and AVCaptureWhiteBalanceGains。我在用AVCamManual:扩展 AVCam 以使用手动捕获为了这。

- (void)setWhiteBalanceGains:(AVCaptureWhiteBalanceGains)gains
{
    NSError *error = nil;

    if ( [videoDevice lockForConfiguration:&error] ) {
        AVCaptureWhiteBalanceGains normalizedGains = [self normalizedGains:gains]; // Conversion can yield out-of-bound values, cap to limits
        [videoDevice setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:normalizedGains completionHandler:nil];
        [videoDevice unlockForConfiguration];
    }
    else {
        NSLog( @"Could not lock device for configuration: %@", error );
    }
}

但为此,我必须通过RGB 增益值1 到 4 之间。所以我创建这个方法来检查 MAX 和 MIN 值。

- (AVCaptureWhiteBalanceGains)normalizedGains:(AVCaptureWhiteBalanceGains) gains
{
    AVCaptureWhiteBalanceGains g = gains;

    g.redGain = MAX( 1.0, g.redGain );
    g.greenGain = MAX( 1.0, g.greenGain );
    g.blueGain = MAX( 1.0, g.blueGain );

    g.redGain = MIN( videoDevice.maxWhiteBalanceGain, g.redGain );
    g.greenGain = MIN( videoDevice.maxWhiteBalanceGain, g.greenGain );
    g.blueGain = MIN( videoDevice.maxWhiteBalanceGain, g.blueGain );

    return g;
}

我还尝试获得不同的效果,例如传递 RGB 增益静态值。

- (AVCaptureWhiteBalanceGains)normalizedGains:(AVCaptureWhiteBalanceGains) gains
{
    AVCaptureWhiteBalanceGains g = gains;
    g.redGain = 3;
    g.greenGain = 2;
    g.blueGain = 1;
    return g;
}

现在,我想在我的自定义相机上设置此灰度(公式:Pixel = 0.30078125f * R + 0.5859375f * G + 0.11328125f * B)。我已经尝试过这个公式。

- (AVCaptureWhiteBalanceGains)normalizedGains:(AVCaptureWhiteBalanceGains) gains
{
    AVCaptureWhiteBalanceGains g = gains;

    g.redGain = g.redGain * 0.30078125;
    g.greenGain = g.greenGain * 0.5859375;
    g.blueGain = g.blueGain * 0.11328125;

    float grayScale = g.redGain + g.greenGain + g.blueGain;

    g.redGain = MAX( 1.0, grayScale );
    g.greenGain = MAX( 1.0, grayScale );
    g.blueGain = MAX( 1.0, grayScale );

    g.redGain = MIN( videoDevice.maxWhiteBalanceGain, g.redGain );
    g.greenGain = MIN( videoDevice.maxWhiteBalanceGain, g.greenGain);
    g.blueGain = MIN( videoDevice.maxWhiteBalanceGain, g.blueGain );

    return g;
}

So 我怎样才能在1到4之间传递这个值..?

有没有什么方法或尺度来比较这些东西..?

任何帮助,将不胜感激。


CoreImage提供了许多用于使用 GPU 调整图像的滤镜,并且可以有效地与来自摄像机源或视频文件的视频数据一起使用。

有一篇文章是关于objc.io展示如何做到这一点。这些例子是 Objective-C 语言的,但解释应该足够清晰,可以理解。

基本步骤是:

  1. 创建一个EAGLContext,配置为使用 OpenGLES2。
  2. 创建一个GLKView显示渲染的输出,使用EAGLContext.
  3. 创建一个CIContext,使用相同的EAGLContext.
  4. 创建一个CIFilter用一个CIColorMonochrome 核心图像过滤器.
  5. 创建一个AVCaptureSessionAVCaptureVideoDataOutput.
  6. In the AVCaptureVideoDataOutputDelegate方法,转换CMSampleBuffer to a CIImage。应用CIFilter到图像。将过滤后的图像绘制到CIImageContext.

该管道确保视频像素缓冲区保留在 GPU 上(从摄像头到显示器),并避免将数据移动到 CPU,以保持实时性能。

要保存过滤后的视频,请实施AVAssetWriter,并将样本缓冲区附加到相同的AVCaptureVideoDataOutputDelegate过滤完成的地方。

这是 Swift 中的一个例子。

GitHub 上的示例.

import UIKit
import GLKit
import AVFoundation

private let rotationTransform = CGAffineTransformMakeRotation(CGFloat(-M_PI * 0.5))

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {

    private var context: CIContext!
    private var targetRect: CGRect!
    private var session: AVCaptureSession!
    private var filter: CIFilter!

    @IBOutlet var glView: GLKView!

    override func prefersStatusBarHidden() -> Bool {
        return true
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)

        let whiteColor = CIColor(
            red: 1.0,
            green: 1.0,
            blue: 1.0
        )

        filter = CIFilter(
            name: "CIColorMonochrome",
            withInputParameters: [
                "inputColor" : whiteColor,
                "inputIntensity" : 1.0
            ]
        )

        // GL context

        let glContext = EAGLContext(
            API: .OpenGLES2
        )

        glView.context = glContext
        glView.enableSetNeedsDisplay = false

        context = CIContext(
            EAGLContext: glContext,
            options: [
                kCIContextOutputColorSpace: NSNull(),
                kCIContextWorkingColorSpace: NSNull(),
            ]
        )

        let screenSize = UIScreen.mainScreen().bounds.size
        let screenScale = UIScreen.mainScreen().scale

        targetRect = CGRect(
            x: 0,
            y: 0,
            width: screenSize.width * screenScale,
            height: screenSize.height * screenScale
        )

        // Setup capture session.

        let cameraDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

        let videoInput = try? AVCaptureDeviceInput(
            device: cameraDevice
        )

        let videoOutput = AVCaptureVideoDataOutput()
        videoOutput.setSampleBufferDelegate(self, queue: dispatch_get_main_queue())

        session = AVCaptureSession()
        session.beginConfiguration()
        session.addInput(videoInput)
        session.addOutput(videoOutput)
        session.commitConfiguration()
        session.startRunning()
    }

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {

        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return
        }

        let originalImage = CIImage(
            CVPixelBuffer: pixelBuffer,
            options: [
                kCIImageColorSpace: NSNull()
            ]
        )

        let rotatedImage = originalImage.imageByApplyingTransform(rotationTransform)

        filter.setValue(rotatedImage, forKey: kCIInputImageKey)

        guard let filteredImage = filter.outputImage else {
            return
        }

        context.drawImage(filteredImage, inRect: targetRect, fromRect: filteredImage.extent)

        glView.display()
    }

    func captureOutput(captureOutput: AVCaptureOutput!, didDropSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
        let seconds = CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer))
        print("dropped sample buffer: \(seconds)")
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 iOS 中设置 AVCaptureDevice 输出的灰度 的相关文章

  • 在 UITextView 中获取 HTML

    我在中显示htmlUITextView by self textView setValue b Content b forKey contentToHTMLString 编辑内容后UITextView 我想获取包含 html 的内容 所以我
  • SceneKit unproject Z 文档解释?

    我正在经历一些 SceneKit 概念 而我试图在脑海中巩固的一个概念是 unprojectPoint 我知道该函数将获取 2D 中的一个点并返回 3D 中的一个点 因此具有正确的 Z 值 当我阅读文档时 我读到了以下内容 method u
  • Objective C 中类别是如何实现的?

    作为一名程序员 我知道如何使用类别 但我很好奇它们是如何实现的 编译器是否将它们编译为对类替换方法 http developer apple com library mac documentation Cocoa Reference Obj
  • 是否可以更改枚举中的关联值?

    我正在使用 Swift 枚举 想知道是否有一种方法可以更改枚举的关联值 例如下面的代码尝试但失败了 enum myEnum case SomeCase Int mutating func someFunc switch self case
  • Swift:检查 UISearchBar.text 是否包含 url

    如何检查 UISearchBar text 是否包含 URL 我想做这样的事情 if searchBar text NSTextCheckingType Link 但我收到错误 String is not convertible to NS
  • 与新 Apple Music 应用程序中相同的动态状态栏

    是否可以动态着色statusBar这是在新的苹果音乐应用程序 Edit iOS 8 4 中的新 Apple Music 应用程序具有此功能 打开应用程序 选择并播放歌曲 状态栏为白色 向下滑动播放器控制器以查看 我的音乐 控制器 它有黑色状
  • iOS 如何触发视频退出全屏后继续播放?

    我正在构建一个在 iOS 中播放视频的网站 我有一个在 iOS 中工作的全屏按钮 但是退出全屏时视频会暂停 有谁知道一种方法可以强制视频在退出全屏时继续播放 或者如何设置一个侦听器来触发视频在退出全屏时自动播放 这是我的代码
  • TTTAttributedLabel 可点击截断标记

    我有一个 TTTAttributedLabel 并为其指定了一个自定义属性截断标记 NSAttributedString atributedTruncationToken NSAttributedString alloc initWithS
  • 带有 allowedEditing 的 UIImagePickerController 不允许平移裁剪

    我在这里看到这个问题 UIImagePicker 允许编辑卡在中心 https stackoverflow com questions 12630155 uiimagepicker allowsediting stuck in center
  • 如何在Sprite Kit中实现鼠标关节?

    我已经在 iOS 上用 Cocos2d Box2d 编写了拖放功能的工作实现 我需要将它移植到 Sprite Kit 逻辑非常基本 当用户触摸屏幕时 找到手指下的精灵 在找到的精灵和场景的物理体之间创建鼠标关节 将关节的目标设置为触摸位置
  • 检查 Objective-C 块类型?

    这主要是出于好奇 我不太确定它的实际用途是什么 但就这样吧 由于块也是 Objective C 对象 是否可以检查它们的类型 也就是说 它是否响应isKindOfClass 消息以及如何使用该消息来处理块 我天真的以为事情大概是这样的 vo
  • iOS Swift 和 reloadRowsAtIndexPaths 编译错误

    我与 xCode Swift 陷入僵局并刷新 UITableView 的单行 这条线有效 self tableView reloadData 而这条线没有 self tableView reloadRowsAtIndexPaths curr
  • UILabel UILongPressGestureRecognizer 不起作用?

    我怎样才能得到UILongPressGestureRecognizer在 uilabel 当我实现以下代码时 它不会调用该函数 那么请告诉我我做错了什么 UILongPressGestureRecognizer longPress UILo
  • 带有文本字段的 iPhone AlertView

    我有一个UIAlertView with a UITextField在里面 我想输入mail id并提交于UIAlertView s ok按钮 但是UITextField in the UIAlertView没有回复 请帮助我 thankz
  • 子类 PFObject 上的 PFUser 属性

    我使用以下类 动态属性以及 m 文件中的 load 和 parseClassName 方法 对 PFObject 进行了子类化 interface DAOpponents PFObject
  • 领域:结果 和列表

    是否可以转换Results
  • 无需越狱即可检测iOS9上哪个应用程序处于前台

    我正在尝试记录用户在 iOS9 上的个人应用程序使用情况 我宁愿它不会使用越狱有限的解决方案 不言自明 在越狱手机上执行此应用程序的变体应该不难 https www andyibanez com create mobilesubstrate
  • 如何观察UserDefaults的变化?

    我有一个 ObservedObject在我看来 struct HomeView View ObservedObject var station Station var body some View Text self station sta
  • iPhone Twitter SDK 与 iOS 5 设备的集成问题

    我已成功将 Twitter Sharekit 与我的 iPad 应用程序源集成 当我在模拟器和装有 iOS 4 X 的 iPad 1 上测试该应用程序时 它运行完美 并且成功发布了推文 但是 如果我在装有 iOS 5 的 iPad 2 上安
  • 在成为FirstResponder或resignFirstResponder的情况下将对象保持在键盘顶部?

    我目前在键盘顶部有一个 UITextField 当您点击它时 它应该粘在键盘顶部并平滑地向上移动 我不知道键盘的具体时长和动画类型 所以确实很坎坷 这是我所拥有的 theTextView resignFirstResponder UIVie

随机推荐