代码拉取完成,页面将自动刷新
本次红外传感器比较小只有64个像素,无法准备描绘出物体轮廓,所以才需要插值提升像素。分辨率较高的传感器也可以插值锐化边缘,抗锯齿。
本次测试使用的是5Hz,传感器每秒发送5次数据,移动端每秒渲染5次热成像画面。实时度高的场景可以增加频率。
由于红外传感器上报给服务器的数据是一维数组,要想显示图像就需要将数据转为二维数组矩阵
//传感器横轴像素
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<double> range = temperatureList.getRange(startIndex ,startIndex + sourcePixelRowCount);
temperature.add(range.toList());
}
如果不进行镜像翻转,显示的画面将和实际的画面是相反的,左右相反
插值提升像素,锐化边缘后,提升后像素为32×32,看下图片基本可以看到物体轮廓了。
//计算权重
static dynamic getCubicWeight(double v) {
double a = -0.5;
// 取整
int nv = v.floor();
// 坐标差值集合
List<double> xList = new List(4);
// 坐标集合
List<int> 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<double> 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};
}
//将温度转为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);
}
//二维温度数组
List<List<double>> 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;
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。