如何将矩阵中强元素附近的弱元素归零?
How can I zero out weak elements near stronger ones in a matrix?
我有一个包含一些点和很多零元素的像素矩阵。从那些非零点开始,我想丢弃那些在矩阵范围 N 中具有更强点的点。范围是像素之间的欧氏距离。
input = [0.0 0.0 0.0 0.9 0.0 0.0
0.0 0.0 0.2 0.0 0.0 0.5
0.0 0.0 0.7 0.0 0.0 0.0
0.0 0.4 0.1 0.0 0.0 0.0];
output = [0.0 0.0 0.0 0.9 0.0 0.0 % 0.7 is the largest number in range
0.0 0.0 0.0 0.0 0.0 0.5 % 0.2 got removed; was next to 0.9 and 0.7
0.0 0.0 0.7 0.0 0.0 0.0 % 0.7 is the largest number in range
0.0 0.0 0.0 0.0 0.0 0.0]; % 0.1 and 0.4 both got removed; were next to 0.7
更新: 这就是我到目前为止的想法。它遍历所有非零像素并将当前像素与最大的邻域像素进行比较。然而,邻域包含很多像素。我需要以某种方式 select 一个圆形区域,而不是通过索引偏移 select 区域。此外,如果有更短的方法,我将不胜感激,也许用 conv2
或 imfilter
.
等内置 Matlab 函数替换循环
% Discard points near stronger points
points = find(Image > 0);
radius = args.Results.min_dist;
for i = 1:size(points)
[index_y, index_x] = ind2sub(size(Image), points(i));
% Find neighborhood
from_x = max(index_x-radius, 1);
from_y = max(index_y-radius, 1);
to_x = min(index_x+radius, size(Image, 2));
to_y = min(index_y+radius, size(Image, 1));
neighbors = Image(from_y:to_y, from_x:to_x);
% Discard if there is a stronger neighbor
largest = max(max(neighbors));
if Image(index_y, index_x) < largest
Image(index_y, index_x) = 0;
end
end
MATLAB
图像处理工具箱函数有多种免费替代品;例如,您可以查看 octave
,或者如果这不适合您,请查看例如this source 虽然它需要 mex 编译。
您正在寻找具有突然截止的滤波器。过滤器是工具箱中的标准工具。首先查看 imfilter
以及 imdilate
和 imopen
.
等工具的文档
解决这个问题的basic workflow
可以描述如下-
- 对所有非零点进行排序。
- 从最高值点开始并将其 N 邻域内的所有非零点设置为零。
- 对第二高的点执行相同的操作,并将其 N 邻域内的所有非零点设置为零排除值高于当前点的非零点 .这个排除部分可以用代码中非常有用的 MATLAB 工具
triu
来实现。
- 继续,直到每个非零点都被覆盖。当然,随着我们沿着这个阶梯向下移动,需要搜索的点会越来越少,因为之前讨论过 排除条款。
这些步骤可以通过矢量化方法实现,不使用 特殊 工具箱并假设 A
作为输入 -
%// Distance parameter
N = 2;
%// Find all non-zero points and then sort them in descending manner
[x,y] = find(A~=0)
pts = [x y]
[val,sorted_idx] = sort(A(A~=0),'descend')
pts = pts(sorted_idx,:)
%// Find euclidean distances
distmat = sqrt(squared_dist(pts,pts))
%// Find points to be removed (set to zero); then calculate their linear indices
rm_pts = pts(any(triu(distmat<N,1),1),:)
rm_lin_idx = sub2ind(size(A),rm_pts(:,1),rm_pts(:,2))
%// Use those linear indices to set those in the input as zeros
out = A;
out(rm_lin_idx) = 0;
关联函数代码(求平方欧氏距离)-
function sq_distmat = squared_dist(A,B)
[nA,dim] = size(A);
nB = size(B,1);
A_ext = ones(nA,dim*3);
A_ext(:,2:3:end) = -2*A;
A_ext(:,3:3:end) = A.^2;
B_ext = ones(nB,dim*3);
B_ext(:,1:3:end) = B.^2;
B_ext(:,2:3:end) = B;
sq_distmat = A_ext * B_ext.';
return;
代码运行-
A =
0 0 0 0.9000 0 0
0 0 0.2000 0 0 0.5000
0 0 0.7000 0 0 0
0 0.4000 0.1000 0 0 0
out =
0 0 0 0.9000 0 0
0 0 0 0 0 0.5000
0 0 0.7000 0 0 0
0 0 0 0 0 0
如果您安装了图像处理工具箱(或 中提到的免费替代品之一),您可以很容易地做到这一点:
函数imdilate
基本上是一个滑动最大过滤器。所以我们所做的是,对于每个像素,我们在您的半径 R
指定的邻域中寻找最大值。然后我们将实际值与找到的最大值进行比较,如果较小,我们将值设置为零。
function A = zeroOutWeakElements(A, R)
[X,Y] = ndgrid(-ceil(R):ceil(R));
neighborhood = (X.^2 + Y.^2)<=R^2;
A(imdilate(A,neighborhood)>A) = 0;
对于大型全矩阵和小距离,这也比当前接受的解决方案快得多。好处会随着稀疏矩阵和大半径而消失,但我想你应该用实际数据进行测试以确定什么是最好的。
我有一个包含一些点和很多零元素的像素矩阵。从那些非零点开始,我想丢弃那些在矩阵范围 N 中具有更强点的点。范围是像素之间的欧氏距离。
input = [0.0 0.0 0.0 0.9 0.0 0.0
0.0 0.0 0.2 0.0 0.0 0.5
0.0 0.0 0.7 0.0 0.0 0.0
0.0 0.4 0.1 0.0 0.0 0.0];
output = [0.0 0.0 0.0 0.9 0.0 0.0 % 0.7 is the largest number in range
0.0 0.0 0.0 0.0 0.0 0.5 % 0.2 got removed; was next to 0.9 and 0.7
0.0 0.0 0.7 0.0 0.0 0.0 % 0.7 is the largest number in range
0.0 0.0 0.0 0.0 0.0 0.0]; % 0.1 and 0.4 both got removed; were next to 0.7
更新: 这就是我到目前为止的想法。它遍历所有非零像素并将当前像素与最大的邻域像素进行比较。然而,邻域包含很多像素。我需要以某种方式 select 一个圆形区域,而不是通过索引偏移 select 区域。此外,如果有更短的方法,我将不胜感激,也许用 conv2
或 imfilter
.
% Discard points near stronger points
points = find(Image > 0);
radius = args.Results.min_dist;
for i = 1:size(points)
[index_y, index_x] = ind2sub(size(Image), points(i));
% Find neighborhood
from_x = max(index_x-radius, 1);
from_y = max(index_y-radius, 1);
to_x = min(index_x+radius, size(Image, 2));
to_y = min(index_y+radius, size(Image, 1));
neighbors = Image(from_y:to_y, from_x:to_x);
% Discard if there is a stronger neighbor
largest = max(max(neighbors));
if Image(index_y, index_x) < largest
Image(index_y, index_x) = 0;
end
end
MATLAB
图像处理工具箱函数有多种免费替代品;例如,您可以查看 octave
,或者如果这不适合您,请查看例如this source 虽然它需要 mex 编译。
您正在寻找具有突然截止的滤波器。过滤器是工具箱中的标准工具。首先查看 imfilter
以及 imdilate
和 imopen
.
解决这个问题的basic workflow
可以描述如下-
- 对所有非零点进行排序。
- 从最高值点开始并将其 N 邻域内的所有非零点设置为零。
- 对第二高的点执行相同的操作,并将其 N 邻域内的所有非零点设置为零排除值高于当前点的非零点 .这个排除部分可以用代码中非常有用的 MATLAB 工具
triu
来实现。 - 继续,直到每个非零点都被覆盖。当然,随着我们沿着这个阶梯向下移动,需要搜索的点会越来越少,因为之前讨论过 排除条款。
这些步骤可以通过矢量化方法实现,不使用 特殊 工具箱并假设 A
作为输入 -
%// Distance parameter
N = 2;
%// Find all non-zero points and then sort them in descending manner
[x,y] = find(A~=0)
pts = [x y]
[val,sorted_idx] = sort(A(A~=0),'descend')
pts = pts(sorted_idx,:)
%// Find euclidean distances
distmat = sqrt(squared_dist(pts,pts))
%// Find points to be removed (set to zero); then calculate their linear indices
rm_pts = pts(any(triu(distmat<N,1),1),:)
rm_lin_idx = sub2ind(size(A),rm_pts(:,1),rm_pts(:,2))
%// Use those linear indices to set those in the input as zeros
out = A;
out(rm_lin_idx) = 0;
关联函数代码(求平方欧氏距离)-
function sq_distmat = squared_dist(A,B)
[nA,dim] = size(A);
nB = size(B,1);
A_ext = ones(nA,dim*3);
A_ext(:,2:3:end) = -2*A;
A_ext(:,3:3:end) = A.^2;
B_ext = ones(nB,dim*3);
B_ext(:,1:3:end) = B.^2;
B_ext(:,2:3:end) = B;
sq_distmat = A_ext * B_ext.';
return;
代码运行-
A =
0 0 0 0.9000 0 0
0 0 0.2000 0 0 0.5000
0 0 0.7000 0 0 0
0 0.4000 0.1000 0 0 0
out =
0 0 0 0.9000 0 0
0 0 0 0 0 0.5000
0 0 0.7000 0 0 0
0 0 0 0 0 0
如果您安装了图像处理工具箱(或
函数imdilate
基本上是一个滑动最大过滤器。所以我们所做的是,对于每个像素,我们在您的半径 R
指定的邻域中寻找最大值。然后我们将实际值与找到的最大值进行比较,如果较小,我们将值设置为零。
function A = zeroOutWeakElements(A, R)
[X,Y] = ndgrid(-ceil(R):ceil(R));
neighborhood = (X.^2 + Y.^2)<=R^2;
A(imdilate(A,neighborhood)>A) = 0;
对于大型全矩阵和小距离,这也比当前接受的解决方案快得多。好处会随着稀疏矩阵和大半径而消失,但我想你应该用实际数据进行测试以确定什么是最好的。