专栏首页一心无二用,本人只专注于基础图像算法的实现与优化。简单而又快速的获取一副真彩色图像实际使用的颜色数。

简单而又快速的获取一副真彩色图像实际使用的颜色数。

  一副真彩色图像,最多可能使用的颜色数为256*256*256=16777216种,但是通常情况下绝对不会有如此之多,因为即使图像中每个像素颜色都不相同,也至少需要4096×4096大小的图,这么大小的图对目前的数码相机来说也不普遍。因此,在现实中一副颜色很丰富的彩色图像,其使用的不同颜色数一般都不会超过100万。本文介绍一种简单而又快速的统计这个数据的方法。

一种最简单而又直接的方式就是定义一个含有16777216个元素的数组,然后循环整幅位图,对位图某处对应的颜色值,计算数组的索引,计算方式有很多种,比如:

Index = Red + Green * 256 + Blue * 65536

如果该位置的数组的值为0,则修改为1,同时计数器增加1;如果为1,说明图像中之前已经存在该颜色,不做任何处理,直接处理下一个像素。

因为我们只需要记录0和1两种状态,因此布尔变量是比较合适的,不过有些语言,比如VB6,布尔类型是占用两个字节的。一般的编程语言中最小的数据类型都是Byte,即一个字节,因此,16777216个最少需要占用16MB的内存。简单示意代码如下:

1     Dim Flag(16777215) As Byte
 2     For Y = 0 To m_Height - 1
 3         Speed = Y * m_Stride            '移动到下一行首个像素
 4         For X = 0 To m_Width - 1
 5             Index = ImageData(Speed + 2) + ImageData(Speed + 1) * 256& + ImageData(Speed) * 65536   '计算索引
 6             If Flag(Index) = 0 Then     '如果之前没有出现过该颜色值
 7                 Flag(Index) = 1         '该颜色值已经出现
 8                 Count = Count + 1       '计数加1
 9             End If
10             Speed = Speed + 3           '移动到下一个像素
11         Next
12     Next

这个代码很简单,也很容易明白,不过令人不是很满意是16MB内存的占用,对于一副3000×4000的图像来说,也许没啥概念,可如果本身是一副300×400的图呢,这个内存比图本身占用的内存还大很多,因此,我们试图对这个方面进行适当的改良。

改良的方式也是很简单,也许大家都能想得到:既然每种颜色只有0和1两种状态,那为何不用位来记录该颜色是否存在过呢。基于这个想法,我们的数组大小就可以修改成16777216/8=2097152字节,即2MB大小。 这样做的好处内存占用量减少为原先的1/8,坏处就是访问位信息要比直接访问字节困难。不过有这么大的内存占用优势,困难是值得的。

首先,我们要定位某个颜色值在我们新定义的数组中对应的索引BytePos,这个没有问题,直接除以8就可以了,8非常特殊,除以8可以优化为右移3位,右移是高效的运算符,很好。

接着,我们要得到需要访问BytePos索引对应的字节的第几位。第几位,很简单,就是颜色值的原始索引(Index变量)对8进行取余运算而已,可惜,取余运算符是个耗时的运算符,但同样可幸,是对8取余,And运算符能帮我们解决。对8取余就是对7进行And运算: Index mod 8 == Index And 7 。 8我爱你。

下一步,没啥好说的了,判断该位是否为0啊,这里我们还是借用And运算,用该位的位置对应的特殊数据进行按位和运算,如果运算后的结果为0,则表示该颜色没有存在过,改变状态,并且将其改为1,改为1的方式加上我们的特殊数据即可,同时计数器加1,;如果不为0(不用管他为多少),则不用做任何处理了。

我们简单的看下实现的代码:

1     Dim Flag(2097151)   As Byte
 2     Dim Pow2(7)         As Long
 3     Dim BitPos          As Long
 4     Dim BytePos         As Long
 5     For Y = 0 To 7
 6         Pow2(Y) = 2 ^ (7 - Y)
 7     Next
 8     For Y = 0 To m_Height - 1
 9         Speed = Y * m_Stride                                    '移动到下一行首个像素
10         For X = 0 To m_Width - 1
11             Index = ImageData(Speed + 2) + ImageData(Speed + 1) * 256& + ImageData(Speed) * 65536   '计算索引
12             BytePos = Index \ 8                                 '计算索引对应的字节位置
13             BitPos = Index And 7                                '计算索引对应的位的位置
14             If (Flag(BytePos) And Pow2(BitPos)) = 0 Then        '判断改位是否为1
15                 Flag(BytePos) = Flag(BytePos) + Pow2(BitPos)    '不为1,则修改为1
16                 Count = Count + 1                               '计数器增1
17             End If
18             Speed = Speed + 3                                   '移动到下一个像素
19         Next
20     Next

  注意,这里的列出的是VB的代码,实际上 ImageData(Speed + 1) * 256&这种表达式在勾选上高级优化时编译器会自动编译为左移8位的,而 Index \ 8则会优化为Index>>3,因此,速度上不会和其他有这些运算符的语言有差别。当然,如果直接用类似VC的语言,请直接使用这些运算符。

关于那个Pow2数组的使用,我感觉我自己表达能力有限,为什么有那种效果,其实明白人还是一看就知道的。在这就不多言了。

两种方式,在我自己的本机上编译后,居然是后一种算法的速度快一些,这个除了是分配内存时使用的使用的时间稍微少些外,其他的实在是不明白,也许和内存的访问之类有关吧,我对这方面了解粗浅,还烦请有兴趣的高手指点。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 索引图像的那些事啊

      索引图像在目前看来,需要应用的场合比真彩图像少的多,但是,在某些特殊的领域(比如游戏)和应用(比如屏幕传输)索引图像依旧发挥这重要的作用。本文将简单的描述下...

    用户1138785
  • 基于局部均方差相关信息的图像去噪及其在实时磨皮美容算法中的应用。      在1979年Lee发表的论文《Lee Filter Digital Image Enhancement and Noise

         在1979年Lee发表的论文《Lee Filter Digital Image Enhancement and Noise Filtering by ...

    用户1138785
  • 访问图像像素信息方式的优化

      如果你做图像处理有一定的经验,并且实战过N次,那么你一定知道代码优化对这个行业是多么的重要。今天,我们首先简单谈谈访问图像像素技术的优化。

    用户1138785
  • 这样自学 Python ,高效不止一点,两点

    经过这些年的自学编程,来跟你谈谈我是怎么自学的,给你做点参考,当然,如果你也有不错的自学方法或者经验,我们可以彼此探讨,借鉴一下,也许大家都能同时进步一点点。

    一墨编程学习
  • Mac安装mysql

    通过以下网站下载安装包https://dev.mysql.com/downloads/mysql/,推荐5.7版本

    代码改变世界-coding
  • 【斯坦福算法分析和设计02】渐进分析

    我们的目的是寻找一种对算法进行衡量的最有效力度,我们希望忽略不重要的细节,例如常数因子和低阶项,把注意力集中在算法的运行时间是怎样随着输入长度的增长而增长的,这...

    TechFlow-承志
  • 《进击的前端工程师》-Node.js事件循环

    事件循环的执行顺序从图中可以看出,每次的事件循环都包含了上图中的6个阶段,接下来我们来一一解读它们。

    童欧巴
  • VMworld 2015:VMware CEO表示人工智能将降临IT界

    VMware CEO Pat Gelsinger在周二的VMworld大会上表示,随着业务日益数字化、移动化和云计算化,我们经营企业的方式也应该发生改变,人工智...

    SDNLAB
  • Unity Shader 屏幕后效果——高斯模糊

    https://www.cnblogs.com/koshio0219/p/11137155.html

    汐夜koshio
  • 干货:Web应用上线之前程序员应该了解的技术细节

    问题 Web 应用上线前,程序员应考虑哪些技术细节呢? 如果 Jeff Atwood 忘记把 HttpOnly cookies、sitemaps 和 cros...

    小小科

扫码关注云+社区

领取腾讯云代金券