# 红外热成像测温app
**Repository Path**: kangchang/thermography
## Basic Information
- **Project Name**: 红外热成像测温app
- **Description**: 红外 热成像 测温 温度矩阵 无线测温 远程测温
- **Primary Language**: Dart
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 24
- **Forks**: 0
- **Created**: 2020-11-17
- **Last Updated**: 2026-01-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
### 以下算法均为自研
### 8.实时识别并标记算法
### 1.调试演示所用传感器为8×8像素(IR64)
```
本次红外传感器比较小只有64个像素,无法准备描绘出物体轮廓,所以才需要插值提升像素。分辨率较高的传感器也可以插值锐化边缘,抗锯齿。
```
### 2.移动端显示
```
本次测试使用的是5Hz,传感器每秒发送5次数据,移动端每秒渲染5次热成像画面。实时度高的场景可以增加频率。
```
### 3.温度数组转为温度矩阵算法
```
由于红外传感器上报给服务器的数据是一维数组,要想显示图像就需要将数据转为二维数组矩阵
//传感器横轴像素
int sourcePixelRowCount = 8;
int len = temperatureList.length;
//传感器纵轴像素
int lineNum = len % sourcePixelRowCount == 0
? (len ~/ sourcePixelRowCount).toInt()
: ((len / sourcePixelRowCount) + 1).floor();
for (var i = 0; i < lineNum; i++) {
int startIndex = i * sourcePixelRowCount;
//截取数组指定长度后生成新数组
Iterable range = temperatureList.getRange(startIndex ,startIndex + sourcePixelRowCount);
temperature.add(range.toList());
}
```
### 4.画面镜像翻转,矩阵重新排序
```
如果不进行镜像翻转,显示的画面将和实际的画面是相反的,左右相反
```
### 5.双三次多项式插值提升像素算法
```
插值提升像素,锐化边缘后,提升后像素为32×32,看下图片基本可以看到物体轮廓了。
//计算权重
static dynamic getCubicWeight(double v) {
double a = -0.5;
// 取整
int nv = v.floor();
// 坐标差值集合
List xList = new List(4);
// 坐标集合
List xs = new List(4);
// 最近的4个坐标差值
xList[0] = nv - v - 1;
xList[1] = nv - v;
xList[2] = nv - v + 1;
xList[3] = nv - v + 2;
//
xs[0] = nv - 1;
xs[1] = nv;
xs[2] = nv + 1;
xs[3] = nv + 2;
// 计算权重
List ws = List(4);
for (int i = 0; i < 4; i++) {
double val = xList[i].abs();
double w = 0;
// 基于BiCubic基函数的双三次插值
if (val <= 1) {
w = (a + 2) * val * val * val - (a + 3) * val * val + 1;
} else if (val < 2) {
w = a * val * val * val - 5 * a * val * val + 8 * a * val - 4 * a;
}
ws[i] = w;
}
return {'weight': ws, 'coordinate': xs};
}
```
### 6.温度数值转为RGB色彩编码算法,想要色阶越多可以用255/色阶数,我用的4
```
//将温度转为RGB,用64将颜色分为4个区间,可以分为更多区间比如51(自研)
RGB grayToPseColor(int grayValue) {
if (grayValue > 255) {
return RGB(255, 0, 0);
}
if (grayValue < 0) {
return RGB(0, 0, 0);
}
if ((grayValue >= 0) && (grayValue <= 63)) {
return RGB(0, 0, (grayValue / 64 * 255).round());
} else if ((grayValue >= 64) && (grayValue <= 127)) {
return RGB(0, ((grayValue - 64) / 64 * 255).round(),((127 - grayValue) / 64 * 255).round());
} else if ((grayValue >= 128) && (grayValue <= 191)) {
return RGB(((grayValue - 128) / 64 * 255).round(), 255, 0);
} else if ((grayValue >= 192) && (grayValue <= 255)) {
return RGB(255, ((255 - grayValue) / 64 * 255).round(), 0);
}
return RGB(0, 0, 0);
}
```
### 7.屏幕实时显示热成像画面算法,优化像素增大后渲染卡顿算法流畅丝滑
```
//二维温度数组
List> temperatureScale;
//每个像素点大小
final static double pixel;
//最低温度
static double temperatureMin = 10;
//最高温度
static double temperatureMax = 38;
//计算最大温度差
double difference = temperatureMax - temperatureMin;
@override
void paint(Canvas canvas, Size size) {
//创建画笔,默认颜色就是填充模式
Paint paint = Paint();
//画笔x轴位置,默认坐标为容器的左上角
double top = 0;
//画笔y轴位置
double left = 0;
//循环二维数组
for (var i = 0; i < temperatureScale.length; i++) {
for (var j = 0; j < temperatureScale[0].length; j++) {
double value = temperatureScale[i][j];
//计算温度系数
double scale = (value - temperatureMin) / difference;
//将温度转为rgb颜色值
RGB rbg = grayToPseColor((255 * scale).round());
//调整画笔的颜色
paint.color = Color.fromARGB(255, rbg.R, rbg.G, rbg.B);
//创建一个矩形
Rect rrect = Rect.fromLTWH(left, top, pixel, pixel);
//画一个矩形到屏幕
canvas.drawRect(rrect, paint);
//画笔向右移动一个像素
left = left + pixel;
}
left = 0;
//画笔向下移动一个像素
top = top + pixel;
}
}
```
### 9.移动端效果8×8图示例(优化前画面像素->优化中项画面像素->优化后画面像素)