自行编程使用Harris算法对lena.png和cameraman.tif图片(或其它图片)进行角点检测。
以下是使用Harris算法对lena.png进行角点检测的MATLAB代码实现:
% 读取图片
im = imread('lena.png');
figure, imshow(im), title('Original Image');
% 转换为灰度图像
grayIm = rgb2gray(im);
figure, imshow(grayIm), title('Gray Image');
% 计算x、y方向上的Sobel梯度
dx = [-1 0 1; -2 0 2; -1 0 1];
dy = dx';
Ix = conv2(double(grayIm), dx, 'same');
Iy = conv2(double(grayIm), dy, 'same');
% 计算矩阵M中每个元素的值
wSize = 3; % 窗口大小(3x3)
k = 0.04; % Harris参数
M11 = conv2(Ix.^2, ones(wSize), 'same');
M12 = conv2(Ix.*Iy, ones(wSize), 'same');
M22 = conv2(Iy.^2, ones(wSize), 'same');
detM = M11.*M22 - M12.^2;
traceM = M11 + M22;
R = detM - k*traceM.^2;
% 非极大值抑制
thres = 1e-6 * max(R(:));
Rmax = ordfilt2(R, wSize^2, ones(wSize)); % 对于每个像素,取其3x3邻域内最大的R值
Rmax = (R == Rmax) & (R > thres); % 与原始R值相同且大于阈值的为角点
% 显示结果
figure, imshow(im), title('Harris Corners');
hold on
[y, x] = find(Rmax);
plot(x, y, 'ro');
结果展示
以下是使用Harris算法对cameraman.tif进行角点检测的MATLAB代码实现:
% 读取图片
im = imread('cameraman.tif');
figure, imshow(im), title('Original Image');
% 计算x、y方向上的Sobel梯度
dx = [-1 0 1; -2 0 2; -1 0 1];
dy = dx';
Ix = conv2(double(im), dx, 'same');
Iy = conv2(double(im), dy, 'same');
% 计算矩阵M中每个元素的值
wSize = 3; % 窗口大小(3x3)
k = 0.04; % Harris参数
M11 = conv2(Ix.^2, ones(wSize), 'same');
M12 = conv2(Ix.*Iy, ones(wSize), 'same');
M22 = conv2(Iy.^2, ones(wSize), 'same');
detM = M11.*M22 - M12.^2;
traceM = M11 + M22;
R = detM - k*traceM.^2;
% 非极大值抑制
thres = 1e-6 * max(R(:));
Rmax = ordfilt2(R, wSize^2, ones(wSize)); % 对于每个像素,取其3x3邻域内最大的R值
Rmax = (R == Rmax) & (R > thres); % 与原始R值相同且大于阈值的为角点
% 显示结果
figure, imshow(im), title('Harris Corners');
hold on
[y, x] = find(Rmax);
plot(x, y, 'ro');
实验结果
编程使用SUSAN算法对lena.png和 cameraman.tif图片(或其它图片)进行角点检测,对结果和harris算法实现的结果进行对比,分析它们之间的不同之处。 进一步自行实现Moravec算法,比较三种角点检测算法的差异。
以下是使用SUSAN算法对lena.png进行角点检测的MATLAB代码实现:
读取图片
im = imread('lena.png');
figure, imshow(im), title('Original Image');
% 转换为灰度图像
grayIm = rgb2gray(im);
figure, imshow(grayIm), title('Gray Image');
% 求解平均灰度值
wSize = 7; % 窗口大小(7x7)
threshold = 0.04; % 阈值
A = fspecial('average', wSize);
meanI = imfilter(double(grayIm), A, 'replicate');
% 计算像素与邻域像素之间的差异
diffIm = abs(double(grayIm) - meanI);
mask = ones(wSize);
mask(4, 4) = 0; % 排除中心点
% 计算响应值
C = threshold * ones(size(diffIm));
C(diffIm > C) = diffIm(diffIm > C);
response = sum(sum(C .* mask));
% 显示结果
figure, imshow(im), title('SUSAN Corners');
hold on
[y, x] = find(diffIm > threshold);
plot(x, y, 'ro');
以下是使用SUSAN算法对cameraman.tif进行角点检测的MATLAB代码实现:
% 读取图片
im = imread('cameraman.tif');
figure, imshow(im), title('Original Image');
% 求解平均灰度值
wSize = 256; % 窗口大小(7x7)
threshold = 27; % 阈值
A = fspecial('average', wSize);
meanI = imfilter(double(im), A, 'replicate');
% 计算像素与邻域像素之间的差异
diffIm = abs(double(im) - meanI);
mask = ones(wSize);
mask(4, 4) = 0; % 排除中心点
% 计算响应值
C = threshold * ones(size(diffIm));
C(diffIm > C) = diffIm(diffIm > C);
response = sum(sum(C .* mask));
% 显示结果
figure, imshow(im), title('SUSAN Corners');
hold on
[y, x] = find(diffIm > threshold);
plot(x, y, 'ro');
以下是使用Moravec算法对lena.png进行角点检测的MATLAB代码实现:
% 读取图片
im = imread('lena.png');
figure, imshow(im), title('Original Image');
% 转换为灰度图像
grayIm = rgb2gray(im);
figure, imshow(grayIm), title('Gray Image');
% 计算窗口大小和平移量
wSize = 7; % 窗口大小(7x7)
shifts = [-1 -1; -1 0; -1 1; 0 -1; 0 1; 1 -1; 1 0; 1 1]; % 平移量
% 计算响应值
threshold = 10000; % 阈值
response = zeros(size(grayIm));
for i = wSize+1 : size(grayIm, 1)-wSize
for j = wSize+1 : size(grayIm, 2)-wSize
S = zeros(8, 1);
for k = 1 : size(shifts, 1)
diffIm = double(grayIm(i:i+wSize-1, j:j+wSize-1)) - ...
double(grayIm(i+shifts(k,1):i+wSize-1+shifts(k,1), j+shifts(k,2):j+wSize-1+shifts(k,2)));
S(k) = sum(diffIm(:).^2);
end
response(i,j) = min(S);
end
end
% 非极大值抑制
thres = 1e-6 * max(response(:));
Rmax = ordfilt2(response, wSize^2, ones(wSize)); % 对于每个像素,取其3x3邻域内最大的响应值
Rmax = (response == Rmax) & (response > thres); % 与原始响应值相同且大于阈值的为角点
% 显示结果
figure, imshow(im), title('Moravec Corners');
hold on
[y, x] = find(Rmax);
plot(x, y, 'ro');
其中,wSize表示窗口大小,shifts表示平移量,threshold表示响应值阈值。
% 读取图片
im = imread('cameraman.tif');
figure, imshow(im), title('Original Image');
% 转换为灰度图像
grayIm = im2double(im);
figure, imshow(grayIm), title('Gray Image');
% 计算窗口大小和平移量
wSize = 7; % 窗口大小(7x7)
shifts = [-1 -1; -1 0; -1 1; 0 -1; 0 1; 1 -1; 1 0; 1 1]; % 平移量
% 计算响应值
threshold = 10000; % 阈值
response = zeros(size(grayIm));
for i = wSize+1 : size(grayIm, 1)-wSize
for j = wSize+1 : size(grayIm, 2)-wSize
S = zeros(8, 1);
for k = 1 : size(shifts, 1)
diffIm = grayIm(i:i+wSize-1, j:j+wSize-1) - ...
grayIm(i+shifts(k,1):i+wSize-1+shifts(k,1), j+shifts(k,2):j+wSize-1+shifts(k,2));
S(k) = sum(diffIm(:).^2);
end
response(i,j) = min(S);
end
end
% 非极大值抑制
thres = 1e-6 * max(response(:));
Rmax = ordfilt2(response, wSize^2, ones(wSize)); % 对于每个像素,取其3x3邻域内最大的响应值
Rmax = (response == Rmax) & (response > thres); % 与原始响应值相同且大于阈值的为角点
% 显示结果
figure, imshow(im), title('Moravec Corners');
hold on
[y, x] = find(Rmax);
plot(x, y, 'ro');
接下来我们比较一下三种角点检测算法的结果和差异。
首先,Harris算法和SUSAN算法都是基于局部特征的检测方法,在处理噪声和纹理丰富的图像时表现优异,但在处理大尺度、低纹理的图像时可能会受到影响。不同之处在于Harris算法计算的是矩阵M中每个元素的值,而SUSAN算法计算的是像素与邻域像素之间的差异。因此,Harris算法能够更好地捕捉角点特征,而SUSAN算法更适用于圆形区域内的特征提取。
其次,Moravec算法通过计算窗口内像素与平移后像素的差异,然后选取最小的差异值作为响应值。由于该算法没有考虑像素之间的相关性,所以在处理噪声和平滑图像时表现良好,但在存在较强纹理或者较多噪声的图像中,容易产生大量错误的角点结果,而且对旋转和尺度变换不具有鲁棒性。
综上所述,不同的角点检测算法适用于不同类型的图像和应用场景。如果需要更精确、鲁棒的角点检测结果,可以考虑使用Harris算法;如果需要处理低纹理图像或者圆形区域内的特征提取,可以使用SUSAN算法;如果需要快速实现角点检测并且对噪声和平滑图像具有较好的适应性,则可以选择Moravec算法。