OpenCV:07图像轮廓

什么是图形轮廓

图像轮廓是具有相同颜色或灰度的连续点的曲线,轮廓在形状分析物体检测与识别中很有用处

轮廓的作用:

  • 用于图形分析
  • 物体的识别与检测

查找轮廓

OpenCV提供的findContours()方法可以通过计算像素梯度来判断出图像的边缘,然后将边缘的点封装成数组返回

注意:

  • 为了保证检测的准确性,需要先对图像进行二值化Canny边缘检测操作
  • 画轮廓时会修改输入的图像,如果之后想继续使用原始图像,应该将原始图像存储一份到其他变量中(备份)—— img_copy = img.copy()

关键API:contours,hierarchy = cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])

利用该函数可以获取轮廓的信息

其中:

  • image:被检测的图像,必须是8位单通道二值图像

    • 如果原始图像是彩色图像,则必须转为灰度图像cv2.cvtColor(),再经过二值化阈值处理cv2.threshold()
  • mode:查找轮廓的模式 (写模式名或数字都可以)

    • cv2.RETR_EXTERNAL / 0:表示只检测外围轮廓
      在这里插入图片描述

    • cv2.RETR_LIST / 1:检测的轮廓不建立等级关系(属于同一轮廓线上即为同一级,),即检测所有的轮廓,从右到左,从里到外画轮廓(一般不会出现这么复杂的索引)
      在这里插入图片描述

    • cv2.RETR_CCOMP / 2: 每层最多两级,从小到大,最里到外
      在这里插入图片描述

    • cv2.RETR_TREE / 3:按照树型存储轮廓,从大到小,从右到左 ——> 先从外到内把右边的算完,再算左边的,!最常用!
      在这里插入图片描述

  • method:轮廓近似方法,也叫ApproximationMode。总的来说就是如何去保存你的轮廓

    • cv2.CHAIN_APPROX_NONE:保存所有轮廓上的点,会把轮廓上所有像素点的坐标都保存下来,存储信息较大
    • cv2.CHAIN_APPROX_SIMPLE:只保存角点,比如四边形,只保存四边形的四个角,存储信息较少,比较常用
      在这里插入图片描述

返回值:

  • contours:检测出所有轮廓的集合,list类型,可以通过contours[i](i = 0,1,2...)来调用某一个轮廓,即每一个元素都是某个轮廓的像素坐标数组
  • hierarchy:轮廓间的层级关系
# 查找轮廓

import cv2
import numpy as np

# 导入图片 该图片显示是黑白的,实际上是三通道的图像
img = cv2.imread('./contours.jpeg')

# 二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 对比一下原图与灰度图
cv2.imshow('img',img)
cv2.imshow('gray',gray)


# 进行二值化操作(注意!threshold有两个返回值!一个是阈值,一个是二值化处理后的图片)
thresh,temp = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) # 最终二值化的效果会受到阈值(第二个参数thresh)的影响

# 查找轮廓 返回两个结果:轮廓和层级关系
contours,hierarchy = cv2.findContours(temp,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) # (操作目标,操作类型,操作方法)
# 注意 : contours的类型是列表list,不是ndarray;列表里面才是ndarray,一个ndarray就是一个轮廓

print(type(contours))
print(contours)

# 展示
# cv2.imshow('dst',dst)
# cv2.imshow('img and dst ',np.hstack((gray,dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

绘制轮廓

通过cv2.findContours()方法找到图像轮廓之后,为了方便开发人员观测,最好能把轮廓画出来,于是OpenCV提供了drawContours()方法专门用来绘制这些轮廓

关键API:img = cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
其中:

  • image操作的图像,由于我们可以设置轮廓的颜色color,所以就不太适合用二值化或灰度化后的图片进行操作,应该用三通道的彩图进行绘画(原图)
  • contours轮廓点,由查找轮廓的函数cv2.findContours()的返回值可得
  • contourIdx要绘制的轮廓编号-1表示绘制所有轮廓,此处是索引!因此不能写成contours[]的形式
  • color轮廓的颜色,使用BGR格式,如(0,0,255)表示红色
  • thickness线宽-1表示全部填充

返回值:

  • img:可以不使用,在执行的时候就已经在对参数中的image进行绘制了
# 绘制轮廓

import cv2
import numpy as np

# 导入图片 该图片显示是黑白的,实际上是三通道的图像
img = cv2.imread('./contours.jpeg')

# 二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

cv2.imshow('img',img)
cv2.imshow('gray',gray)


# 进行二值化操作(注意!threshold有两个返回值!一个是阈值,一个是二值化处理后的图片)
thresh,temp = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) # 最终二值化的效果会受到阈值(第二个参数thresh)的影响

# 查找轮廓 返回两个结果:轮廓和层级关系
contours,hierarchy = cv2.findContours(temp,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) # (操作目标,操作类型,操作方法)
# 注意 : contours的类型是列表list,不是ndarray;列表里面才是ndarray,一个ndarray就是一个轮廓

# 绘制轮廓:会直接修改原图
# 如果想保持原图不变,可以copy一份
img_copy = img.copy()
cv2.drawContours(img_copy,contours,-1,(0,0,255),2) # 会直接对操作的图像进行修改,因此可以不用接受

# 展示
cv2.imshow('img',img)
cv2.imshow('img_copy',img_copy)

cv2.waitKey(0)
cv2.destroyAllWindows()

结果:
在这里插入图片描述

如果我们想只画一个轮廓,那么可以根据目标轮廓的层级来绘制(我们使用的是cv2.RETR_TREE:从左到右、从外到内)

例如把参数中的-1改成0

cv2.drawContours(img_copy,contours,0,(0,0,255),2) # 会直接对操作的图像进行修改,因此可以不用接受

结果:
在这里插入图片描述


计算轮廓的面积和周长

轮廓面积

轮廓面积是指每个轮廓中所有的像素点围成区域的面积,单位为像素

轮廓面积是轮廓重要的统计特性之一,通过轮廓面积的大小可以进一步分析每个轮廓隐含的信息,例如通过轮廓面积区分物体大小、识别不同的物体

在查找到轮廓后,可能会有很多细小的轮廓,我们可以通过轮廓的面积进行过滤(比如小于某一个阈值,就把这个轮廓过滤掉)

关键API:cv2.contourArea(contour[, oriented])

  • 参数是countour(不加s,加了s(countours)后表示轮廓的集合)

轮廓周长

关键API:cv2.arcLength(curve, closed)

  • curve:轮廓
  • closed:是否是闭合的轮廓,为布尔类型,一般设置为closed = True
# 计算轮廓的面积和周长

import cv2
import numpy as np

# 导入图片 该图片显示是黑白的,实际上是三通道的图像
img = cv2.imread('./contours.jpeg')

# 二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

cv2.imshow('img',img)
cv2.imshow('gray',gray)


# 进行二值化操作(注意!threshold有两个返回值!一个是阈值,一个是二值化处理后的图片)
  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
图像分割是计算机视觉中的重要任务之一,它的目标是将一幅图像分割成多个具有独立语义的区域。在OCR中,图像分割是将文本区域从图像中分离出来的重要步骤。PythonOpenCV是常用的图像处理工具,下面我们来介绍如何使用PythonOpenCV实现OCR图像分割。 首先,我们需要安装OpenCV和Tesseract OCR。可以通过以下命令安装: ``` pip install opencv-python pip install pytesseract ``` 接下来,我们可以使用以下代码对图像进行分割: ```python import cv2 import pytesseract # 读入图像 img = cv2.imread("test.jpg") # 灰度化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化 thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # 腐蚀操作 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) erode = cv2.erode(thresh, kernel, iterations=1) # 查找轮廓 contours, hierarchy = cv2.findContours(erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓 for contour in contours: x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 显示结果 cv2.imshow('result', img) cv2.waitKey(0) ``` 代码解释: 1. 首先读入图像。 2. 灰度化:将图像转换为灰度图像,方便后续处理。 3. 二值化:将图像转换为黑白图像,方便后续处理。 4. 腐蚀操作:对二值图像进行腐蚀操作,将字符区域连接成一个整体。 5. 查找轮廓:使用OpenCV的findContours函数查找轮廓。 6. 绘制轮廓:将轮廓绘制在原始图像上。 7. 显示结果:显示处理结果。 使用pytesseract库可以将分割出来的文本区域进行OCR识别,具体代码如下: ```python import cv2 import pytesseract # 读入图像 img = cv2.imread("test.jpg") # 灰度化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化 thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # 腐蚀操作 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3)) erode = cv2.erode(thresh, kernel, iterations=1) # 查找轮廓 contours, hierarchy = cv2.findContours(erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓并识别文本 for contour in contours: x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) roi = img[y:y+h, x:x+w] text = pytesseract.image_to_string(roi, lang='chi_sim') print(text) # 显示结果 cv2.imshow('result', img) cv2.waitKey(0) ``` 代码解释: 1. 首先读入图像。 2. 灰度化:将图像转换为灰度图像,方便后续处理。 3. 二值化:将图像转换为黑白图像,方便后续处理。 4. 腐蚀操作:对二值图像进行腐蚀操作,将字符区域连接成一个整体。 5. 查找轮廓:使用OpenCV的findContours函数查找轮廓。 6. 绘制轮廓并识别文本:将轮廓绘制在原始图像上,并使用pytesseract库对文本进行OCR识别。 7. 显示结果:显示处理结果。 以上就是使用PythonOpenCV实现OCR图像分割的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值