c++ - 从视频帧 OpenCV 模拟长时间曝光

标签 c++ ios objective-c opencv

我试图通过将图像(帧)组合成一张图像并通过基于预设 alpha 的操作来模拟长时间曝光的照片。我在 iPhone 上执行此操作,我目前将视频长度设置为 1 秒(30 帧)。 alpha 设置为 1.0/frameCount 但是我硬编码为 30 以表示 30 FPS 视频捕获的一秒。一旦达到一秒的视频/30 帧,我就会停止操作。这个想法是用户可以设置一个 x 秒的计时器,我将计算出允许多少帧。

这是我正在使用的代码:

- (void)processImage:(Mat&)image
{

    if (_isRecording) {

        // first frame
        
        double alpha = 1.0/30;
        
        if (_frameCount == 0) {
            
            _exposed = image;
            _frameCount++;
        } else {
            
            Mat exposed = _exposed.clone();
            addWeighted(exposed, alpha, image, 1.0 - alpha, 0.0, _exposed);
            _frameCount++;
        }

        // stop and save image
        if (_frameCount == 30) {
            _isRecording = NO;
            _frameCount = 0;
            
            cvtColor(_exposed, _exposed, CV_BGRA2RGB, 30);
            UIImage *exposed = [LEMatConverter UIImageFromCVMat:_exposed];
            UIImageWriteToSavedPhotosAlbum(exposed, nil, nil, nil);
            NSLog(@"saved");
        }
    }
}

当我运行这段代码时,我基本上会得到一个看起来好像是单帧的静止图像。这是一个例子:

enter image description here

在我知道会有多少帧的情况下,有谁知道如何从视频帧中产生所需的长时间曝光图像效果?

最佳答案

首先,(可能这不是您的情况,因为您指出您正在处理视频而不是相机)如果您的代码基于帧速率的值,请确保 30fps 是有效值而不是最大值。有时相机会根据从环境中获得的光量自动调整该数字。如果它是黑暗的,那么曝光时间会增加,因此帧率会降低。

第二点,给定一堆像素,很难模拟照片曝光的真实机制。 想象一下,你想将曝光时间加倍,这应该通过两个连续的帧来模拟。 在现实世界中,将曝光时间加倍意味着快门速度减半,因此有两倍的光线照射到传感器或胶片上,结果就是更亮的图像。
你如何模拟这个?为简单起见,考虑您要合并的两个非常明亮的灰度图像的情况。如果在给定点的像素值是 180 和 181,那么结果值是多少?第一个答案是 180+181,但像素强度介于 0 和 255 之间,因此必须在 255 处截断。 增加曝光的真实相机可能会表现不同,没有达到最大值。

现在我会考虑你的代码。
第一次处理图像(即运行函数)时,只需将帧存储在变量 _exposed 中。
第二次混合新帧的 29/30 和之前存储的图像的 1/30。
第三帧的第三次 29/30 与先前操作的结果。这会导致在第一帧上放置一个逐渐消失的权重,该权重实际上消失了。
上次调用该函数时,再次将最后一帧的 29/30 和前一帧的 1/30 相加。反过来,这意味着第一帧的效果实际上消失了,甚至前一帧也仅占 29/(30x30) 的份额。 您获得的图像只是最后一帧,前一帧略有模糊。
如何获得曝光模拟? 如果您只想平均 30 帧,则必须替换以下行:

    if (_frameCount == 0) {
       _exposed = image.clone();
        addWeighted(_exposed, 0.0, image, alpha, 0.0, _exposed);
    } else {
        addWeighted(_exposed, 1.0, image, alpha, 0.0, _exposed);
    }
    _frameCount++;

如果你也想让图像在某种程度上更亮,你可以通过一个乘数来模拟它:

    if (_frameCount == 0) {
       _exposed = image.clone();
        addWeighted(_exposed, 0.0, image, alpha*brightfactor, 0.0, _exposed);
    } else {
        addWeighted(_exposed, 1.0, image, alpha*brightfactor, 0.0, _exposed);
    }
    _frameCount++;

将亮度因子调整为最能模拟曝光时间实际增加的值。 (编辑:1.5 和 2.5 之间的值应该可以完成这项工作)

关于c++ - 从视频帧 OpenCV 模拟长时间曝光,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31377832/

相关文章:

c++ - 是否有 C++ 的简单 GStreamer 示例?

objective-c - 带有http代码405的Restkit Basic Auth

objective-c - 针对 kMDItemPath 的搜索在 Spotlight 中没有结果

c++ - 将 C++ 与 Cocoa 一起使用而不是 Objective-C?

c++ - 如果 C/C++ 指针是 "just"地址,为什么需要类型?

c++ - 初级程序员;程序立即关闭开关(C++)

c++ - C++ 中的模板参数太多?

ios - 地理围栏无法正常工作

ios - UIImage 未保存在文档目录中并终止应用程序

ios - 在 iOS 8.1 之后,在所有设备上,当点击 alertview 取消按钮时,ScrollView 会向上移动并且不会滚动