图片分割处理(以玉米颗粒的图片分割为例)

问题:

为完成玉米颗粒分类任务,现需要处理训练图片,将以下图片中的玉米颗粒进行分割:
在这里插入图片描述
目标:
在这里插入图片描述

操作步骤(完整代码附在最后,该部分为解释说明)

一、提取通道并进行二值化

# 提取蓝色通道
blue_channel = image[:, :, 0]
# 二值化图像
threshold = 150  # 阈值
_, binary_image = cv2.threshold(blue_channel, threshold, 255, cv2.THRESH_BINARY)

结果:
在这里插入图片描述
说明:

1、cv2.threshold()
retval, threshold_image = cv2.threshold(src, thresh, maxval, type[, dst])参数:
src: 输入的单通道图像。这里是提取的蓝色通道图像。
thresh: 阈值,将像素值分为大于等于阈值和小于阈值的两部分。
maxval: 分类后大于等于阈值的像素值,通常设置为最大值255type: 阈值化的类型,包括以下几种:
cv2.THRESH_BINARY: 如果像素值大于等于阈值,设置为 maxval,否则设置为0。
cv2.THRESH_BINARY_INV: 如果像素值大于等于阈值,设置为0,否则设置为 maxval。
cv2.THRESH_TRUNC: 如果像素值大于等于阈值,保持原始值,否则设置为阈值。
cv2.THRESH_TOZERO: 如果像素值大于等于阈值,保持原始值,否则设置为0。
cv2.THRESH_TOZERO_INV: 如果像素值大于等于阈值,设置为0,否则保持原始值。
dst(可选):输出图像,与输入图像大小和类型相同,通常不需要指定。返回值:
retval:选择的阈值,通常与输入阈值 thresh 相同,但如果使用自适应阈值化时,可能不同。
threshold_image:阈值化后的图像,是一个与输入图像大小和类型相同的单通道灰度图像。
2、为什么选择提取蓝色通道?

黄色是由红色和绿色混合而成的颜色,因此在RGB颜色模型中,黄色物体在红色通道和绿色通道上都具有较高的强度,而在蓝色通道上的强度较低。提取蓝色通道后,黄色物体通常会变得比背景更暗,从而更容易与背景区分开来,有助于突出玉米颗粒并进行后续的图像处理和分割。
那么怎么判断出这个物体的颜色和哪个通道强度有关呢:可以分别将图像分离成不同的颜色通道(红色、绿色和蓝色),然后可以查看每个通道的图像。

blue_channel = image[:, :, 0]  # 蓝色通道
green_channel = image[:, :, 1]  # 绿色通道
red_channel = image[:, :, 2]  # 红色通道
3、二值化阈值的选择

由于在这个任务中,训练集图像具有一致的背景和物体颜色,因此可以简单地手动选择一个固定的阈值。但如果图片包含了更多场景,可以选择其他的阈值设置方式,如自适应阈值等。

二、反转图像像素值

inverted_image = cv2.bitwise_not(binary_image)

结果:
在这里插入图片描述
说明:

1、cv2.bitwise_not()
result = cv2.bitwise_not(src[, dst[, mask]])参数:
src:输入图像,可以是单通道或多通道的图像。
dst:输出图像,与输入图像具有相同的大小和通道数。如果未提供,函数会创建一个新的图像来存储结果。
mask:可选参数,用于指定一个掩模,只有掩模中值为非零的像素才会执行位反转操作。
2、为什么要反转图像像素值?

后续使用到的形态学操作和轮廓查找是基于目标区域是白色的前提下进行的,反转操作是为了提高分割的准确性和可靠性。

三、闭运算

# 定义结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))  # 使用矩形结构元素
# 闭运算
closed_image = cv2.morphologyEx(inverted_image, cv2.MORPH_CLOSE, kernel)

结果:
在这里插入图片描述
说明:

1、cv2.getStructuringElement()
element = cv2.getStructuringElement(shape, ksize[, anchor])cv2.getStructuringElement 函数是OpenCV库中用于创建图像处理中的结构元素的函数。
结构元素通常用于形态学操作,如腐蚀、膨胀、开运算、闭运算等。
结构元素可以是不同形状的内核,例如矩形、椭圆、十字形等,
用于定义操作的邻域,例如腐蚀和膨胀操作中的探测窗口。参数:
shape:结构元素的形状,可以是以下之一:
cv2.MORPH_RECT:矩形结构元素
cv2.MORPH_CROSS:十字形结构元素
cv2.MORPH_ELLIPSE:椭圆形结构元素
ksize:结构元素的大小,通常以 (width, height) 或者单个整数值指定。
anchor:可选参数,结构元素的锚点位置,默认为结构元素的中心。

注:结构元素的不同形状和大小可以用于不同的任务和图像处理需求。例如,矩形结构元素通常用于一般形态学操作,椭圆结构元素可以更好地适应曲线或圆形物体的形状,十字形结构元素可用于特定方向的操作,如边缘检测。

2、cv2.morphologyEx()
result = cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])参数:
src:输入图像,通常是二进制图像(黑白图像)。
op:形态学操作的类型,可以是以下之一:
cv2.MORPH_ERODE:腐蚀操作
cv2.MORPH_DILATE:膨胀操作
cv2.MORPH_OPEN:开运算(先腐蚀后膨胀)
cv2.MORPH_CLOSE:闭运算(先膨胀后腐蚀)
其他高级形态学操作如梯度、礼帽、黑帽等。
kernel:形态学操作的内核(结构元素),用于定义操作的邻域。可以使用 cv2.getStructuringElement 函数创建内核。
dst:可选参数,输出图像,用于存储结果。如果不提供,函数会创建一个新的图像。
anchor:可选参数,内核的锚点位置,默认为内核的中心。
iterations:可选参数,操作的迭代次数,默认为1。
borderType:可选参数,边界处理方式,默认为 cv2.BORDER_CONSTANT。
borderValue:可选参数,当边界处理方式为 cv2.BORDER_CONSTANT 时使用的边界值,默认为0

cv2.morphologyEx()函数根据指定的操作类型 op 和内核 kernel,对输入图像进行操作。
1、腐蚀:缩小白色区域,使物体变小。它将内核滑动到图像上,只有当内核下的所有像素都是白色时,中心像素才保持白色,否则变成黑色。
2、膨胀:扩展白色区域,使物体变大。它将内核滑动到图像上,将内核下的任何白色像素(像素值为255)扩展到中心像素位置,从而使前景区域变大。
3、开运算:先腐蚀后膨胀的组合操作,用于去除小白色噪点或分离物体,平滑物体的边界。
4、闭运算:先膨胀后腐蚀的组合操作,用于关闭物体之间的小孔或连接物体。从结果对比中可以发现小孔面积减小。

四、填充轮廓

# 寻找轮廓
contours, _ = cv2.findContours(closed_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 创建一个空白的二值掩模
mask = np.zeros_like(image[:, :, 0], dtype=np.uint8)
# 填充轮廓
filled_image = cv2.drawContours(mask, contours, -1, (255, 255, 255), thickness=cv2.FILLED)

结果:
在这里插入图片描述
说明:

1、cv2.findContours()
contours, hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])参数:
image:输入的二值化图像,通常是一个黑白图像(只包含两个像素值,如0255)。
mode:轮廓检索模式,是一个表示如何检索轮廓的标志。常用的模式包括:
cv2.RETR_EXTERNAL:只检测最外层的轮廓。
cv2.RETR_LIST:检测所有轮廓并将它们存储在列表中,不建立层次关系。
cv2.RETR_CCOMP:检测所有轮廓并将它们存储在两层的层次结构中。
cv2.RETR_TREE:检测所有轮廓并重建一个完整的轮廓层次。
method:轮廓逼近方法,是一个表示如何逼近轮廓的标志。常用的方法包括:
cv2.CHAIN_APPROX_SIMPLE:压缩水平、垂直和对角方向的像素,只保留端点。
cv2.CHAIN_APPROX_TC89_L1:使用 Teh-Chin 近似算法。
cv2.CHAIN_APPROX_TC89_KCOS:使用 Teh-Chin 近似算法的一种改进版本。
contours:返回的轮廓列表,每个轮廓是一个表示对象边界的点的集合。
hierarchy:可选参数,返回的轮廓层次结构信息。在某些情况下,可以用于分析轮廓之间的关系。
offset:可选参数,轮廓点坐标的偏移量。返回值:
contours:包含检测到的轮廓的列表,每个轮廓是一个点的集合。
hierarchy:包含轮廓层次结构信息的列表。
2、二值掩膜

在图像处理中,二值掩膜是一种用于标记图像中某些区域的图像,通常是黑白图像,其中白色像素表示感兴趣的区域,而黑色像素表示不感兴趣的区域。它是一种用于遮罩或选择特定图像区域的工具。

np.zeros_like(image[:, :, 0], dtype=np.uint8)这个操作的目的是创建一个黑色背景的图像:
以输入图像 image 中的一个通道(通常是蓝色通道,即 image[:, :, 0])作为模板,
创建一个与模板图像具有相同形状的全零图像,其中所有像素值都初始化为零。
使用 dtype=np.uint8 指定了像素值的数据类型为无符号8位整数,即像素值的范围在 0255 之间。

这个全零图像用作后续的轮廓填充操作的目标图像,轮廓填充会将感兴趣的区域标记为白色(255),而不感兴趣的区域保持黑色(0)。

3、cv2.drawContours()
cv2.drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel, offset)参数:
image: 要在其上绘制轮廓的图像。
contours: 要绘制的轮廓,通常是通过 cv2.findContours 函数获得的轮廓列表。
contourIdx: 要绘制的轮廓的索引,如果为负数,将绘制所有轮廓。
color: 绘制轮廓的颜色,通常是一个三元组 (B, G, R),其中 B、G、R 分别表示蓝色、绿色和红色的颜色通道值。可以用 (0, 255, 0) 表示绿色。
thickness: 绘制轮廓线的厚度,如果设置为负数或 cv2.FILLED,则填充轮廓内部。
lineType: 线的类型,通常使用默认值 8。
hierarchy: 轮廓的层次信息,通常不需要手动指定。
maxLevel: 最大层次级别,通常使用默认值 0。
offset: 绘制轮廓时的偏移,通常使用默认值 (0, 0)

补充:

在以上步骤处理的基础上,我们会遍历得到的轮廓列表,对图片进行剪裁,由于闭运算之后的图片会存在白色噪点,因此它们也会加入到轮廓列表中,因此,我们需要设置面积阈值,筛选掉小面积的轮廓。但可以发现,文章最开头的输出仍包含一张与待测目标物体无关的corn_0.jpg图。
在这里插入图片描述
为了解决这个问题,我们需要尽可能地减少白色早点的产生,意味着我们需要做进一步的腐蚀操作,将白色噪点去掉。为了减小腐蚀带来的目标物体的信息丢失,在腐蚀后再进行膨胀操作,扩大目标物体的区域范围。因此我们再次进行开运算。

# 闭运算
closed_image = cv2.morphologyEx(inverted_image, cv2.MORPH_CLOSE, kernel)
#开运算
closed_image2 = cv2.morphologyEx(closed_image, cv2.MORPH_OPEN, kernel)
# 寻找轮廓
contours, _ = cv2.findContours(closed_image2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

结果:
在这里插入图片描述
增加开运算后的分割效果:
在这里插入图片描述

完整代码

import os
import timeimport cv2
import numpy as npdef crop_corn():# 确保 "output" 文件夹存在output_folder = "output_p"if not os.path.exists(output_folder):os.makedirs(output_folder)# 加载图像image = cv2.imread("./input_p/image.jpg")# 提取蓝色通道blue_channel = image[:, :, 0]# 二值化图像threshold = 150  # 阈值_, binary_image = cv2.threshold(blue_channel, threshold, 255, cv2.THRESH_BINARY)# 反转图像像素值inverted_image = cv2.bitwise_not(binary_image)# 定义结构元素kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))  # 使用矩形结构元素# 闭运算closed_image = cv2.morphologyEx(inverted_image, cv2.MORPH_CLOSE, kernel)#开运算closed_image2 = cv2.morphologyEx(closed_image, cv2.MORPH_OPEN, kernel)# 寻找轮廓contours, _ = cv2.findContours(closed_image2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 创建一个空白的二值掩模mask = np.zeros_like(image[:, :, 0], dtype=np.uint8)# 填充轮廓filled_image = cv2.drawContours(mask, contours, -1, (255, 255, 255), thickness=cv2.FILLED)cv2.imwrite("filled_image.jpg",filled_image)# 寻找填充后的轮廓filled_contours, _ = cv2.findContours(filled_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 根据轮廓进行剪裁corn_images = []for contour in filled_contours:area = cv2.contourArea(contour)if area > 1000:  # 设置面积阈值,筛选掉小面积的轮廓x, y, w, h = cv2.boundingRect(contour)corn_image = image[y:y+h, x:x+w]corn_images.append(corn_image)# 保存剪裁下来的玉米颗粒for i, corn_image in enumerate(corn_images):# cv2.imwrite(f"corn_{i}.jpg", corn_image)  # 保存剪切下来的玉米颗粒图像output_filename = f"corn_{i}.jpg"output_path = os.path.join(output_folder, output_filename)cv2.imwrite(output_path, corn_image)if __name__ == "__main__":crop_corn()

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用ChatGPT写申请文书?国外大学对此有何看法?

现在,人工智能的发展确实引起了广泛的关注,尤其是在自然语言处理领域。 Chat GPT(Generative Pre-trained Transformer)作为一种人工智能驱动的自然语言处理工具,具有令人瞩目的功能。 它可以根据用户提出的需求&…

智慧工地工程项目管理平台源码,塔机安全监控管理系统;吊钩可视化管理系统;升降机监控系统;高支模监控系统;

智慧工地是指运用信息化手段,通过三维设计平台对工程项目进行精确设计和施工模拟,围绕施工过程管理,建立互联协同、智能生产、科学管理的施工项目信息化生态圈,并将此数据在虚拟现实环境下与物联网采集到的工程信息进行数据挖掘分…

Netflix 零配置服务网格与按需集群发现

本文翻译自由 David Vroom, James Mulcahy, Ling Yuan, Rob Gulewich 编写的 Netflix 博客 Zero Configuration Service Mesh with On-Demand Cluster Discovery。 Netflix 相信大家并不陌生,在 Spring Cloud 生态中就有 Netflix 全家桶。多年前,我也曾…

【计算机网络】——数据链路层(应用:介质访问控制)

//仅做个人复习和技术交流,图片取自王道考研,侵删 一、大纲 1、介质访问控制 信道划分介质访问控制 随机访问介质访问控制 2、局域网 3、广域网 4、数据链路层设备 二、介质访问控制 省流:把广播信道通过介质访问控制机制 逻辑上转换为 …

C#里面的三种定时计时器:Timer

在.NET中有三种计时器: 1、System.Windows.Forms命名空间下的Timer控件,它直接继承自Componet。Timer控件只有绑定了Tick事件和设置EnabledTrue后才会自动计时,停止计时可以用Stop()方法控制,通过Stop()停止之后,如果想…

vue点击pdf文件直接在浏览器中预览文件

好久没有更新文章了,说说为什么会有这篇文章呢,其实是应某个热线评论的要求出的,不过由于最近很长一段时间没打开csdn现在才看到,所以才会导致到现在才出。 先来看看封装完这个预览方法的使用,主打一个方便使用&#x…

MySQL - 关于约束类型和作用的介绍

约束的概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。 约束的作用:用于保证数据库中数据的正确性、完整性和一致性。 约束分类: 约束类型作用关键字非空约束限制该字段的数据不能为nullnot null唯一约束保证该…

网络编程-TCP协议(客户端和服务端)

需要了解UDP协议的,可以看往期文章 https://flypeppa.blog.csdn.net/article/details/133273416 TCP/IP参考模型 代码案例 服务端代码 package com.hidata.devops.paas.udp;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr…

使用Jaeger进行分布式跟踪:学习如何在服务网格中使用Jaeger来监控和分析请求的跟踪信息

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

硬件基本功--MOS管

一、上下拉电阻Rgs的作用 Rgs:经验值,一般取10K左右。 1. 上电时给MOS管的栅极一个确定的电平,防止上电时GPIO为高阻态时,MOS管的栅极电平不确定,从而受到干扰。 2. 断电时,如果MOS管是导通的状态&#xff…

什么是 Redis?

Redis 是一种基于内存的数据库,对数据的读写操作都是在内存中完成的,因此读写速度非常快,常用于缓存,消息队列,分布式锁等场景。 Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Has…

基于springboot+vue的大学生创新创业系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

【Vue】Mock.js介绍和使用与首页导航栏左侧菜单搭建

目录 一、Mock.js 1.1 mockjs介绍 1.2 mock.js安装与配置 1.2.1 安装mock.js 1.2.2 引入mock.js 1.3 mock.js的使用 1.3.1 准备模拟数据 1.3.2 定义拦截路由 1.3.3 测试 二、首页导航栏左侧菜单搭建 2.1 自定义界面组件 (完整代码) 2.2 配置路由 2.3 组件显示折叠和…

矿山定位系统-矿井人员定位系统在矿山自动化安全监控过程中的应用

一,矿井人员定位系统现阶段使用的必要性 1,煤矿开采是一项非常特殊的工作,现场属于非常复杂多变的环境,井下信号极差,数据传输非常不稳定,人员安全难以保证,煤矿企业一直在研究如何使用更合适的…

Linux学习之HIS部署(4)

ElasticSearch部署 ElasticSearch资源 RabbitMQ资源 ElasticSearch服务部署 #OpenJDK环境部署 [rootServices ~]# yum clean all; yum repolist -v ... Total packages: 8,265 [rootServices ~]# yum -y install java-1.8.0-openjdk-devel.x86_64 #安装OpenJDk ... Compl…

什么是LIMS(实验室信息管理系统)?LIMS软件有哪些功能?

LIMS 是实验室信息管理系统(Laboratory Information Management System)的缩写。LIMS 是一种软件,它可以帮助实验室收集、组织和跟踪其数据。这种系统可以提高实验室的效率,同时确保数据的准确性和一致性。 LIMS 可以处理各种实验…

centos7用docker安装WireGuard教程

1、 检查centos内核版本 uname -r2、升级内核 下载脚本上传到服务器运行脚本进行升级内核 链接:https://pan.baidu.com/s/1vYmqVy2St3nFnJWGPIwdOw 提取码:owac 3、安装WireGuard 方案一:使用脚本安装 执行第二步脚本进行安装#启动wg0wg…

go-redis 框架基本使用

文章目录 redis使用场景下载框架和连接redis1. 安装go-redis2. 连接redis 字符串操作有序集合操作流水线事务1. 普通事务2. Watch redis使用场景 缓存系统,减轻主数据库(MySQL)的压力。计数场景,比如微博、抖音中的关注数和粉丝数…

xss原理分析

插入法,弹窗法,事件法 绕过HttpOnly通过找到phpinfo的方式,可以看到cookie

新版收款码三合一在线生成系统源码

收款码三合一这个概念相信大家很多人都已经听说过了,而且大家在很多场景也见过商家们已经开始使用这样的收款码了, 前台放着一个二维码,上边写着“支付宝、微信、QQ扫码付款”不管你用哪个软件扫码,都能正确识别,但是…