[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭

这篇具有很好参考价值的文章主要介绍了[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考文献:

OTSU阈值分割+孔洞填充+海陆分离_SwordKii的博客-CSDN博客

drawContours函数_普通网友的博客-CSDN博客_drawcontours

R329-opencv阈值分割算法——自适应阈值_Third Impact的博客-CSDN博客_opencv自适应阈值分割

分水岭算法的python实现及解析_进不去的博客-CSDN博客_python分水岭算法

分水岭算法的理解和应用_Evonne_H的博客-CSDN博客_分水岭算法详细介绍与应用

目录

OTSU大津算法(常用于海陆分割)

1.原理:

2.代码API

3.实现:

自适应阈值算法(复杂颜色地物提取例如打鱼船)

1.原理

2.代码API

3.实现

分水岭算法


OTSU大津算法(常用于海陆分割)

1.原理:

寻找海陆分割二值化的阈值,通过统计学方法,常用来处理直方图中有俩个峰的图像,就如同海陆俩个颜色比较多的图片,找到方差最大的时候的灰度值

2.代码API

#获取二值图像轮廓

contours, hierarchy=cv.findContours( img, mode,  method);

contours:输出的轮廓,每一个轮廓用std::vector<std::vector<cv::Point> >来存储;

hierarchy:输出的轮廓关系的存储;

img:二值图像;

mode:轮廓模式

cv.RETR_EXTERNAL:只有最外层轮廓;

cv.RETR_LIST  : 检测所有的轮廓,但是轮廓之间都是单独的,没有父子关系;

cv.RETR_CCOMP : 检测所有的轮廓,但所有轮廓只建立两个等级关系;如果超过两个等级关系的,从顶层开始每两层分解成一个轮廓;

cv.RETR_TREE : 检测所有轮廓,所有轮廓按照真实的情况建立等级关系,层数不限;

method:轮廓处理:

cv.CHAIN_APPROX_NONE :不经过处理

cv.CHAIN_APPROX_SIMPLE:压缩轮廓

cv.CHAIN_APPROX_TC89_L1:用Teh-Chin chain approximation algorithm的一种算法压缩轮廓;

cv.CHAIN_APPROX_TC89_KCOS:用Teh-Chin chain approximation algorithm的另一种算法压缩轮廓;


#画出二值图像轮廓

cv.drawContours( img, contours, contourIdx,color, thickness=1)

函数参数详解:

contours:输入的轮廓组,每一组轮廓由点vector构成,

contourIdx:int 指明画第几个轮廓,如果该参数为负值,则画全部轮廓,

color:轮廓的颜色,

thickness:轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,

#轮廓面积

area = cv.contourArea(contours[i])

#填充轮廓

cv.fillPoly(img,contours,color)

3.实现:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
#解决中文显示问题,固定格式
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

#1.转化为灰度图
pic1=cv.imread("DJI_0023.jpg")
#2.高斯滤波去噪
pic1 = cv.GaussianBlur(pic1, (5,5), 0)    # 高斯滤波
gray=cv.cvtColor(pic1,cv.COLOR_BGR2GRAY)
#3.OUST算法转换为二值图
floatshold,bin = cv.threshold(gray, 0, 255, cv.THRESH_BINARY+cv.THRESH_OTSU)  #方法选择为THRESH_OTSU
#4.形态学操作,闭运算去除孔洞,链接细小边缘
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (10, 10))
bin = cv.morphologyEx(bin, cv.MORPH_CLOSE, kernel)

#4.获取轮廓
contours, hierarchy=cv.findContours(bin, cv.RETR_TREE,cv.CHAIN_APPROX_NONE)
#5.填充轮廓
len_contour = len(contours)
contour_list = []
mask = np.zeros_like(bin, np.uint8)  # 纯黑模板
for i in range(len_contour):
    cv.drawContours(mask, contours,i,(255,255, 255), -1)
print(mask)
#6.彩色图片去除黑色蒙版
pic2=cv.bitwise_and(pic1,pic1, mask=mask)


#绘制图像
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10))
axes[0,0].set_title("原图")
axes[0,0].imshow(pic1[:,:,::-1])
axes[0,1].set_title("二值图")
axes[0,1].imshow(bin,plt.cm.gray)
axes[1,0].set_title("轮廓合并")
axes[1,0].imshow(mask,plt.cm.gray)
axes[1,1].set_title("彩色图片去除黑色蒙版")
axes[1,1].imshow(pic2[:,:,::-1])
plt.show()
cv.waitKey()


结果:

[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭

大津算法有利于海路分割,屏蔽海洋

自适应阈值算法(复杂颜色地物提取例如打鱼船)

1.原理

对分割的小块进行二值化阈值处理,而不考虑整体图像,有利于处理光照不均匀的图像

2.代码API

dst = cv.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)

src:要处理的图像数据,为单通道灰度图像;
maxValue:double类型,二值化后的最大值;
adaptiveMethod:动态计算阈值的方法,有以下两种:

    cv.ADAPTIVE_THRESH_MEAN_C:计算区域内的平均值减去C;
    cv.ADAPTIVE_THRESH_GAUSSIAN_C:计算区域内的高斯均值减去C;

thresholdType:二值化类型flags,在该函数中仅能使用cv.THRESH_BINARY和cv.THRESH_BINARY_INV两种
blockSize:动态化计算阈值时所使用的区域的大小,类似卷积时的卷积核大小,需要为奇数;
C:计算区域内的均值后减去的常量,最后作为阈值;

3.实现

1.

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
#解决中文显示问题,固定格式
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

#1.转化为灰度图
pic1=cv.imread("DJI_0023.jpg")
#2.高斯滤波去噪
pic1 = cv.GaussianBlur(pic1, (5,5), 0)    # 高斯滤波
gray=cv.cvtColor(pic1,cv.COLOR_BGR2GRAY)
#3.adaptiveThreshold转换为二值图
bin=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,5)
#4.形态学操作,闭运算去除孔洞,链接细小边缘
bin2=255-bin
bin2=cv.medianBlur(bin2,5)#中值去噪
bin2=cv.dilate(bin2,np.ones(20,np.uint8))#膨胀
#5.获取轮廓
contours, hierarchy=cv.findContours(bin2, cv.RETR_TREE,cv.CHAIN_APPROX_NONE)

#6.填充轮廓
len_contour = len(contours)
contour_list = []
for i in range(len_contour):
    area=cv.contourArea(contours[i])
    if(area<5000):
        contour_list.append(contours[i])
cv.fillPoly(bin2,contour_list,(255,255,255))
#7.腐蚀
bin3=cv.erode(bin2,np.ones(20,np.uint8))#腐蚀
#8.彩色图片去除黑色蒙版
pic2=cv.bitwise_and(pic1,pic1, mask=bin3)

#绘制图像
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10))
axes[0,0].set_title("原图")
axes[0,0].imshow(pic1[:,:,::-1])
axes[0,1].set_title("自适应二值图")
axes[0,1].imshow(bin,plt.cm.gray)
axes[1,0].set_title("人为进一步处理")
axes[1,0].imshow(bin3,plt.cm.gray)
axes[1,1].set_title("腐蚀后彩色图片去除黑色蒙版")
axes[1,1].imshow(pic2[:,:,::-1])
plt.show()
cv.waitKey()


[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭

 第三幅图靠作者的现阶段能力只能处理到这了。。不要嫌弃

 噪声影响比较严重,对于复杂颜色的渔船提取较好

可见自适应二值化,对于边缘线提取比较有优势,但也提取了不必要的高亮海面部分

2.

如果扩大填充面积,area<50000,“船只”的提取情况更好一些,但相应不必要高亮海面也提取的更多

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
#解决中文显示问题,固定格式
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

#1.转化为灰度图
pic1=cv.imread("DJI_0023.jpg")
#2.高斯滤波去噪
pic1 = cv.GaussianBlur(pic1, (5,5), 0)    # 高斯滤波
gray=cv.cvtColor(pic1,cv.COLOR_BGR2GRAY)
#3.adaptiveThreshold转换为二值图
bin=cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,5)
#4.形态学操作,闭运算去除孔洞,链接细小边缘
bin2=255-bin
bin2=cv.dilate(bin2,np.ones(20,np.uint8))#膨胀
#5.获取轮廓
contours, hierarchy=cv.findContours(bin2, cv.RETR_TREE,cv.CHAIN_APPROX_NONE)

#6.填充轮廓
len_contour = len(contours)
contour_list = []
# mask = np.zeros_like(bin, np.uint8)  # 纯黑模板
for i in range(len_contour):
    area=cv.contourArea(contours[i])
    if(area<50000):
        contour_list.append(contours[i])
cv.fillPoly(bin2,contour_list,(255,255,255))
#7.腐蚀
bin3=cv.erode(bin2,np.ones(20,np.uint8))#腐蚀
#8.彩色图片去除黑色蒙版
pic2=cv.bitwise_and(pic1,pic1, mask=bin3)

#绘制图像
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,10))
axes[0,0].set_title("原图")
axes[0,0].imshow(pic1[:,:,::-1])
axes[0,1].set_title("自适应二值图")
axes[0,1].imshow(bin,plt.cm.gray)
axes[1,0].set_title("人为进一步处理")
axes[1,0].imshow(bin3,plt.cm.gray)
axes[1,1].set_title("腐蚀后彩色图片去除黑色蒙版")
axes[1,1].imshow(pic2[:,:,::-1])
plt.show()
cv.waitKey()


[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭

 3.自己调参数改算法步骤吧。累了,陆地提取的一点不好。。。

分水岭算法

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

# 解决中文显示问题,固定格式,直接复制下面俩行代码就行
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False


def watershed_image(image):
    """分水岭算法"""
    # 图像二值化
    blurred = cv.pyrMeanShiftFiltering(image, 10, 50)  # 均值迁移滤波
    gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)  # 转换成灰度图
    # cv.imshow("gray", gray)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)  # 图像二值化
    # cv.imshow("binary", binary)

    # 去除噪声
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))  # 构造25×25的方形结构元素
    opening = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel=kernel, iterations=2)  # 开操作(需要去除图像中的任何白点噪声),迭代次数2
    # cv.imshow("noise removal", opening)

    # 确定背景区域sure_bg
    sure_bg = cv.dilate(opening, kernel, iterations=3)  # 腐蚀,迭代次数3,会去除边界像素
    cv.imshow("sure_bg", sure_bg)

    # 寻找前景区域sure_fg
    """ 距离变换的基本含义是计算一个图像中非零像素点到最近的零像素点的距离,也就是到零像素点的最短距离
    一个最常见的距离变换算法就是通过连续的腐蚀操作来实现,腐蚀操作的停止条件是所有前景像素都被完全腐蚀。
    这样根据腐蚀的先后顺序,我们就得到各个前景像素点到前景中心像素点的距离。根据各个像素点的距离值,设置
    为不同的灰度值。这样就完成了二值图像的距离变换。
    cv2.distanceTransform(src, distanceType, maskSize)
    distanceType为距离类型CV_DIST_L1, CV_DIST_L2 , CV_DIST_C;maskSize为距离转换掩码的大小
    """
    dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)  # 距离变换
    dist_output = cv.normalize(dist_transform, 0, 1.0, cv.NORM_MINMAX)  # 矩阵归一化,主要是为了显示出dist_output
    cv.imshow("dist_transform", dist_output * 50)  # dist_output不乘50看不出来
    ret, sure_fg = cv.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)  # 图像二值化
    cv.imshow("sure_fg", sure_fg)

    # 找到未知的区域unknown
    sure_fg = np.uint8(sure_fg)
    unknown = cv.subtract(sure_bg, sure_fg)  # 从sure_bg区域中减去sure_fg区域来获得unknown
    cv.imshow("unknown", unknown)

    # 类别标记
    ret, markers1 = cv.connectedComponents(sure_fg)
    print(ret)  # 计算数量,但此时会把图像边框也算进去,因此ret会多1
    # print(markers1)

    # 为所有的标记加1,保证背景是0而不是1
    markers = markers1 + 1
    # print(markers)

    # 现在让所有的未知区域为0
    markers[unknown == 255] = 0

    # 使用分水岭算法
    markers3 = cv.watershed(image, markers=markers)  # 边界区域将被修改标记为-1
    image[markers3 == -1] = [0, 0,255]  # 边界区域画红色
    #创建黑色蒙版
    mask=np.zeros_like(image,np.uint8)
    mask[markers3 == -1]=(255,255,255)
    mask=cv.dilate(mask,np.ones(20,np.uint8))
    # print(markers3)
    fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 10))
    axes[0, 0].set_title("边框")
    axes[0, 0].imshow(mask, plt.cm.gray)
    axes[0, 1].set_title("原图")
    axes[0, 1].imshow(image[:,:,::-1])
    axes[1, 0].set_title("sure_fg")
    axes[1, 0].imshow(sure_fg, plt.cm.gray)
    axes[1, 1].set_title("sure_bg")
    axes[1, 1].imshow(sure_bg, plt.cm.gray)
    plt.show()
    cv.waitKey()
if __name__=="__main__":
    image=cv.imread("DJI_0023.JPG")
    watershed_image(image)

[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭

 分水岭算法提取的边框比较规整,但是将顶上一部分水面也提取出来了,还是需要改进文章来源地址https://www.toymoban.com/news/detail-484116.html

到了这里,关于[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV中的图像处理 —— 霍夫线 / 圈变换 + 图像分割(分水岭算法) + 交互式前景提取(GrabCut算法)

    🌎上一节我们介绍了OpenCV中傅里叶变换和模板匹配,这一部分我们来聊一聊霍夫线/圈变换的原理和应用、使用分水岭算法实现图像分割和使用GrabCut算法实现交互式前景提取 🏠哈喽大家好,这里是ErrorError!,一枚某高校大二本科在读的♂同学,希望未来在机器视觉领域能够有

    2023年04月08日
    浏览(34)
  • 【图像分割】基于浣熊优化算法COA的Otsu(大津法)多阈值电表数字图像分割 电表数字识别【Matlab代码#52】

    长鼻浣熊优化算法(Cоati Optimization Algorithm,COA)是一种启发式优化算法,灵感来源于长鼻浣熊(Coati)的行为策略。长鼻浣熊优化算法基于长鼻浣熊在觅食过程中的特性和行为模式。长鼻浣熊是一种树栖动物,具有长而灵活的鼻子,用于觅食和捕食。它们通过嗅觉感知周围环

    2024年02月16日
    浏览(28)
  • 【GEE笔记】最大类间方差法(otsu、大津法)算法实现——计算阈值、图像二值化分割

    1、最大类间方差法原理概述 2、GEE频率分布统计,直方图绘制 3、算法具体实现,以GEE JavaScript版本为例 4、目标像元提取,以遥感影像提取水体为示例 最大类间方差法(又名otsu、大津法)是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。算法假定该图像根据

    2024年02月06日
    浏览(40)
  • 图像处理技术:数字图像分割 ------ 图像分割、边界分割(边缘检测)、区域分割

    是指根据灰度、彩色、空间纹理、几何形状等特征把图像划分 成若干个互不相交的区域,使得这些特征在同一区域内表现出一致 性或相似性,而在不同区域间表现出明显的不同 分割出来的区域应该同时满足:  (1)分割出来的图像区域的均匀性和连通性。 • 均匀性是指该

    2024年02月04日
    浏览(36)
  • Matlab|图像处理04|图像分割-阈值分割方法

    一、人工阈值分割方法threshold_test1.m 1、分析修改阈值对分割结果的影响 分析:取直方图中第一个谷底的灰度值作为阈值,图像分割效果较好。当阈值改变时,分割后的图像有部分信息丢失,本图中当阈值减小时分割后的图像黑色部分较多,当阈值增大时分割后的图像白色部

    2024年02月11日
    浏览(30)
  • 数字图像处理:图像分割——边缘检测与区域分割

    1.图像分割:根据图像的某些局部特征(灰度级、纹理、彩色或统计特征等)的相似性和互斥性,将图像分割成若干子区域,在每个子区域内部具有相似(相同或相近)特性,而相邻子区域的特性互斥。所以图像分割是利用图像局部特征的相似性和互斥性。 2.图像分割方法分

    2024年02月05日
    浏览(30)
  • 数字图像处理:实验六 图像分割

    数据分割是由图像处理到图像分析的关键步骤,是图像识别和计算机视觉至关重要的预处理,图像分割后提取的目标可用于图像识别、特征提取,图像搜索等领域。图像分割的基本策略主要是基于图像灰度值的两个特性,即灰度的不连续性和灰度的相似性,因此图像分割方法

    2024年02月06日
    浏览(34)
  • python 图像处理——图像分割及经典案例篇之图像分割简介

    前言 图像处理是近些年来空前火热的领域之一,而图像分割作为其中最为重要的处理方式之一,在在医疗、军事、工业等各个方面都有广泛应用。本文将详细介绍图像分割的相关概念、概述目前主要的图像分割方法以及应用场景,后面再对个别方法做详细的了解和学习。 图

    2024年02月06日
    浏览(30)
  • Python Unet ++ :医学图像分割,医学细胞分割,Unet医学图像处理,语义分割

    一,语义分割:分割领域前几年的发展 图像分割是机器视觉任务的一个重要基础任务,在图像分析、自动驾驶、视频监控等方面都有很重要的作用。图像分割可以被看成一个分类任务,需要给每个像素进行分类,所以就比图像分类任务更加复杂。此处主要介绍 Deep Learning-ba

    2024年02月16日
    浏览(40)
  • OpenCV图像处理-图像分割-MeanShift

    MeanShift严格说来并不是用来对图像进行分割的,而是在色彩层面的平滑滤波。它会中和色彩分布相近的颜色,平滑色彩细节,侵蚀掉面积较小的的颜色区域,它以图像上任意一点P为圆心,半径为sp,色彩幅值为sr进行不断地迭代。 语法:pyrMeanShiftFiltering(img, double sp, double sr,

    2024年02月16日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包