什么是图像轮廓?
具有相同颜色或强度的连续点的曲线
轮廓的作用:
注意:
1.为了检测的准确性,需要先对图像进行二值化或Canny操作
使用 print(img.shape) 查看图片属性
2.画轮廓时会修改输入的图像
如果不想改变原图像,则把原图像进行深拷贝一份
findContours(img, mode, ApproximationMode...)
该API有两个返回值 contours和hierarchy
contours 查找到的所有轮廓的列表
hierarchy 层级,查找到的轮廓之间的关系
一般情况下选择使用 LIST或者TREE
一般使用第二种较多,比如四边形只保存四个脚,数据量会少很多,但不会减少相应的信息
import cv2
from matplotlib.pyplot import gray
import numpy as np
# 读取文件
img = cv2.imread('E:\\contours1.jpeg')
print(img.shape)
# 将图片转化为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY )
print(gray.shape)
#二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# ret为转化是否成功判断,binary为二值化图像,150为阈值
print(ret)
# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# contours 为轮廓 hierarchy为层级
print(contours)
# cv2.imshow('img',img)
# #cv2.imshow('gray',gray)
# cv2.imshow('binary',binary)
cv2.waitKey(0)
img 在那张图上进行绘制轮廓
contours 坐标点
contourIdx 轮廓顺序号,-1表示绘制所有轮廓
color 轮廓颜色 (0,0,255)
thickness 线宽, -1表示全部填充
# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# contours 为轮廓 hierarchy为层级
print(contours)
# 绘制轮廓
cv2.drawContours(img,contours, -1 ,(0,0,255), 1)
cv2.imshow('img',img)
# #cv2.imshow('gray',gray)
# cv2.imshow('binary',binary)
cv2.waitKey(0)
实用场景:通过判断轮廓的面积来过滤小的轮廓,计算物体的面积
闭合:true 不闭合:false
# 计算面积
area = cv2.contourArea(contours[0])
print("area = %d"%(area))
# 计算周长
len = cv2.arcLength(contours[0], True)
# 若为false,则会少计算一条边
print("len = %d"%(len))
多边形逼近更接近真实的物体
approxPolyDP(curve, epsilon, closed)
curve 轮廓
epsilon 精度
closed 轮廓是否闭合
convexHull(points, clockwise)
points 轮廓
clockwise true为顺时针,false为逆时针
import cv2
from matplotlib.pyplot import gray
import numpy as np
# 读取文件
img = cv2.imread('E:\\opencv_photo\\hand.png')
print(img.shape)
# 将图片转化为单通道
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY )
print(gray.shape)
#二值化
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
# ret为转化是否成功判断,binary为二值化图像,150为阈值
# print(ret)
# 轮廓查找
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# contours 为轮廓 hierarchy为层级
# print(contours)
# 绘制轮廓
# cv2.drawContours(img,contours, 0 ,(255,255,0), 1)
# # 计算面积
# area = cv2.contourArea(contours[0])
# print("area = %d"%(area))
# # 计算周长
# len = cv2.arcLength(contours[0], True)
# # 若为false,则会少计算一条边
# print("len = %d"%(len))
# 多边形逼近
e = 20
approx = cv2.approxPolyDP(contours[0], e, True)
def drawShape(src, points):
i = 0
while i < len(points):
if(i == len(points) - 1):
x, y = points[i][0]
x1, y1 = points[0][0]
cv2.line(src, (x, y), (x1, y1), (0, 0, 255), 3)
else:
x, y = points[i][0]
x1, y1 = points[i+1][0]
cv2.line(src, (x, y), (x1, y1), (0, 0, 255), 3)
i = i+1
drawShape(img, approx)
# 凸包
hull = cv2.convexHull(contours[0])
drawShape(img, hull)
cv2.imshow('img',img)
# #cv2.imshow('gray',gray)
# cv2.imshow('binary',binary)
cv2.waitKey(0)
最小外接矩形、最大外接矩形
最小外接矩形:红框,按照最小面积进行连接,判断物体是否发生了旋转,采用该种方式
最大外接矩形:绿框,按照最大面积进行连接
minAreaRect(points)
points 轮廓
返回值 RotatedRect 矩形的旋转角度,具体参数:
#最小外界矩形
r = cv2.minAreaRect(contours[1])
box = cv2.boxPoints(r) #取出其中的宽和高
box = np.int0(box)
cv2.drawContours(img, [box], 0, (0,0,255),2) #轮廓绘制
cv2.imshow('img',img)
# #cv2.imshow('gray',gray)
# cv2.imshow('binary',binary)
cv2.waitKey(0)
boundingRect(array)
array 轮廓
返回值 Rect (宽、高)
# 最大外界矩形
x, y , w, h = cv2.boundingRect(contours[1])
cv2.rectangle(img, (x,y),(x+w, y+h), (255, 0, 0), 2)