首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐
2025年7月3日 星期四 9:03pm

python-opencv图像分割

  • 25-02-18 13:41
  • 4099
  • 6042
blog.csdn.net

文章目录

    • 二值化
    • 图像骨骼
    • 连通域分割

二值化

所谓图像分割,就是将图像的目标和背景分离开来,更直观一点,就是把目标涂成白色,背景涂成黑色,言尽于此,是不是恍然大悟:这不就是二值化么?

【threshold]是此前提到的二值化函数,但只讲解了固定阈值分割模式,而并未讲解其自动分割的OTSU模式。

【adaptiveThreshold】是opencv提供的自适应阈值函数,可根据不同的卷积核来对局部进行二值化,可以更加细致地得到物体边缘。

OTSU算法,mean核,高斯核的分割结果如下图所示,其中150是手动设置的分割阈值;100是OTSU自动计算出的分割阈值。

提示说图像违规,也不知道哪违规了。

代码如下

import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import ascent
import cv2

path = 'coins.jpg'

coins = {}
coins["original"] = plt.imread(path)
coins["gray"] = cv2.cvtColor(coins["original"],cv2.COLOR_RGB2GRAY)

_, coins['th150'] = cv2.threshold(coins["gray"], 150, 255, 
    cv2.THRESH_BINARY)
th, bImg = cv2.threshold(coins["gray"], 0, 255,
    cv2.THRESH_BINARY+cv2.THRESH_OTSU)
coins[f'otsu({th})'] = bImg


method = {"mean":cv2.ADAPTIVE_THRESH_MEAN_C,
          "gaussian":cv2.ADAPTIVE_THRESH_GAUSSIAN_C}
for key in method:
    coins[key] = cv2.adaptiveThreshold(coins["gray"], 255,
        method[key], cv2.THRESH_BINARY, 11, 2)

for i,key in enumerate(coins,1):
    plt.subplot(2,3,i)
    plt.imshow(coins[key], cmap='gray')
    plt.title(key)
    plt.axis('off')

plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

图像骨骼

如果把二值图像理解成地形,黑色表示海洋,白色表示陆地,那么陆地上任意一点,到海洋都有一个最近的距离,如下图所示。由于硬币图案的颜色并不完全一致,所以在二值化时可能会出现不一致的情况,为此,需要通过腐蚀或者膨胀等形态学处理,将其内部涂抹均匀,从而得到一张目标与背景完全分割的图像,此即【dilate】图。对dilate图而言,【dist-bg】为其黑色区域的骨骼;【dist-fg】为白色区域的骨骼。

在这里插入图片描述

实现代码如下

import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import ascent
import cv2

bImg = coins[f'otsu({th})']

kernel = np.ones((5,5),np.uint8)
coins["dilate"] = cv2.dilate(coins[f'otsu({th})'], kernel)
coins["dist-fg"] = cv2.distanceTransform(
    coins["dilate"], cv2.DIST_L2,5)
coins["dist-bg"] = cv2.distanceTransform(
    255-coins["dilate"], cv2.DIST_L2,5)

keys = ['dilate', 'dist-bg', 'dist-fg']
for i,key in enumerate(keys,1):
    plt.subplot(1,3,i)
    plt.imshow(coins[key], cmap='gray')
    plt.title(key)
    plt.axis('off')

plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

【distanceTransform】函数的功能是,计算当前像素点到零像素点的最短距离,其输入参数有三,分别是输入的二值图像;求解距离的类型,以及掩膜尺寸,一般可设为3或者5。

在一张图像中,两点之间的距离有多种计算方式,比如

  • a a a 水平和数竖直方向的变化量
  • b b b 对角方向的变化量
  • c c c 条约移动的变化量

距离变换函数综合了这三种距离,根据各种距离的权重不同,提供了下面几种不同的距离类别

distanceTypemaskSize参数
CV_DIST_C3 ( 3 × 3 ) (3\times3) (3×3) a = 1 , b = 1 a=1, b=1 a=1,b=1
CV_DIST_L13 ( 3 × 3 ) (3\times3) (3×3) a = 1 , b = 2 a=1, b=2 a=1,b=2
CV_DIST_L23 ( 3 × 3 ) (3\times3) (3×3) a = 0.955 , b = 1.3693 a=0.955, b=1.3693 a=0.955,b=1.3693
CV_DIST_L25 ( 5 × 5 ) (5\times5) (5×5) a = 1 , b = 1.4 , c = 2.1969 a=1, b=1.4, c=2.1969 a=1,b=1.4,c=2.1969

连通域分割

所谓连通域,即Connected Component,是一组彼此相连的像素点的集合,这些像素点彼此之间可以假设一条互相链接的路径,路径上所有像素的灰度一致,或者符合某个特定的条件。

通过连通域分割,可以将图像中不同的目标区分开来,为进一步的处理打下基础,最常用的连通域滤波流程大致如下:图像灰度化->二值化->形态学处理->标记连通域,其前面的几个步骤已经在二值化以及距离变换中得以体现,其生成标签的结果如下图所示

在这里插入图片描述

其中,dilate是膨胀二值图。对其进行连通域分割,得到labels图像,其中每一枚硬币所在区域,都被分配到了一个编号,即Label,最后的三维图,便是这张图像的标签值。

处理和绘图代码如下

ret, coins["labels"] = cv2.connectedComponents(coins["dilate"])

for i,key in enumerate(['dilate', 'labels'],1):
    plt.subplot(1,3,i)
    plt.imshow(coins[key], cmap='gray')
    plt.title(key)
    plt.axis('off')

ax = plt.subplot(133, projection='3d')
ys, xs = np.indices(coins['labels'].shape)
ax.plot_surface(xs, ys, coins['labels'])
plt.title("labels")
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

【connectedComponents】是opencv提供的连通域分割函数,其必不可少的输入参数是一个二值图像,此外还有两个整型参数,分别用于规定邻域形式和输出的Labels类型。其中,邻域形式主要分为4-邻域和8邻域,前者把当前像素的上下左右四个像素算作邻域,换言之,这四个像素与当前像素是连通的;8-邻域则将一个像素周围的8个像素视作邻域。

注:本文转载自blog.csdn.net的微小冷的文章"https://tinycool.blog.csdn.net/article/details/139232769"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top