JoyD
图像处理相关
InfoImage, ImageBuffer, 图像框的bitmap, LastImage, DisplayImage
- 初始化时,都创建成512x384的透明bitmap
- 中途不进行Dispose和设置为null,只在上面进行绘制
- 仅当控件被Dispose时,才进行Dispose和设置为null
操作流程
修改流程
- 暂停或恢复时,设置暂停状态,调用更新Info
- 断开或连接时,设置连接状态,调用更新Info
- Ping通状态变化时,修改Ping状态,调用更新Info
- 图像更新时,保存LastImage,调用更新UI
- 2-4 只在非暂停状态下调用更新,暂停状态下不更新Info和UI
- 数据显示菜单勾选变化时,只在非暂停状态下调用更新实时信息
更新Info
- 以透明色清空Info
- 如果暂停,显示暂停信息,否则如果Ping不通或断开,显示重连信息,否则就绪
- 如果未就绪,调用更新UI
更新UI
- 先将LastImage绘制到全局缓冲
- 再将InfoImage绘制到缓冲
- 在就绪条件下,调用更新实时信息,并将DisplayImage绘制到缓冲
- 最后一次性绘制到图像框的bitmap
- 同步更新检测配置窗口的实时图像属性
更新实时信息
- 以透明色清空DisplayImage
- 如果没有温度数据或温度数据的时间3秒之前,返回
- 温度显示菜单下如果未勾选区域温度和全局温度,则不显示任何温度信息
- 如果勾选了全局温度,则显示全局温度(居中显示),否则显示区域温度(居中显示)
- 如果勾选了区域温度,则显示区域框,否则不显示区域框
- 如果勾选了平均温度,显示平均温度(居中显示)
- 如果勾选了最低温度,显示最低温度(居中显示)
- 如果勾选了最高温度,显示最高温度(居中显示)
- 如果是全局温度时,最低温度和最高温度、平均温度,显示三行(左对齐),整体水平和垂直相对于图像框居中显示
- 如果是区域温度时,最低温度和最高温度、平均温度,显示三行(左对齐),整体水平和垂直相对于区域框居中显示
TCP温度数据接收
- 系统初始化时,创建后台线程
- 然后线程循环执行
- 判断是否存在tcp连接实例
- 如果不存在连接实例,则判断是否暂停。如果暂停,则Sleep 1秒后继续执行。否则创建一个新的连接实例。
- 如果存在连接实例,则判断是否连接。如果未连接,则重新连接
- 同步接收和处理数据
- 收到数据后,如果暂停,接收后丢弃,Sleep 1秒。否则同步将收到的数组复制放到待处理列表(线程安全列表)。
- 通知处理线程,有新数据到达
- 跳转到6
- Dispose时,关闭后台线程
温度数据接收时的补充说明
总之就是不主动断开连接:
- 同步机制简单,不用考虑阻塞,因为在后台线程里
- 不用心跳机制,协议约定是每秒1帧数据
- 异常情况处理,出现异常就跳转到第3步
- 不用考虑波动问题,这是在一个循环中,它会下次重试
- 在异常出现且需要重新创建对象前,先释放旧的资源
- 数据完整性验证放在了数据处理环节
- 连接失败,会跳转到第3步。下一循环会自动重试
温度数据处理逻辑
- 收到的数组放到待处理列表中
- 开始循环处理列表
- 如果列表为空,退出循环
- 从列表中读取第一个数组,查看是否有头信息
- 如果没有头信息,将数组从列表中移除,跳转到3
- 如果有头信息,查看头信息中数据长度信息
- 检查数组中是否有足够的数据长度
- 如果没有足够的数据长度,看列表中是否有下一个数组
- 如果没有,则退出循环,否则将下一个数组合并到当前数组中尾部,将下一个数组从列表中移除,然后跳转到7
- 如果有足够的数据长度,则检查数据长度范围内是否又出现了头信息
- 如果有,则将数组中第二个头信息之前的数据移除,然后跳转到6
- 如果没有,则将数据长度范围内的数据从数组取出进行解析处理,剩余部分保留到数组中,跳转到4
- 处理完毕后,跳转到3
- 循环完成,进入等待状态
温度数据解析处理逻辑
根据热像仪SDK文档,原始温度数据的解析处理需遵循以下逻辑:
原始温度数据格式说明
- 通过TCP端口8081获取温度数据
- 数据包含24字节头部和温度数据两部分
- 头部结构体(header)包含:
- mark[5]: 固定标识"+TEMP"
- payload_length: 温度数据长度
- timestamp: 时间戳(前4字节为秒级时间,后2字节为毫秒级时间)
- 温度数据长度计算:宽×高×2字节,例如240×180分辨率时为240×180×2字节
- 数据按字节低位在前读取,如读取为80 51 01 00时实际值为00 01 51 80的16进制值
原始温度数据解析方法
-
单像素温度计算:
- 每个像素点温度由两个字节组成(L为低8位,H为高8位)
- 公式:摄氏温度×10 = H×256 + L
- 实际温度:摄氏温度 = (H×256 + L)/10
-
温度数据布局:
- 数据按行优先顺序排列
- 例如分辨率为4×3时,数据顺序为:L1 H1 L2 H2 L3 H3 L4 H4 L5 H5 ...
温补值处理
-
温补值获取:
- 通过SDK函数
sdk_get_comp_temp获取温补值 - 函数原型:
sdk_get_comp_temp(const char* ip, int* comp_temp) - 返回值为0表示获取成功
- 通过SDK函数
-
温补值应用:
- 温补值也是摄氏度乘以10的结果
- 最终温度计算公式:
最终温度 = 原始温度 + 温补值 - 示例:原始温度为243(24.3°C),温补值为5(0.5°C),则最终温度为248(24.8°C)
温度数据解析处理流程
- 接收TCP数据并解析头部信息
- 验证mark标识是否为"+TEMP"
- 根据payload_length确定温度数据长度
- 按像素点顺序解析每个像素的温度值
- 获取温补值并应用到每个像素的温度上
- 计算得到最终的温度数据
注意事项
- 时间戳转换时需注意低字节在前、高字节在后的顺序
- 温补值是设备补偿值,必须应用到原始温度上才能得到与网页计算结果一致的温度
- 分辨率不同时,温度数据长度会相应变化,解析时需根据实际分辨率计算
- 原始温度数据更新频率约为每秒一条
温度显示菜单
- 在右键菜单中增加温度显示菜单
- 温度显示菜单下显示全局温度(可勾选)
- 温度显示菜单下显示区域温度(可勾选)
- 区域温度和全局温度只能二选一显示
- 温度显示菜单下显示最高温度、平均温度和最低温度(可勾选)
检测配置
区域绘制逻辑
- 创建独立的叠加层图像 :专门维护一个与显示图像同尺寸的Image对象作为矩形框的叠加层
- 分离绘制逻辑 :将临时绘制和最终绘制分离,临时矩形仍通过Paint事件显示,完成的矩形绘制到叠加层
- 图像合并机制 :在Paint事件中先绘制叠加层,再绘制临时矩形。
- 保存的矩形框位置和大小信息应该是相对于图像的,而不是相对于控件的。
- 当btnDrawRegion按下后,处于绘制状态, btnSelectColor才显示出来
- 当绘制状态时,右击鼠标,退出绘制状态,且清除所有临时绘制。
- 当绘制状态时,双击鼠标,随机生成一个颜色,用于绘制矩形框。
- 当就绪状态时,鼠标移到区域内,该区域内填充半透明色,当有多个重叠时,填充索引号最大的区域
- 当鼠标在半透明区域内单击时,该区域填充半透明色,且显示八个句柄,表示选中该区域。
- 选中区域时,工具栏显示按钮btnDeleteRegion和btnSelectColor;隐藏btnDrawRegion。
- 当选中区域时,btnSelectColor用于改变选中区域的颜色。
- 当选中区域时,btnDeleteRegion用于删除该区域,删除后btnSelectColor隐藏,btnDrawRegion显示。
- 当选中区域时,鼠标移动到八个句柄上,显示对应的光标,用于调整区域大小。
- 当选中区域时,鼠标可以移动区域,用于调整区域位置。
- 当选中区域时,右击鼠标,退出选中状态,转为就绪状态
- 当就绪状态时,工具栏显示绘制温差图按钮(btnDrawTempDiff)
- 当绘制温差图按钮按下时,进入绘制温差图状态,显示添加和删除温差图例按钮(btnAddTempDiff、btnDeleteTempDiff),显示温差图例列表(dataGridViewTempDiff)
- 当绘制温差图状态时,右击鼠标进入就绪状态
- 初始状态/就绪状态,显示dataGridViewTempDiff,但只允许查看
btnNewTempRegion(新建测温区)
- 移除所有已有的测温区列表
- 用透明色清空叠加层图像
btnLoadTempRegion(加载测温区)
- 弹出用户打开文件对话框,用户选择要加载的csv文件
- 移除所有已有的测温区列表,用透明色清空叠加层图像
- 从csv文件中读取所有测温区位置大小和颜色信息,添加到测温区列表中
- 用读取的颜色填充叠加层图像对应的区域
btnSaveTempRegion(保存测温区)
- 弹出用户保存文件对话框,用户选择保存路径和文件名
- 保存测温区列表中的所有测温区位置大小和颜色信息为csv文件
btnNewTempDiff(新建温差图)
- 用透明色清空温差层图像
- 移除所有已有的温差图例列表
btnLoadTempDiff(加载温差图)
- 弹出用户打开文件对话框,用户选择要加载的csv文件
- 用透明色清空温差层图像
- 移除所有已有的温差图例列表
- 从csv文件中读取所有温差图例信息,添加到温差图例列表中
- 从csv文件中读取所有像素的温度值,绘制温差层图像对应的像素
btnSaveTempDiff(保存温差图)
- 弹出用户保存文件对话框,用户选择保存路径和文件名
- 保存温差图例列表中的所有温差图例信息到csv文件
- 每个温差图例信息占一行,格式为:
- 温度(如20°C)
- 颜色(如#FF0000表示红色)
- 保存温差图每个像素的温度值到csv文件
- 每个像素温度值占一行,格式为:
- X坐标(如100)
- Y坐标(如300)
- 温度值(°C)(如25.5)
- 每个像素温度值占一行,格式为:
配置状态说明
- 初始状态/就绪状态:
- 显示btnDrawRegion和btnDrawTempDiff按钮、dataGridViewTempDiff
- 显示btnNewTempRegion按钮、btnLoadTempRegion按钮、btnSaveTempRegion按钮、btnNewTempDiff按钮、btnLoadTempDiff按钮、btnSaveTempDiff按钮
- 隐藏btnSelectColor、btnDeleteRegion按钮、btnAddTempDiff、btnDeleteTempDiff、btnBrushSize1、btnBrushSize3、btnBrushSize5、btnBrushSize10、btnBrushSize15、btnBrushSize25、txtRegionNumber
- 选中区域状态:
- 显示btnDeleteRegion和btnSelectColor按钮、txtRegionNumber
- 隐藏btnDrawRegion和btnDrawTempDiff按钮、dataGridViewTempDiff、btnAddTempDiff、btnDeleteTempDiff、btnBrushSize1、btnBrushSize3、btnBrushSize5、btnBrushSize10、btnBrushSize15、btnBrushSize25
- 隐藏btnNewTempRegion按钮、btnLoadTempRegion按钮、btnSaveTempRegion按钮、btnNewTempDiff按钮、btnLoadTempDiff按钮、btnSaveTempDiff按钮
- 绘制状态:
- 显示btnSelectColor按钮
- 显示btnDrawRegion按钮、txtRegionNumber
- 隐藏btnDeleteRegion按钮
- 隐藏btnDrawTempDiff按钮、dataGridViewTempDiff、btnAddTempDiff、btnDeleteTempDiff、btnBrushSize1、btnBrushSize3、btnBrushSize5、btnBrushSize10、btnBrushSize15、btnBrushSize25
- 隐藏btnNewTempRegion按钮、btnLoadTempRegion按钮、btnSaveTempRegion按钮、btnNewTempDiff按钮、btnLoadTempDiff按钮、btnSaveTempDiff按钮
- 绘制温差图状态:
- 显示btnDrawTempDiff按钮,显示dataGridViewTempDiff、btnAddTempDiff、btnDeleteTempDiff
- 当选定温差图例后,显示btnBrushSize1、btnBrushSize3、btnBrushSize5、btnBrushSize10、btnBrushSize15、btnBrushSize25
- 隐藏btnSelectColor、btnDeleteRegion、btnDrawRegion按钮
- 隐藏btnNewTempRegion按钮、btnLoadTempRegion按钮、btnSaveTempRegion按钮、btnNewTempDiff按钮、btnLoadTempDiff按钮、btnSaveTempDiff按钮