用STM32F407ZGT6与AMG8833(8×8点阵)热成像传感器做一个热成像测试,程序采用的是csdn下载的双线性插值的算法,但在实际跑程序过程中,有如下几个问题:
1.2.8寸屏幕(240*320)刷新较慢,需要大概1秒时间才能从左扫到右,
2.最主要的问题是显示的图像仅屏幕左上角及屏幕右侧(一竖线)有不同温度色块显示且刷新,中间区域不显示不同色块且也不刷新。
以下是主程序main.c及屏幕显示截图求支招:
/**
* AMG8833 8*8图像 双线性插值程序
* Date: 2020/09/24
* File Name: main.c
* Copyright (c) 2020, cx2008lxl@vip.qq.com All Rights Reserved.
* @author Li Xinliang
*/
#include "main.h"
/*256位的温度颜色对照表*/
const uint16_t camColors[] = {0x480F,
0x400F,0x400F,0x400F,0x4010,0x3810,0x3810,0x3810,0x3810,0x3010,0x3010,
0x3010,0x2810,0x2810,0x2810,0x2810,0x2010,0x2010,0x2010,0x1810,0x1810,
0x1811,0x1811,0x1011,0x1011,0x1011,0x0811,0x0811,0x0811,0x0011,0x0011,
0x0011,0x0011,0x0011,0x0031,0x0031,0x0051,0x0072,0x0072,0x0092,0x00B2,
0x00B2,0x00D2,0x00F2,0x00F2,0x0112,0x0132,0x0152,0x0152,0x0172,0x0192,
0x0192,0x01B2,0x01D2,0x01F3,0x01F3,0x0213,0x0233,0x0253,0x0253,0x0273,
0x0293,0x02B3,0x02D3,0x02D3,0x02F3,0x0313,0x0333,0x0333,0x0353,0x0373,
0x0394,0x03B4,0x03D4,0x03D4,0x03F4,0x0414,0x0434,0x0454,0x0474,0x0474,
0x0494,0x04B4,0x04D4,0x04F4,0x0514,0x0534,0x0534,0x0554,0x0554,0x0574,
0x0574,0x0573,0x0573,0x0573,0x0572,0x0572,0x0572,0x0571,0x0591,0x0591,
0x0590,0x0590,0x058F,0x058F,0x058F,0x058E,0x05AE,0x05AE,0x05AD,0x05AD,
0x05AD,0x05AC,0x05AC,0x05AB,0x05CB,0x05CB,0x05CA,0x05CA,0x05CA,0x05C9,
0x05C9,0x05C8,0x05E8,0x05E8,0x05E7,0x05E7,0x05E6,0x05E6,0x05E6,0x05E5,
0x05E5,0x0604,0x0604,0x0604,0x0603,0x0603,0x0602,0x0602,0x0601,0x0621,
0x0621,0x0620,0x0620,0x0620,0x0620,0x0E20,0x0E20,0x0E40,0x1640,0x1640,
0x1E40,0x1E40,0x2640,0x2640,0x2E40,0x2E60,0x3660,0x3660,0x3E60,0x3E60,
0x3E60,0x4660,0x4660,0x4E60,0x4E80,0x5680,0x5680,0x5E80,0x5E80,0x6680,
0x6680,0x6E80,0x6EA0,0x76A0,0x76A0,0x7EA0,0x7EA0,0x86A0,0x86A0,0x8EA0,
0x8EC0,0x96C0,0x96C0,0x9EC0,0x9EC0,0xA6C0,0xAEC0,0xAEC0,0xB6E0,0xB6E0,
0xBEE0,0xBEE0,0xC6E0,0xC6E0,0xCEE0,0xCEE0,0xD6E0,0xD700,0xDF00,0xDEE0,
0xDEC0,0xDEA0,0xDE80,0xDE80,0xE660,0xE640,0xE620,0xE600,0xE5E0,0xE5C0,
0xE5A0,0xE580,0xE560,0xE540,0xE520,0xE500,0xE4E0,0xE4C0,0xE4A0,0xE480,
0xE460,0xEC40,0xEC20,0xEC00,0xEBE0,0xEBC0,0xEBA0,0xEB80,0xEB60,0xEB40,
0xEB20,0xEB00,0xEAE0,0xEAC0,0xEAA0,0xEA80,0xEA60,0xEA40,0xF220,0xF200,
0xF1E0,0xF1C0,0xF1A0,0xF180,0xF160,0xF140,0xF100,0xF0E0,0xF0C0,0xF0A0,
0xF080,0xF060,0xF040,0xF020,0xF800,
};
int main(void)
{
u8 lcd_id[12]; //存放LCD ID字符串
u8 temp_max[20]; //存放高温度字符串
u8 temp_min[20]; //存放低温字符串
HAL_Init();
Stm32_Clock_Init(336,8,2,7);
delay_init(168);
uart_init(115200);
SRAM_Init();
my_mem_init(SRAMIN); //初始化内部内存池
my_mem_init(SRAMEX); //初始化外部内存池
my_mem_init(SRAMCCM); //初始化CCM内存池
LCD_Init();
EXIIC_Init();
AMG8883_Init(15, 40); //设定大致温度范围,可使图像颜色差异更明显
TIM6_Init(10000-1,8400-1); //10Khz计数频率,1秒钟中断
//定义原图像和扩充图像大小信息
u8 srcImgW = 8;
u8 srcImgH = 8;
u16 dstImgW = 240;
u16 dstImgH = 320;
//获取长宽比系数
double dstAsrcKw = srcImgW/(double)dstImgW;
double dstAsrcKh = srcImgH/(double)dstImgH;
//申请内存空间
u8 *srcColor = (u8 *)mymalloc(SRAMEX, srcImgW*srcImgH);
u8 *dstColor = (u8 *)mymalloc(SRAMEX, dstImgW*dstImgH);
u16 i, j;
u16 srcXaxis, srcYaxis; //目标图像变换到原图像对应的坐标(浮点数)
u16 srcXint, srcYint; //原坐标浮点数取 整数部分
u16 srcXdou, srcYdou; //原坐标浮点数取 小数部分
//速度优化临时变量
u32 volatile yMUL2048;
u32 volatile xMUL2048;
u32 volatile xMULy;
u32 volatile xintMULwADDy;
sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//将LCD ID打印到lcd_id数组。
while(1)
{
//从传感器读取温度
AMG8833_GetTemperature(AMG8833_Struct.TMat); //获取温度数据
printf("Environment: %lf\r\n", AMG8833_GetThermistor);
printf("OBJ: %lf\r\n",AMG8833_GetOBJT);
MatSort(AMG8833_Struct.TMat, 64, 1);
sprintf((char*)temp_max,"Temp_MAX:%4.1f",AMG8833_Struct.TMat[0]*0.25);//将最大温度值大隐刀数组temp_max
sprintf((char*)temp_min,"Temp_MIN:%4.1f",AMG8833_Struct.TMat[30]*0.25);//最小温度值大隐刀数组temp_min
// //范围内的温度转为0~255灰度 范围在AMG8883_Init的形参指定
//AMG8883_Init(26, 42)即范围为26~42度,0~255的灰度值即对应26~42度
int imgTemp = 0;
for(i=0; i<srcImgW; i++)
{
for(j=0; j<srcImgH; j++)
{
imgTemp = (u16)((AMG8833_Struct.TMat[__smlad(i,srcImgW,j)]-AMG8833_Struct.Tmin)*(255/(double)(AMG8833_Struct.Tmax-AMG8833_Struct.Tmin))+0.5); //四舍五入获取原图像灰度值(0~255)///////////////////
if(imgTemp>255) srcColor[__smlad(i,srcImgW,j)] = 255;
else if(imgTemp<0) srcColor[__smlad(i,srcImgW,j)] = 0;
else srcColor[__smlad(i,srcImgW,j)] = imgTemp;
}
}
// //双线性插值
for(i=0; i<dstImgW; i++)
{
for(j=0; j<dstImgH; j++)
{
//根据目的图像坐标 反推原图像坐标
srcXaxis = ((i+0.5)*dstAsrcKw-0.5)*2046; //+-0.5为了使原图像和目标图像中心对齐
srcYaxis = ((j+10.5)*dstAsrcKh-0.5)*2046;
srcXint = srcXaxis>>11;
srcYint = srcYaxis>>11;
srcXdou = __uqsub16(srcXaxis, (srcXint<<11)); //速度优化。*2048即扩大2048倍后四舍五入取整
srcYdou = __uqsub16(srcYaxis, (srcYint<<11)); //下面计算dstColor时,需将系数部分的1也替换为2048。最后除以2048*2048还原
//
// // 以下方法二选一
// //一、根据公式进行 双线性插值
dstColor[i*dstImgW+j] = ((u32)(((2048-srcXdou)*(2048-srcYdou)*srcColor[srcXint*srcImgW+srcYint] +
(2048-srcXdou)*srcYdou*srcColor[srcXint*srcImgW+(srcYint+1)] +
srcXdou*(2048-srcYdou)*srcColor[(srcXint+1)*srcImgW+srcYint] +
srcXdou*srcYdou*srcColor[(srcXint+1)*srcImgW+(srcYint+1)])+0.5))>>22;
// //二、双线性插值 使用DSP运算速度优化
// //2048*2048 2048*y 2048*x x*y
// //2048*y x*y
// //2048*x x*y
// //x*y
// xMUL2048 = srcXdou<<11;
// yMUL2048 = srcYdou<<11;
// xMULy = __smuad(srcXdou,srcYdou);
// xintMULwADDy = __smlad(srcXint,srcImgW,srcYint);
// dstColor[__smlad(i,dstImgW,j)] = ((4194304-yMUL2048-xMUL2048+xMULy)*srcColor[xintMULwADDy] +
// (yMUL2048-xMULy)*srcColor[xintMULwADDy+1] +
// (xMUL2048-xMULy)*srcColor[xintMULwADDy+srcImgW] +
// xMULy*srcColor[xintMULwADDy+srcImgW+1])>>22;
//查表获取color进行LCD显示
LCD_Fill(i,j,i+2,j+2,camColors[dstColor[__smlad(i,dstImgW,j)]]);
// LCD_Fast_DrawPoint(i+40,j+100,camColors[dstColor[__smlad(i,dstImgW,j)]]);
// LCD_ShowString(30,650,450,16,24,temp_max); //显示最大温度值
// LCD_ShowString(30,700,450,16,32,temp_min); //显示最小温度值
}
}
// ov_frame++;
// printf("\r\n");
//printf("\r\n\r\n");
//delay_ms(1000);
}
}
屏幕显示截图
刷新慢的问题,可能是刷屏慢,也可能是计算慢,也可能是获取新的数据慢,建议在开始获取数据,获取数据结束,开始计算,结束计算,开始刷屏,结束刷屏这个点分别加上调试输出,确认到底是哪个慢,然后针对性解决
可以借鉴下
clc;
clear;
b = [28.00, 31.25, 33.00, 29.75, 31.75, 29.25, 27.25, 27.25
29.75, 34.25, 38.25, 35.25, 36.75, 31.75, 27.50, 26.50
30.00, 37.00, 39.25, 38.25, 37.75, 33.00, 28.25, 26.75
29.50, 34.50, 39.25, 38.75, 37.00, 31.75, 27.25, 26.75
28.00, 31.00, 33.75, 34.25, 32.25, 28.75, 26.25, 26.25
26.75, 27.25, 28.25, 28.50, 27.25, 26.00, 26.75, 26.25
26.25, 26.50, 26.25, 26.00, 26.25, 26.50, 26.00, 26.00
27.50, 26.00, 26.50, 25.75, 26.00, 26.50, 26.25, 27.25
]
t=imresize(b,45,'bicubic'); %45倍插值
imagesc(t);
该算法是不是有问题呢?算法处理太慢了,导致刷新跟着也慢~
针对2.8寸屏幕(240*320)刷新较慢的问题,建议少用库函数,写寄存器,可以显著加快刷新的速度。对于图形显示不正常的问题,建议检查点阵数据是否有问题从而导致图像显示不正确,或者显示区域和显示模式的设置问题。
可以通过优化程序算法、减少需要扫描的数据量等方式来加快刷新速度,解决刷新较慢的问题。
刷新速度较慢:可能是由于屏幕刷新的频率不够高导致的。您可以尝试使用双缓冲区技术来加快屏幕的刷新速度。使用双缓冲区可以在后台进行图像渲染,然后一次性将整个图像更新到屏幕上,以减少刷新的时间。
图像显示问题:根据您的描述,图像只在屏幕左上角和右侧显示,中间区域不显示。这可能是因为您在计算插值时没有正确处理边界条件。请确保您的插值算法在计算像素值时处理边界情况,以确保整个图像都能正确显示。
图像刷新问题:您提到图像刷新只在屏幕左上角和右侧的一条竖线上进行。这可能是由于您的刷新代码只更新了特定区域的像素值,而没有更新整个屏幕。请确保您的图像刷新代码能够正确更新整个屏幕的像素值,以显示完整的图像。
性能优化:您的双线性插值算法使用了一些优化技术,但仍然可能存在性能瓶颈。您可以尝试使用其他优化技术,如使用查表法来加快插值计算的速度。
1:直接使用LCD_DrawPoint画点,只画有效的温度像素点,整个屏幕填充的话会比较慢的
2: //根据目的图像坐标 反推原图像坐标
srcXaxis = ((i+0.5)*dstAsrcKw-0.5)*2046; //+-0.5为了使原图像和目标图像中心对齐
srcYaxis = ((j+10.5)*dstAsrcKh-0.5)*2046;
像素中心对齐,改成+0.5
目前看出了这两点问题