Python OpenCV图像分割:阈值与轮廓算法详解

江岸
江岸
发布时间:2026-10-15 | 2人浏览过
原创

本文详解Python OpenCV中的图像分割技术,涵盖固定阈值、自适应阈值及Otsu大津法。重点解析基于轮廓的字符分离流程,包括二值化、轮廓提取与包围框计算,并提供完整代码示例,帮助开发者实现高精度的图像分割应用。

前言

图像分割的核心任务,是依据灰度、色彩、空间纹理或几何形状等特征,将图像划分为若干个互不重叠的区域。

最基础的图像分割场景,即是将目标物体从背景中分离出来。

1.图像二值化

在opencv-python库中,cv2.threshold函数常用于实现基础的图像二值化分割功能。

其函数调用格式为:retval, dst = cv2.threshold(src, thresh, maxval, thresholdType[, dst])

参数src代表原图像,且必须为灰度图像。

参数dst用于存储处理后的结果图像。

参数thresh指定用于判断的阈值。

参数maxVal定义结果图像中像素的最大值。

参数thresholdType指定二值化的具体类型。

然而,使用固定阈值方法存在两个主要局限:

问题一:

该方法依据全图统一的阈值对像素进行判断,并非在所有场景下都能取得理想效果。

例如,当图像不同区域的光照条件存在显著差异时,统一阈值往往导致分割失败。

问题二:

阈值需要人工手动设定,不同图片适宜的阈值各不相同,更换图片后可能需要重新调整代码中的阈值参数。

为解决全图统一阈值带来的问题,可采用自适应阈值分割法。

自适应阈值分割算法依据像素周围的局部区域来确定该像素的阈值。

这意味着同一图像的不同区域可以拥有不同的阈值。

这种方法能为光照变化较大的图像提供更好的分割效果。

2.自适应阈值分割算法

其函数调用格式为:dst= cv2.adaptiveThreshold(src, maxValue, adaptiveMethod,thresholdType, blockSize, C, dst=None)

各参数具体解释如下:

参数src代表原图像,必须为灰度图像。

参数maxValue定义结果图像中像素的最大值,通常设置为255。

参数adaptiveMethod指定阈值的计算方法,包含以下两种计算方式:

参数thresholdType指定二值化方式,例如cv2.THRESH_BINARY、cv2.THRESH_TRUNC、

cv2.THRESH_TOZERO等。

参数blockSize定义局部区域的大小。

参数C为阈值计算中减去的常数。

该方法的缺点在于blockSize需要手动指定,但实际物体的大小存在差异,难以一概而论。

3.Otsu阈值分割算法

该算法能够根据图像内容自动计算最佳阈值:

  • Otsu阈值分割算法
  • 大津法
  • 直方图技术

其函数调用格式为:retval, dst = cv2.threshold(src, thresh, maxval, thresholdType[, dst])

各参数具体解释如下:

  • 参数src代表原图像,要求必须是灰度图像。
  • 参数dst用于存储结果图像。
  • 参数thresh在此模式下无实际作用。
  • 参数maxVal定义像素灰度的最大值。
  • 参数thresholdType指定阈值类型,需在原有参数值基础上额外传递一个参数值,即cv2.THRESH_OTSU。
  • 例如组合使用:cv2.THRESH_BINARY+cv2.THRESH_OTSU

利用固定阈值算法进行分割,适用的图片范围较为局限。

同一个固定阈值,在某些图像上表现良好,但在其他图片上效果可能不佳。

如:

利用Otsu阈值算法进行分割,适用的图片范围相对较广。

对于每张图片,Otsu阈值算法能自动找到针对性的最佳阈值。

如:

4.基于轮廓的字符分离

具体分割步骤如下:

1. 检测出图像中字符的轮廓。

2. 获取每一条轮廓的包围框,并根据包围框坐标提取感兴趣区域(ROI)。

4.1轮廓检测

函数调用格式为:contours, hierarchy = cv2.findContours(image, mode, method)

各参数具体解释如下:

参数contours返回轮廓列表,每条轮廓包含构成该轮廓的一系列点的坐标。

参数hierarchy表示轮廓之间的层级关系。

参数image代表原始图像,需为二值图。

参数mode指定轮廓的检索模式。

参数method指定轮廓的近似办法。

4.2轮廓绘制

函数调用格式为:cv2.drawContours(image, contours, contourIdx, color, thickness)

  • 参数image指定要在哪张图片上绘制轮廓。
  • 参数contours为轮廓列表。
  • 参数contourIdx指定绘制轮廓list中的哪条轮廓,若设为-1,则绘制其中的所有轮廓。
  • 参数color指定轮廓的颜色。
  • 参数thickness(可选)指定轮廓的宽度。
import cv2
img=cv2.imread("D:\\desk\\images\\car_license\\test1.png")
 
#去噪
image=cv2.GaussianBlur(img,(3,3),0)
 
#转为灰度图
gray1 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
#Ostu阈值分割
ret, th1 = cv2.threshold(gray1, 127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
 
'''轮廓检测与绘制'''
#检测轮廓(外轮廓)
th1=cv2.dilate(th1,None)      #膨胀,保证同一个字符只有一个外轮廓
contours,hierarchy=cv2.findContours(th1,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
 
#轮廓可视化
th1_bgr=cv2.cvtColor(th1,cv2.COLOR_GRAY2BGR)     #转为三通道图
 
cv2.drawContours(th1_bgr,contours,-1,(0,0,255),2)    #轮廓可视化
 
cv2.imshow("th1_bgr",th1_bgr)
 
cv2.waitKey()

4.3包围框获取

函数调用格式为:rect= cv2.boundingRect(points)

  • 参数points为一组点的坐标。
  • 参数rect返回能够包围这些点的最小外接矩形信息,格式为(x,y,width,height)。

4.4矩形绘制

函数调用格式为:cv2.rectangle(img, pt1, pt2, color[, thickness)

  • 参数img指定要绘制的图片。
  • 参数pt1为矩形的某个顶点的坐标。
  • 参数pt2为和pt1相对的顶点坐标。
  • 参数color指定矩形的颜色。
  • 参数thickness(可选)指定矩形轮廓的宽度。

基于轮廓的字符分离完整代码如下:

import cv2
img=cv2.imread("D:\\desk\\images\\car_license\\test1.png")
 
#去噪
image=cv2.GaussianBlur(img,(3,3),0)
 
#转为灰度图
gray1 = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
 
#Ostu阈值分割
ret, th1 = cv2.threshold(gray1, 127,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
 
'''轮廓检测与绘制'''
#检测轮廓(外轮廓)
th1=cv2.dilate(th1,None)      #膨胀,保证同一个字符只有一个外轮廓
contours,hierarchy=cv2.findContours(th1,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
 
#轮廓可视化
th1_bgr=cv2.cvtColor(th1,cv2.COLOR_GRAY2BGR)     #转为三通道图
 
# cv2.drawContours(th1_bgr,contours,-1,(0,0,255),2)    #轮廓可视化
 
'''包围框获取'''
words=[]         #保存包围框信息
height,width=th1.shape
for contour in contours:     #对于每一条轮廓
    rest=cv2.boundingRect(contour)       #得到这条轮廓的外接矩阵
    #只有高宽比在1.5到3.5之间,且高 度比图片高度大于0.3的矩阵才保留
    if rest[3]/rest[2]>1.5 and rest[3]/rest[2]<3.5 and rest[3]/height>0.3:
        words.append(rest)         #将当前矩形加入矩形列表
        cv2.rectangle(th1_bgr,(rest[0],rest[1]),(rest[0]+rest[2],rest[1]+rest[3]),(0,0,255),3)    #绘制矩形
 
 
 
#显示
# cv2.imshow("img",img)
cv2.imshow("th1",th1)
cv2.imshow("th1_bgr",th1_bgr)
 
cv2.waitKey()

以上就是详解Python OpenCV图像分割算法的实现的详细内容,更多关于OpenCV图像分割算法的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表