colormap

原理

什么热图,光谱图,等等,它的本质就是数值和颜色在一张地图上的映射,我们称之为colormap。

这里,为了简化描述,采用RGBA模式进行颜色统一,RGB是红色、绿色和蓝色,A代表透明度。

所以画一个色图,也就是遍历整张图片,给每个像素设置一个RGBA值。该函数可以表示为:

int color matrix[宽度][高度];void draw colormap(){ for(int I = 0;我& lt宽度;++ I){ for(int j = 0;j & lt身高;++ j){ colormap[I][j]= color matrix[I][j];}}}最后得到以下形式的效果:

colormap

实现方法以Qt为UI框架采用第三方库QCustomplot, 因为这个库使用起来很方便,只需要导入 .h 和 .cpp 文件就行,无需编译成动态链接库。

首先,我们对QCustomplot所呈现的图像有了一个基本的了解,我已经标注了需要用来实现colormap的地方,主要包括。

坐标轴的隐藏(看个人需求)创建一个QCPColorMap类,用于实现上边所说的 drawColorMap 功能创建一个图标尺,用来显示颜色的区间

以上三个步骤与程序相对应:

//配置axis rect:m _ custom plot = new QCustomPlot(this);m _ custom plot-& gt;setInteractions(QCP::伊兰格德拉格|QCP::伊兰格祖姆);//这也允许通过拖动/缩放m _ custom plot-& gt;axis rect()-& gt;setupFullAxeox(true);//隐藏坐标,上下左右m _ custom plot-& gt;xAxis-& gt;set visible(true);m _ custom plot-& gt;yAxis-& gt;set visible(true);m _ custom plot-& gt;xAxis2->set visible(true);m _ custom plot-& gt;ya xis 2->;set visible(true);//设置QCPColorMap:m _ colorMap = new QCPColorMap(m _ custom plot-& gt;xAxis,m _ custom plot-& gt;yAxis);//添加一个色标:m _ color scale = new QCPColorScale(m _ custom plot);m _ custom plot-& gt;plot layout()-& gt;addElement(0,1,m _ color scale);//添加到主轴rect m_colorScale的右边-& gt;setType(qcp axis::a tright);//刻度应该是竖条,刻度/轴标签在右边(实际上右边已经是默认的了)m _ colorMap-& gt;setColorScale(m _ colorScale);//将颜色图与色标关联//将颜色图的颜色渐变设置为预设之一:m _ colorMap-& gt;set gradient(QCPColorGradient::gp jet);引入一个QCPColorGradient的概念,我们就不难想到这样一个问题:值为0时颜色是蓝色,值为10时是红色,值为5时是什么颜色?这就是QCPColorGradient要做的事情。

难道就这么简单?

如果我们要画的图像可以分成400 * 300个网格,按照常理,我们只需要遍历这些网格,设置颜色就可以了,但实际情况往往是我们得到的数据很少。

比如只有64个位置,如何展开成400 * 300那么大的网格,如何插值?

不难想象,网格离这些点越近,这个点的影响力越大,反之亦然。

距离,关键词是距离,设距离为r,那么r代表插值方法是线性的,r2是曲线的,效果更好更平滑,r3,r^4等等。

为了简化计算,采用距离的平方作为权重,只需要累加已知点在未知点的权重:

for(int I = 0;我& ltdatax++ I){ for(int j = 0;j & ltdatay++ j){ m _ colorMap-& gt;data()-& gt;celltocord(I,j,&x,& y);//计算权重值double sum = 0.0for(int k = 0;k & ltm _ channel axis . size();++k) ++k){ //(x,y)是(I,j)在colormap坐标系中的映射auto & point = m _ channel axis[k];double RR =(point . x()-x)*(point . x()-x)+(point . y()-y)*(point . y()-y);sum+= 1/RR;m _ channel weight[I][j][k]= 1/RR;} for(int k = 0;k & ltm _ channel axis . size();++ k){ m _ channel weight[I][j][k]/= sum;}}}所以我们可以计算所有网格对应的颜色值,时间复杂度为O(宽度*高度*点数)。

等等,这看起来很复杂?400 * 300 * 64 = 7,680,000。700万的订单很大,让leetcode跑肯定是加班。

所以我们需要优化时间复杂度。

时间复杂度优化

如果你做过图像处理估算,你就已经知道如何优化了。上述问题相当于:知道一张小尺寸的图片,如何放大成大尺寸的图片。

没错,小号。我们上面400 * 300的格子太大了。如果是40 * 30呢?一瞬间的计算量很小!我们会在计算后为他放大。

这里采用双线性插值法:

for(int I = 0;我& ltdatax-1;i++){ for(int j = 0;j & ltdatay-1;j++){ double V1 = m _ matrix 1[I][j];双V2 = m _ matrix 1[I+1][j];double V3 = m _ matrix 1[I+1][j+1];double V4 = m _ matrix 1[I][j+1];for(int m = 0;m & ltratexm++){ for(int n = 0;n & ltrateyn++) { int x = i * ratex + m,y = j * ratey+n;if(m_inCircle[x][y] == false)继续;m_matrix[x][y] = doubleLinear(m,n,ratex,ratey,V1,V2,V3,V4);m _ colorMap-& gt;data()-& gt;setCell(x,y,m _ matrix[x][y]);} } } } double hot plot::double linear(int m,int n,int X,int Y,double V1,double V2,double V3,double V4){ return(m * n *(V3-V4-V2+V1)+X * n *(V4-V1)+m * Y *(V2-V1))/(X * Y)+V1;}我们来看看现在的计算:40 * 30 * 64+400 * 300 = 19.68万,从700万到20万!当然,计算量少了会影响画质。让我们适当地平衡复杂性和图像效果。

原文链接:Qt绘制热图、频谱图、地形图、色彩图-QT开发中文网

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论