使用 MATLAB 和没有图像处理工具箱找到裁剪圆的中心
finding center of cropped circle using MATLAB and no image processing toolbox
我有一大组图像 (~2000),显示裁剪圆圈的灰度图片。每张图片都是一个圆圈,背景清晰。图像是均匀的,背景也是如此。图像几乎没有噪音。图片大小约为 700x700 像素。
一些图像被裁剪了,因为其中一部分在图像边界之外。圆圈大约是图像的 1/2 大小。
我有Matlab,但没有图像处理工具箱。
我有关于图像半径的先验信息。我很高兴从算法中收到它用于验证目的,但我可以先验地使用它。
如何获得圆心和半径?
谢谢!
这是霍夫变换的典型应用,但由于只有一个圆,我们可以做得更好一些。
下面的代码计算图像的梯度。你的噪音很大,但你的圈子也很大。我正在为梯度算子使用的高斯正则化使用大西格玛(我喜欢使用与高斯导数的卷积来计算导数)。接下来,我找到具有最大梯度幅度的像素,并为这些点建立一个方程组。我们注意到,对于每个点 i,
原点_x + 半径 * gradient_x(i) = coordinate_x(i)
原点_y + 半径 * gradient_y(i) = coordinate_y(i)
(抱歉,我们无法对 SO 进行适当的方程式计算)。 coordinate是该点的坐标,gradient是该点的归一化梯度,_x和_y表示向量对应的分量。 radius可以是负数,取决于渐变的方向。我们可以用 MATLAB 的 \
运算符求解这个线性方程组。
% Load image (take only first channel, they're all the same)
img = imread('https://i.stack.imgur.com/wAwdh.jpg');
img = dip_image(img(:,:,1));
% Compute gradient
grad = gradient(img,10);
% Find N pixels with largest gradient magnitude
N = 5000;
mask = norm(grad);
mask = setborder(mask,0,50); % Don't use data close to the edge of the image
tmp = sort(double(mask(:)));
mask = mask > tmp(end-N);
index = find(mask);
value = grad(index);
value = value / norm(value);
coords = ind2sub(mask,index); % value(i) at coords(i,:)
% Solve set of linear equations
p = [ones(N,1),zeros(N,1),double(value{1})';zeros(N,1),ones(N,1),double(value{2})'] \ coords(:);
origin = p(1:2)'
radius = p(3)
rmse = sqrt(mean((origin + radius * squeeze(double(value))' - coords).^2))
% Plot some of the lines
img
hold on
for ii=1:25:N
plot(coords(ii,1)-[0,radius*double(value{1}(ii-1))],coords(ii,2)-[0,radius*double(value{2}(ii-1))],'r-')
end
输出:
origin =
-2.5667 177.5305
radius =
322.5899
rmse =
13.8160 13.0136
如您所见,噪音给估计梯度带来了很多麻烦。但是因为每个像素的估计都没有偏差,所以最小二乘估计应该会得出准确的值。
上面的代码使用了DIPimage 3, which is an open-source image analysis toolbox for MATLAB (Apache License). You'll have to compile it yourself, because we don't have a pre-compiled release package yet. You can instead download DIPimage 2.9,它具有相同的功能,虽然我可能在上面的代码中使用了一些新的语法,但我不确定。 DIPimage 2.9 不是开源的,仅在 non-commercial 应用程序中免费使用。
我有一大组图像 (~2000),显示裁剪圆圈的灰度图片。每张图片都是一个圆圈,背景清晰。图像是均匀的,背景也是如此。图像几乎没有噪音。图片大小约为 700x700 像素。
一些图像被裁剪了,因为其中一部分在图像边界之外。圆圈大约是图像的 1/2 大小。
我有Matlab,但没有图像处理工具箱。
我有关于图像半径的先验信息。我很高兴从算法中收到它用于验证目的,但我可以先验地使用它。
如何获得圆心和半径?
谢谢!
这是霍夫变换的典型应用,但由于只有一个圆,我们可以做得更好一些。
下面的代码计算图像的梯度。你的噪音很大,但你的圈子也很大。我正在为梯度算子使用的高斯正则化使用大西格玛(我喜欢使用与高斯导数的卷积来计算导数)。接下来,我找到具有最大梯度幅度的像素,并为这些点建立一个方程组。我们注意到,对于每个点 i,
原点_x + 半径 * gradient_x(i) = coordinate_x(i)
原点_y + 半径 * gradient_y(i) = coordinate_y(i)
(抱歉,我们无法对 SO 进行适当的方程式计算)。 coordinate是该点的坐标,gradient是该点的归一化梯度,_x和_y表示向量对应的分量。 radius可以是负数,取决于渐变的方向。我们可以用 MATLAB 的 \
运算符求解这个线性方程组。
% Load image (take only first channel, they're all the same)
img = imread('https://i.stack.imgur.com/wAwdh.jpg');
img = dip_image(img(:,:,1));
% Compute gradient
grad = gradient(img,10);
% Find N pixels with largest gradient magnitude
N = 5000;
mask = norm(grad);
mask = setborder(mask,0,50); % Don't use data close to the edge of the image
tmp = sort(double(mask(:)));
mask = mask > tmp(end-N);
index = find(mask);
value = grad(index);
value = value / norm(value);
coords = ind2sub(mask,index); % value(i) at coords(i,:)
% Solve set of linear equations
p = [ones(N,1),zeros(N,1),double(value{1})';zeros(N,1),ones(N,1),double(value{2})'] \ coords(:);
origin = p(1:2)'
radius = p(3)
rmse = sqrt(mean((origin + radius * squeeze(double(value))' - coords).^2))
% Plot some of the lines
img
hold on
for ii=1:25:N
plot(coords(ii,1)-[0,radius*double(value{1}(ii-1))],coords(ii,2)-[0,radius*double(value{2}(ii-1))],'r-')
end
输出:
origin =
-2.5667 177.5305
radius =
322.5899
rmse =
13.8160 13.0136
如您所见,噪音给估计梯度带来了很多麻烦。但是因为每个像素的估计都没有偏差,所以最小二乘估计应该会得出准确的值。
上面的代码使用了DIPimage 3, which is an open-source image analysis toolbox for MATLAB (Apache License). You'll have to compile it yourself, because we don't have a pre-compiled release package yet. You can instead download DIPimage 2.9,它具有相同的功能,虽然我可能在上面的代码中使用了一些新的语法,但我不确定。 DIPimage 2.9 不是开源的,仅在 non-commercial 应用程序中免费使用。