通常我们生活中遇到的图像,无论是jpg、还是png或者bmp格式,一般都是8位的(每个通道的像素值范围是0-255),但是随着一些硬件的发展,在很多行业比如医疗、红外、航拍等一些场景下,拥有更宽的量化范围的图像也越来越常见,比如10位(带宽1024)、12位(带宽4096)、14位(带宽16384)以及16位(带宽32768)的图像,当然还有以浮点数保存的高动态图像(hdr格式的那种),但是目前大部分的显示器还是只支持8位图像的显示,因此,对于这一类图像,一个很重要的问题就是如何将他们的数据量化到0到255之间,而且尽量的保留更多的细节信息,这也就是常见的HDR到LDR的过程。 在我前面的博客里其实也有讲到这方面的信息,本文再尝试将直方图均衡化引入到这个过程中。

首先,我们统一一下由一组ushort数据(带宽是10、12、14、16的Raw图像,都可以用ushort数据类型表示)直接量化为8位显示的函数,这样我们的处理就可以集中在原始的ushort数据经过算法处理后得到新的ushort数据的过程。这个函数简单如下所示:

  1. // 这个只是个辅助用来显示的函数
  2. int IM_ConvetUshortToByte(unsigned short *Src, unsigned char *Dest, int Width, int Height, int Stride, int WindowWidth, int WindowLevel)
  3. {
  4. int Channel = Stride / Width;
  5. int Min = WindowLevel - WindowWidth / 2;
  6. int Max = WindowLevel + WindowWidth / 2;
  7. if (Min < 0) Min = 0;
  8. if (Max > 65535) Max = 65535;
  9. int Diff = Max - Min;
  10. if (Diff == 0)
  11. {
  12. memset(Dest, Max, Height * Stride * sizeof(unsigned char));
  13. }
  14. else
  15. {
  16. unsigned char Table[65536];
  17. for (int X = 0; X < 65536; X++)
  18. {
  19. if (X < Min)
  20. Table[X] = 0;
  21. else if (X > Max)
  22. Table[X] = 255;
  23. else
  24. Table[X] = IM_ClampToByte((X - Min) * 255 / Diff);
  25. }
  26. for (int Y = 0; Y < Height; Y++)
  27. {
  28. unsigned short *LinePS = Src + Y * Width * Channel;
  29. unsigned char *LinePD = Dest + Y * Stride;
  30. for (int X = 0; X < Width * Channel; X++)
  31. {
  32. LinePD[X] = Table[LinePS[X]];
  33. }
  34. }
  35. }
  36. return IM_STATUS_OK;
  37. }

   其中的WindowWidth表示窗宽,WindowLevel表示窗位,这个其实是借助了医学图像上的一些概念,对于普通的RAW图像,比如12位,我们通常就认为WindowWidth = 1 << 12 = 4096,而WindowLevel则就为窗宽的一半。

一般来说,RAW图像中的数据每一行是没有冗余量的,即没有BMP位图中所谓的扫描行对齐的概念。所以可以直接遍历每一个数据。

那么我们来看看如何把普通的直方图均衡化算法利用到RAW图像中来。

以灰度图为例,如果已经统计了图像的直方图,则直方图均衡化的新的隐射曲线由以下代码获取:

  1. for (int Y = 0, Num = 0; Y < 256; Y++)
  2. {
  3. Num = Num + Histgram[Y];
  4. Table[Y] = (unsigned char)(((float)Num * 255) / (Width * Height)); // 注意(float)强制转换的位置,否则对于大图就溢出了,2014.11.1修正
  5. }

简单的,扩展到ushort类型的RAW图像,我们也可以用以下的类似代码搞定:

  1. for (int Y = 0, Num = 0; Y < WindowWidth; Y++)
  2. {
  3. Num = Num + Histgram[Y];
  4. Table[Y] = (unsigned short)(((float)Num * WindowWidth) / (Width * Height)); // 注意(float)强制转换的位置,否则对于大图就溢出了,2014.11.1修正
  5. }

关于这个WindowWidth,我觉得一般可以由两种方法得到,一个是我们已经知道了这个硬件生成的图像是多少位的,常见的就是10、12、14、16等,这个时候WindowWidth可以直接指定,而如果只有RAW数据,一种方式就是根据数据的最大值来确定WindowWidth,即取大于最大值的2的整数次幂的那个值。
      如下代码所示:

  1. ushort MaxValue = IM_GetMaxValue(ImageData, ImageWidth * ImageHeight * ImageChannel);
  2. int ProperWindowWidth = 1;
  3. while (ProperWindowWidth < MaxValue)
  4. ProperWindowWidth *= 2;
  5. WindowWidth = ProperWindowWidth;
  6. WindowLevel = WindowWidth / 2;

这个简单的数据范围的调整,我们看下一些效果:

     

      

a、RAW数据直接ConvetUshortToByte的8位结果图            b、直方图均衡后的RAW数据转换为8位的效果图           c、对8位的a图直接在直方图均衡后的结果图

通过比较可以看到确实还是有明显的增强效果的,但是似乎有过曝的现象。

我们可以仿照一种强化的基于局部直方图裁剪均衡化的对比度调节算法 或者限制对比度自适应直方图均衡化算法原理、实现及效果 文中的方法将局部直方图均衡化引入到16位中,尝试看看效果是否有改善,这里不多谈,只说下我遇到的几个问题。

一个是在ClipHistogram 这个函数的过程中,我们发现往往会出现这个函数陷入死循环的结果,特备是对于12位以上的图像,因此,这个可能需要其他的一些改进方案。

二个是我们还可以学习【算法随记四】自动色阶、对比度、直方图均衡等算法的一些小改进 一文中的getWeightedValue函数,即对获取的直方图数据开平方,起到一定的压缩作用,这个可以明显的改善上述的曝光效果。

另外,同样的道理,在局部算法里,还可以不用直方图均衡化算法,可以使用任何其他的基于直方图的调整基数,比如自动色剂等等。

   

a、RAW数据直接ConvetUshortToByte的8位结果图                          b、局部压缩直方图均衡后的RAW数据转换为8位的效果图           

很明显这样处理后的效果要好很多。细节、曝光等等都较为合适。

关于16位RAW图像,本人开发了一个简易的增强和处理程序,可在https://files.cnblogs.com/files/Imageshop/Optimization_Demo_16.rar下载测试。

其他相关链接:

【16位RAW图像处理一】:基于Fast Bilateral Filtering 算法的 High-Dynamic Range(HDR) 图像显示技术。

【16位RAW图像处理二】:一种自适应对数映射的高对比度图像显示技术及其速度优化。

【16位RAW图像处理三】直方图均衡化及局部直方图均衡用于16位图像的细节增强。的更多相关文章

  1. 图像处理之直方图均衡化及C源码实现

    1 直方图均衡化(Histogram Equalization)简介 图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法.直方图拉伸和直方图均衡化是两种最常见的间接 ...

  2. OpenCV-跟我一起学数字图像处理之直方图均衡化

    从这篇博文开始,小生正式从一个毫不相干专业转投数字图像处理.废话不多说了,talk is cheap. show me the code. 直方图均衡化目的 由于一些图像灰度的分布过于集中,这样会导致 ...

  3. 机器学习进阶-直方图与傅里叶变化-直方图均衡化 1.cv2.equalizeHist(进行直方图均衡化) 2. cv2.createCLAHA(用于生成自适应均衡化图像)

    1. cv2.equalizeHist(img)  # 表示进行直方图均衡化 参数说明:img表示输入的图片 2.cv2.createCLAHA(clipLimit=8.0, titleGridSiz ...

  4. 彩色图像的直方图均衡化matlab代码

    彩色图像的直方图均衡化 - YangYudong2014的专栏 - CSDN博客 http://blog.csdn.net/yangyudong2014/article/details/4051503 ...

  5. 16位/32位/64位CPU的位究竟是说啥

    平时,我们谈论CPU,都会说某程序是32位编译,可以跑在32位机或64位机,或则是在下载某些开源包时,也分32位CPU版本或64CPU位版本,又或者在看计算机组成相关书籍时,特别时谈到X86 CPU时 ...

  6. [Effective JavaScript 笔记] 第7条:视字符串为16位的代码单元序列

    Unicode编码,基础:它为世界上所有的文字系统的每个字符单位分配一个唯一的整数,该整数介于0~1114111之间,在Unicode术语中称为代码点(code point). 和其它字符编码几乎没有 ...

  7. 16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16

    一.Intel 32 位处理器的工作模式 如上图所示,Intel 32 位处理器有3种工作模式. (1)实模式:工作方式相当于一个8086 (2)保护模式:提供支持多任务环境的工作方式,建立保护机制 ...

  8. opencv——图像的灰度处理(线性变换/拉伸/直方图/均衡化)

    实验内容及实验原理: 1.灰度的线性变换 灰度的线性变换就是将图像中所有的点的灰度按照线性灰度变换函数进行变换.该线性灰度变换函数是一个一维线性函数:f(x)=a*x+b 其中参数a为线性函数的斜率, ...

  9. 图像处理 Matlab实现线性点运算、非线性点运算、点运算与直方图、直方图均衡化

    今天,我们学习了直方图.于是乎,回来我就用matlab代码实现一下.昨天受到道路检测老师课上一个内容的影响(对于道路裂缝的检测,我突发奇想,如果对于道路图像进行操作,是否能够让裂缝与道路分离,使得图像 ...

随机推荐

  1. 台积电5nm光刻技术

    台积电5nm光刻技术 在IEEE IEDM会议上,台积电发表了一篇论文,概述了其5nm工艺的初步成果.对于目前使用N7或N7P工艺的客户来说,下一步将会采用此工艺,因为这两种工艺共享了一些设计规则.新 ...

  2. 微调torchvision 0.3的目标检测模型

    微调torchvision 0.3的目标检测模型 本文将微调在 Penn-Fudan 数据库中对行人检测和分割的已预先训练的 Mask R-CNN 模型.它包含170个图像和345个行人实例,说明如何 ...

  3. C#将DataTable数据导出CSV文件

    C#将DataTable数据导出CSV文件通用方法! //导出按钮调用导出方法    protected void btnCSV_Click(object sender, EventArgs e)   ...

  4. spring如何集成第三方框架? 比如mybatis

    实体Bean的创建: 1: 基于class构建, 2: 构造方法构建 3: 静态工厂方法创建 4: FactoryBean构建 spring如何集成第三方框架? 比如mybatis 在mybatis中 ...

  5. 小目标增强(Augmentation for small object)

    小物体检测的增强 摘要:在近些年来,目标检测已经有了长足的进步.尽管有很大改进,但是在小目标和大目标检测性能方面还是有巨大的差距.我们在具有挑战性的数据集MS-COCO上分析了目前性能最好的模型Mas ...

  6. 彻底解决Spring mvc中时间类型的转换和序列化问题

    在使用Spring mvc 进行开发时我们经常遇到前端传来的某种格式的时间字符串无法用java8时间包下的具体类型参数来直接接收.同时还有一系列的序列化 .反序列化问题,在返回前端带时间类型的同样会出 ...

  7. 关于Linux服务器部署

    服务器信息: 此小节的内容: SecurityCRT:用来连接到Linux服务器命令操作. FTP(FTPRush):本地文件和Linux服务器文件交互的 工具服务器 借助客户端工具来链接到Linux ...

  8. Linux添加永久静态路由

    1.首先查看一下本机的路由 route -n 2.比如我们添加两条静态路由,访问192.168.142.100时通过192.168.142.10:访问192.168.142.200时通过192.168 ...

  9. HTTP Cookies知识-查看、发送、获取、返回

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 HTTP Cookies是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求 ...

  10. [.NET大牛之路 002] 什么是 .NET

    .NET 是一个开发平台,或者叫开发者平台.使用 .NET 你可以创建不同类型的应用程序,使用多种开发语言.编辑器和工具库创建网页.手机.桌面以及游戏等应用.其核心特点是:免费.开源和跨平台. 语言和 ...