classdef Touch_Filter < handle
properties
% 滤波器对象
Mid_ComboFilter
High_ComboFilter_LimLpf
Low_ComboFilter_LimLpf
% 原始数据相关
raw_data
raw_data_path
len
% 可调节参数
Mid_alpha_double
High_alpha_double
Low_alpha_double
limit_up
limit_down
Avgwindow
K
% 结果保存
MidFilter_Dara
HighFilter_Dara
LowFilter_Dara
ResultDta
% 文件保存路径
Result_File_Path
% 绘图相关
FigMonitor
Line0
Line1
Line2
Line3
end
methods
function obj = Touch_Filter(filename , sheet , column , varargin)
% 构造函数
% 获得原始数据
obj.raw_data = My_readExcelColumn(filename , sheet , column , varargin);
obj.raw_data = cell2mat(cellfun(@double, obj.raw_data, 'UniformOutput', false));
% 转换为 int16 类型
obj.raw_data = int16(obj.raw_data);
% 获得元胞数组长度
obj.len = length(raw_data);
% 可调节参数
obj.Mid_alpha_double = 0.6;
obj.High_alpha_double = 0.25;
obj.Low_alpha_double = 0.55;
obj.limit_up = 75;
obj.limit_down = 50;
obj.Avgwindow = 12;
obj.K = 1 + 1/4;
% 初始化滤波器
obj = obj.initializeFilters();
end
function obj = setParameters(obj, Mid_alpha, High_alpha, Low_alpha, up, down, avgwin, k , Path)
% 设置自定义参数
obj.Mid_alpha_double = Mid_alpha;
obj.High_alpha_double = High_alpha;
obj.Low_alpha_double = Low_alpha;
obj.limit_up = up;
obj.limit_down = down;
obj.Avgwindow = avgwin;
obj.K = k;
obj.Result_File_Path = Path;
% 重新初始化滤波器
obj = obj.initializeFilters();
end
function obj = initializeFilters(obj)
% 初始化滤波器对象
Mid_alpha2 = int16(32767 * obj.Mid_alpha_double);
High_alpha2 = int16(32767 * obj.High_alpha_double);
Low_alpha2 = int16(32767 * obj.Low_alpha_double);
High_up_limit2 = int16(obj.limit_up * obj.Mid_alpha_double);
High_down_limit2 = int16(obj.limit_down * obj.Mid_alpha_double);
Low_up_limit2 = int16(obj.limit_up * obj.Mid_alpha_double);
Low_down_limit2 = int16(obj.limit_down * obj.Mid_alpha_double);
obj.Mid_ComboFilter = ComboFilter(obj.limit_up, obj.limit_down, obj.Avgwindow, Mid_alpha2);
obj.High_ComboFilter_LimLpf = ComboFilter_limit_lpf(High_up_limit2, High_down_limit2, High_alpha2);
obj.Low_ComboFilter_LimLpf = ComboFilter_limit_lpf(Low_up_limit2, Low_down_limit2, Low_alpha2);
end
function obj = setupPlot(obj)
% 设置实时绘图窗口
obj.FigMonitor = figure('Name', '实时滤波过程监控', 'Position', [100, 100, 1200, 800]);
% 工具栏设置
toolbar = uitoolbar(obj.FigMonitor);
uipushtool(toolbar, 'TooltipString', '放大', 'ClickedCallback', 'zoom(gcf, ''on'')');
uipushtool(toolbar, 'TooltipString', '缩小', 'ClickedCallback', 'zoom(gcf, ''out'')');
uipushtool(toolbar, 'TooltipString', '平移', 'ClickedCallback', 'pan(gcf, ''on'')');
uipushtool(toolbar, 'TooltipString', '重置视图', 'ClickedCallback', 'resetplotview(gcf, ''InitializeCurrentView'')');
% 子图初始化
subplot(5,1,1);
title('原始数据');
hold on;
plot(obj.raw_data, 'b-', 'LineWidth', 1.5);
h0 = subplot(5,1,2);
title('中值滤波结果');
hold on;
obj.Line0 = plot(NaN, NaN, 'b-', 'LineWidth', 1.5);
h1 = subplot(5,1,3);
title('强滤波结果');
hold on;
obj.Line1 = plot(NaN, NaN, 'b-', 'LineWidth', 1.5);
h2 = subplot(5,1,4);
title('弱滤波结果');
hold on;
obj.Line2 = plot(NaN, NaN, 'b-', 'LineWidth', 1.5);
h3 = subplot(5,1,5);
title('最终结果');
hold on;
obj.Line3 = plot(NaN, NaN, 'b-', 'LineWidth', 1.5);
% 设置缩放功能
set([h0, h1, h2, h3], 'XLimMode', 'auto', 'YLimMode', 'auto');
end
function Process(obj)
obj.MidFilter_Dara = zeros(1,obj.len,"int16");
obj.HighFilter_Dara = zeros(1,obj.len,"int16");
obj.LowFilter_Dara = zeros(1,obj.len,"int16");
% 数据处理循环
for i = 1:obj.len
MID2 = obj.Mid_ComboFilter.update(int16(obj.raw_data(i)));
obj.MidFilter_Dara(i) = MID2;
obj.HighFilter_Dara(i) = obj.High_ComboFilter_LimLpf.update(MID2);
obj.LowFilter_Dara(i) = obj.Low_ComboFilter_LimLpf.update(MID2);
obj.ResultDta(i) = int16(obj.K * (double(obj.HighFilter_Dara(i)) - double(obj.LowFilter_Dara(i))));
% 实时更新图形
if mod(i, 50) == 0 || i == obj.len
set(obj.Line0, 'XData', 1:i, 'YData', obj.MidFilter_Dara(1:i));
set(obj.Line1, 'XData', 1:i, 'YData', obj.HighFilter_Dara(1:i));
set(obj.Line2, 'XData', 1:i, 'YData', obj.LowFilter_Dara(1:i));
set(obj.Line3, 'XData', 1:i, 'YData', obj.ResultDta(1:i));
title(subplot(5,1,2), ['中值滤波 (当前点: ' num2str(i) ')']);
title(subplot(5,1,3), ['强滤波 (当前点: ' num2str(i) ')']);
title(subplot(5,1,4), ['弱滤波 (当前点: ' num2str(i) ')']);
title(subplot(5,1,5), ['最终结果 (当前点: ' num2str(i) ')']);
drawnow;
end
end
% 保存结果
obj.saveResults();
end
function saveResults(obj)
% 保存结果到CSV
raw_data_col = row2col(obj.raw_data);
Mid_data_col = row2col(obj.MidFilter_Dara);
High_data_col = row2col(obj.HighFilter_Dara);
Low_data_col = row2col(obj.LowFilter_Dara);
result_col = row2col(obj.ResultDta);
writeColumnToCSV(obj.Result_File_Path, raw_data_col, 1);
writeColumnToCSV(obj.Result_File_Path, Mid_data_col, 2);
writeColumnToCSV(obj.Result_File_Path, High_data_col, 3);
writeColumnToCSV(obj.Result_File_Path, Low_data_col, 4);
writeColumnToCSV(obj.Result_File_Path, result_col, 5);
end
end
end
myFilter = Touch_Filter("动态3v 2" , "动态3v 2" ,"I0");
错误使用 My_readExcelColumn (第 38 行)
需要字符串标量或字符向量形式的参数名称。
出错 Touch_Filter (第 45 行)
obj.raw_data = My_readExcelColumn(filename , sheet , column , varargin);
出错 TOUCH_Process (第 17 行)
myFilter = Touch_Filter("动态3v 2" , "动态3v 2" ,"I0");
%
% data1 = My_readExcelColumn('13MHz 110参考电容 定时时间6.5ms.xlsx', '13MHz 110参考电容 定时时间6.5ms', 'I3');
% data1 = cell2mat(data1);
% writeColumnToCSV('不同频点的组合数据1.csv', data1, 1);
%
% data2 = My_readExcelColumn('1MHz 215参考电容 定时时间6.5ms.xlsx', '1MHz 215参考电容 定时时间6.5ms', 'I3');
% data2 = cell2mat(data2);
% writeColumnToCSV('不同频点的组合数据1.csv', data2, 2);
%
% data3 = My_readExcelColumn('5MHz 130参考电容 定时时间6.5ms.xlsx', '5MHz 130参考电容 定时时间6.5ms', 'I3');
% data3 = cell2mat(data3);
% writeColumnToCSV('不同频点的组合数据1.csv', data3, 3);
%
% data4 = My_readExcelColumn('5MHz 130参考电容 定时时间6.5ms.xlsx', '5MHz 130参考电容 定时时间6.5ms', 'I4');
% data4 = cell2mat(data4);
% writeColumnToCSV('不同频点的组合数据1.csv', data4, 4);
function columnData = My_readExcelColumn(filename, sheet, column, varargin)
% READEXCELCOLUMN 读取Excel文件中指定sheet的指定列数据,并自动截断空白数据
% columnData = My_readExcelColumn(filename, sheet, column)
% columnData = My_readExcelColumn(..., 'HeaderLines', N) 跳过N行表头
% columnData = My_readExcelColumn(..., 'TrimBlanks', true) 自动截断空白数据(默认true)
%
% 输入参数:
% filename - Excel文件路径(字符串)
% sheet - sheet名称(字符串)或sheet索引(整数)
% column - 列标识(字符串如'A'、'down_1_1')或列索引(整数如1)
% 'HeaderLines' - 可选参数,跳过的表头行数(默认0)
% 'TrimBlanks' - 可选参数,是否截断空白数据(默认true)
%
% 输出参数:
% columnData - 包含指定列数据的元胞数组,空白数据已被截断
% 解析可选参数
p = inputParser;
addParameter(p, 'HeaderLines', 0, @isnumeric);
addParameter(p, 'TrimBlanks', true, @islogical);
parse(p, varargin{:});
headerLines = p.Results.HeaderLines;
trimBlanks = p.Results.TrimBlanks;
% 验证输入参数
if ~(ischar(filename) || isstring(filename))
error('文件名必须是字符串');
end
if ~(ischar(sheet) || isnumeric(sheet) || isstring(sheet))
error('sheet参数必须是字符串或整数');
end
if ~(ischar(column) || isnumeric(column) || isstring(column))
error('列标识必须是字符串或整数');
end
% 转换字符串输入
if isstring(filename), filename = char(filename); end
if isstring(sheet), sheet = char(sheet); end
if isstring(column), column = char(column); end
try
% 创建导入选项
opts = detectImportOptions(filename, 'Sheet', sheet);
% 统一将列标识转换为数字索引
if isnumeric(column)
colIndex = column;
else
% 尝试将列标识转换为索引
colIndex = find(strcmpi(opts.VariableNames, column));
% 如果找不到,尝试解析为列字母
if isempty(colIndex)
try
colIndex = colLetter2num(column);
catch
error('无法识别列标识: "%s"', column);
end
end
end
% 检查列索引是否有效
if isempty(colIndex) || colIndex < 1 || colIndex > numel(opts.VariableNames)
error('列索引 %d 超出范围(有效列数: %d)', colIndex, numel(opts.VariableNames));
end
% 获取实际列名
columnName = opts.VariableNames{colIndex};
% 设置列选择
opts.SelectedVariableNames = {columnName};
% 设置表头处理
if headerLines > 0
opts.VariableNamesRange = '';
opts.DataRange = headerLines + 1; % 跳过指定行数
end
% 读取数据
dataTable = readtable(filename, opts);
% 转换为元胞数组
columnData = table2cell(dataTable);
% 自动截断空白数据
if trimBlanks
columnData = trimBlankCells(columnData);
end
catch ME
error('读取Excel失败: %s', ME.message);
end
end
%% 辅助函数:将列字母转换为数字索引
function colNum = colLetter2num(colLetters)
colLetters = upper(colLetters);
colNum = 0;
for i = 1:length(colLetters)
charCode = colLetters(i);
if charCode < 'A' || charCode > 'Z'
error('无效的列字母: %s', colLetters);
end
colNum = colNum * 26 + (charCode - 'A' + 1);
end
end
%% 辅助函数:截断空白单元格
function trimmedData = trimBlankCells(cellData)
% 查找第一个非空单元格的位置
startIndex = 1;
while startIndex <= numel(cellData) && isCellEmpty(cellData{startIndex})
startIndex = startIndex + 1;
end
% 查找最后一个非空单元格的位置
endIndex = numel(cellData);
while endIndex >= 1 && isCellEmpty(cellData{endIndex})
endIndex = endIndex - 1;
end
% 如果所有单元格都为空,返回空数组
if startIndex > endIndex
trimmedData = {};
return;
end
% 截取非空数据部分
trimmedData = cellData(startIndex:endIndex);
end
%% 辅助函数:判断单元格是否为空
function isEmpty = isCellEmpty(cellContent)
% 处理不同类型的数据
if ismissing(cellContent) || isempty(cellContent) || ...
(ischar(cellContent) && all(isspace(cellContent))) || ...
(isstring(cellContent) && (ismissing(cellContent) || strlength(cellContent) == 0))
isEmpty = true;
elseif isnumeric(cellContent) && isnan(cellContent)
isEmpty = true;
else
isEmpty = false;
end
end
最新发布