轮廓检测
先将图像转换成二值
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度图
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 变为二值,大于127置为255,小于100置为0.
使用cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)函数读取轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# contours:轮廓信息 hierarchy:层级
# cv2.RETR_TREE:检测所有轮廓,并重构嵌套轮廓的整个层次
# cv2.CHAIN_APPROX_NONE:freeman链码方式输出轮廓,所有其他方式输出多边形(顶点的序列)
绘图
-1表示画出全部轮廓,0,1,2依次为第1,2,3个轮廓
(0, 0, 255)bgr表示画红色
2表示线条宽度
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
# -1表示画出全部轮廓,(0, 0, 255)bgr表示画红色,2表示线条宽度
结果
show.cv_show('iron', img)
show.cv_show('thresh', thresh)
show.cv_show('res', res)
原图
二值图
轮廓图
轮廓特征
先提取另一幅图的轮廓
img2 = cv2.imread('duobianxing.png')
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 灰度图
ret2, thresh2 = cv2.threshold(gray2, 127, 255, cv2.THRESH_BINARY) # 变为二值,大于127置为255,小于100置为0.
contours2, hierarchy2 = cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
draw_img2 = img2.copy()
res2 = cv2.drawContours(draw_img2, contours2, -1, (0, 0, 255), 2) # -1表示画出所有轮廓
show.cv_show('duobianx', img2)
show.cv_show('res', res2)
提取第一个轮廓
cnt = contours2[0]
面积
area = cv2.contourArea(cnt)
周长
length = cv2.arcLength(cnt, True) # 周长,True表示闭合
轮廓近似
设置一个阈值,越小越接近原轮廓
yuzhi = 0.01*cv2.arcLength(cnt, True) # 阈值
approx = cv2.approxPolyDP(cnt, yuzhi, True)
draw_img2 = img2.copy()
res2 = cv2.drawContours(draw_img2, [approx], -1, (0, 0, 255), 2)
show.cv_show('res2', res2)
阈值为0.1倍周长时
阈值为0.01倍周长时
边界矩形
x, y, w, h = cv2.boundingRect(cnt)
ju = cv2.rectangle(img2, (x, y), (x+w, y+h), (0, 255, 0), 2)
show.cv_show('ju', ju)
轮廓面积与边界矩形面积之比
area2 = cv2.contourArea(cnt)
ju_area = w * h
bi = float(area2) / ju_area
print('轮廓面积与边界矩形面积之比', bi)
外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
yuan = cv2.circle(img2, center, radius, (0, 255, 0), 2)
show.cv_show('yuan', yuan)