This commit is contained in:
xin
2025-05-07 11:13:56 +08:00
parent fb037dbf6f
commit 94336c9ba1
23 changed files with 215 additions and 382 deletions

View File

@ -31,3 +31,13 @@ pub fn find_peek(data: Vec<f64>, minheigh: f64) -> Vec<(u32, f64)> {
pub fn compute_weave_coeff(x: Vec<f64>, y: Vec<f64>) -> Vec<f64> {
spectraltools::compute_weave_coeff(x, y)
}
pub fn polynomial_smooth_u32(y: &[u32], degree: usize) -> Vec<u32> {
smoothmethod::polynomial_smooth_u32(y, degree)
}
pub fn polynomial_smooth_u16(y: Vec<u16>, degree: usize) -> Vec<u16> {
smoothmethod::polynomial_smooth_u16(&y, degree)
}

View File

@ -6,7 +6,7 @@ use ndarray_ndimage::{gaussian_filter, BorderMode};
pub fn high_pass_gaussian_filter(input: Vec<f64>, sigma: f64) -> Vec<f64> {
// 将输入 Vec<f64> 转换为 Array1<f64>
let mut input_array = Array1::from_vec(input);
let input_array = Array1::from_vec(input);
// for i in 0..input_array.len(){
//
// input_array[i]=input_array[i]*input_array[i]/( 65535f64);
@ -16,7 +16,7 @@ pub fn high_pass_gaussian_filter(input: Vec<f64>, sigma: f64) -> Vec<f64> {
// 高斯低通滤波
let mut low_pass = gaussian_filter(&input_array, sigma, 0, BorderMode::Reflect, 3);
let low_pass = gaussian_filter(&input_array, sigma, 0, BorderMode::Reflect, 3);
// Modify the result: set values less than zero to zero
println!("{:?}",low_pass);
// 高通滤波:原始信号 - 低通滤波结果

View File

@ -1,4 +1,6 @@
extern crate savgol_rs;
use nalgebra::{DMatrix, DVector};
use std::convert::TryFrom;
use savgol_rs::savgol_filter;
pub fn savgol(data: Vec<f64>, window: usize, order: usize) -> Vec<f64> {
@ -7,7 +9,134 @@ pub fn savgol(data: Vec<f64>, window: usize, order: usize) -> Vec<f64> {
savgol_filter(&svinput).unwrap()
}
/// 多项式拟合函数 (f64版本)
///
/// 参数:
/// - x: x坐标序列
/// - y: y坐标序列
/// - degree: 多项式次数 (7或8)
///
/// 返回: 平滑后的y值序列
pub fn polynomial_fit_f64(x: &[f64], y: &[f64], degree: usize) -> Vec<f64> {
assert_eq!(x.len(), y.len(), "x和y的长度必须相同");
if x.len() < degree + 1 {
panic!("数据点数量必须大于多项式次数");
}
let n = x.len();
let y_vec = DVector::from_vec(y.to_vec());
// 构建范德蒙矩阵
let mut vandermonde = DMatrix::zeros(n, degree + 1);
for i in 0..n {
for j in 0..=degree {
vandermonde[(i, j)] = x[i].powi(j as i32);
}
}
// 解最小二乘问题 - 新版本nalgebra的调用方式
let svd = vandermonde.svd(true, true);
let coefficients = svd.solve(&y_vec, f64::EPSILON).unwrap();
// 计算拟合值
let fitted_y: Vec<f64> = x
.iter()
.map(|&xi| {
(0..=degree).fold(0.0, |acc, j| acc + coefficients[j] * xi.powi(j as i32))
})
.collect();
fitted_y
}
/// 多项式拟合函数 (u32版本)
///
/// 参数:
/// - x: x坐标序列
/// - y: y坐标序列
/// - degree: 多项式次数 (7或8)
///
/// 返回: 平滑后的y值序列
pub fn polynomial_fit_u32(x: &[u32], y: &[u32], degree: usize) -> Vec<u32> {
// 转换为f64处理
let x_f64: Vec<f64> = x.iter().map(|&xi| xi as f64).collect();
let y_f64: Vec<f64> = y.iter().map(|&yi| yi as f64).collect();
let fitted_f64 = polynomial_fit_f64(&x_f64, &y_f64, degree);
// 转换回u32处理可能的负值(截断为0)和溢出
fitted_f64
.into_iter()
.map(|y| {
if y < 0.0 {
0
} else {
u32::try_from(y.round() as i64).unwrap_or(u32::MAX)
}
})
.collect()
}
/// 简化版当x是等间距时的平滑函数 (u32版本)
pub fn polynomial_smooth_u32(y: &[u32], degree: usize) -> Vec<u32> {
let x: Vec<u32> = (0..y.len() as u32).collect();
polynomial_fit_u32(&x, y, degree)
}
/// 多项式拟合函数 (u16版本)
pub fn polynomial_fit_u16(x: &[u16], y: &[u16], degree: usize) -> Vec<u16> {
let x_f64: Vec<f64> = x.iter().map(|&xi| xi as f64).collect();
let y_f64: Vec<f64> = y.iter().map(|&yi| yi as f64).collect();
let fitted_f64 = polynomial_fit_f64(&x_f64, &y_f64, degree);
fitted_f64
.into_iter()
.map(|y| {
if y < 0.0 {
0
} else if y > u16::MAX as f64 {
u16::MAX
} else {
y.round() as u16
}
})
.collect()
}
/// 简化版当x是等间距时的平滑函数 (u16版本)
pub fn polynomial_smooth_u16(y: &[u16], degree: usize) -> Vec<u16> {
let x: Vec<u16> = (0..y.len() as u16).collect();
polynomial_fit_u16(&x, y, degree)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_polynomial_fit() {
// 测试数据: 一个简单的二次函数加一些噪声
let x = vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
let y = vec![1.0, 3.0, 6.0, 10.0, 15.0, 24.0, 35.0, 50.0, 65.0, 82.0];
// 2次多项式拟合应该能很好拟合
let fitted = polynomial_fit_f64(&x, &y, 2);
assert_eq!(fitted.len(), y.len());
// 检查拟合结果是否接近原始数据
for (original, fitted) in y.iter().zip(fitted.iter()) {
assert!((original - fitted).abs() < 5.0);
}
}
#[test]
fn test_polynomial_smooth() {
// 测试数据: 一个简单的上升序列加一些噪声
let y = vec![
10,12,11,13,12,14,13,15,14,16,
15,17,16,18,17,19,18,20,19,21,
];
// 7次多项式平滑
let smoothed_7 = polynomial_smooth_u32(&y, 7);
print!("smoothed_7: {:?}", smoothed_7);
assert_eq!(smoothed_7.len(), y.len());
// 8次多项式平滑
let smoothed_8 = polynomial_smooth_u32(&y, 8);
assert_eq!(smoothed_8.len(), y.len());
}
}
#[test]
fn test_savgol() {
// 示例数据

View File

@ -39,7 +39,7 @@ pub fn interpolate_spline<T: Copy + Into<f64>,>(x_t: Vec<T>, y_t: Vec<T>, step:
Ok(result)
}
pub fn interpolate_spline_at_points<T: Copy + Into<f64>>(x_t: Vec<T>, y_t: Vec<T>, x_target: Vec<f64>) -> Result<Vec<(f64)>, Box<dyn Error>> {
pub fn interpolate_spline_at_points<T: Copy + Into<f64>>(x_t: Vec<T>, y_t: Vec<T>, x_target: Vec<f64>) -> Result<Vec<f64>, Box<dyn Error>> {
let x: Vec<f64> = x_t.iter().map(|&x| x.into()).collect();
let y: Vec<f64> = y_t.iter().map(|&y| y.into()).collect();
@ -138,7 +138,7 @@ pub fn compute_weave_coeff(x_data:Vec<f64>,y_data:Vec<f64>)->Vec<f64>{
// 构建设计矩阵 X 和观测向量 y
let mut x_matrix = DMatrix::zeros(n, 4); // 三阶多项式有 4 个系数
let mut y_vector = DVector::from_vec(y_data.clone());
let y_vector = DVector::from_vec(y_data.clone());
for (i, &x) in x_data.iter().enumerate() {
x_matrix[(i, 0)] = 1.0; // 常数项

View File

@ -1,6 +1,5 @@
use super::serport::serport::*;
use super::mylog::*;
#[tauri::command]

View File

@ -1,9 +1,7 @@
use super::mydefine::*;
pub mod spectralserver;
pub mod spectralbase;
use std::fmt::format;
use std::fs;
use std::fs::File;
use super::mylog::*;
use serde_json::json;
use spectralserver::calibrate_file;

View File

@ -1,5 +1,4 @@
use libc::{c_uchar,c_char,c_long,c_float, size_t};
use std::ffi::CStr;
use libc::{c_uchar, size_t};
use std::slice;
use crate::serport::serport::*;

View File

@ -1,5 +1,4 @@
use libc::{c_uchar,c_char,c_long,c_float, size_t};
use std::ffi::CStr;
use libc::{c_uchar, size_t};
use std::slice;
use crate::serport::serport::*;

View File

@ -7,7 +7,6 @@ use std::{
};
mod IS3_sensor;
mod IS11_sensor;
// 定义emun 不同光谱仪
#[derive(Copy, Clone)]
pub enum Senortype {
@ -204,11 +203,12 @@ pub fn sensor_get_data(shuttertime: i32) -> Vec<u16> {
unsafe {
let len = sensor_get_data_base(outdata.as_mut_ptr(), shuttertime);
outdata.truncate(len as usize);
outdata.truncate(len as usize);
}
// polynomial_smooth_u16( outdata ,7)
outdata
}

View File

@ -2,16 +2,12 @@ use super::spectralbase;
use super::spectralbase::*;
use super::super::mydefine::*;
use lazy_static::lazy_static;
use chrono::{self, format, Datelike, Timelike};
use serde::de;
use tauri::http::header::UPGRADE;
use chrono::{self, Datelike, Timelike};
use std::thread;
use std::fs;
use std::fs::File;
use std::mem;
use std::path::Path;
use std::io::Read;
use super::super::algorithm::*;
#[derive(PartialEq)]
enum WorkStat {
IDLE,
@ -132,7 +128,7 @@ pub fn opt_sensor(percent: i32) -> i32 {
pub fn get_now_stat()->(String,String,i32){
let mut dev_stat=DEV_STAT.lock().unwrap();
let dev_stat=DEV_STAT.lock().unwrap();
match dev_stat.stat {
WorkStat::IDLE => {
return ("finish".to_string(),dev_stat.workname.clone(),100);
@ -415,12 +411,12 @@ pub fn calibrate_file(orgdata: &IS11DataStruct) -> IS11DataStruct {
let cali_gaindb = calidata.temprature[0];
let cali_shutter = calidata.shutter_time;
//db 转系数
let mut collect_gain = 10.0_f32.powf(collect_gaindb / 20.0);
let mut cali_gain = 10.0_f32.powf(cali_gaindb / 20.0);
let collect_gain = 10.0_f32.powf(collect_gaindb / 20.0);
let cali_gain = 10.0_f32.powf(cali_gaindb / 20.0);
//计算增益
let mut Scale_gain = cali_gain / collect_gain;
let mut Scale_shutter = cali_shutter as f32/ collect_shutter as f32;
let mut SCale = Scale_gain * Scale_shutter as f32;
let Scale_gain = cali_gain / collect_gain;
let Scale_shutter = cali_shutter as f32/ collect_shutter as f32;
let SCale = Scale_gain * Scale_shutter as f32;
let len = orgdata.data.len();
for i in 0..len {
data.data[i] = orgdata.data[i] * SCale * calidata.data[i]+offsetdata.data[i];

View File

@ -2,16 +2,12 @@
use core::str;
use std::fs;
use std::fs::File;
use std::io::{self, Read, Write};
use std::io::{Write};
// use std::sync::WaitTimeoutResult;
use std::path::Path;
use super::algorithm::interpolate_spline;
use super::algorithm::sg_smooth;
use std::mem;
use super::mylog::*;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use super::serport::serport::*;
use super::mydefine::*;
@ -335,8 +331,8 @@ if command == "\"get_data\"" {
if datatype == 0x02 {
let mut is11data = IS11DataStruct::default();
unsafe {
let mut is11data_ptr = &mut is11data as *mut IS11DataStruct;
let mut ret_ptr = &mut ret[0] as *mut u8;
let is11data_ptr = &mut is11data as *mut IS11DataStruct;
let ret_ptr = &mut ret[0] as *mut u8;
std::ptr::copy_nonoverlapping(
ret_ptr,
is11data_ptr as *mut u8,

View File

@ -21,9 +21,7 @@ enum DevName {
}
use lazy_static::lazy_static;
use tauri::api::version;
use std::sync::Mutex;
use std::sync::Arc;
//设置一个可修改的全局变量
lazy_static! {
static ref DEVNAME: Mutex<DevName> = Mutex::new(DevName::IRIS_SENSOR(Senortype::IS3));

View File

@ -1,12 +1,11 @@
use tklog::{
debugs, errors, fatals, infos,
sync::Logger,LEVEL, LOG,
traces, warns, Format, MODE,async_traces,
infos,
sync::Logger, Format, MODE,
};
use lazy_static::lazy_static;
use std::{
// fmt::format,
borrow::{ BorrowMut}, sync::{Arc, Mutex}, thread::sleep
borrow::{ BorrowMut}, sync::{Arc, Mutex}
};
struct LOGERME{
@ -31,11 +30,11 @@ lazy_static! {
pub fn change_log_path(path: &str,string: &str) {
if string=="RUST"{
let mut loggerglobel = LOGERGLOBLE.lock().unwrap();
let loggerglobel = LOGERGLOBLE.lock().unwrap();
let mut log=loggerglobel.logger_rust.lock().unwrap();
log.set_cutmode_by_time(path, MODE::DAY, 10, false);
}else if string=="JS"{
let mut loggerglobel=LOGERGLOBLE.lock().unwrap();
let loggerglobel=LOGERGLOBLE.lock().unwrap();
let mut log=loggerglobel.logger_js.lock().unwrap();
log.set_cutmode_by_time(path, MODE::DAY, 10, false);
}
@ -44,7 +43,7 @@ pub fn change_log_path(path: &str,string: &str) {
pub fn initlog() {
//let mut logger = LOGERGloble.lock().unwrap().LOGGER_RUST;
let mut loggerglobel = LOGERGLOBLE.lock().unwrap();
let loggerglobel = LOGERGLOBLE.lock().unwrap();
let mut log=loggerglobel.logger_rust.lock().unwrap();
log.set_console(true).set_format(Format::Date|Format::Time).set_formatter("{time} {file}{level}:{message}\n")
.set_cutmode_by_time("rust_log.log",MODE::DAY, 10, false);
@ -59,7 +58,7 @@ pub fn initlog() {
pub fn logtorust<T>(str:T)
where T: std::fmt::Display
{
let mut loggerglobe=LOGERGLOBLE.lock().unwrap();
let loggerglobe=LOGERGLOBLE.lock().unwrap();
let mut log=Arc::clone(&loggerglobe.logger_rust);
let log1 = log.borrow_mut();
@ -69,7 +68,7 @@ where T: std::fmt::Display
pub fn logtojs<T>(str:T)
where T: std::fmt::Display
{
let mut loggerglobe=LOGERGLOBLE.lock().unwrap();
let loggerglobe=LOGERGLOBLE.lock().unwrap();
let mut log=Arc::clone(&loggerglobe.logger_js);
let log1 = log.borrow_mut();

View File

@ -131,7 +131,7 @@ pub fn clearserilport() -> String{
match &mut port_info.port {
Some(p) => {
p.set_timeout(Duration::from_millis(100)).unwrap();
while true{
loop{
let sizeread =match p.read(&mut buf){
Ok(size)=>{size},
Err(_e)=>{return "Port is not open".to_string()}