(数字图像处理MATLAB+Python)第十章图像分割-第四,五节:分水岭分割和综合案例

news2024/11/25 10:56:33

文章目录

  • 一:分水岭分割
    • (1)原理
    • (2)程序
  • 二:综合案例:答题卡图像分割
    • (1)设计思路
    • (2)各模块设计
    • (3)代码

一:分水岭分割

(1)原理

分水岭分割:图像处理中常用的一种分割方法,它基于图像中灰度或颜色的变化来划分不同的区域。分水岭分割算法的原理是基于地理学上的分水岭概念。将图像看作一个地貌图,在图像中低洼的部分被看作水池,而高处则表示山脉。通过在图像中加入水并让其逐渐充满,当水位上升到高峰时,不同山脉之间的低洼部分就形成了分割边界。其算法步骤如下

  • 预处理:对原始图像进行预处理,包括去噪、平滑和增强等操作,以提高分割结果的准确性
  • 标记区域:通过手动标记或自动选择一些种子像素来指定感兴趣的目标区域和背景区域。这些种子像素可以根据图像的特征进行选择,如明暗度、颜色等
  • 计算距离变换:利用标记区域生成距离变换图,其中每个像素的值表示该像素到最近标记点的距离。距离变换可以将图像中的低洼区域与高处区域进行区分
  • 寻找分割线:根据距离变换图,通过寻找局部最大值点和极小值点来确定分水岭线。这些分水岭线将图像分为不同的区域
  • 分割结果优化:根据具体需求,可以对分割结果进行后处理操作,如合并相邻区域、去除小区域等,以得到更好的分割效果

分水岭分割方法在图像处理领域有着广泛的应用,特别适用于复杂背景下的目标提取和图像分割任务。但它也存在一些问题,例如对噪声敏感,容易产生过分割或欠分割等情况,因此在实际应用中需要结合其他方法进行改进和优化

在这里插入图片描述

(2)程序

如下图

在这里插入图片描述


matlab实现

clear,clc,close all;
image=im2double(rgb2gray(imread('bricks.jpg')));
figure,imshow(image),title('原图');
hv=fspecial('prewitt');
hh=hv.';
gv=abs(imfilter(image,hv,'replicate'));
gh=abs(imfilter(image,hh,'replicate'));
% g=sqrt(gv.^2+gh.^2);
g=abs(gv)+abs(gh);
figure,imshow(g),title('梯度图像');
L=watershed(g);
wr=L==0;
figure,imshow(wr),title('分水岭');
image(wr)=0;
figure,imshow(image),title('分割结果');
% imwrite(g,'watergrad.jpg');
% imwrite(wr,'fenshuiling.jpg');
% imwrite(image,'waterresult.jpg');
import numpy as np
import cv2
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('bricks.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image_gray = image_gray.astype(np.float64) / 255.0

# 显示原图
plt.figure()
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.title('原图')

# 计算梯度
hx = cv2.Sobel(image_gray, cv2.CV_64F, 1, 0, ksize=3)
hy = cv2.Sobel(image_gray, cv2.CV_64F, 0, 1, ksize=3)
gx = np.abs(hx)
gy = np.abs(hy)
gradient = gx + gy

# 显示梯度图像
plt.figure()
plt.imshow(gradient, cmap='gray')
plt.title('梯度图像')

# 分水岭分割
ret, markers = cv2.connectedComponents(cv2.threshold(np.uint8(gradient * 255), 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1])
markers = markers + 1
markers[gradient == 0] = 0
labels = cv2.watershed(image, markers)
segmented = image.copy()
segmented[labels == -1] = [0, 0, 255]

# 显示分水岭结果
plt.figure()
plt.imshow(cv2.cvtColor(segmented, cv2.COLOR_BGR2RGB))
plt.title('分割结果')

plt.show()

二:综合案例:答题卡图像分割

(1)设计思路

要求:将答题卡分割成不同区域。采用所学基础处理方法实现题目要求
操作

  • 几何校正
  • 裁切
  • 上下区域分割
  • 信息区和答题区分割

(2)各模块设计

主程序

在这里插入图片描述

几何校正

在这里插入图片描述

在这里插入图片描述

裁切

在这里插入图片描述

在这里插入图片描述

信息区域分割:通过检测边缘来进行分割:canny边缘检测、边缘滤波、边界修复和区域定位四个步骤

在这里插入图片描述

答题区分割

在这里插入图片描述

在这里插入图片描述

(3)代码

    clear,clc,close all;
    RGB=im2double(imread('card1.jpg'));
    figure,imshow(RGB),title('原图');
    adjustI=correction(RGB);

    figure,imshow(adjustI),title('几何校正结果图');
    [cropIu,cropId]=crop(adjustI);
 
    rectup(cropIu);
    rectdown(cropId);
    
    
function out=correction(in)
    bw=prepro(in);
    lines=linedetect(bw,2);
    line1=[lines(1).point1;lines(1).point2];
    line2=[lines(2).point1;lines(2).point2];
    angle1=abs(atan((line1(2,2)-line1(1,2))/(line1(2,1)-line1(1,1)))*180/pi);
    angle2=abs(atan((line2(2,2)-line2(1,2))/(line2(2,1)-line2(1,1)))*180/pi);
    
    if angle1<angle2
        temp=angle1;
        angle1=angle2;
        angle2=temp;
        temp=line1;
        line1=line2;
        line2=temp;   
    end
    first=line1(1,:);    second=line1(2,:);    third=line2(1,:);    fourth=line2(2,:);
    input_points=[first;second;third;fourth];
    
    first(2)=(first(2)+second(2))/2;    second(2)=first(2);
    third(1)=first(1);    fourth(1)=second(1);
    third(2)=(third(2)+fourth(2))/2;    fourth(2)=third(2);
    base_points=[first;second;third;fourth];
    
    tform=cp2tform(input_points,base_points,'projective');
    
    out=1-in(:,:,:);
    out=imtransform(out,tform);  
    out(:,:,:)=1-out(:,:,:);
end
function out=prepro(in)
    bw=1-imbinarize(rgb2gray(in));
    se=strel('square',2);
    out=imopen(bw,se);
end
function [lines,width]=linedetect(bw,n)
    [B,L]=bwboundaries(bw);
    [N,M]=size(bw);
    STATS=regionprops(L,'MajorAxisLength','MinorAxisLength');%统计几何特征
    len=length(STATS);
    for i=1:len          
        if STATS(i).MajorAxisLength<M/2 || STATS(i).MinorAxisLength>10
            L(L==i)=0;
        end
    end
    L(L~=0)=1;
    [B,L]=bwboundaries(L);
    STATS=regionprops(L,'MinorAxisLength');%统计几何特征
    len=length(STATS);
    width=0;
    for i=1:len   
        width=width+STATS(i).MinorAxisLength;
    end
    width=width/len;
    [h,theta,rho]=hough(L,'RhoResolution',0.5,'ThetaResolution',0.5);
    P=houghpeaks(h,n);
    lines=houghlines(L,theta,rho,P);
end

function [out1,out2]=crop(in)
    gray=1-rgb2gray(in);
    sumy=sum(gray,2);
    sumx=sum(gray);
 
    avery=mean(sumy);
    averx=mean(sumx);
    posy=find(sumy>avery);
    posx=find(sumx>averx);
    [C,maxx]=max(sumx);
    out=in(posy(1)-3:posy(end),posx(1)-3:maxx,:);    
    
    bw=prepro(out);
    [N,M]=size(bw);
    [lines,width]=linedetect(bw,2);
    line1=[lines(1).point1;lines(1).point2];
    line2=[lines(2).point1;lines(2).point2];
    if line1(1,2)>line2(1,2)
        temp=line1;
        line1=line2;
        line2=temp;
    end
    left=1;
    right=(line1(2,1)+line2(2,1))/2;
    right=floor(right+(M-right)*2/3);
    top=1;
    middle=(line1(1,2)+line1(2,2))/2;
    bottom=floor((line2(1,2)+line2(2,2))/2-width);
    out1=out(top:middle-width,left:right,:);   
    out2=out(middle+width/2:bottom,left:right,:); 
end

function out=rectup(in)
    out=imresize(in,2,'bilinear');
    gray=rgb2gray(out);       
    bw=edge(gray,'canny');
    [B,L]=bwboundaries(bw);
    STATS=regionprops(L,'MajorAxisLength');%统计几何特征
    len=length(STATS);
    [N,M]=size(gray);
    for i=1:len   
        if STATS(i).MajorAxisLength<M/8
            bw(L==i)=0;
        end
    end
    bw=restore(bw);
    bw=imfill(bw,'holes');
    se=strel('square',3);
    bw=imopen(bw,se);
    [B,L]=bwboundaries(bw);
    STATS=regionprops(L,'BoundingBox');%统计几何特征
    len=length(STATS);
    figure,imshow(out),title('个人信息区定位');
    hold on;
    for i=1:len
        rect=STATS(i).BoundingBox;
        rectangle('position',rect,'edgecolor','b');
    end
end
function out=restore(in)
    [N,M]=size(in);
    for x=2:M-1
        for y=2:N-1
            i=x;  j=y;
            while j<=N-1 && i<=M-1 && i>=2 && j>=2 && in(j,i)~=0
                neighbor=[in(j-1,i-1) in(j-1,i) in(j-1,i+1) in(j,i-1) in(j,i+1) in(j+1,i-1) in(j+1,i) in(j+1,i+1)];
                pos=find(neighbor~=0);
                if size(pos)==1
                    switch pos(1)
                        case 1
                            i=i+1;j=j+1;     
                        case 2
                            j=j+1;
                        case 3
                            i=i-1;j=j+1;
                        case 4
                            i=i+1;
                        case 5
                            i=i-1;
                        case 6
                            i=i+1;j=j-1;
                        case 7
                            j=j-1;
                        case 8
                            i=i-1;j=j-1;
                    end
                    in(j,i)=1;
                else
                    break;
                end
            end
        end
    end
    out=in;                        
end
function out=rectdown(in)
    hsv=rgb2hsv(in);
    s=hsv(:,:,2);
    v=hsv(:,:,3);
    [N,M]=size(v);
    sbw=imbinarize(s);
    se=strel('disk',3);
    sbw=imopen(sbw,se);

    [B,L]=bwboundaries(sbw);
    STATS=regionprops(L,'Area','BoundingBox');
    len=length(STATS);
    area=[];
    for i=1:len
        area=[area;STATS(i).Area];
    end
    [Y,Index]=sort(abs(area),'descend'); 
    if len>3
        count=3;
    else
        count=len;
    end
    for i=1:count
        rect=STATS(Index(i)).BoundingBox;
        v(rect(2):rect(2)+rect(4),rect(1):rect(1)+rect(3))=v(1,1);        
    end

    vbw=edge(v,'canny');
    [B,L]=bwboundaries(vbw);
    STATS=regionprops(L,'Area','MajorAxisLength','MinorAxisLength');%统计几何特征
    len=length(STATS);
    for i=1:len   
        if STATS(i).MajorAxisLength>M/16 || STATS(i).MinorAxisLength<3 || STATS(i).Area<10
            L(L==i)=0;
        end
    end
    L(L~=0)=1;
    se=strel('line',M/25,0);
    L=imclose(L,se);
    se=strel('line',N/35,90);
    L=imclose(L,se);
    se=strel('square',3);
    L=imopen(L,se);
    L=imfill(L,'holes');
    [B,L]=bwboundaries(L);
    STATS=regionprops(L,'BoundingBox');%统计几何特征
    len=length(STATS);
    figure,imshow(in),title('答题区定位');
    hold on;
    for i=1:len
        rect=STATS(i).BoundingBox;
        rectangle('position',rect,'edgecolor','b');
    end
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/949498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通信原理板块——基础知识(四)

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 10、确知信号的时域性质主要包括自…

自然语言处理(NLP)是什么?

NLP(自然语言处理) 和 Phoebe Liu 的简介 您有没有和聊天机器人互动过&#xff1f;或者您是否向虚拟助手&#xff0c;例如 Siri、Alexa 或您车上的车载娱乐系统发出过某些请求&#xff1f;您使用过在线翻译吗&#xff1f;我们大多数人都曾与这些人工智能 (AI) 互动过&#xff…

校园用电安全管理系统可以识别违规电器吗

校园用电安全管理系统是处理恶意用电问题有效手段之一&#xff0c;系统具有实时监测、异常预警、监测设备运行状态、远程控制用电等功能&#xff0c;可以从根本上管理学校用电量&#xff0c;制定合理的用电计划&#xff0c;限制用电成本&#xff0c;避免各种恶意用电行为&#…

windows环境搭建ELK

目录 资源下载&#xff08;8.9.1&#xff09; ES安装、注册、使用 Kibana安装、注册、使用 Logstash安装、注册、使用 Filebeat安装、使用&#xff08;如果只有一个数据流&#xff0c;则不需要使用filebeat&#xff0c;直接上logstash即可&#xff09; 资源下载&#xff0…

关于商品活动的H5页面技术总结

背景 在单个html文件里面使用vue3、jquery等其他第三方js库&#xff0c;实现规定的页面效果&#xff0c;其中主要功能是从商品json数据中读取数据&#xff0c;然后可以通过搜索框、下拉框、左侧菜单来筛选商户信息。 页面布局 技术要点&#xff1a; 1、通过路由来进行页面布…

Django实现音乐网站 ⒁

使用Python Django框架制作一个音乐网站&#xff0c; 本篇主要是歌手页-全部歌手页功能开发。 目录 分出首页样式内容 创建首页样式文件 首页引入样式文件 全部歌手列表 创建路由 显示视图 引入分页实现库 视图方法 创建歌手首页 增加歌手跳转 导航条改活 首页增加…

移动端通讯录相关代码

vue3更新版本 附件地址 代码在附件里噜 太多了不好贴

EMC 性能优异的ISO7761QDBQQ1、ISO7762QDWQ1、ISO7741QDWWQ1、ISO7710QDRQ1汽车类数字隔离器

一、EMC 性能优异的 ISO776x-Q1 高速、增强型六通道数字隔离器 ISO776x-Q1 器件是高性能六通道数字隔离器&#xff0c;可提供符合 UL 1577 的 5000VRMS&#xff08;DW 封装&#xff09;和 3000VRMS&#xff08;DBQ 封装&#xff09;隔离额定值。该系列器件还通过了VDE、CSA、T…

2023_Spark_实验二:IDEA安装及配置

一、下载安装包 链接&#xff1a;百度网盘 请输入提取码 所在文件夹&#xff1a;大数据必备工具--》开发工具(前端后端)--》后端 下载文件名称&#xff1a;ideaIU-2019.2.3.exe &#xff08;喜欢新版本也可安装新版本&#xff0c;新旧版本会存在部分差异&#xff09; IDEA …

极智AI | 地平线天工开物工具链部署流程详解

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文来介绍一下 地平线天工开物工具链部署流程详解。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq 地平线天工开物工具链从完备…

【AI】数学基础——线代(向量部分)

参考&#xff1a; kenjihiranabe——The-Art-of-Linear-Algebra-zh-CN 详细计算方法与理论&#xff1a;见 矩阵论 线性代数的本质在于将具体事物抽象为数学对象&#xff0c;并描述其静态和动态特性 最基本的概念是 set 集合的定义是由某些具有某些共性的对象汇总成的集体。 将这…

go语言 go mod生成

1. go hello world 创建文件夹gotest&#xff0c;在其中创建test1.go文件&#xff0c;并写入 package mainimport ("fmt" )func main() {fmt.Println("hello world") } 运行命令 go run test1.go 可以看到输出hello world 2. cli 命令行的使用 代码如下…

Git 速查表:中级用户必备的 12 个 Git 命令

本文译自&#xff1a;Git Cheat Sheet: 12 Essential Git Commands For Intermediate Users&#xff0c;原文链接&#xff1a;https://initialcommit.com/blog/git-cheat-sheet-intermediate 本系列共有三篇文章&#xff0c;本文是第二篇&#xff1a; Git Cheat Sheet: 12 Ess…

了解 HarmonyOS

引言 在开始 HarmonyOS 开发之前&#xff0c;了解其背景、特点和架构是非常重要的。本章将为你提供一个全面的 HarmonyOS 概览。 目录 什么是 HarmonyOS HarmonyOS 的发展历程 HarmonyOS 的特点 HarmonyOS 的架构 HarmonyOS 与其他操作系统的比较 1. 什么是 HarmonyOS …

如何在WSL上导入任何Linux发行版

文章目录 一、准备1. 开启WSL相关功能2. 升级WSL3. 设置默认的wsl版本 二、通过 Microsoft Store 安装 Linux1. 查看 Microsoft Store 有哪些可安装的 Linux 发行版2. 安装 Linux 发行版3. 查看已安装的 Linux 发行版4. 启动Linux发行版 三、通过Linux发行商提供的tar文件安装1…

[PyTorch][chapter 53][Auto Encoder 实战]

前言&#xff1a; 结合手写数字识别的例子&#xff0c;实现以下AutoEncoder ae.py: 实现autoEncoder 网络 main.py: 加载手写数字数据集&#xff0c;以及训练&#xff0c;验证&#xff0c;测试网络。 左图&#xff1a;原图像 右图&#xff1a;重构图像 ----main----- 每轮训…

DHCP 服务器部署

| DHCP - - > Dynamic Host Configuration Protocol 动态主机配置协议 背景 任何一个需要上网的设备&#xff0c;都必须得有IP地址&#xff0c;子网掩码&#xff0c;网关&#xff0c;等等网络参数。比如&#xff1a;手机&#xff0c;电脑&#xff0c;智能手表&#xff0c…

【SpringBoot学习笔记】02.静态资源与首页订制

静态资源 Spring Boot 通过 MVC 的自动配置类 WebMvcAutoConfiguration 为这些 WebJars 前端资源提供了默认映射规则&#xff0c;部分源码如下。 jar包&#xff1a; JAR 文件就是 Java Archive File&#xff0c;顾名思意&#xff0c;它的应用是与 Java 息息相关的&#xff0c;…

IDEA 报 Cannot resolve symbol ‘HttpServletResponse‘ 解决

springboot2版本换成springboot3之后&#xff0c;代码这里突然报红了&#xff0c; 首先要淡定&#xff0c;把原先Import的引入删掉&#xff0c;重新引入试试呢&#xff0c;是不是很简单哈哈。 原来&#xff0c;springboot3的路径是&#xff1a; import jakarta.servlet.http…