检测图像的边缘在Matlab中不起作用 [英] Detecting edges of an image doesn't work in Matlab
问题描述
我正在研究检测图像边缘的脚本。
I'm working on a script detecting edges of an image.
这是脚本:
clear all; close all; clc;
c = rgb2gray(imread('image_S004_I0004.jpg'));
c = double(c);
k = imnoise(c, 'salt & pepper', 0.01);
gg = [-1 0 1;-2 0 2; -1 0 1];
gh = gg';
grad_g = conv2(k, gg);
grad_h = conv2(k, gh);
grad = sqrt(grad_g.^2 + grad_h.^2);
[r s] = size(grad);
T = 80;
for ii = 1:r
for jj = 1:s
if grad(ii, jj) < T
thresh_grad(ii, jj) = 0;
else
thresh_grad(ii, jj) = 1;
end
end
end
figure()
subplot(121); imshow(uint8(c));
subplot(122); imshow(thresh_grad);
这是我一直得到的:
左边是原始图像,在右边应该是一个检测到边缘的图像(正如你在脚本中看到的,我在图像上实现了一些噪声 - 必须在那里)。但是我什么都没有,无论阈值T的值是什么。
On the left is an original image, on the right should be an image with detected edges (as you can see in the script, I have implemented some noise on the image - has to be there). But I get literally nothing, not matter what the value of threshold T is.
你能帮我找错吗?
推荐答案
在应用噪声之前,代码中存在问题。您在调用 imnoise
之前将图像转换为 double
。通过这样做, double
精度图像被假定具有 [0,1]
的动态范围,因此输出 imnoise
将被剪裁到 [0,1]
范围内。这意味着您的 80
的阈值因此不合适,因为永远不会有任何超过80的梯度值,因此所有内容都可视化为黑色。
The problem in your code is right before you apply the noise. You are casting the image to double
prior to calling imnoise
. By doing this, double
precision images are assumed to have a dynamic range of [0,1]
and so the output of imnoise
would be clipped to the [0,1]
range. This means that your threshold of 80
would therefore be unsuitable because there will never be any gradient values that would exceed the value of 80 so everything is visualized as black.
此外, thresh_grad
未定义,建议您在使用之前预先分配图像。只需 thresh_grad = zeros(size(grad));
在循环的双之前。
In addition, thresh_grad
is not defined and it's recommended you pre-allocate the image prior to using it. Simply do thresh_grad = zeros(size(grad));
prior to the double for
loop.
因此,在您拨打 imnoise
之后,请致电 double
使图像仍然在 uint8
中,然后转换为 double
以进行卷积。通过这样做,我设法获得输出。我无法访问您的图片,但我使用了内置在MATLAB图像处理工具箱中的 cameraman.tif
图片。
As such, call double
after you make the call to imnoise
which would make the image still be in uint8
and then convert to double
for the purposes of convolution. By doing this I managed to get output. I don't have access to your image, but I used the cameraman.tif
image that's built-into MATLAB's image processing toolbox.
因此:
c = imread('cameraman.tif');
k = imnoise(c, 'salt & pepper', 0.01);
k = double(k); % Change
gg = [-1 0 1;-2 0 2; -1 0 1];
gh = gg';
grad_g = conv2(k, gg);
grad_h = conv2(k, gh);
grad = sqrt(grad_g.^2 + grad_h.^2);
[r, s] = size(grad);
thresh_grad = zeros(size(grad)); % Added
T = 80;
for ii = 1:r
for jj = 1:s
if grad(ii, jj) < T
thresh_grad(ii, jj) = 0;
else
thresh_grad(ii, jj) = 1;
end
end
end
figure()
subplot(121); imshow(uint8(c));
subplot(122); imshow(thresh_grad);
我得到:
至于未来的发展,我建议你使用 im2double
实际将图片转换为 double
precision,它还会将数据转换为 [0,1]
范围。因此,您需要将阈值从 80
更改为 80/255
作为的阈值80
最初是为 uint8
图像而设计的。
As for future development, I recommend you use im2double
to actually convert the images to double
precision, which would also convert the data into a [0,1]
range. You would thus need to change the threshold from 80
to 80/255
as the threshold of 80
was originally designed for uint8
images.
最后,当你展示原版时图像你可以摆脱 uint8
投射。
Finally, when you show the original image you can get rid of the uint8
casting.
为了完整性:
c = imread('cameraman.tif');
c = im2double(c); % Change
k = imnoise(c, 'salt & pepper', 0.01);
gg = [-1 0 1;-2 0 2; -1 0 1];
gh = gg';
grad_g = conv2(k, gg);
grad_h = conv2(k, gh);
grad = sqrt(grad_g.^2 + grad_h.^2);
[r, s] = size(grad);
thresh_grad = zeros(size(grad)); % Added
T = 80 / 255; % Change
for ii = 1:r
for jj = 1:s
if grad(ii, jj) < T
thresh_grad(ii, jj) = 0;
else
thresh_grad(ii, jj) = 1;
end
end
end
figure()
subplot(121); imshow(c);
subplot(122); imshow(thresh_grad);
这篇关于检测图像的边缘在Matlab中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!