图像分割基本知识
计算机视觉和图像处理
- Tensorflow入门
- 深度神经网络
- 图像分类
- 目标检测
- 图像分割
图像分割
- 一、目标分割
- 1.1 图像分割的定义
- 1.2 任务类型
- 1.2.1 任务描述
- 1.2.2 任务类型
- 二、语义分割
- 2.1 FCN网络
- 2.1.1网络结构
- 2.2 Unet网络
- 三、UNet案例
- 3.1 数据集获取
- 3.1.1 设置相关信息
- 3.1.2 图像展示
- 3.1.3 数据集生成器
- 3.2 模型构建
- 3.2.1 编码部分
- 3.2.2 解码部分
- 3.2.3 模型构建
- 3.3 模型训练
- 3.3.1 数据集划分
- 3.3.2 数据获取
- 3.3.3 模型编译
- 3.3.4 模型训练
- 3.4 模型预测
一、目标分割
- 图像分类旨在判断该图像所属类别
- 目标检测是在图像分类的基础上,进一步判断图像中的目标具体在图像的什么位置,通常是以外包矩阵的形式表示。
- 图像分割是目标检测更进阶的任务,目标检测只需要框出每个目标的包围盒,语义分割需要进一步判断图像中哪些像素属于哪个目标。但是,语义分割不区分属于相同类别的不同实例。
1.1 图像分割的定义
在计算机视觉领域,图像分割指的是将数字图像细分为多个图像子区域(像素的集合)的过程,并且同一个子区域内的特征具有一定相似性,不同子区域的特征呈现较为明显的差异。
1.2 任务类型
1.2.1 任务描述
我们的目标是输入一个RGB彩色图片或者一个灰度图,然后输出一个包含各个像素类别标签的分割图。
预测目标可以采用one-hot编码,即为每一个可能的类创建一个输出通道。通过取每个像素点在各个通道的argmax可以得到最终的预测分割图。
1.2.2 任务类型
目前的图像分割任务主要有两类: 语义分割和实例分割
- 语义分割就是把图像中每个像素赋予一个类别标签
- 实例分割,相对于语义分割来讲,不仅要区分不同类别的像素,还需要需要对同一类别的不同个体进行区分。如下图所示,不仅需要进行类别的划分,还要将各个个体划分出来:羊1,羊2,羊3,羊4,羊5等。
二、语义分割
2.1 FCN网络
FCN用于图像语义分割,自从该网络提出后,就成为语义分割的基本框架,后续算法基本都是在该网络框架中改进而来。
简而言之,FCN和CNN的区别就是:CNN卷积层之后连接的是全连接层;FCN卷积层之后仍然连卷积层,输出的是与输入大小相同的特征图。
2.1.1网络结构
FCN是一个端到端,像素对像素的全卷积网络,用于进行图像的语义分割。整体的网络结构分为两个部分:全卷积部分和上采样部分。
- 全卷积部分
全卷积部分使用经典的CNN网络(以AlexNet网络为例),并把最后的全连接层换成1x1卷积,用于特征提取。 - 上采用部分
上采样部分将最终得到的特征图上采样得到原图像大小的语义分割结果。
在这里采用的上卷积方法是反卷积,也叫转置卷积,反卷积是一种特殊的正向卷积,通俗的讲,就是输入补0+卷积。先按照一定的比例通过补0来扩大输入图像的尺寸,再进行正向卷积即可。
2.2 Unet网络
Unet网络是建立再FCNN网络基础上的。
整个网络由编码部分(左)和解码部分(右)组成,类似于一个大大的u字母,具体介绍如下:
1.编码部分是典型的卷积网络架构
编码部分的主要功能是提取输入图像的特征。通过一系列的卷积层和池化层(通常是最大池化层),编码部分逐渐减少特征图的尺寸,同时增加特征图的深度(即特征图的数量)。
- 架构中含有一种重复结构,每次重复中有2个3x3卷积层、非线性ReLU层和一个2x2 max pooling层(stride为2)。
- 每一次下采样后我们都把特征通道的数量加倍。
下采样(编码部分):减少数据点的数量或降低数据的分辨率,用于减少数据量、简化模型训练等
- 解码部分也使用了类似的模式:
解码部分的主要功能是恢复特征图的空间分辨率,最终生成与输入图像相同尺寸的分割结果。解码部分通过一系列的上采样操作(如转置卷积或上采样层)和卷积操作来逐步恢复特征图的尺寸。
- 每一步都首先使用反卷积,每次使用反卷积都将特征通道数量减半,特征图大小加倍。
- 反卷积过后,将反卷积的结果与编码部分中对应步骤的特征图拼接起来。
- 编码部分中的特征图尺寸稍大,将其修建过后进行拼接。
- 对拼接后的map再进行2次3x3的卷积。
- 最后一层的卷积核大小为1x1,将64通道的特征图转化为特定类比数量的结果。
上采样(解码部分):增加数据点的数量或提高数据的分辨率,用于恢复细节、改善图像质量等。
三、UNet案例
Oxford-IIIT Pet Dataset宠物图像分割数据集,包含37种宠物类别,其中有12种猫的类别和25种狗的类别,每个类别大约有200张图片,所有图像都具有品种,头部ROI和像素级分割的标注,如下图所示:
import os
from IPython.display import Image,display
from tensorflow.keras.preprocessing.image import load_img
import PIL
from PIL import ImageOps
3.1 数据集获取
3.1.1 设置相关信息
# 图像位置
input_dir = 'segdata/images/'
# 图像路径
input_img_path = sorted([os.path.join(input_dir,fname) for fname in os.listdir(input_dir) if fname.endswith('jpg')])
input_img_path
# 标注信息
target_dir = 'segdata/annotations/trimaps/'
# 目标值
target_img_path = sorted([os.path.join(target_dir,fname) for fname in os.listdir(target_dir) if fname.endswith('png') and not fname.startswith('.')])
target_img_path
# 图像大小及类别信息
img_size = (160,160)
batch_size = 32
num_classes = 4
3.1.2 图像展示
display(Image(input_img_path[10]))
img = PIL.ImageOps.autocontrast(load_img(target_img_path[10]))
display(img)
3.1.3 数据集生成器
from tensorflow import keras
import numpy as np
# 数据集获取类
class OxfordPets(keras.utils.Sequence):# 初始化def __init__(self,batch_size,img_size,input_img_path,target_img_path):self.batch_size = batch_sizeself.img_size = img_sizeself.input_img_path = input_img_pathself.target_img_path = target_img_path# 迭代次数def __len__(self):return len(self.target_img_path)//self.batch_size # 或者batch数据def __getitem__(self,idx):# 当前批次对应的索引值i = idx * self.batch_size# 图像数据batch_input_img_path = self.input_img_path[i:i+self.batch_size]# 标签数据batch_target_img_path = self.target_img_path[i:i+self.batch_size]# 构建送入网络中图像数据x = np.zeros((self.batch_size,)+self.img_size+(3,),dtype='float32')for j,path in enumerate(batch_input_img_path):img = load_img(path,target_size=self.img_size)# 将PIL图像对象转换成Numpy数组x[j] = keras.preprocessing.image.img_to_array(img)y = np.zeros((self.target_size,) + self.img_size +(1,),dtype='uint8')for j,path in enumerate(batch_target_img_path):img = load_img(path,target_size=self.img_size,color_mode="grayscale")# 再数组的末尾增加一个维度y[j] = np.expand_dims(img,2)return x,y
3.2 模型构建
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.layers import Input,Conv2D,Conv2DTranspose
from tensorflow.keras.layers import MaxPooling2D,Cropping2D,Concatenate,ZeroPadding2D
from tensorflow.keras.layers import Lambda,Activation,BatchNormalization,Dropout
from tensorflow.keras.models import Model
3.2.1 编码部分
# 下采样:输出张量,卷积核个数
def downsampling_block(input_tensor,filters):# 输入层x = Conv2D(filters,kernel_size=(3,3),padding='same')(input_tensor)# BN层x = BatchNormalization()(x)# 激活层x = Activation('relu')(x)# 卷积x = Conv2D(filters,kernel_size=(3,3),padding='same')(x)# BN层x = BatchNormalization()(x)# 激活层x = Activation('relu')(x)# 返回return MaxPooling2D(pool_size=(2,2))(x),x
3.2.2 解码部分
# 上采样:输入张量,特征融合张量(编码部分产生的特征图),卷积核个数
def upsampling_block(input_tensor,skip_tensor,filters):# 反卷积x = Conv2DTranspose(filters,kernel_size=(3,3),strides=2,padding='same')(input_tensor)# 获取当前特征图的尺寸_,x_hight,x_width,_ = x.shape# 获取特征融合图的尺寸_,s_hight,s_width,_ = skip_tensor.shape# 获取特征图大小差异h_crop = x_hight - s_hightw_crop = x_width - s_width# 若特征图大小相同则不进行裁剪if h_crop == 0 and w_crop ==0:y = skip_tensorelse:cropping = ((h_crop//2,h_crop-h_crop//2),(w_crop//2,w_crop-w_crop//2))y = ZeroPadding2D(cropping=cropping)(skip_tensor)# 特征融合x = Concatenate()([x,y])# 卷积x = Conv2D(filters,kernel_size=(3,3),padding='same')(x)# BN层x = BatchNormalization()(x)# 激活层x = Activation('relu')(x)# 卷积x = Conv2D(filters,kernel_size=(3,3),padding='same')(x)# BN层x = BatchNormalization()(x)# 激活层x = Activation('relu')(x)return x
3.2.3 模型构建
def unet(imagesize,classes,fetures=64,depth=3):# 定义输入inputs = keras.Input(shape=(img_size)+(3,))x = inputs# ⽤来存放进⾏特征融合的特征图skips=[]# 构建编码部分for i in range(depth):# 下采样x,x0 = downsampling_block(x,fetures)skips.append(x0)# 特征翻倍fetures *=2# 卷积x = Conv2D(fetures,kernel_size=(3,3),padding="same")(x)# BN层x = BatchNormalization()(x)# 激活层x = Activation("relu")(x)# 卷积x = Conv2D(fetures,kernel_size=(3,3),padding='same')(x)# BN层x = BatchNormalization()(x)# 激活层x = Activation("relu")(x)# 构建解码部分for i in reversed(range(depth)):# 深度增加,特征图通道减半fetures //= 2# 下采样x = upsampling_block(x,skips[i],fetures)# 卷积x = Conv2D(fetures,kernel_size=(1,1),padding="same")(x)# 激活outputs = Activation("softmax")(x)# 模型定义model = keras.Model(inputs,outputs)return model
model = unet(img_size,4)
model.summary()
3.3 模型训练
3.3.1 数据集划分
import random
# 验证集数量
val_sample = 500
# 将数据集打乱
random.Random(100).shuffle(input_img_path)
random.Random(100).shuffle(target_img_path)
# 训练集
train_input_img_path = input_img_path[:-val_sample]
train_target_img_path = target_img_path[:-val_sample]
# 验证集
test_input_img_path = input_img_path[-val_sample:]
test_target_img_path = target_img_path[-val_sample:]
3.3.2 数据获取
train_gen = OxfordPets(batch_size,img_size,train_input_img_path,train_target_img_path)
test_gen = OxfordPets(batch_size,img_size,test_input_img_path,test_target_img_path)
3.3.3 模型编译
model.compile(optimizer=tf.keras.optimizers.RMSprop(),loss=tf.keras.losses.sparse_categorical_crossentropy)
3.3.4 模型训练
model.fit(train_gen,epochs=8,validation_data=test_gen,steps_per_epoch=1,validation_steps=1)
3.4 模型预测
# predict = model.predict(test_gen)
predictions = []# 获取数据集的大小
steps = len(test_gen)# 分批进行预测
for i in range(steps):# 获取下一个批次的数据batch = next(iter(test_gen))# batch 是一个元组,第一个元素是输入数据,第二个元素是标签batch_inputs, batch_labels = batch# 使用输入数据进行预测batch_predictions = model.predict(batch_inputs)predictions.append(batch_predictions)# 合并所有的预测结果
final_predictions = np.concatenate(predictions, axis=0)
def display_mask(i):# 获取第i个样本预测结果mask = np.argmax(final_predictions[i],axis=-1)# 扩展维度mask =np.expand_dims(mask,axis=-1)# 将掩码转换为PIL Image对象img = keras.preprocessing.image.array_to_img(mask)# 增强图像对比度img = PIL.ImageOps.autocontrast(img)display(img)
display(Image(filename=test_input_img_path[5]))
img = PIL.ImageOps.autocontrast(load_img(test_target_img_path[5]))
display(img)
display_mask(5)
**这人工智能不学也罢,没有个好电脑根本跑不出来,只能降低epoch,降低batch_size,分批次去预测模型,勉强可以训练预测模型,但结果就有点不敬人意了
相关文章:

图像分割基本知识
计算机视觉和图像处理 Tensorflow入门深度神经网络图像分类目标检测图像分割 图像分割 一、目标分割1.1 图像分割的定义1.2 任务类型1.2.1 任务描述1.2.2 任务类型 二、语义分割2.1 FCN网络2.1.1网络结构 2.2 Unet网络 三、UNet案例3.1 数据集获取3.1.1 设置相关信息3.1.2 图像…...

LIN总线CAPL函数——干扰LIN帧响应段(linInvertRespBit )
🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】🍅 玩转CANoe&…...
【30天玩转python】网络编程基础
网络编程基础 网络编程是指编写能够在网络上进行通信的程序,通过网络进行数据的发送与接收。Python 提供了许多库和工具来进行网络编程,如 socket、urllib 和 requests。在这篇文章中,我们将介绍网络编程的基础知识,并演示如何使…...

【PCB工艺】如何实现PCB板层间的互连
系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言①、什么是通孔②、通孔是怎样产生的③、通孔种类④、盘中孔⑤、设计建议 前言 送给大学毕业后找不到奋斗方向的你…...
FastAPI--如何自定义Docs UI,包括多个APP、静态资源、元数据等
如何mount 一个FastAPI Application? “Mounting” means adding a completely “independent” application in a specific path, that then takes care of handling everything under that path, with the path operations declared in that sub-application. 示例代码 主…...

【FPGA XDMA AXI Bridge 模式】PCIe:BARs 和 AXI:BARs 含义解析
一. XDMA IP核两种模式 Xilinx的 DMA/Bridge Subsystem for PCI Express IP核中,支持普通的XDMA模式,但是这种模式只允许主机端发起PCIe 读写请求,FPGA内部无法主动发起读写请求,也即FPGA无法主动读写HOST的内存。 而该IP核的另…...

嵌入式-QT学习-小练习
1. 实现多窗口 2. 给按键增加图标 3. 动图展示 结果演示: Mul_Con main.cpp #include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }一、第一个窗口展示 …...
使用 Flask-Limiter 和 Nginx 实现接口访问次数限制
在现代 Web 应用中,针对敏感接口(如短信验证码、登录接口等)的访问次数限制至关重要。通过设置合理的限流策略,可以有效防止接口滥用,避免过多的资源消耗,并提升安全性。本文将通过 Nginx 和 Flask-Limiter…...

【数据结构】排序算法---冒泡排序
文章目录 1. 定义2. 算法步骤3. 动图演示4. 性质5. 算法分析6. 代码实现C语言PythonJavaCGo 结语 1. 定义 冒泡排序(英语:Bubble sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的…...
mysql数据库中事务锁的机制
读锁又称为共享锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。 写锁又称为排他锁,简称X锁,排他锁就是不能与其他所并存,如一个事务获取了一个…...
并发工具类-CountDownLatch
CountDownLatch 是 Java 中提供的一种非常有用的并发工具类,位于 java.util.concurrent 包中。它可以使一个或多个线程等待其他线程完成一组特定的操作后再继续执行。CountDownLatch 通过维护一个计数器来实现这一点,计数器的初始值由构造函数设定。每当…...

进程的重要函数
进程的重要函数: fork函数 了解fork函数 通过调用fork()函数,则会产生一个新的进程。调用fork()函数的进程叫做 父进程,产生的新进程则为子进程。 其编码过程: 1.函数功能: 函数头文件 #include <sys/types.h> #include <unistd.h> 函数…...
python 实现average median平均中位数算法
average median平均中位数算法介绍 平均(Mean)和中位数(Median)是统计学中常用的两个概念,用于描述一组数据的中心趋势,但它们并不是算法,而是数据处理的结果。不过,我可以解释如何…...
HTML概述
1. HTML概述 1.1 HTML定义 HTML超文本标记语言,其中超文本是链接,标记也叫标签(即带尖括号的文本)。 1.2 HTML基本骨架 HTML基本骨架是网页模板。 <html><head><title>网页的标题</title></head&…...

【FFT】信号处理——快速傅里叶变换【通俗易懂】
快速傅里叶变换(Fast Fourier Transform, FFT)是一种用于将信号从时间域转换到频率域的算法。 傅里叶变换的核心思想是:任何周期性信号都可以分解成多个不同频率的正弦波或余弦波的叠加。 简单来说,FFT可以帮助我们理解一个信号…...
电脑升级WIN11之后需要注意哪些东西
1.记事本,在前单位时,电脑升级后,记事本会需要手动更新,或手动安装 2.任务栏,WIN11默认任务栏在中间位置,想要调成WIN10一样的位置,分享两个方法 拖拽法(适用于Windows 11 2022年1…...
GEE 教程:利用sentinel-5p数据进行长时序CO一氧化碳的监测分析并结合夜间灯光数据分析
目录 简介 数据 哨兵5号 NOAA/VIIRS/DNB/MONTHLY_V1/VCMCF 函数 ui.Chart.image.series(imageCollection, region, reducer, scale, xProperty) Arguments: Returns: ui.Chart 代码 结果 简介 利用sentinel-5p数据进行长时序CO一氧化碳的监测分析并结合夜间灯光数据…...

【教程】鸿蒙ARKTS 打造数据驾驶舱---前序
鸿蒙ARKTS 打造数据驾驶舱 前面2章我介绍了如何通过定义View绘制箭头以及圆形进度,初步了解了鸿蒙如何进行自定义View。接下来我将通过我最近在带的一个VUE的项目,简单实现了几个鸿蒙原生页面。帮助大家快速上手纯血鸿蒙开发. 本项目基于Api11Stage模…...

Html css样式总结
1.Html css样式总结 CSS 定义 中文名称:层叠样式表 。 英文全称:Cascading Style Sheets ,简称CSS。在网页制作时采用CSS技术,可以有效地对页面的布局、字体、颜色、背景和其它效果实现更加精确的控制。 (1)…...
决策树基础概论
1. 概述 在机器学习领域,决策树(Decision Tree) 是一种高度直观且广泛应用的算法。它通过一系列简单的是/否问题,将复杂的决策过程分解为一棵树状结构,使得分类或回归问题的解决过程直观明了。决策树的最大特点在于可…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
python爬虫——气象数据爬取
一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用: 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests:发送 …...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...