栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

opencv实现阈值分割

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

opencv实现阈值分割

文章目录
      • 基础函数
      • 直方图阈值
        • 实现
        • threshold 函数使用
      • 三角法阈值
        • 实现
      • 迭代法阈值
        • 算法步骤
        • Python语法补充
        • 实现
      • 大津法
        • 理论
        • cv实现
        • 底层复现
      • 自适应阈值
        • 理论
        • 具体操作步骤
        • 优化
        • CV实现
        • 底层复现

基础函数

在此列出,后面将直接使用,不再赘述

  1. 导入库
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
  1. 展示函数
def show(img):
	if img.ndim == 2:
		plt.imshow(img, cmap='gray', vmin=0, vmax=255)
	else:
		img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
		plt.imshow(img)
	plt.show()
直方图阈值

算法描述:根据图像灰度直方图,人工寻找阈值
算法特点:适用双峰图像

实现

导入图片

img = cv.imread('pic/eagle.jpg', 0)
show(img) 


画出直方图

plt.hist(img.ravel(), 256, [0, 256])
plt.show()

plt.hist(img.flatten(), np.arange(-0.5, 256, 1), color='g')
plt.show()


二值化

_, img_bin = cv.threshold(img, 125, 255, cv.THRESH_BINARY)
show(img_bin)

threshold 函数使用

三角法阈值

论文:AUTOMATIC MEASUREMENT OF SISTER CHROMATID EXCHANGE FREQUENCY

算法思想:几何法,适用单峰图像


距离最远的点,即为分割点

实现
img = cv.imread('pic/blossom', 0)
show(img)

plt.hist(img.flattern(), np.arange(-0.5, 256, 1), color='g')
plt.show()

th, img_ = cv.threshold(img, 0, 255, cv.THRESH_TRIANGLE)
print(th)
show(np.hstack([img, img_bin])

三角法自动寻找阈值,第二个参数随便写就行

迭代法阈值 算法步骤
  1. 选取初始分割阈值,通常可选图像灰度平均值 T T T
  2. 根据阈值 T T T将图像像素分割为背景和前景,分别求出两者的平均灰度 T 0 和 T 1 T_0和T_1 T0​和T1​
  3. 计算新的阈值 T ′ = T 0 + T 1 2 T'={T_0+T_1 over 2} T′=2T0​+T1​​
  4. 若 T = = T ′ T==T' T==T′,则迭代结束, T T T即为最终阈值。否则令 T = T ′ T=T' T=T′,转第(2)步。

前景为 > T >T >T的部分,背景为 < T

Python语法补充
a = np.random.randint(0, 10, (4, 4))

a[a <= 5]

a[a <= 5].mean()

实现
img = cv.imread('pic/eagle', 0)

T = img.mean()

while True:
	t0 = img[img < T].mean()	// 背景平均灰度值
	t1 = img[img >= T].mean()	// 前景平均灰度值
	t = (t0 + t1) / 2

	print(T, t)
	if T == t:	// 可适当放宽条件, abs(T-t) < 1
		break
	T = t
T = int(T)	// 浮点数没有用

ptint(f"Best Threshold = {T}")

Best Threshold = 120

大津法 理论

算法思想:最大类间方差
对于给定阈值 T T T,可以将图像分为目标和背景。其中背景点数占图像比例为 p 0 p_0 p0​,平均灰度值为 m 0 m_0 m0​。而且标定数占图像比例为 p 1 p_1 p1​,平均灰度值为 m 1 m_1 m1​,其中满足
p 0 + p 1 = 1 p_0+p_1=1 p0​+p1​=1
整幅图像的平均灰度值为常数,跟阈值无关,且为
m ˉ = p 0 m 0 + p 1 m 1 bar m = p_0m_0+p_1m_1 mˉ=p0​m0​+p1​m1​
类间方差为
σ 2 = p 0 ( m 0 − m ˉ ) 2 + p 1 ( m 1 − m ˉ ) 2 sigma^2=p_0(m_0-bar m)^2+p_1(m_1-bar m)^2 σ2=p0​(m0​−mˉ)2+p1​(m1​−mˉ)2
代入 p 0 + p 1 = 1 和 m ˉ p_0+p_1=1和bar m p0​+p1​=1和mˉ可简化为
σ 2 = p 0 p 1 ( m 0 − m 1 ) 2 sigma^2=p_0p_1(m_0-m_1)^2 σ2=p0​p1​(m0​−m1​)2
遍历灰度值,找出能使 σ 2 sigma^2 σ2最大的值

cv实现
img = cv.imread('pic/eagle.jpg', 0)

th, img_bin = cv.threshod(img, -1, 255, cv.THRESH_OTSU)
print(th)
show(img_bin)

底层复现
img = cv.imread('pic/eagle', 0)

Sigma = -1
T = 0

for t in range(0, 256):
	bg = img[img <= t]
	obj = img[img > t]
	
	p0 = bg.size / img.size
	p1 = obj.size / img.size

	m0 = 0 if obj.size==0 else bg.mean()
	m1 =  0 if obj.size==0 else obj.mean()

	sigma = p0*p1*(m0-m1)**2

	if sigma > Sigma:
		Sigma = sigma
		T = t
自适应阈值 理论

算法思想:局部二值化

全局二值化容易受阴影影响,所以可以局部二值化。自适应阈值分割的本质就是局部二值化。

具体操作步骤
  1. 对某个像素值,原来为 S S S,取其周围的 n × n n times n n×n的区域,求区域均值或高斯加权值,记为T;
  2. 对8位图像,如果 S > T S>T S>T,则该像素点二值化为255,否则为0.
优化
  1. 在实际操作中,通过卷积操作,即均值模糊或高斯模糊,实现求区域均值或高斯加权值;
  2. 上面步骤中,增加超参数 C C C, C C C可以为任何实数,当 S > T − C S>T-C S>T−C时,把原像素二值化为255.
  3. 也可以设置超参数 α ∈ [ 0 , 1 ] alpha in [0,1] α∈[0,1],当 S > ( 1 − α ) T S>(1-alpha)T S>(1−α)T时把原像素点二值化为255,通常取 α = 0.15 alpha=0.15 α=0.15。

注:邻域大小一般要大于目标大小,但也不能太大,否则效果不好。

CV实现
img = cv.imread('pic/page', 0)
show(img)

img_bin = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 21, 6)
show(img_bin)

6 就是上面的C,21就是核大小

底层复现

一. 通过超参数C实现

img = cv.imrad('pic/page', 0)

C = 0
winSize = 21	// 和一个字体差不多大

img_blur = cv.blur(img, (winSize, winSize))
show(img > img_blur)

C = 6

img_bin = np.uint8(img>img_blur.astype(np.int) - C) * 255

show(img_bin)


二. 通过超参数 α alpha α实现

img = cv.imread('pic/page.jpg', 0)

alpha = 0.15
winSize = 21

img_blur = cv.GaussianBlur(img, (winSize, winSize), 5)
img_bin = np.uint8(img > (1-alpha) * img_blur) * 255 

show(img_bin)

对于参数不是很敏感

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1012912.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号