Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';从JPEG图像中提取亮度的正确方法是什么?_C++_Image_Image Processing_Camera_Exif - Fatal编程技术网

C++ 什么';从JPEG图像中提取亮度的正确方法是什么?

C++ 什么';从JPEG图像中提取亮度的正确方法是什么?,c++,image,image-processing,camera,exif,C++,Image,Image Processing,Camera,Exif,简而言之:我无法从JPEG照片的RGB值中提取出有意义的光强度,而试图解释伽马校正或sRGB只会让事情变得更糟 我正在做一个玩具项目,涉及处理一堆照片图像,用间隔计拍摄。基本上,我想做一个时间推移了他们,与一些更正,使剪辑是整洁的。我使用佳能单反相机 我需要一个函数,给定一个JPEG文件,计算出“平均场景亮度”。结果应该是一个简单的数字;不需要用任何绝对光度单位表示,我只做相对比较。例如,你拍了一张某个房间的照片,函数返回,比如说,“5.0”。然后将第二个灯泡添加到照明中,与第一个灯泡的类型完全

简而言之:我无法从JPEG照片的RGB值中提取出有意义的光强度,而试图解释伽马校正或sRGB只会让事情变得更糟

我正在做一个玩具项目,涉及处理一堆照片图像,用间隔计拍摄。基本上,我想做一个时间推移了他们,与一些更正,使剪辑是整洁的。我使用佳能单反相机

我需要一个函数,给定一个JPEG文件,计算出“平均场景亮度”。结果应该是一个简单的数字;不需要用任何绝对光度单位表示,我只做相对比较。例如,你拍了一张某个房间的照片,函数返回,比如说,“5.0”。然后将第二个灯泡添加到照明中,与第一个灯泡的类型完全相同,放置在其旁边,然后再次拍摄。该函数现在应该为您提供“10.0”

因此,我目前实现的这个功能结合了几个方面:ISO速度、快门速度、光圈(从EXIF中提取)和平均图像亮度。Exif的东西显然更重要,因为在自动模式下,相机会尝试使用这样或那样的设置,所以图像亮度在中间灰度点附近。 然而,ISO/快门/光圈设置都具有1/3光圈或更小的分辨率,因此检测图像亮度对于“微调”非常重要

当我这样做的时候,我得到了一些明显虚假的结果,我越是钻研,我就越感到困惑。所以最后我做了一个“近乎严肃”的实验:

测试设置: 房间里的一面简单的墙,用白炽灯照明,照明相当均匀。 使用两台摄像机比较结果:50毫米底色的5D,35毫米底色的350D。 到墙的距离:约3米。 所有照片都是以1/10秒的快门速度拍摄的。 相机设置:手动,“忠实模式”(无增强,无饱和度或对比度凹凸),钨WB,无自定义功能,JPEG精细,sRGB色彩空间。这些镜头没有滤镜。照明没有改变,我只改变ISO和光圈设置。 以下是我得到的结果:

     Avg   Spd   ISO  Aperture
1. 0.3507, 0.10, 100, f/2.8
2. 0.5382, 0.10, 200, f/2.8
3. 0.3557, 0.10, 200, f/4.0
4. 0.2709, 0.10, 200, f/5.0
5. 0.2118, 0.10, 200, f/5.6
6. 0.1718, 0.10, 200, f/6.3
7. 0.1459, 0.10, 200, f/7.1
8. 0.1112, 0.10, 200, f/8.0
9. 0.0883, 0.10, 200, f/9.0
第一列是平均像素值(直接来自JPEG),在整个图像上取平均值,转换为灰度为(R+G+B)/3。通过将[0..255]范围除以255,在[0..1]范围内对颜色进行规格化。 因此,在1)和2)之间,我只更改ISO设置,图像亮度应该是原来的两倍,但平均像素值仅上升53%(没有任何过度曝光区域)

2..3:光圈向下一个光圈,因此图像亮度应为原来的一半,因此1)和3)一致(额外亮度可能是由于渐晕减少)

3..5:再说一次,一站下来,5)的亮度应该是3)的一半

5..8:相同,应该是一半(虽然这基本上是可以的)

这一切都非常非常奇怪。顺便说一句,两台摄像机之间的结果是一致的,这表明这不仅仅是特定模型的一个特点

这不需要应用任何伽马校正。JPEG读取代码是C++的,基本上遵循IJG示例代码(<代码> DJPEG</代码>实用程序)。现在,JPEG保存gamma校正值,因此像素值应视为sRGB颜色空间中的值(获取源像素,转换为[0..1],然后应用。让我们尝试一下:

     Avg   Spd   ISO  Aperture
1. 0.1140, 0.10, 100, f/2.8
2. 0.2746, 0.10, 200, f/2.8
3. 0.1175, 0.10, 200, f/4.0
4. 0.0682, 0.10, 200, f/5.0
5. 0.0424, 0.10, 200, f/5.6
6. 0.0287, 0.10, 200, f/6.3
7. 0.0213, 0.10, 200, f/7.1
8. 0.0133, 0.10, 200, f/8.0
9. 0.0092, 0.10, 200, f/9.0
我还尝试了“普通”伽马校正(伽马=2.2),结果与sRGB校正非常相似

所以我非常非常困惑。
有人能解释一下,既然我已经没有主意了,那么相机JPEG图像中的RGB强度应该如何解释:)

所以,随着我继续阅读,谜团慢慢揭开

虽然相机的传感器在理论上能够测量线性光强度,但它显然不能测量线性光强度,而是模仿具有众所周知的非线性响应的照相胶片的行为(例如,见图3)。 因此,dSLR的响应曲线远不是线性的,而是更像这样:

因此,在没有精确校准的情况下,从像素值中获取绝对场景亮度是不切实际的

然而,我只想对照片进行亮度调整,而大致正确的亮度估计对我来说就是一个窍门,因此我继续重建我的相机(佳能350D)的传递函数:

白色数据点对应于不同光圈值下的不同曝光(f/22、f/20、f/18、f/16等,以1/3光圈增量)。与上一张图一样,X轴在传入亮度方面是对数的,而Y轴在像素值方面是线性的(在伽马校正之后)。假设图形为单位平方,我还通过五阶多项式计算了近似拟合曲线:

(((((- 6.76219 * x) + 12.0459) * x - 5.8683) * x + 1.72338) * x - 0.148753) * x + 0.0105364;
对于x英寸[0.05,1]

因此,如果您获得了原始(“真实”)亮度,那么获得像素值的结果如下:

  • 获取输入亮度的对数,并对其进行线性变换,得到7⅓ [0..1]间隔内的曝光停止
  • 应用上面的多项式(不过需要对[0..0.05]区间进行特殊处理)
  • 应用sRGB压缩
  • 术语此转换T,我的应用程序中的整个工作流现在如下所示:

  • 使用T-1处理输入的JPEG图像
  • 结果值以浮点格式保存,并作为线性RGB值处理
  • 在将结果保存回JPEG之前应用T

  • 我怀疑摄像头传感器是完全线性的。此外,它看起来像是你想要一个线性亮度值。每个像素都覆盖一个区域,所以也许可以尝试取你亮度值的平方根。你也可以尝试转换为HSB,并使用其中的brigtess值。这看起来很有用:@Pete,谢谢你的指针。是的,我