草庐IT

【计算机视觉】图像分割与特征提取——基于Roberts、Prewitt、Sobel算子的图像分割实验

赵四司机 2023-09-04 原文

个人简介: 

> 📦个人主页:赵四司机
> 🏆学习方向:JAVA后端开发 
> ⏰往期文章:SpringBoot项目整合微信支付
> 🔔博主推荐网站:牛客网 刷题|面试|找工作神器
> 📣种一棵树最好的时间是十年前,其次是现在!
> 💖喜欢的话麻烦点点关注喔,你们的支持是我的最大动力。

前言:

实验中要求能够自行评价各主要算子在无噪声条件下和噪声条件下的分割性能。能够掌握分割条件(阈值等)的选择。完成规定图像的处理并要求正确评价处理结果,能够从理论上作出合理的解释。通过实验体会一些主要的分割算子对图像处理的效果,以及各种因素对分割效果的影响。

目录

一:相关概念

1.什么是边缘

2.边缘检测算法

(1)一阶梯度算子

(2)二阶导数

二:使用Roberts算子进行分割

1.实验原理

2.代码实现

3.实验分析

三:使用Prewitt算子进行分割 

1.实验原理

2.代码实现

3.实验分析

四: 使用Sobel算子进行分割

1.实验原理

2.代码实现

3.实验分析


一:相关概念

1.什么是边缘

        什么是边缘?相信很多人都能说出什么是边缘或者指出一幅图片中哪些是边缘,但是如何用计算机视觉相关概念描述出来呢?首先我们先观察一下边缘有什么特点,你会发现所有边缘与其相邻的区域有很大的颜色/灰度越变,我们就可以通过这个特点将边缘区分出来,进而就可以做到对图像的分割。

        对灰度图像的分割常可基于像素灰度值的2个性质:不连续性和相似性。 区域内部的像素一般具有灰度相似性,而在区域之间的边界上一般具有灰度不连续性。

2.边缘检测算法

(1)一阶梯度算子

  • Sobel算子
  • Prewitt算子
  • Roberts算子

(2)二阶导数

  • 拉普拉斯算子(对噪音敏感)

  • 高斯-拉普拉斯算子(LOG)(对图像先进行滤波再求导数)

二:使用Roberts算子进行分割

1.实验原理

        调入并显示图像room.tif(或room.png)中图像;使用Roberts 算子对图像进行边缘检测处理; Roberts 算子为一对模板:

        相应的矩阵为:rh = [0 1;-1 0]; rv = [1 0;0 -1];这里的rh 为水平Roberts 算子,rv为垂直Roberts 算子。分别显示处理后的水平边界和垂直边界检测结果;用“欧几里德距离”和“街区距离”方式计算梯度的模,并显示检测结果;对于检测结果进行二值化处理,并显示处理结果;

        提示:先做检测结果的直方图,参考直方图中灰度的分布尝试确定阈值;应反复调节阈值的大小,直至二值化的效果最为满意为止。分别显示处理后的水平边界和垂直边界检测结果;将处理结果转化为“白底黑线条”的方式;给图像加上零均值的高斯噪声;对于噪声图像重复以上步骤。

2.代码实现

function Roberts(I_in)
    figure(1),subplot(121),imshow(I_in),title('原图');
    [row,col] = size(I_in);
    I=double(I_in);
    I(:, size(I_in, 2) + 1) = 195;
    I(size(I_in, 1) + 1, :) = 195;

    g = zeros(row,col);
    g_x=zeros(row,col);  % 水平方向
    g_y=zeros(row,col);  % 垂直方向

    for i=1:row
        for j=1:col
            x=abs(I(i+1,j+1)-I(i,j));
            y=abs(I(i+1,j)-I(i,j+1));
            sum=x+y;
            g(i,j) = sum;
            g_x(i,j)=x;
            g_y(i,j)=y;
        end
    end


    NumPixel = zeros(1,400);  % 建立一个256列的行向量,以统计各灰度级的像素个数
    for i = 1 : row
        for j = 1 : col
            k = g(i,j);  % k是像素点(i,j)的灰度值
            NumPixel(k+1) = NumPixel(k+1) + 1;  % 对应灰度值像素点数量加1 
        end
    end

    figure(2),bar(NumPixel);  % 灰度图像的直方图
    figure(1),subplot(122),imshow(g,[]),title('卷积结果');

    I2=g;
    for i = 1 : row
        for j = 1 : col
            if I2(i,j) < 80
                I2(i,j) = 1;
            else
                I2(i,j) = 0;
            end
        end
    end


    figure(3),subplot(121),imshow(g_x,[]),title('水平边界检测结果');
    figure(3),subplot(122),imshow(g_y,[]),title('垂直边界检测结果');
    figure,imshow(I2),title('二值化图像');
end

3.实验分析

图3.1-1 灰度分布直方图

图3.1-2 水平边界与垂直边界检测结果

图3.1-3 room原图与卷积结果

图3.1-4 结果二值化

图3.1-5 加入高斯噪声后灰度分布直方图

图3.1-6 水平边界与垂直边界检测结果

图3.1-7 room加入高斯噪声原图与卷积结果

图3.1-8 卷积结果二值化

分析:

        可以看到,进行卷积后得到的图像灰度值大多集中在0-25之间,这是因为图像中边缘部分占的信息比较少,而平滑部分信息较多,当在梯度较小的区域做梯度幅值计算时,得到的结果会接近于0。从水平边界检测和垂直边界检测结果来看(见图3.1-2),可以看到Roberts算子对正45度和负45度的边缘检测效果较明显,其中水平方向检测正45度方向,垂直方向检测负45度方向。要注意的是,实验中发现当用uint8类型的矩阵来存储结果时,由于uint8类型存储的是0-255之间的值,而计算结果会大于255,此时会将大于255的值置为255,会造成一些信息丢失,得到的结果也不明显。对于水平和垂直的边缘,两个方向的检测结果都基本一致。

        在对卷积结果进行二值化处理时,从灰度分布图中可以得到大概的最小值阈值(即该阈值往后的灰度分布较少),但是将这个值作为阈值得到的图像会有较多非边缘部分信息(如房顶部分),此时就需要增大阈值,以过滤这些非边缘信息。

        加入高斯噪声之后,可以看到灰度值分布呈现很明显的正态分布,得到的卷积结果不理想,无论怎么调整阈值,噪声都会造成很大的影响。假如阈值过小,噪声会覆盖掉边缘信息,噪声过大则会将边缘部分过滤。罗伯特算法对于噪声较多的图片处理效果较差。

三:使用Prewitt算子进行分割 

1.实验原理

Prewitt算子的模板大小为3*3,其X方向和Y方向偏导数分别为:

梯度计算公式:

2.代码实现

function Prewitt(I_in)
    figure(1),subplot(121),imshow(I_in),title('原图');
    [row,col] = size(I_in);
    I=ones(row+2,col+2);
    for i=2:row+1
        for j=2:col+1
            I(i,j)=I_in(i-1,j-1);
        end
    end

    g = zeros(row,col);
    g_x=zeros(row,col);  % 水平方向
    g_y=zeros(row,col);  % 垂直方向

    for i=2:row+1
        for j=2:col+1
            x=abs(I(i-1,j-1)+I(i,j-1)+I(i+1,j-1)-(I(i-1,j+1)+I(i,j+1)+I(i+1,j+1)));
            y=abs(I(i-1,j-1)+I(i-1,j)+I(i-1,j+1)-(I(i+1,j-1)+I(i+1,j)+I(i+1,j+1)));
            sum=x+y;
            g(i-1,j-1) = sum;
            g_x(i-1,j-1)=x;
            g_y(i-1,j-1)=y;
        end
    end
    
    g(1,:) = 1;
    g(row,:) = 1; 
    g(:,1) = 1;
    g(:,col) = 1;

    NumPixel = zeros(1,1000);  % 建立一个256列的行向量,以统计各灰度级的像素个数
    for i = 1 : row
        for j = 1 : col
            k = g(i,j);  % k是像素点(i,j)的灰度值
            NumPixel(k+1) = NumPixel(k+1) + 1;  % 对应灰度值像素点数量加1 
        end
    end

    figure(2),bar(NumPixel);  % 灰度图像的直方图
    figure(1),subplot(122),imshow(g,[]),title('卷积结果');

    I2=g;
    for i = 1 : row
        for j = 1 : col
            if I2(i,j) < 100
                I2(i,j) = 1;
            else
                I2(i,j) = 0;
            end
        end
    end


    figure(3),subplot(121),imshow(g_x,[]),title('水平边界检测结果');
    figure(3),subplot(122),imshow(g_y,[]),title('垂直边界检测结果');
    figure,imshow(I2),title('二值化图像');
end

3.实验分析

图3.2-1 灰度值分布图

图3.2-2 水平与垂直边界检测结果

图3.2-3 原图与卷积结果

图3.2-4 卷积结果二值化

图3.2-5 加入高斯噪声后卷积结果灰度分布图

图3.2-6 加入高斯噪声后水平边界和垂直边界检测结果

图3.2-7 加入高斯噪声后原图及卷积结果

图3.2-8 卷积结果二值化

分析:

        相较于Roberts算子,Prewitt算子采用的是3*3的模板,因此需要处理图像边界问题,在Roberts算子中我处理边界的方式是在最后一列和最后一行添加一个普遍像素值195,在Prewitt算子中由于选取得是模板中心位置,所以需要再图像像素矩阵四周添加像素点,我选择的是在四周添加1。在横向和纵向的边缘检测Prewitt算子要比Roberts算子要强,从图3.2-2中可以看到,Prewitt算子的x方向检测主要检测纵向边缘信息,y方向主要检测横向边缘信息,对于斜边的检测两个方向基本一致。从图3.2-4中可以看到,Prewitt算子的边缘检测能力要比Roberts算子要强,在一些细节方面Prewitt算子保留得更到位,Roberts算子会造成一些边缘信息的丢失,特别是灰度变化梯度较小的区域。

        在处理带噪声的图片上,由于Prewitt算子采用了3*3的模板,其对噪声的处理能力也更强,相较于图3.1-8,图3.2-8的处理效果更好,在去除了部分的噪声后边缘信息仍能看出来,但是噪声还是很明显。

四: 使用Sobel算子进行分割

1.实验原理

Sobel算子考察它上下、左右邻点灰度的加权差。与之接近的邻点的权重:

用卷积模板来实现:

Sobel算子结合了高斯平滑和微分求导,相当于先做了平滑再做边缘提取,有抑制噪声的作用。

另一个角度:Sobel算子在Prewitt算子的基础上增加了权重的概念认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。 

2.代码实现

function Sobel(I_in)
    figure(1),subplot(121),imshow(I_in),title('原图');
    [row,col] = size(I_in);
    I=ones(row+2,col+2);
    for i=2:row+1
        for j=2:col+1
            I(i,j)=I_in(i-1,j-1);
        end
    end

    g = zeros(row,col);
    g_x=zeros(row,col);  % 水平方向
    g_y=zeros(row,col);  % 垂直方向

    for i=2:row+1
        for j=2:col+1
            x=abs(I(i-1,j-1)+2*I(i,j-1)+I(i+1,j-1)-(I(i-1,j+1)+2*I(i,j+1)+I(i+1,j+1)));
            y=abs(I(i-1,j-1)+2*I(i-1,j)+I(i-1,j+1)-(I(i+1,j-1)+2*I(i+1,j)+I(i+1,j+1)));
            sum=x+y;
            g(i-1,j-1) = sum;
            g_x(i-1,j-1)=x;
            g_y(i-1,j-1)=y;
        end
    end
    
    g(1,:) = 1;
    g(row,:) = 1; 
    g(:,1) = 1;
    g(:,col) = 1;

    NumPixel = zeros(1,1500);  % 建立一个256列的行向量,以统计各灰度级的像素个数
    for i = 1 : row
        for j = 1 : col
            k = g(i,j);  % k是像素点(i,j)的灰度值
            NumPixel(k+1) = NumPixel(k+1) + 1;  % 对应灰度值像素点数量加1 
        end
    end

    figure(2),bar(NumPixel);  % 灰度图像的直方图
    figure(1),subplot(122),imshow(g,[]),title('卷积结果');

    I2=g;
    for i = 1 : row
        for j = 1 : col
            if I2(i,j) < 280
                I2(i,j) = 1;
            else
                I2(i,j) = 0;
            end
        end
    end


    figure(3),subplot(121),imshow(g_x,[]),title('水平边界检测结果');
    figure(3),subplot(122),imshow(g_y,[]),title('垂直边界检测结果');
    figure,imshow(I2),title('二值化图像');
end

3.实验分析

图3.3-1 Sobel算子处理结果灰度分布直方图

图3.3-2 水平边界和垂直边界检测结果

图3.3-3 room原图及Robel算子处理结果

图3.3-4 二值化结果

图3.3-5 加入高斯噪声后图像灰度分布图

图3.3-6 加入高斯噪声后水平及垂直边界检测结果

图3.3-7 加入高斯噪声后原图及卷积化结果

图3.3-8 二值化结果

分析:

        对于Sobel算子,其原理与Prewitt算子基本一致,不同的是Sobel算子Sobel算子在Prewitt算子的基础上增加了权重的概念认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。其结合了高斯平滑和微分求导,相当于先做了平滑再做边缘提取,有抑制噪声的作用。在不添加噪声的情况下,可以看到Sobel算子的处理效果与Prewitt算子基本一致,但是加入高斯噪声之后,可以看到明显的差别,Sobel算子对噪声具有平滑作用,其边缘信息相较于Prewitt算子更清晰。

有关【计算机视觉】图像分割与特征提取——基于Roberts、Prewitt、Sobel算子的图像分割实验的更多相关文章

  1. ruby-on-rails - 使用一系列等级计算字母等级 - 2

    这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,

  2. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  3. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  4. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

    我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

  5. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - 使用 Ruby,计算 n x m 数组的每一列中有多少个 true 的简单方法是什么? - 2

    给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in

  8. ruby - 是否有将图像文件转换为 ASCII 艺术的命令行程序或库? - 2

    有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/

  9. ruby-on-rails - 使用 Dragonfly 从 URL 分配图像 - 2

    我正在使用Dragonfly在Rails3.1应用程序上处理图像。我正在努力通过url将图像分配给模型。我有一个很好的表格:{:multipart=>true}do|f|%>RemovePicture?Dragonfly的文档指出:Dragonfly提供了一个直接从url分配的访问器:@album.cover_image_url='http://some.url/file.jpg'但是当我在控制台中尝试时:=>#ruby-1.9.2-p290>picture.image_url="http://i.imgur.com/QQiMz.jpg"=>"http://i.imgur.com/QQ

  10. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

随机推荐