处理文件 208a.bmp 时出错: 无法执行赋值,因为左侧的大小为 1×100,右侧的大小为 1×199。根据报错信息修改代码
时间: 2025-07-22 13:32:53 浏览: 3
<think>我们遇到了一个错误:在提取行特征时,期望输出100维特征,但实际输出了199维(100维原始特征+99维差分特征)。我们需要调整特征提取函数,使其输出固定维度的特征(例如100维),或者调整后续代码以适应这个特征维度。
但是,根据之前的代码,我们设计的是100维原始特征+99维差分特征,总共199维。而在初始化特征矩阵时,我们使用:
features = zeros(size(pairs,1), 100);
这显然会出错,因为100列无法容纳199维特征。
解决方案有两种:
1. 修改特征提取函数,使其只返回100维特征(例如只使用原始投影特征,或者将原始特征和差分特征合并后降维到100维)。
2. 修改初始化代码,将特征矩阵初始化为199列。
考虑到我们之前设计使用199维特征,这里我们选择方案2:将特征矩阵初始化为199列。
同时,我们还需要注意,在特征提取函数中,对于非常短的图像(高度小于100),我们使用imresize将其归一化为100维,然后计算差分特征(99维)。因此,总特征维度为199。
修改步骤:
1. 在初始化特征矩阵时,将列数改为199。
2. 在分类函数中,确保能够处理199维特征。
另外,我们还需要注意,在特征提取函数中,如果图像高度为1,则差分特征无法计算(会得到99个0)。这种情况应该很少,但为了安全,我们保留这样的处理。
修改后的代码:
在“提取行特征”部分:
features = zeros(size(pairs,1), 199); % 修改为199维
同时,在特征提取函数中,我们保持不变。
此外,我们还需要检查分类函数(classify_rows)是否能处理199维特征。由于我们使用了PCA降维,所以可以处理任意维度的特征,只要样本数足够。
因此,我们主要修改两处:
1. 初始化特征矩阵为199列
2. 在特征提取函数中,确保返回199维特征(已经如此)
但是,在特征提取函数中,我们可能会遇到返回特征维度不足199的情况(例如,当图像高度小于100时,原始特征部分为100维,差分特征部分为99维,总共199维;当图像高度大于100时,我们取前100行,差分取前99行,所以也是199维)。所以特征提取函数返回的始终是199维。
因此,我们只需要修改初始化特征矩阵的列数。
另外,在错误信息中提到的文件是'208a.bmp',这个文件名可能不包含数字ID,导致在配对时出现问题?但根据错误信息,是特征维度不匹配,所以我们先解决特征维度问题。
修改后的代码段:
原代码:
features = zeros(size(pairs,1), 100); % 100维特征
修改为:
features = zeros(size(pairs,1), 199); % 199维特征
同时,我们还需要注意在特征提取函数中,如果图像高度不足100,我们使用imresize将其调整到100,所以原始特征部分总是100维,差分部分总是99维,总共199维。
另外,在分类函数中,我们使用PCA降维,所以可以处理199维特征。
但是,我们也要检查文件'208a.bmp'是否被正确读取和处理。在预处理和特征提取函数中,我们使用了try-catch,如果出错会填充零特征。现在错误发生在赋值时,是因为返回的特征向量长度(199)与预分配的长度(100)不一致。所以修改预分配长度即可。
此外,我们还需要确保在配对时,文件名包含数字ID。对于'208a.bmp',我们提取数字ID为208。所以它应该能够被正确配对。
因此,我们修改代码:
在特征提取前的预分配改为199列。
同时,为了确保代码健壮性,我们还可以在特征提取函数的最后添加一个检查,确保输出特征为199维:
if length(features) ~= 199
features = zeros(1,199); % 如果维度不对,则用0填充
end
但通常不会出现这种情况,所以可以不加,但为了安全,可以加上。
修改后的特征提取函数:
```matlab
function features = extract_row_features(bw_img)
% ... 前面代码不变 ...
% 最后确保特征维度为199
if length(features) ~= 199
features = zeros(1,199);
end
end
```
但是,我们更希望知道为什么会出现维度不对的情况,所以我们可以添加一个错误消息:
```matlab
function features = extract_row_features(bw_img)
% ... 前面代码不变 ...
% 最后确保特征维度为199
if length(features) ~= 199
warning('特征维度异常:%d,重置为199维', length(features));
features = zeros(1,199);
end
end
```
现在,我们修改整个代码,包括预分配和特征提取函数中的维度检查。
另外,在分类函数中,我们使用k-means,它对于特征维度没有特殊要求(只要样本数大于类别数),所以199维是可以的。
修改后的代码(仅修改部分)如下:
在特征提取部分:
features = zeros(size(pairs,1), 199); % 199维特征
在特征提取函数最后添加维度检查。
同时,我们还需要注意,在并行循环中,每个特征向量必须是行向量,且长度为199。
下面给出修改后的完整代码(只修改了相关部分,其他部分不变):</think>我理解问题了,错误发生在特征维度不匹配上。左侧分配的是100维特征,但右侧提取了199维特征。让我们修复这个问题并提供完整的解决方案:
```matlab
function dual_side_fragment_classification()
% 初始化
clc; clear; close all; warning off;
% 选择文件夹
folder_path = uigetdir('', '选择包含双面碎片的文件夹(附件5)');
if folder_path == 0
error('用户取消选择');
end
%% 1. 加载并配对碎片文件
[pairs, unmatched] = load_and_pair_fragments(folder_path);
fprintf('已加载 %d 对有效碎片,%d 个未匹配碎片\n', size(pairs,1), length(unmatched));
%% 2. 提取行特征 - 修复维度问题
if ~isempty(pairs)
% 使用动态维度分配
features = zeros(size(pairs,1), 199); % 改为199维特征
parfor i = 1:size(pairs,1)
try
img = preprocess_image(fullfile(folder_path, pairs{i,1}));
features(i,:) = extract_row_features(img);
catch ME
fprintf('处理文件 %s 时出错: %s\n', pairs{i,1}, ME.message);
features(i,:) = zeros(1,199); % 使用零值填充
end
end
else
features = [];
row_labels = [];
end
%% 3. 行分类(22行)
if ~isempty(features)
try
row_labels = classify_rows(features, 14);
catch ME
fprintf('分类出错: %s\n', ME.message);
% 使用简单分组作为后备方案
row_labels = mod(1:size(pairs,1), 22) + 1;
end
else
row_labels = [];
end
%% 4. 生成分类结果表
create_result_table(folder_path, pairs, row_labels, unmatched);
fprintf('分类完成!结果已保存到:%s\n', fullfile(folder_path, 'classification_results.xlsx'));
end
%% 文件加载与配对函数(安全版本)
function [pairs, unmatched] = load_and_pair_fragments(folder)
% 获取所有图像文件(支持多种格式)
extensions = {'.bmp', '.BMP', '.png', '.PNG', '.jpg', '.JPG'};
file_list = [];
for i = 1:length(extensions)
file_list = [file_list; dir(fullfile(folder, ['*' extensions{i}]))];
end
if isempty(file_list)
error('未找到任何图像文件');
end
% 提取所有数字ID
file_ids = zeros(length(file_list), 1);
file_names = cell(length(file_list), 1);
for i = 1:length(file_list)
[~, name, ext] = fileparts(file_list(i).name);
full_name = [name ext];
file_names{i} = full_name;
% 提取文件名中的数字部分
num_str = regexp(name, '\d+', 'match');
if isempty(num_str)
file_ids(i) = NaN;
else
% 取最长的数字串
[~, idx] = max(cellfun(@length, num_str));
file_ids(i) = str2double(num_str{idx});
end
end
% 找出所有唯一ID
unique_ids = unique(file_ids);
unique_ids = unique_ids(~isnan(unique_ids));
% 配对文件(每个ID对应两个文件)
pairs = cell(0,2);
unmatched = cell(0,1);
for id = unique_ids'
idx = find(file_ids == id);
if length(idx) >= 2
% 使用前两个文件(确保有足够的文件)
pairs(end+1, :) = file_names(idx(1:2));
% 处理多余的文件
if length(idx) > 2
for j = 3:length(idx)
unmatched{end+1} = file_names{idx(j)};
end
end
else
% 处理单个文件的情况
for j = 1:length(idx)
unmatched{end+1} = file_names{idx(j)};
end
end
end
% 按ID排序
if ~isempty(pairs)
pair_ids = zeros(size(pairs,1),1);
for i = 1:size(pairs,1)
num_str = regexp(pairs{i,1}, '\d+', 'match');
if ~isempty(num_str)
pair_ids(i) = str2double(num_str{1});
else
pair_ids(i) = i; % 后备方案
end
end
[~, sort_idx] = sort(pair_ids);
pairs = pairs(sort_idx, :);
end
% 处理未匹配文件
for i = 1:length(file_list)
if isnan(file_ids(i)) || ~any(file_ids(i) == unique_ids)
unmatched{end+1} = file_names{i};
end
end
end
%% 图像预处理(安全版本)
function img = preprocess_image(filepath)
img = imread(filepath);
if size(img, 3) == 3
img = rgb2gray(img);
end
% 自适应二值化
try
img = imbinarize(img, 'adaptive');
catch
% 后备方案:使用全局阈值
level = graythresh(img);
img = imbinarize(img, level);
end
% 移除小噪点
img = bwareaopen(img, 20);
end
%% 行特征提取(修复维度问题)
function features = extract_row_features(bw_img)
% 确保图像是二值图像
if ~islogical(bw_img)
bw_img = imbinarize(bw_img);
end
% 水平投影
h_proj = sum(~bw_img, 2);
% 归一化为100维
if length(h_proj) < 100
proj_feature = imresize(h_proj, [100, 1])';
else
proj_feature = h_proj(1:100)';
end
% 添加二阶特征
if length(h_proj) > 1
diff_feature = diff(h_proj);
if length(diff_feature) < 99
diff_feature = imresize(diff_feature, [99, 1])';
else
diff_feature = diff_feature(1:99)';
end
else
diff_feature = zeros(1, 99);
end
% 组合特征 - 确保总维度为199
features = [proj_feature, diff_feature];
% 确保特征维度正确
if length(features) ~= 199
% 动态调整维度
if length(features) < 199
features = [features, zeros(1, 199 - length(features))];
else
features = features(1:199);
end
end
end
%% 行分类函数(安全版本)
function labels = classify_rows(features, k)
% 确保有足够的数据点
if size(features, 1) < k
labels = ones(size(features, 1), 1);
return;
end
% 移除NaN值
features(any(isnan(features), 2), :) = 0;
% 使用PCA降维
try
[~, score] = pca(features);
n_components = min(10, size(score, 2));
catch
% PCA失败时使用原始特征
score = features;
n_components = min(10, size(features, 2));
end
% 使用k-means聚类(安全版本)
try
[labels, ~] = kmeans(score(:, 1:n_components), k, 'Replicates', 5);
catch ME
fprintf('k-means聚类失败: %s\n', ME.message);
% 使用简单分组作为后备方案
labels = mod(1:size(features,1), k) + 1;
end
end
%% 创建结果表格(安全版本)
function create_result_table(folder, pairs, row_labels, unmatched)
% 初始化22x19的cell数组
max_rows = 22;
max_cols = 19;
result_table1 = cell(max_rows, max_cols);
result_table2 = cell(max_rows, max_cols);
% 按行组织碎片
if ~isempty(row_labels) && ~isempty(pairs)
unique_rows = unique(row_labels);
for r = 1:min(length(unique_rows), max_rows)
row_num = unique_rows(r);
idx = find(row_labels == row_num);
% 按文件ID排序当前行的碎片
if ~isempty(idx)
ids = zeros(length(idx), 1);
for i = 1:length(idx)
if idx(i) <= size(pairs, 1)
file_name = pairs{idx(i),1};
num_str = regexp(file_name, '\d+', 'match');
if ~isempty(num_str)
ids(i) = str2double(num_str{1});
else
ids(i) = i; % 后备方案
end
else
ids(i) = i; % 索引越界处理
end
end
[~, sort_idx] = sort(ids);
row_pairs = pairs(idx(sort_idx), :);
% 填充到表格(最多max_cols列)
num_pairs = min(max_cols, size(row_pairs, 1));
for col = 1:num_pairs
% 碎片1(包含扩展名)
if col <= size(row_pairs, 1)
result_table1{r, col} = row_pairs{col, 1};
else
result_table1{r, col} = '';
end
% 碎片2
if col <= size(row_pairs, 1) && size(row_pairs, 2) >= 2
result_table2{r, col} = row_pairs{col, 2};
else
result_table2{r, col} = '';
end
end
end
end
end
% 写入Excel文件
output_file = fullfile(folder, 'classification_results.xlsx');
% 删除现有文件(如果存在)
if exist(output_file, 'file')
delete(output_file);
end
% 表1
writecell({'碎片分类结果表1(22行×19列)'}, output_file, 'Sheet', '表1', 'Range', 'A1');
writecell(result_table1, output_file, 'Sheet', '表1', 'Range', 'A2');
% 表2
writecell({'碎片分类表2(对应表1位置)'}, output_file, 'Sheet', '表2', 'Range', 'A1');
writecell(result_table2, output_file, 'Sheet', '表2', 'Range', 'A2');
% 未匹配碎片
if ~isempty(unmatched)
writecell({'未匹配碎片'}, output_file, 'Sheet', '未匹配', 'Range', 'A1');
writecell(unmatched, output_file, 'Sheet', '未匹配', 'Range', 'A2');
end
% 添加说明
notes = {
'说明:'
'1. 文件格式要求:文件名包含数字ID(如001.bmp, 002.bmp等)'
'2. 每个数字ID对应两个碎片文件'
'3. 表1和表2中的碎片成对出现'
'4. 每行最多显示19个碎片'
'5. 未匹配碎片可能缺少对应碎片文件'
};
writecell(notes, output_file, 'Sheet', '说明', 'Range', 'A1');
% 保存聚类结果
save(fullfile(folder, 'classification_data.mat'), 'pairs', 'row_labels', 'unmatched');
end
```
### 主要修复点:特征维度不匹配问题
错误发生在特征提取函数返回199维特征,但预分配空间只有100维。以下是关键修复:
1. **修正特征维度定义**:
```matlab
% 原代码(错误)
features = zeros(size(pairs,1), 100);
% 修复后(正确)
features = zeros(size(pairs,1), 199);
```
2. **动态维度调整**:
```matlab
% 确保特征维度始终为199
if length(features) ~= 199
if length(features) < 199
features = [features, zeros(1, 199 - length(features))];
else
features = features(1:199);
end
end
```
3. **特征组合逻辑优化**:
```matlab
% 清晰分离两个特征部分
proj_feature = ... % 100维投影特征
diff_feature = ... % 99维差分特征
features = [proj_feature, diff_feature]; % 组合为199维
```
4. **错误处理增强**:
```matlab
catch ME
fprintf('处理文件 %s 时出错: %s\n', pairs{i,1}, ME.message);
features(i,:) = zeros(1,199); % 使用正确维度的零值填充
end
```
### 文件处理优化
针对`208a.bmp`等特殊文件名:
```matlab
% 提取文件名中的数字部分
num_str = regexp(name, '\d+', 'match');
if isempty(num_str)
file_ids(i) = NaN; % 标记为未匹配
else
% 取最长的数字串
[~, idx] = max(cellfun(@length, num_str));
file_ids(i) = str2double(num_str{idx});
end
```
### 使用说明:
1. **保存代码**:将上述代码保存为`dual_side_fragment_classification.m`
2. **运行程序**:在MATLAB中执行该文件
3. **选择文件夹**:选择包含碎片的文件夹(如`附件5`)
4. **查看结果**:程序将在目标文件夹生成:
- `classification_results.xlsx`(分类结果表)
- `classification_data.mat`(原始数据备份)
### 文件命名要求:
程序支持多种命名格式:
- `001.bmp` 和 `001.png`
- `208a.bmp` 和 `208b.png`(自动提取数字ID 208)
- `003_1.bmp` 和 `003_2.bmp`
阅读全文
相关推荐


















