中位切分法

总述

它能把图像上的颜色一一列举出来。这个过程其实被称为图像的颜色提取,中位切分法就是针对该过程的算法之一。这个过程更专业一点的称谓应该是颜色的量化过程,量化一词不仅仅限于颜色,它适用于一切连续的量,而量化其实就是把连续的量转换成离散的量的过程。于是准确概括就是,中位切分法是一种针对图像的颜色量化算法。

演示.gif

图像是什么?

图像,就是照片嘛。你能通过它的内容接收到一些信息,有用的,没用的,好的,还是坏的,看你自己。但是,如果你从颜色的角度看,图像其实是各种颜色容器,你之所以能看到各种各样的图像,只不过是因为这些颜色的种类不同,数量不同,以及排列组合的形式不同而已。

什么是真彩色?

其实很简单,真彩色是用4个颜色的分量来表示的,分别是R(Red:红)、G(Green:绿)、B(Blue:蓝)、A(Alpha:透明度),每个分量占用了1个字节,所以真彩色中每个颜色要用4字节表示,于是有232种颜色。
然而,人眼并不需要如此多的颜色种类,256种足够了。
很显然28=256于是表示某种颜色只需要1byte,但是这其实只不过是个标识,这个标识应该指向一个具体的颜色的列表。
也就是说,这个列表里面的颜色都已经是确定了啦,就是256种不同的颜色。每次要取一种颜色只需要根据这个标识到列表中去取出来就可以了。

什么是颜色空间?

空间一般指三维空间,就是立体几何那个玩意,空间坐标系,就XYZ那玩意。现在假设不考虑透明度,只考虑RGB分量,那么每个分量就自成一条坐标轴了,于是RGB坐标轴就形成了一个立体的坐标系,这个坐标系就是所谓的颜色空间。大家都知道XYZ坐标体系中的点都可以三维坐标来表示——(x,y,z),同理,颜色空间中的颜色都能用颜色坐标来表示,即(r,g,b)。

图像的映射

正如上面所说,图像是各种颜色的容器,而颜色又可以被映射到颜色空间。于是,图像中,从r分量的角度来看,在各种颜色组成的集合中,必有最大的r分量值和最小的r分量值,于是从最大的r值到最小的r值形成了一条边。同理,最大的g值到最小的g值又形成了一条边,最大的b值到最小的b值还是形成了一条边,于是3条边就形成了1个立方体。图像中所有的颜色都处于这个立方体中。

立方体的分裂

现在说的立方体并不仅限于第一个立方体,而是任何一个立方体。立方体嘛,肯定有个最长边,或者最长边不止一个,反正就是找到最长的边就是了。不过这样说有点抽象,说得直接一点就是找到RGB分量中最大值最小值相差最大的那个分量。
这个分量一旦知道了,你就可以把当前立方体中的颜色值按照该分量进行排序了。因为获取某分量最大值和最小值只需要比较而已,但是该分量对应的颜色值还是无序的,你应该排序。

为什么要排序呢?

因为一排序,该分量就成了有序了,而有序就形成了该分量的梯度变化,而梯度变化的极限就是渐变。3个分量都是梯度变化以后,那么各个颜色值也就成了逐渐的变化的形式了。

该怎么分裂?

你知道每种颜色都对应至少1个像素,你需要把这些数量的像素一分为二。按照某个分量排好序以后,你需要把当前立方体中该分量较高的和较低的像素分开,并且这两部分的像素数量尽量相等,没错这就是分裂所要达到的目的。

这个分裂有啥用?

这样做你可以把像素均匀地分布到各个颜色立方体中,分裂到最后的立方体可以得到该立方体的代表色,也就是说该立方体中所有的像素点都是这样个颜色了,即,颜色接近的像素点被集中到了一起。仔细想一下你会发现这样做并不会让图像所表达的内容变化太大,不会变化太大就是说你现在所分裂出来的所有的小立方体所代表的颜色已经足够接近图像上面的各个颜色了,当然,分裂出来的小立方体越多就越接近原图像中的各个颜色。
如此一来用中位切分法获取图像各个颜色的原理解释完毕。

适用于部分数组排序的堆排序

这是个工具,不仅仅能排序整个数组,还能排序部分数组,很方便实用,需要的尽管拿去。

+ (void)heapSort:(NSMutableArray *)sourceArray
      startIndex:(NSInteger)startIndex
  subarrayLength:(NSInteger)length {
    for (NSInteger counter = length / 2 - 1 + startIndex; counter > startIndex - 1; counter--) {
        [HeapSort adjust:sourceArray
              startIndex:startIndex
               rootIndex:counter
            adjustLength:length];
    }
    for (NSInteger counter = startIndex + length - 1; counter > startIndex; counter--) {
        [sourceArray exchangeObjectAtIndex:startIndex
                         withObjectAtIndex:counter];
        [HeapSort adjust:sourceArray
              startIndex:startIndex
               rootIndex:startIndex
            adjustLength:counter - startIndex];
    }
}

+ (void)adjust:(NSMutableArray *)souceArray
    startIndex:(NSInteger)startIndex
     rootIndex:(NSInteger)rootIndex
  adjustLength:(NSInteger)adjustLength {
    for (NSInteger count = rootIndex; count < adjustLength / 2 + startIndex;) {
        NSInteger leftChildIndex = 2 * (count - startIndex) + 1 + startIndex;
        NSInteger rightChildIndex = leftChildIndex + 1;
        NSInteger smallerPointer = leftChildIndex;
        if (rightChildIndex < adjustLength + startIndex) {
            NSComparisonResult compareResult = [souceArray[leftChildIndex] compare:souceArray[rightChildIndex]];
            if (compareResult == NSOrderedDescending) {
                smallerPointer = rightChildIndex;
            }
        }
        NSComparisonResult compareResult = [souceArray[count] compare:souceArray[smallerPointer]];
        if (compareResult == NSOrderedDescending) {
            [souceArray exchangeObjectAtIndex:count withObjectAtIndex:smallerPointer];
            count = smallerPointer;
        } else break;
    }
}

源代码

这是基于iOS平台,用Objective-C编的,需要用XCode运行的工程,别搞错了。
点此下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容