@TOC
凸包检测提取轮廓
原理
对二值图像进行轮廓分析之后,对获取到的每个轮廓数据,
可以构建每个轮廓的凸包,构建完成之后会返回该凸包包含
的点集。根据返回的凸包点集可以绘制该轮廓对应的凸包。
OpenCV对轮廓提取凸包的API函数如下:
convexHull(
InputArray points,
OutputArray hull,
bool clockwise = false,
bool returnPoints = true
)
points参数是输入的轮廓点集
hull凸包检测的输出结果,当参数returnPoints为ture的时候返回
凸包的顶点坐标是个点集、returnPoints为false的是返回的是一个
integer的vector里面是凸包各个顶点在轮廓点集对应的index
clockwise 表示顺时针方向或者逆时针方向
returnPoints表示是否返回点集
opencvAPI函数用来判断一个轮廓是否为凸包,该方法如下:
isContourConvex(
InputArray contour
)
复制代码
代码
def findholl(src):#凸包检测
# 读取图片并转至灰度模式
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值化,取阈值为235
ret, thresh = cv.threshold(gray, 235, 255, cv.THRESH_BINARY)
# 寻找图像中的轮廓
contours, hierarchy = cv.findContours(thresh, 2, 1)
# 寻找物体的凸包并绘制凸包的轮廓
for cnt in contours:
hull = cv.convexHull(cnt)
length = len(hull)
# 如果凸包点集中的点个数大于5
if length > 5:
# 绘制图像凸包的轮廓
for i in range(length):
cv.line(src, tuple(hull[i][0]), tuple(hull[(i + 1) % length][0]), (0, 0, 255), 2)
cv.imshow('finger', src)
复制代码
测试:
轮廓检测 绘出矩形框
获取轮廓
OpenCV2获取轮廓主要是用 cv2.findContours()
cv2.findContours(img, mode, method)
复制代码
绘出轮廓
cv2.drawContours()函数
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
第一个参数是指明在哪幅图像上绘制轮廓;
第二个参数是轮廓本身,在Python中是一个list。
第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。
复制代码
代码
def Conmtours(img):
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY)
contours, hierarchy = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
draw_img0 = cv.drawContours(img.copy(), contours, 0, (0, 255, 255), 3)
draw_img1 = cv.drawContours(img.copy(), contours, 1, (255, 0, 255), 3)
draw_img2 = cv.drawContours(img.copy(), contours, 2, (255, 255, 0), 3)
draw_img3 = cv.drawContours(img.copy(), contours, -1, (0, 0, 255), 3)
cv.imshow("img", img)
cv.imshow("draw_img0", draw_img0)
cv.imshow("draw_img1", draw_img1)
cv.imshow("draw_img2", draw_img2)
cv.imshow("draw_img3", draw_img3)
复制代码
将图中的轮廓用圆和矩形绘制
def ConmtoursMAX(img):
# 二值化, 黑白二值化
ret, thresh = cv.threshold(
cv.cvtColor(img.copy(), cv.COLOR_BGR2GRAY), # 转换为灰度图像,
127, 255, # 大于127的改为255 否则改为0
cv.THRESH_BINARY) # 黑白二值化
# 搜索轮廓
contours, hierarchy = cv.findContours(
thresh,
cv.RETR_EXTERNAL,
cv.CHAIN_APPROX_SIMPLE)
for c in contours:
x, y, w, h = cv.boundingRect(c)
"""
传入一个轮廓图像,返回 x y 是左上角的点, w和h是矩形边框的宽度和高度
"""
cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 获得最小的矩形轮廓 可能带旋转角度
rect = cv.minAreaRect(c)
# 计算最小区域的坐标
box = cv.boxPoints(rect)
# 坐标规范化为整数
box = np.int0(box)
# 画出轮廓
cv.drawContours(img, [box], 0, (0, 0, 255), 3)
# 计算最小封闭圆形的中心和半径
(x, y), radius = cv.minEnclosingCircle(c)
# 转换成整数
center = (int(x), int(y))
radius = int(radius)
# 画出圆形
img = cv.circle(img, center, radius, (0, 255, 0), 2)
# 画出轮廓
cv.drawContours(img, contours, -1, (255, 0, 0), 1)
cv.imshow("contours", img)
复制代码
(画这个圆心累啊)
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END