怎样把mlx90640的输出显示为彩色的热成像图

2024-02-08 01:20

本文主要是介绍怎样把mlx90640的输出显示为彩色的热成像图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0、热成像图


如你所见,下图就是一张人手的热成像图,可以看作是显示手部温度分布的图像。


在这里插入图片描述


1、伪彩色图和RGB图

在文章如何使用STM32F10x驱动MLX90640模块(移植官方驱动)中,咱们的讨论了怎么用Melexis的官方驱动读取Mlx90640的数据,但是咋个显示呢?

实际上,这是个灰度图转伪彩色图的问题。不清楚伪彩色是啥的,可以参考伪彩色_百科

我们从Mlx90640读出数据以后用官方驱动中的API函数MLX90640_CalculateTo()解算得到一个温度矩阵,mlx9064032×24的热成像芯片,所以温度矩阵也就是32×24的,如下图所示(单位为℃)。


在这里插入图片描述
这是个一维的矩阵,而我们熟悉的RGB图像呢,需要R(红)、G(绿)、B(蓝)三个分量的数据,也就是说,RGB图像可以看做一个有三个维度的结构,如下图所示:
在这里插入图片描述
灰度图转化的RGB彩图,就是伪彩图。


这样,任务就转化成两个步骤

  • 把温度矩阵转化为一维的灰度矩阵;
  • 把灰度矩阵转化为三维的RGB三个分量组成的结构。

2、灰度值转RGB

明明是一个值,怎么转成三个值呢?映射。
这个映射关系不太好找吧,咱查查论文呗,已经有人说的很清楚啦。

具体可以参考这篇文章:A perceptive uniform pseudo-color coding method of SAR images
主要就看下面这张图:
在这里插入图片描述
也就是三个步骤:

  • 灰度矩阵中的最大值

  • 计算HSI

/* 计算HSI */
float I = grey,H = (2*PI*grey)/L;
float S;
/* grey < L/2 */
if(grey<L/2){S = 1.5 * grey;
}else{S = 1.5 * (L-grey);
}
  • 计算RGB
/* 计算RGB */
float V1 = S* cos(H);
float V2 = S* sin(H);
float R = I - 0.204*V1 + 0.612*V2;
float G = I - 0.204*V1 - 0.612*V2;
float B = I + 0.408*V1; 

3、温度转灰度

知道灰度和RGB之间怎么转化了,那怎么把温度转成灰度呢?放缩。
Mlx90640采集的最高温度为300度,把(0,300)放缩到(0,200),用下面这段代码就行啦

for(int i=0;i<size;i++){float grey = (temp[i]*255)/300;
}

4、Code

所谓Talk is free,咱闲话少说,直接上代码哈


  • 一个函数Temp2RGB(float* temp,int size,float maxTemp,uint16_t* rgb)
void Temp2RGB(float* temp,int size,float maxTemp,uint16_t* rgb)
{double miniNum = 0.0002;float L = maxTemp;float PI = 3.14;for(int i=0;i<size;i++){/* 转温度为灰度 */float grey = (temp[i]*255)/300;/* 计算HSI */float I = grey,H = (2*PI*grey)/L;float S;/* grey < L/2 */if((grey-L/2) < miniNum){//if(grey<L/2){S = 1.5 * grey;}else{S = 1.5 * (L-grey);}/* 计算RGB */float V1 = S* cos(H);float V2 = S* sin(H);float R = I - 0.204*V1 + 0.612*V2;float G = I - 0.204*V1 - 0.612*V2;float B = I + 0.408*V1; /* 转为16bits RGB[5-6-5]色彩 *//* (2^5-1)/(2^8-1) = 0.12 (2^6-1)/(2^8-1) = 0.24*/		uint16_t rbits = (R*0.125);uint16_t gbits = (G*0.250);uint16_t bbits = (B*0.125);rgb[i] = (rbits<<11)|(gbits<<5)|bbits;}}

函数有四个参数:
temp:温度矩阵转成的一维向量,就是从API函数MLX90640_CalculateTo()得到的数组
sizetemp的长度
maxTemptemp中的最大值
rgb:保存rgb值的数组


5、疑问

转换函数Temp2RGB(float* temp,int size,float maxTemp,uint16_t* rgb)的定义中有一段


uint16_t rbits = (R*0.125);
uint16_t gbits = (G*0.250);
uint16_t bbits = (B*0.125);
rgb[i] = (rbits<<11)|(gbits<<5)|bbits;

这是啥呢?我们得到RGB值之后为啥要把三个数转成一个uint16_t类型的数呢?
这是为了显示到彩色OLED屏幕上。


在这里插入图片描述


屏幕显示彩色当然有编码方式呀,就是用三个颜色的值编成一个数据,那编码方式是咋样的呢?看一下屏幕模块里芯片的数据手册哈。


在这里插入图片描述


可以看到色彩数据编码的长度最长为18位,不够三个完整的八位的数据拼接。我们选16位的编码方式,也就是五位用于R,中间六位用于G,右侧五位用于B,如下图所示

在这里插入图片描述


五位最多表示32个不同的数,六位最多表示64个不同的数,除以八位最大表示数255分别约等于0.1250.250,可以乘这两个因子放缩

uint16_t rbits = (R*0.125);
uint16_t gbits = (G*0.250);
uint16_t bbits = (B*0.125);

然后移位,最后再通过或运算拼接起来,得到色彩编码。

rgb[i] = (rbits<<11)|(gbits<<5)|bbits;

好啦,完毕。

这篇关于怎样把mlx90640的输出显示为彩色的热成像图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/689522

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

顺序表之创建,判满,插入,输出

文章目录 🍊自我介绍🍊创建一个空的顺序表,为结构体在堆区分配空间🍊插入数据🍊输出数据🍊判断顺序表是否满了,满了返回值1,否则返回0🍊main函数 你的点赞评论就是对博主最大的鼓励 当然喜欢的小伙伴可以:点赞+关注+评论+收藏(一键四连)哦~ 🍊自我介绍   Hello,大家好,我是小珑也要变强(也是小珑),我是易编程·终身成长社群的一名“创始团队·嘉宾”

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器

C# dateTimePicker 显示年月日,时分秒

dateTimePicker默认只显示日期,如果需要显示年月日,时分秒,只需要以下两步: 1.dateTimePicker1.Format = DateTimePickerFormat.Time 2.dateTimePicker1.CustomFormat = yyyy-MM-dd HH:mm:ss Tips:  a. dateTimePicker1.ShowUpDown = t

如何将一个文件里不包含某个字符的行输出到另一个文件?

第一种: grep -v 'string' filename > newfilenamegrep -v 'string' filename >> newfilename 第二种: sed -n '/string/!'p filename > newfilenamesed -n '/string/!'p filename >> newfilename

Detectorn2预训练模型复现:数据准备、训练命令、日志分析与输出目录

Detectorn2预训练模型复现:数据准备、训练命令、日志分析与输出目录 在深度学习项目中,目标检测是一项重要的任务。本文将详细介绍如何使用Detectron2进行目标检测模型的复现训练,涵盖训练数据准备、训练命令、训练日志分析、训练指标以及训练输出目录的各个文件及其作用。特别地,我们将演示在训练过程中出现中断后,如何使用 resume 功能继续训练,并将我们复现的模型与Model Zoo中的

小程序button控件上下边框的显示和隐藏

问题 想使用button自带的loading图标功能,但又不需要button显示边框线 button控件有一条淡灰色的边框,在控件上了样式 border:none; 无法让button边框隐藏 代码如下: <button class="btn">.btn{border:none; /*一般使用这个就是可以去掉边框了*/} 解决方案 发现button控件有一个伪元素(::after