【OpenCV-Python】14 轮廓检测

绘制轮廓

代码

# -*- coding: utf-8 -*-
"""
Created on Sat Dec 26 16:33:44 2020

@author: gkm0120
"""
import cv2

img = cv2.imread('handwriting.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 使用Otsu自动阈值,注意用的是cv2.THRESH_BINARY_INV
ret, thresh = cv2.threshold(
    img_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 寻找轮廓
# 参数2:轮廓的层次类型,一般使用cv2.RETR_TREE,表示提取所有的轮廓并建立轮廓间的层级
# 参数3:轮廓的近似方法。使用cv2.CHAIN_APPROX_SIMPLE就表示用尽可能少的像素点表示轮廓。
contours, hierarchy = cv2.findContours(
    thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# cv2.drawContours:参数2是得到的contours,参数3表示要绘制哪一条轮廓,-1表示绘制所有轮廓,参数4是颜色(B/G/R通道,所以(0,0,255)表示红色),参数5是线宽
# cv2.drawContours用来计算近似的多边形框
cv2.drawContours(img, contours, -1, (0, 0, 255), 2)
# 按顺序绘制
# cnt = contours[1]
# cv2.drawContours(img, [cnt], 0, (0, 0, 255), 2)

cv2.imshow('contours', img)
cv2.waitKey(0)

图例

原图
轮廓图

按顺序绘制

原图
轮廓图

轮廓检测

代码

# -*- coding: utf-8 -*-
"""
Created on Sat Dec 26 16:38:44 2020

@author: gkm0120
"""
import cv2
import numpy as np

img = np.zeros((200, 200), dtype=np.uint8)
img[50:150, 50:150] = 255

# cv2.threshold:参数1是源图片, 参数2是阈值, 参数3是填充色, 参数4是阈值类型
ret, thresh = cv2.threshold(img, 127, 255, 0)
# cv2.findContours:参数2是轮廓的检索模式,参数3是轮廓的近似办法
# cv2.RETR_TREE 建立一个等级树结构的轮廓,
# cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# cv2.drawContours:参数2接收保存一个轮廓的数组,参数3是绘制轮廓数组的索引,-1表绘制所有轮廓
img = cv2.drawContours(color, contours, -1, (0,255,0), 2)
cv2.imshow("contours", color)
cv2.waitKey()
cv2.destroyAllWindows()

图例

在这里插入图片描述

边界框、最小矩阵区域和最小闭圆的轮廓

代码

# -*- coding: utf-8 -*-
"""
Created on Tue Dec 29 20:33:14 2020

@author: gkm0120
"""
import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("hammer.png", cv2.IMREAD_UNCHANGED))

ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) , 127, 255, cv2.THRESH_BINARY)
contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
  # 查找边界框坐标
  x,y,w,h = cv2.boundingRect(c)
  cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2)

  # 求最小面积
  rect = cv2.minAreaRect(c)
  # 计算最小面积矩形的坐标
  box = cv2.boxPoints(rect)
  # 将坐标规格化为整数
  box = np.int0(box)
  # 绘制等高线
  cv2.drawContours(img, [box], 0, (0,0, 255), 3)
  
  # 计算最小外圆的圆心和半径
  (x,y),radius = cv2.minEnclosingCircle(c)
  # 转换为整数
  center = (int(x),int(y))
  radius = int(radius)
  # 画圆
  img = cv2.circle(img,center,radius,(0,255,0),2)

cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow("contours", img)
cv2.imwrite("out-hammer.png",img)

cv2.waitKey()
cv2.destroyAllWindows()

图例

原图
轮廓图

凸轮廓和Douglas-Peucker算法

代码

# -*- coding: utf-8 -*-
"""
Created on Tue Dec 29 20:56:01 2020

@author: gkm0120
"""
import cv2
import numpy as np

img = cv2.pyrDown(cv2.imread("hammer.png", cv2.IMREAD_UNCHANGED))

# cv2.threshold:参数1是源图片, 参数2是阈值, 参数3是填充色, 参数4是阈值类型
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) , 127, 255, cv2.THRESH_BINARY)
black = cv2.cvtColor(np.zeros((img.shape[1], img.shape[0]), dtype=np.uint8), cv2.COLOR_GRAY2BGR)

contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for cnt in contours:
  epsilon = 0.01 * cv2.arcLength(cnt,True)
  # cv2.approxPolyDP:参数1是轮廓,参数2是epsilon值,表源轮廓与近似多边形的最大差值,参数3是布尔标记,表示多边形是否闭合
  approx = cv2.approxPolyDP(cnt,epsilon,True)
  hull = cv2.convexHull(cnt) # 获取处理过的轮廓信息
  cv2.drawContours(black, [cnt], -1, (0, 255, 0), 2)
  cv2.drawContours(black, [approx], -1, (255, 255, 0), 2)
  cv2.drawContours(black, [hull], -1, (0, 0, 255), 2)

cv2.imshow("hull", black)
cv2.waitKey()
cv2.destroyAllWindows()

图例

原图
凸轮廓
凸包包围着整个物体,最里面的为近似多边形,这两者之间的是源轮廓,它主要由弧线构成。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值