JAVA-通过大疆TSDK的API直接获取红外图片温度信息

news/2024/12/22 17:40:34/文章来源:https://www.cnblogs.com/zn19961006/p/18622320

一、前言

看过很多关于大疆红外图片用TSDK取温的方式,但是网上能搜到的大部分教程都是通过官方下载文件smple编译出来的程序来取温,如果这样做,虽然确实也能够实现目的,但不得不说,不但会降低运行速度,而且代码调用起来也麻烦。所以不如研究一下怎么直接调用他们的C++ API。先说下大疆TSDK(Thermal Sdk),目前更新版本为1.6,这个版本目前已经适配的机型和镜头包括御2、御3无人机、M30T无人机、H20T/N镜头、H30T镜头,理论上这个SDK能够在任何基于X86架构的操作系统中使用,包含Linux和windows,但对于ARM架构的操作系统比如Android、移动计算设备等都是不支持的,这个SDK定位就只是桌面端应用。Thermal Sdk下载地址:https://www.dji.com/cn/downloads/softwares/dji-thermal-sdk,下载之后可以看到以下目录:

sample目录是一个集成所有功能的实例程序,可以直接运行里面的build就可编译出来,然后参考readme.md来执行命名行,相应的在JAVA可以通过调用命令行来实现功能。但本文并不讲这个。调用api所需要的所有库都存放在tsdk-coare,打开后是这样的:

api中的头文件可以看到官方暴露出来的api,lib则是对应的so/dll库文件,需要将所有库文件放在同一目录。

二、环境依赖

既然TSDK的库是so或dll,那么理所当然的可以使用JNA或者JNI调用,我使用的是JNA。在pom.xml中引入JNA依赖:
<dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId><version>5.13.0</version>
</dependency>
<dependency><groupId>net.java.dev.jna</groupId><artifactId>jna-platform</artifactId><version>5.13.0</version>
</dependency>

三、调用

1、调用准备

新建一个TsdkLibrary类,并继承jna的library接口:

去api目录中的dirp_api.h找需要的函数,比如说下面几个是红外取温需要的:
// 存放图片分辨率的结构体
typedef struct { int32_t width;                              /**< Horizontal size */int32_t height;                             /**< Vertical size */
} dirp_resolution_t;
// 通过图片创建指针DIRP_HANDLE
dllexport int32_t dirp_create_from_rjpeg(const uint8_t *data, int32_t size, DIRP_HANDLE *ph);
// 获取图片分辨率
dllexport int32_t dirp_get_rjpeg_resolution(DIRP_HANDLE h, dirp_resolution_t *resolution);
// 销毁DIRP_HANDLE
dllexport int32_t dirp_destroy(DIRP_HANDLE h);
// 获取红外图片温度,返回值为整数(真实温度=返回值/10)
dllexport int32_t dirp_measure(DIRP_HANDLE h, int16_t *temp_image, int32_t size);
// 获取红外图片温度,返回值为小数(为真实温度)
dllexport int32_t dirp_measure_ex(DIRP_HANDLE h, float *temp_image, int32_t size);
因为有结构体,所以还有创建一个jna对应的图片分辨率结构体类,然后将属性填入(注意要初始化):
package org.fly.library.struct;import com.sun.jna.Structure;public class dirp_resolution_t extends Structure {public int width = 0;public int height = 0;@Overrideprotected java.util.List<String> getFieldOrder() {return java.util.Arrays.asList("width", "height");}
}
比如要重写getFieldOrder方法!!!然后再将需要的函数填写到TsdkLibrary接口(要注意名字一定要对应上!!):
package org.fly.library;import com.sun.jna.Library;
import com.sun.jna.Pointer;
import org.fly.library.struct.dirp_resolution_t;public interface TsdkLibrary extends Library {// 通过图片创建指针DIRP_HANDLEint dirp_create_from_rjpeg(byte[] data, int size, Pointer ph);// 获取图片分辨率int dirp_get_rjpeg_resolution(Pointer h, dirp_resolution_t resolution);// 销毁DIRP_HANDLEint dirp_destroy(Pointer h);// 获取红外图片温度,返回值为整数(真实温度=返回值/10)int dirp_measure(Pointer h, byte[] temp_image, int size);// 获取红外图片温度,返回值为小数(为真实温度)int dirp_measure_ex(Pointer h, byte[] temp_image, int size);
}
因为c++中很多数据类型是java中没有的,所以需要更换对应,比如说c++中的int32_t对应java中的int,int8对应byte,typedef void对应Pointer等等,可自行网上查找,这里不列举了。

2、使用

新建一个工具类或者在你想要调用api的类中通过静态代码块加载TsdkLibrary:
    // tsdk库public static TsdkLibrary tsdkLibrary;static {tsdkLibrary = Native.load("E:\\SDK\\dji_thermal_sdk_v1.6_20240927\\tsdk-core\\lib\\windows\\release_x64\\libdirp.dll", TsdkLibrary.class);}
然后就可以进行使用了,获取图片温度如下:
package org.fly;import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import org.fly.library.TsdkLibrary;
import org.fly.library.struct.dirp_resolution_t;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class Main {// tsdk库public static TsdkLibrary tsdkLibrary;static {tsdkLibrary = Native.load("E:\\SDK\\dji_thermal_sdk_v1.6_20240927\\tsdk-core\\lib\\windows\\release_x64\\libdirp.dll", TsdkLibrary.class);}// 图像处理指针public static Pointer dirpHandle;/*** 创建指针句柄*/public static void createHandle(InputStream is,long length) throws IOException {// 创建空句柄指针dirpHandle = new Memory(length);byte[] buffer = new byte[(int)length];is.read(buffer,0,(int)length);// 指针分配tsdkLibrary.dirp_create_from_rjpeg(buffer, buffer.length, dirpHandle);}/*** 关闭指针*/public static void closeHandle(Pointer handle) {tsdkLibrary.dirp_destroy(handle.getPointer(0));}/*** 设置红外图片*/public static void setImageFile(String fileName) throws IOException {FileInputStream fis = new FileInputStream(fileName);if(dirpHandle !=null){closeHandle(dirpHandle);}createHandle(fis,fis.available());fis.close();}/*** 获取红外图片温度*/public static float[][] getImageTem(String fileName) throws IOException {setImageFile(fileName);// 获取分辨率dirp_resolution_t resolution = new dirp_resolution_t();tsdkLibrary.dirp_get_rjpeg_resolution(dirpHandle.getPointer(0),resolution);int imageSize = resolution.width * resolution.height*4;byte[] imageBytes = new byte[imageSize];tsdkLibrary.dirp_measure_ex(dirpHandle.getPointer(0),imageBytes,imageSize);int k = 0;float[][] imageTem = new float[resolution.height][resolution.width];byte[] data = new byte[4];int col = 0;int row = 0;// 循环获取float温度while (k < imageSize) {data[0] = imageBytes[k];data[1] = imageBytes[k+1];data[2] = imageBytes[k+2];data[3] = imageBytes[k+3];imageTem[row][col] = bytes2Float(data);k += 4;col++;if(col == resolution.width){row++;col = 0;}}return imageTem;}/*** 字节数组转float*/public static float bytes2Float(byte[] bytes) {int accum = 0;accum = accum | ( bytes[0] & 0xFF);accum = accum | ( bytes[1] & 0xFF) << 8;accum = accum | ( bytes[2] & 0xFF) << 16;accum = accum | ( bytes[3] & 0xFF) << 24;return Float.intBitsToFloat(accum);}public static void main(String[] args) {float[][] imageTem = null;try {imageTem = getImageTem("E:\\SDK\\dji_thermal_sdk_v1.6_20240927\\dataset\\H20T\\DJI_0001_R.JPG");} catch (IOException e) {throw new RuntimeException(e);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/856861.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4-14文件上传刷题日记

buuctf[是兄弟就来传马 先传一个php木马页面报错,随便改一个后缀,看看是黑名单还是白名单过滤,这里php代码前加GIF89a绕过图片大小检查报错,接着试一下是不是MIME过滤 Content-Type: image/png 上传成功 /var/www/html/upload/743be915f2c6ab5de3600d87068cafd2/hack.jpg s…

24浮动案例练习-布局方案总结

一、浮动案例三 float的兼容性是大于flex布局的,然后flex大于grid布局 一般的公司都不实用浮动了,大公司一般会使用浮动 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" co…

《计算机组成及汇编语言原理》阅读笔记:p28-p47

《计算机组成及汇编语言原理》学习第 3 天,p28-p47 总结,总计 20 页。 一、技术总结 1.Virtual Machine 2.stack 3.The fetch-execute Cycle 在控制单元(Control Unit, CU)里面有一个指令寄存器(Instruction Register, IR)和一个程序计数器(Program Counter, PC)。PC保存下次…

20241313 刘鸣宇 《计算机基础与程序设计》第13周学习总结

作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标 <写上具体方面>作业正文 ... 本博客链接教材学习内容总结 《C语言程序…

中考阅读理解深入逻辑分析-002 Battle of the Classroom: Bits vs. Books 课堂之战:比特对抗书本

文章正文 The debate on “textbooks vs computers” has been going on for years. How much technology is in the classroom? Should textbooks be placed by notebook computers? The is no doubt that computers are powerful. Computer-based lesson plans are updated…

基于HarmonyOS 5.0 (Next)技术的渐变模糊效果技术实现【代码实战】

基于HarmonyOS 5.0 (Next)技术的渐变模糊效果技术实现【代码实战】 HarmonyOS 5.0(Next)作为华为自主研发的操作系统,以其强大的性能和丰富的开发功能吸引了众多开发者。本文将详细介绍如何在HarmonyOS 5.0(Next)中实现渐变模糊效果,并通过代码实战展示具体操作步骤。Ark…

渗透测试-前后端加密分析之RSA+AES

本文是高级前端加解密与验签实战的第8篇文章,本系列文章实验靶场为Yakit里自带的Vulinbox靶场,本文讲述的是绕过RSA与AES加密来爆破登录。本文是高级前端加解密与验签实战的第8篇文章,本系列文章实验靶场为Yakit里自带的Vulinbox靶场,本文讲述的是绕过RSA与AES加密来爆破登…

MCGSPRO密码输入访问页面

MCGSPRO密码输入访问页面

jquery响应式弹出层lightbox插件slick-lightbox.js

slick-lightbox.js是一款基于slick.js和jquery的响应式弹出层lightbox插件。该jquery lightbox插件支持图片懒加载,支持键盘交互,支持HTML5 History API等。功能非常强大。在线预览 下载安装 可以通过bower来安装slick-lightbox.js插件。bower install -S slick-lightbox …

我用cursor, 半就开发了一个手机壁纸小程序,真的太强了

我用cursor, 半就开发了一个手机壁纸小程序,真的太强了。原来一周的工作量,半天搞定。体验可以微信搜索《程序员博博》同名。前言 我用chatGPT帮我写后端爬虫,分析知乎html代码,爬取知乎壁纸。然后用cursor AI工具,完全使我一个不懂前端uniapp框架的人,开发了一个小程序手…

投票:你愿意为了gxyz的图标捐献token吗?

投票:你愿意为了gxyz的图标捐献token吗?(点击选项进行投票): 愿意,请把token发给洛谷上的Leo2126 不愿意,但不愿意加入铁一 不愿意,要去铁一 蒟蒻的每一天

存储引擎整理

// 数据库的结构 // 连接层,服务层,引擎层,存储层 //创建表时,指定存储引擎 // create table name ( // ... // )engine = 存储引擎; // 查看当前数据库支持的存储引擎 // show engines; // ---------------------------------------------------------------------------…