Labview程序图像与移动端显示
引言:大家使用Labview进行图像处理绘图时候,不免会想更进一步,移植到移动端显示,无论是做科研,还是打比赛都有一定的帮助,下面将为大家阐述具体步骤。
一、Labview端处理
Labview是一款图形化编辑语言,目前科研上使用较多,因为其较为简单的操作手段,所以深受科研人员喜爱,不仅图像处理方便,还很容易进行一些硬件测试连接。本篇着重讲解Labview图像绘制以及如何实现交互效果。
1.通讯方式
本次实例以实际项目中为例,使用Labview接收Stm32数据,这里方便演示采用串口方式。
2.数据处理(重点)
本次测试中,单片机的传输数据为:xxx,xxx,xxx…xxx,每行会发送25个数据,所以咱们只需要每次读取25个数据出来,再进行操作即可,这里由于涉及到持续读取操作,所以将数据处理放在While循环中。
数据处理我这里采用,每次把一行数据全部读完之后再进行操作,这里仅仅展示了5个数据的处理(也就是一行数据),这样子就提取出来了数据点。
提取出来数据点之后,可以根据自己的需要进行调试,这里我只展示了一个点的像素点绘制效果,分别设有三个颜色,对应不同压力情况下的颜色变化。
最后汇总到一个面板中,就可以实现Labview端的图像绘制效果。前面板展示图:
3.图像移植
想实现电脑端和移动端交互,这里有多种方式:其中企业上使用的一定是将数据传送到服务器中,然后移动端读取服务器数据,达到完美显示效果。如果使用服务器,这里Labview端可以采用Http通讯方式,完成需求。这里为了方便演示,我采用第二种方式,仅仅使用本地即可完成需求。
实现思路:将Labview端图像存储到电脑本地PNG(或JPG)文件中,然后还需要一个服务器端,不断读取这个文件里面的图像,将图片数据存储到本地数据库中,最后移动端读取数据库信息即可实现效果,不过存在500ms左右的延迟。
可能会有初学者感到疑惑,为什么不直接让移动端读取本地文件,非要借助数据库。这里我解释一下,我尝试之后,发现移动端并不能直接本地磁盘文件,我使用的是Android Studio,通过查询资料也发现微信小程序好像也不可以,必须要把图像先保存到项目路径下,才可以访问,这样操作肯定是不行的,因为我们本地文件中的图像是一直在随着Labview程序的跑动而改变的。
4.服务器端代码
既然需要服务器不断读取本地文件,并将图像转化成二进制存入到数据库中,这就涉及到IO处理,这里我采用Java语言进行该操作,只需要简单使用JDBC就可以完成该需求,后续如果想做完善的项目,可以使用Mybatis框架进行处理。本篇博客只是提供一种思路和解决方式,所以代码写的比较随意,以实现需求为主,请大家理性看待。
package ck.preparedStatement;
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author ck
* 演示使用
*/
public class PrepareStatement {
public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {
Class.forName("com.mysql.cj.jdbc.Driver");
//创建url,user,password
String url = "jdbc:mysql://localhost:3306/picture";
String user = "root";
String password = "970125";
Connection connection = DriverManager.getConnection(url, user, password);
final FileInputStream[] fis = {null};
final PreparedStatement[] ps = {null};
Timer timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run() {
try {
fis[0] = new FileInputStream(new File("D:\\Desktop\\png\\2.png"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String sql = "insert into photo (data) values (?)";
try {
ps[0] = connection.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
try {
ps[0].setBinaryStream(1, fis[0], fis[0].available());
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
int i = 0;
try {
i = ps[0].executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
if (i > 0){
System.out.println("执行成功");
}else{
System.out.println("失败");
}
}
},0,500);
ps[0].close();
fis[0].close();
connection.close();
}
}
而在数据库表的设计也是十分简单。data字段采用bomb格式存储。我这里也是为了方便测试为主,选择的是直接讲二进制存入到数据库中,这种方式对于小内存的图像处理是没问题的,但是大内存的话还是会存在问题的。
5.移动端代码
移动端由于要读取数据库,所以也是需要对数据库进行索引,选用Android Studio也是为了方便,跟Java有着99%的相似度。不过多阐述。
package com.ck.picture;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class MainActivity extends AppCompatActivity {
private static final String DB_URL = "jdbc:mysql://192.168.75.76:3306/picture";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "970125";
private ImageView imageView;
private int currentImageId = 3586; // Start with the first image ID
private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = findViewById(R.id.myImageView);
// Schedule the task to load images periodically
scheduledExecutorService.scheduleAtFixedRate(new LoadImageTask(), 0, 400, TimeUnit.MILLISECONDS);
}
private class LoadImageTask implements Runnable {
@Override
public void run() {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(DB_URL,DB_USER,DB_PASSWORD);
String query = "SELECT data FROM photo WHERE id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setInt(1, currentImageId);
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
byte[] imageBytes = resultSet.getBytes("data");
final Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
// Update UI on the main thread
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
currentImageId++; // Move to the next image
}
resultSet.close();
preparedStatement.close();
connection.close();
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// Stop the scheduled task when the activity is destroyed
scheduledExecutorService.shutdown();
}
}