利用matlab构建自己的colormap(色彩搭配)_matlab colormap-程序员宅基地

技术标签: matlab  可视化  色彩搭配  

利用matlab构建自己的colormap

这个博客是自己的第一篇博客,瞎写实验中。。。
(2020年2月第一次更新,调整了一下格式,增加了常用的颜色图形式)

1 色彩空间

因为平时绘制多条曲线,多种颜色的散点图以及二维色彩图时,经常受colormap折磨,嫌弃matlab自带的太丑,自己想要的效果没有。所以这篇文章主要从RGB格式和HSV格式两种颜色模式去衡量构造颜色条。
##1.颜色模式
首先说一下RBG格式,是通过对红、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色。可以理解为RGB是利用三维直角坐标系来描述颜色空间。
(转)RBG色彩空间
一般情况RGB的每个颜色分量的值在[0,255]之间,共涉及256个整数。但是matlab的RGB设定是规定每个分量的值在[0,1]之间,所以这个转换的时候要尤其注意。

另外还有一种色彩空间模式是HSV模式(也叫HSB模式),是通过色调(H),饱和度(S),明度(V)三个颜色参数去描述颜色。其中色调是描述颜色色彩的一个参数,表现为 红橙黄绿青蓝紫红 一圈的颜色环。饱和度是描述颜色所占比例的一个参数,当饱和度为1时颜色为色调所表现出的颜色,饱和度为0表现为灰度色。明度V则表示颜色的明亮程度。可以理解为HSV是利用柱坐标(也有利用锥坐标)去描述色彩空间。
(转)HSV色彩空间
同RGB模式,matlab里HSV颜色也是利用由三个[0,1]区间的值构成的行向量定义的。其中RGB和HSV格式的转换如下:

%两种颜色模式的互相转换
color_hsv=rgb2hsv(color_rgb)
color_rgb=hsv2rgb(color_hsv)

2.matlab自带的colormap的提取与评估

2.1colormap提取

使用matlab自带的帮助可以获取颜色图的信息。

help colormap

可以看到matlab有很多自带的colorbar图,我们以“hot”为例,去交换hot里的红色和蓝色颜色通道,去改变颜色图。
matlab的colorbar种类

color_hot=colormap(hot);%颜色图的提取
mycolor=[color_hot(:,3),color_hot(:,2),color_hot(:,1)];%也可以用fliplr()函数,交换红蓝颜色通道
figure(1)
ax1 = subplot(2,1,1);
contourf(peaks,'LineStyle','none')%可以取消线条
colormap(ax1,hot);colorbar

ax2 = subplot(2,1,2);
contourf(peaks,'LineStyle','none')
colormap(ax2,mycolor);colorbar

输出的效果图如下:
提取colormap
可以看到colormap不仅可以提取,还可以自行更改创建。接下来一段我将利用这个来进行颜色图好坏的评估。

2.2颜色图的评估

一个颜色图的评估没有固定的标准,但是为了一些场合的实用性,主要的评估是以颜色的色调(H),颜色的灰度值(Gray scale),其中色调影响了颜色图的色彩变化,在展示的时候效果最明显;颜色的灰度值影响了颜色的色彩的明暗,在打印的时候效果最明显。最好的颜色图我认为是在色调和灰度值都显著变化的颜色图。
灰度的算法参见https://blog.csdn.net/cuixiping/article/details/40291389。
其它注意事项参见:《为可视化数据寻找适合的配色》http://colachan.com/post/3472。

同时次要的颜色评估指标是颜色的饱和度。一般我喜欢把饱和度设置成中间高两边低的曲线,这要感觉好看一些。
例如matlab中在2014b版本之前colormap的默认值都是jet,但是到了之后的版本被替换为parula。我们通过RGB和HSV曲线来对比两个颜色图的区别差异。

四宫格左半边为RGB颜色图,左上图为实际颜色图以及打印灰度图,左下图其中RGB曲线中红线代表R通道,绿线代表G通道,蓝线代表B通道,黑色虚线代表灰度值。右半边为HSV颜色图,右上图分别为颜色的H,S,V,右下图红线代表色调H,蓝线代表饱和度S,黑线代表明度V。(明度V和灰度不是一样的)
jet图的曲线
color_jet
parula图的曲线(parula是北美洲一种鸟,这个颜色图因为和parula羽毛的颜色很相近,因此命名)
color_parula
可以看到parula的色调和灰度都是单调渐变的,这使得颜色图无论在颜色区分还是明暗度区分都有很好的视觉体验;而且整体色调的明度和饱和度都变化不大,整体色调给人很均匀舒服的感觉。相比较jet,可以看到最大的缺点就是颜色的灰度不均一,这在变成黑白打印时会造成一定的误会,这也是jet被新版本被嫌弃的原因。但是我个人在某些场合还是喜欢用jet的,因为它的饱和度和明度都非常高,而且颜色图极大值和极小值正好位于灰度最深的两侧,展示的时候对比效果非常好。

接下来附上我比较喜欢的hot颜色图以及matlab绘制代码:

    mycolor=colormap(hot);%提取RGB值
    mycolor_hsv=rgb2hsv(mycolor);%转换成HSV值
    


    mycolor_gray = ((255*mycolor(:,1)).^2.2 * 0.2973 + (255*mycolor(:,2)).^2.2 * 0.6274 + (255*mycolor(:,3)).^2.2 * 0.0753).^(1/2.2);
    mycolor_g=mycolor_gray./255*ones(1,3);%计算图形灰度(灰度和明度不是一码事)
    mycolor_g(mycolor_g>=1)=1;

    figure(1)

    % set(gcf,'color',0.82*[1 1 1])
    % set(gcf, 'InvertHardCopy', 'off');
    subplot(2,2,4)%绘制右下角的HSV曲线图
    hold on
    plot(1:64,mycolor_hsv(:,1),'LineWidth',1,'color','r');%H 颜色
    plot(1:64,mycolor_hsv(:,2),'LineWidth',1,'color','b');%S 饱和
    plot(1:64,mycolor_hsv(:,3),'LineWidth',2,'color','k');%V 亮度
    hold off
    title('HSV')
    xlim([0 65]);ylim([0 1]);
    %legend('H 颜色','%S 饱和','%V 亮度')
    set(gca,'xtick',[]);

    subplot(2,2,1)%绘制左上角的颜色图
    hold on
    for j=1:64
        plot(j,0.5,'--rs','LineWidth',2,'MarkerEdgeColor','none','MarkerFaceColor',mycolor(j,:),'MarkerSize',6,'LineStyle','none')
    end
    for j=1:64
        plot(j,0.25,'--rs','LineWidth',2,'MarkerEdgeColor','none','MarkerFaceColor',mycolor_g(j,:),'MarkerSize',6,'LineStyle','none')
    end
    hold off
    title('COLOR')
    ylim([0 0.75])
    xlim([0 65])
    set(gca,'xtick',[]);
    set(gca,'ytick',[0.25 0.5],'yTickLabel',{'灰度','颜图'})

    subplot(2,2,2)%绘制右上的HSV颜色图
    mycolor_hsv1=[mycolor_hsv(:,1),ones(64,1),ones(64,1)];
    mycolor_hsv2=[mycolor_hsv(:,1),mycolor_hsv(:,2),ones(64,1)];
    mycolor_hsv3=[zeros(64,1),zeros(64,1),mycolor_hsv(:,3)];
    mycolor_h=hsv2rgb(mycolor_hsv1);
    mycolor_s=hsv2rgb(mycolor_hsv2);
    mycolor_v=hsv2rgb(mycolor_hsv3);
    hold on
    for j=1:64
        plot(j,0.75,'--rs','LineWidth',2,'MarkerEdgeColor','none','MarkerFaceColor',mycolor_h(j,:),'MarkerSize',6,'LineStyle','none')
    end
    for j=1:64
        plot(j,0.5,'--rs','LineWidth',2,'MarkerEdgeColor','none','MarkerFaceColor',mycolor_s(j,:),'MarkerSize',6,'LineStyle','none')
    end
    for j=1:64
        plot(j,0.25,'--rs','LineWidth',2,'MarkerEdgeColor','none','MarkerFaceColor',mycolor_v(j,:),'MarkerSize',6,'LineStyle','none')
    end
    hold off
    title('COLOR HSV')
    ylim([0 1])
    xlim([0 65])
    set(gca,'xtick',[]);
    set(gca,'ytick',[0.25 0.5 0.75],'yTickLabel',{'明度','饱和','颜色'})

    subplot(2,2,3)%绘制左下的RGB通道曲线图
    hold on
    plot(1:64,mycolor(:,1),'LineWidth',2,'color','r');%R 红色
    plot(1:64,mycolor(:,2),'LineWidth',2,'color','g');%G 绿色
    plot(1:64,mycolor(:,3),'LineWidth',2,'color','b');%B 蓝色
    plot(1:64,mycolor_gray/255,'LineWidth',2,'color','k','LineStyle','--');%灰度

    hold off
    title('RGB')
    xlim([0 65]);ylim([0 1]);
    set(gca,'xtick',[]);

hot颜色图↓↓↓,灰度单调,色调也变化,无论展示还是打印都不会失真。
color_hot

3.自己创建colormap的两种方式

3.1从好看的图片上提取RGB

有了上面的基础,就可以从好看的图片上提取出自己喜欢的colormap了。
所需工具:

  • 360浏览器的截图工具(或其它图片像素值RGB提取工具)
  • matlab

下面以 Dan Mumford 的一幅插画作为colormap的来源图,我很喜欢他的颜色搭配风格。
飞出个未来
我总共取了6个像素点作为颜色图的插值点进行线性插值,程序如下:

mycolorpoint=[[0 0 16];...
    [8 69 99];...
    [57 174 156];...
    [198 243 99];...
    [222 251 123];...
    [239 255 190]];
mycolorposition=[1 11 33 50 57 64];
mycolormap_r=interp1(mycolorposition,mycolorpoint(:,1),1:64,'linear','extrap');
mycolormap_g=interp1(mycolorposition,mycolorpoint(:,2),1:64,'linear','extrap');
mycolormap_b=interp1(mycolorposition,mycolorpoint(:,3),1:64,'linear','extrap');
mycolor=[mycolormap_r',mycolormap_g',mycolormap_b']/255;
mycolor=round(mycolor*10^4)/10^4;%保留4位小数

然后它的颜色分解曲线图如下:
Dan Mumford
然后利用matlab自带的flujet图进行colormap的展示

figure(2)
load flujet
image(X)
colormap(mycolor)

展示结果如下:
一口毒雾喷出
无论是HSV曲线,灰度曲线,以及最终的效果图来看,都非常漂亮,我很喜欢。

3.2自己根据HSV绘制colormap

自己选择HSV的原则比较自由,主要还是要注意颜色的变化和明暗的变化相结合。这里的颜色我主要用两个案例来讲解,其余的颜色图可以根据具体需求自己发挥创造。

第一个颜色图是夕阳天空的颜色图,色彩初步定在蓝紫红橙黄这个渐变上,数值为0.6到1.1(也就是0.1)。明度逐渐增大。饱和度偏柔和,两边低中间饱和度高一些。有了这个初步的设想之后,就可以绘制HSV曲线,然后逐步微调曲线的某些数值点就可以了。比如下图就是我调出来的颜色图:
自然总是给我们灵感
个人觉得这张图优点是基本满足前面的预想,缺点是整个颜色图的灰度偏暗。颜色图的插值点如下面代码所示:

mycolormap_h=interp1([1 64],[0.55 1.18],1:64,'linear','extrap');
mycolormap_s=interp1([1 6 32.5 47 59 64],[0.1 0.6 0.7 0.5 0.45 0.1],1:64,'linear','extrap');
mycolormap_v=interp1([1 16 48 64],[0.05 0.55 1 1],1:64,'linear','extrap');
mycolormap_h(mycolormap_h>=1)=mycolormap_h(mycolormap_h>=1)-1;
mycolor=hsv2rgb([mycolormap_h',mycolormap_s',mycolormap_v']);

之后我在介绍另一个案例,就是怎么绘制一个温度计式的颜色图,可以在区分数据的正负值时使用。初步设想是两头颜色一红一蓝,颜色在中间为白色,两头为深色。为了满足这个需求,我需要把颜色在两边保持不变,中间做突变,但之后觉得太难看,又尝试变成两边渐变,中间快速渐变的方式。明度要中间为1,两侧大约为0.5;饱和度为了让中间为白色需要设为0。所以最终调整的颜色图如下所示:
温度计

4 常用颜色图分类

4.1 渐变方式

渐变是颜色图最常用的方式之一,一般采用2个或多个颜色作为控制点,颜色条上其余颜色采用过渡插值的方式生成。

比如matlab中常见的gray、hot、winter等都属于这样。

这种colormap需要注意:
0.永远不要高估投影仪的质量以及其他人的视力!!!!
1.颜色渐变的色彩不要太相近。
2.颜色渐变尽量保证,在灰度(gray)和色调(H)上单调。
3.和已有自然颜色相仿,避免反自然配色。这样可以避免配色的违和感,也有利于读图者快速理解颜色意义。

举例如下:
在这里插入图片描述
此外,还需要注意,不是颜色越多越好。有时候,为了突出要表示的变量,反而会采用减少颜色的方式去表示。
在这里插入图片描述

4.2 温度计式(Diverging)

温度计式的颜色图,通常用于突出和区分正和负。这种颜色图呈现明显的3色过渡,颜色条两端的颜色分别代表正、负,中间颜色采用过渡色。灰度图上,一般温度计式配色呈现正V形状,或者倒V形状。

matlab中的温度计式配色只有jet一种。
所以python中的为例:
在这里插入图片描述

这种colormap需要注意:
1.正负颜色要有所区别,在色环上角度相差最好大于90度以上。
2 正负颜色的定义,需要与读图者的常识相符(比如温度上认为蓝负红正;比如中国股市的绿跌红涨)。
3.中间过渡色对应的变量值应为0。可以通过检查背景色是否为中间过渡色来判断。

举例如下:
在这里插入图片描述

4.3 条纹式

条纹式颜色条往往更强调区分,而不是渐变与过渡。所以有些颜色条甚至会刻意增加相邻区域的对比。

matlab里条纹式颜色条有:lines、flag等。
其它常用软件中,条纹式颜色条如下:
在这里插入图片描述
网站
http://colorbrewer2.org/#type=diverging&scheme=Spectral&n=4
也提供了一些常用的色彩方案。

4.4 其它伪彩色

还有一类,使用颜色条的目的,只是为了给图像上色。比如各种简单的定性分析。还比如一些定量分析,比如给山川河流上色用到的地形颜色图。或者用作辅助图像的储存,比如把图像或材质的内容转换成数值,之后利用特定的颜色图输出。

比如matlab中hsv就常用于此。
这类颜色图往往具体问题具体分析,难以一块概括,所以就不再描述了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42943114/article/details/81811556

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf

推荐文章

热门文章

相关标签