Python 深入了解opencv图像分割算法
作者:jinhuazhe2013 发布时间:2021-11-30 09:42:00
本文主要是基于Python Opencv 实现的图像分割,其中使用到的opencv的函数有:
使用 OpenCV 函数 cv::filter2D 执行一些拉普拉斯滤波以进行图像锐化
使用 OpenCV 函数 cv::distanceTransform 以获得二值图像的派生(derived)表示,其中每个像素的值被替换为其到最近背景像素的距离
使用 OpenCV 函数 cv::watershed 将图像中的对象与背景隔离
加载源图像并检查它是否加载没有任何问题,然后显示它:
# Load the image
parser = argparse.ArgumentParser(description='Code for Image Segmentation with Distance Transform and Watershed Algorithm.\
Sample code showing how to segment overlapping objects using Laplacian filtering, \
in addition to Watershed and Distance Transformation')
parser.add_argument('--input', help='Path to input image.', default='cards.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Show source image
cv.imshow('Source Image', src)
原图
将背景从白色更改为黑色,因为这将有助于稍后在使用距离变换(Distance Transform)期间提取更好的结果
src[np.all(src == 255, axis=2)] = 0
如果不太理解numpy.all的的用法,可以参考这里
之后,我们将锐化(sharpen)我们的图像,以锐化前景对象(the foreground objects)的边缘。 我们将应用具有相当强过滤器的拉普拉斯(laplacian)过滤器(二阶导数的近似值):
# 创建一个内核,我们将用它来锐化我们的图像
# 一个二阶导数的近似值,一个非常强大的内核
kernel = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]], dtype=np.float32)
# do the laplacian filtering as it is
# well, we need to convert everything in something more deeper then CV_8U
# because the kernel has some negative values,
# and we can expect in general to have a Laplacian image with negative values
# BUT a 8bits unsigned int (the one we are working with) can contain values from 0 to 255
# so the possible negative number will be truncated
imgLaplacian = cv.filter2D(src, cv.CV_32F, kernel)
sharp = np.float32(src)
imgResult = sharp - imgLaplacian
# convert back to 8bits gray scale
imgResult = np.clip(imgResult, 0, 255)
imgResult = imgResult.astype('uint8')
imgLaplacian = np.clip(imgLaplacian, 0, 255)
imgLaplacian = np.uint8(imgLaplacian)
#cv.imshow('Laplace Filtered Image', imgLaplacian)
cv.imshow('New Sharped Image', imgResult)
锐化处理的主要目的是突出灰度的过度部分。由于拉普拉斯是一种微分算子,如果所使用的定义具有负的中心系数,那么必须将原图像减去经拉普拉斯变换后的图像,而不是加上它,从而得到锐化结果。----摘自《数字图像处理(第三版)》
现在我们将新的锐化源图像分别转换为灰度和二值图像(binary):
# Create binary image from source image
bw = cv.cvtColor(imgResult, cv.COLOR_BGR2GRAY)
_, bw = cv.threshold(bw, 40, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
cv.imshow('Binary Image', bw)
我们现在准备在二值图像(binary image)上应用距离变换。 此外,我们对输出图像进行归一化,以便能够对结果进行可视化和阈值处理:
# Perform the distance transform algorithm
dist = cv.distanceTransform(bw, cv.DIST_L2, 3)
# 对范围 = {0.0, 1.0} 的距离图像(the distance image)进行归一化(Normalize),
# 以便我们可以对其进行可视化和阈值处理
cv.normalize(dist, dist, 0, 1.0, cv.NORM_MINMAX)
cv.imshow('Distance Transform Image', dist)
distanceTransform用法
cv.distanceTransform( src, distanceType, maskSize[, dst[, dstType]] )
src:输入图像,数据类型为CV_8U的单通道图像
dst: 输出图像,与输入图像具有相同的尺寸,数据类型为CV_8U或者CV_32F的单通道图像。
distanceType:选择计算两个像素之间距离方法的标志,其常用的距离度量方法, DIST_L1(distance = |x1-x2| + |y1-y2| 街区距离), DIST_L2 (Euclidean distance 欧几里得距离,欧式距离) 。
maskSize:距离变换掩码矩阵的大小,参数可以选择的尺寸为DIST_MASK_3(3×3)和DIST_MASK_5(5×5).
我们对 dist 图像进行阈值处理,然后执行一些形态学操作(即膨胀)以从上述图像中提取峰值:
# Threshold to obtain the peaks
# This will be the markers for the foreground objects
_, dist = cv.threshold(dist, 0.4, 1.0, cv.THRESH_BINARY)
# Dilate a bit the dist image
kernel1 = np.ones((3,3), dtype=np.uint8)
dist = cv.dilate(dist, kernel1)
cv.imshow('Peaks', dist)
从每个 blob 中,我们在 cv::findContours 函数的帮助下为分水岭算法创建一个种子/标记:
# Create the CV_8U version of the distance image
# It is needed for findContours()
dist_8u = dist.astype('uint8')
# Find total markers
contours, _ = cv.findContours(dist_8u, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# Create the marker image for the watershed algorithm
markers = np.zeros(dist.shape, dtype=np.int32)
# Draw the foreground markers
for i in range(len(contours)):
cv.drawContours(markers, contours, i, (i+1), -1)
# Draw the background marker
cv.circle(markers, (5,5), 3, (255,255,255), -1)
markers_8u = (markers * 10).astype('uint8')
cv.imshow('Markers', markers_8u)
最后,我们可以应用分水岭算法,并将结果可视化:
# Perform the watershed algorithm
cv.watershed(imgResult, markers)
#mark = np.zeros(markers.shape, dtype=np.uint8)
mark = markers.astype('uint8')
mark = cv.bitwise_not(mark)
# uncomment this if you want to see how the mark
# image looks like at that point
#cv.imshow('Markers_v2', mark)
# Generate random colors
colors = []
for contour in contours:
colors.append((rng.randint(0,256), rng.randint(0,256), rng.randint(0,256)))
# Create the result image
dst = np.zeros((markers.shape[0], markers.shape[1], 3), dtype=np.uint8)
# Fill labeled objects with random colors
for i in range(markers.shape[0]):
for j in range(markers.shape[1]):
index = markers[i,j]
if index > 0 and index <= len(contours):
dst[i,j,:] = colors[index-1]
# Visualize the final image
cv.imshow('Final Result', dst)
代码
基于机器学习的图像分割
Pixellib是一个用于对图像和视频中的对象进行分割的库。 它支持两种主要类型的图像分割:
1.语义分割
2.实例分割
PixelLib 支持两个用于图像分割的深度学习库,分别是 Pytorch 和 Tensorflow
来源:https://blog.csdn.net/u012386311/article/details/121356798


猜你喜欢
- 支付宝支付和微信支付是当今互联网产品常用的功能,我使用Django Rest Framework实现了网页上支付宝支付和微信支付的一个通用服
- PayPal支付功能其实一直在更新文档和接口,这里说的是一个简单的支付功能大概流程如下1,在网站的结账页面,设置一个提交到PayPal网站的
- 问题描述:通过EasyConnect登录后可以用xshell连接服务器,同时可以使用navicat和pymysql连接mysql数据库(无论
- 在我之前写的几篇网站优化的文章中,着墨最多的是减少HTTP请求。通过减少请求数目,你的浏览器必须能对你的网站所有内容成功检索,总的HTTP请
- 最近项目用到了bootstrap框架,其中前端用的校验,采用的是bootstrapvalidator插件,也是非常强大的一款插件。我这里用的
- 本文介绍了通过Cursor 工具使用GPT-4的方法。Cursor 是集成了 GPT-4 的 IDE 工具,目前免费并且无需 API Key
- 本文实例讲述了Python中的单继承与多继承。分享给大家供大家参考,具体如下:单继承一、介绍Python 同样支持类的继承,如果一种语言不支
- 前言当需要将多张图像拼接成一张更大的图像时,通常会用到图片拼接技术。这种技术在许多领域中都有广泛的应用,例如计算机视觉、图像处理、卫星图像、
- 说明: a、以下字符中数据库名forum,数据库服务器名WWW-2443D34E558\SQL2005(或者127.0.0.1) b、查看s
- 本文实例为大家分享了python3实现人脸识别的具体代码,供大家参考,具体内容如下第一种:import cv2import numpy as
- SQL语言是一门简单易学却又功能强大的语言,它能让你快速上手并写出比较复杂的查询语句。但对于大多数开发者来说,使用SQL查询数据库并没有一个
- Microsoft SQL Server Management Studio是SQL SERVER的客户端工具,相信大家都知道。我不知道大伙
- auth模块简介auth模块是对登录认证方法的一种封装,之前我们获取用户输入的用户名及密码后需要自己从user表里查询有没有用户名和密码符合
- 一.相关说明:1、openpyxl(可读写excel表)专门处理Excel2007及以上版本产生的xlsx文件;2007一下的版本为xls结
- 看Python简明教程,学习使用print打印字符串,试了下打印中文,不行。编辑环境:IDLE上网搜了下解决办法,各种说法,试了两种:pri
- 如果使用的是MySQL 5.0.x可以直接将以下内容保存替换MySQL中的my.ini,记得要修改basedir和datadir两个栏目的路
- 这次要为我的python程序加上数据库,主要是实现从mysql中查询出数据并在页面上显示出来。首先是mysql的配置文件config.pyh
- 这个效果并不难,要点是位置和比例设置,捕获鼠标位置、判断鼠标位置区域、还有onmouseover事件、onmousemove事件、onmou
- 当我们写用例断言时,往往一个断言结果是不够的,所以需要加入多重断言,而多重断言,当断言中间出现断言结果False时,会中断后续的断言执行,会
- 有时候完全备份, 当还原的时候说不时数据库文件不让还原, 解决办法: 可以直接复制数据库文件, xxx.mdf 和 xxx.ldf (实际复