1

我有一个大小为 10x100 的矩阵 A,如下所示。我想做的是:

  1. 我将逐行工作,对于每一行,我将检查该行中每个列的数据
  2. 假设我现在在第一行的第一个 col 单元格中。我将检查该值是否为零我将移至下一个列,依此类推,直到我找到一个具有非零值的列并保存其列号,例如列 3“这意味着列 1 和 2 为零”
  3. 现在我在第 1 行的第一个非零列中,我将移动到下一个列,直到找到一个零值的列。我将在这个必须是非零的零之前获取 col 并保存它。例如 col 7 “这意味着 col4&5&6 是非零并且 col8 是零”
  4. 现在我想保存这两列之间的中间中间列,例如 col3 和 col7,然后中间 col 是 col5,所以我将保存索引 row1_col5。如果有两个中间值,那么它们中的任何一个都可以。
  5. 然后我将移动到下一个列,直到找到一个非零列“从 2--> 5 执行相同的步骤”,直到第一行完成。
  6. 移动到下一行并从步骤 2--> 5 重新开始。
  7. 有两个规则:-第一个是只有当至少有 3 个非零连续值时,我才会得到非零连续值的中间索引,如果有两个非零连续值,那么中间不会被计算 - 第二个是如果零连续值的数量小于3,那么它们将被忽略并被视为非零值。例如,在下面的示例中,第一行中间值为 col5 和 col11。在 row2 中 col5 被计算在内,而 row3 中没有 cols 满足此条件,在 row4 中 col6 或 col7 将被计算在内。
  8. 完成所有行后,希望有一个向量或数组来保存所有中间索引的位置,例如 row1_col5 row1_col17 row2_col_10 等等。

例子:

A = [ 0 0 0 2 4 1 0 0 0 1 3 2;
      0 0 0 5 1 1 1 1 0 0 0 1;
      0 3 4 1 0 3 1 2 0 0 1 3;
      0 0 0 0 1 3 4 5 0 0 0 0];

对于第一行,中间值将是 5 和 11 等等所以如果有人可以请告诉我如何用最少的处理来做到这一点,因为这可以使用循环来完成,但是如果有更有效的方法来做到这一点?如果需要任何澄清,请告诉我。

4

3 回答 3

3

现在你已经澄清了你的问题(再次......)这是一个解决方案(仍然使用 for 循环......)。它包括“规则 7”——不包括少于三个元素的运行;它还包括该规则的第二部分 - 少于三个零的运行不算为零。新代码如下所示:

A = [ 0 0 0 2 4 1 0 0 0 1 3 2;
      0 0 0 5 1 1 1 1 0 0 0 1;
      0 3 4 1 0 3 1 2 0 0 1 3;
      0 0 0 0 1 3 4 5 0 0 0 0];

 retVal = cell(1, size(A, 1));
 for ri = 1:size(A,1)
     temp = [1 0 0 0 A(ri,:) 0 0 0 1]; % pad ends with 3 zeros + 1
                                       % so that is always a "good run"
     isz = (temp == 0); % find zeros - pad "short runs of 0" with ones
     diffIsZ = diff(isz);
     f = find(diffIsZ == 1);     
     l = find(diffIsZ == -1);
     shortRun = find((l-f)<3); % these are the zeros that need eliminating

     for ii = 1:numel(shortRun)
         temp(f(shortRun(ii))+1:l(shortRun(ii))) = 1;
     end

     % now take the modified row:
     nz = (temp(4:end-3)~=0);
     dnz = diff(nz); % find first and last nonzero elements
     f = find(dnz==1); 
     l = find(dnz==-1);
     middleValue = floor((f + l)/2);
     rule7 = find((l - f) > 2);
     retVal{ri} = middleValue(rule7);
 end

您必须使用元胞数组作为返回值,因为您不知道每行将返回多少个元素(根据您更新的要求)。

上面的代码返回以下元胞数组:

{[5 11], [6], [7], [7]}

我似乎仍然不理解您的“规则 7”,因为您说“第 3 行中没有列满足此条件”。但在我看来,一旦我们消除了零的短期运行,它就可以了。除非我误解了你想如何处理一系列非零数字,这些数字一直延伸到边缘(我认为这没关系 - 这就是为什么你11在第 1 行中作为有效列返回;那么你为什么不返回7第 3 行??)

于 2013-08-02T16:47:06.230 回答
1

尝试这个:

sizeA = size(A);
N = sizeA(1);
D = diff([zeros(1, N); (A.' ~= 0); zeros(1,N)]) ~= 0;
[a b] = find(D ~= 0);

c = reshape(a, 2, []);
midRow = floor(sum(c)/2);
midCol = b(1:2:length(b))

在此之后, midRow 和 midCol 包含您的质心的索引(例如,对于您上面给出的示例矩阵, midRow(1) = 1, midCol(1) = 4。

于 2013-08-02T17:08:05.283 回答
0

如果您不介意使用for循环:

A = [ 0 0 1 1 1 0 1;
      0 0 0 0 0 0 0;
      0 1 1 1 1 0 0;
      0 1 1 1 0 1 1;
      0 0 0 0 1 0 0]; % data

sol = repmat(NaN,size(A,1),1);
for row = 1:size(A,1)
  [aux_row aux_col aux_val] = find(A(row,:));
  if ~isempty(aux_col)
    sol(row) = aux_col(1) + floor((find(diff([aux_col 0])~=1,1)-1)/2);
    % the final 0 is necessary in case the row of A ends with ones
    % you can use either "floor" or "ceil"
  end
end

disp(sol)

尝试一下,看看它是否符合您的要求。我希望代码清晰;如果没有,请告诉我

于 2013-08-02T16:24:55.720 回答