在二值图像中查找轮廓
findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
绘制轮廓轮廓或填充轮廓
drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image
def canny(image):
"""canny边缘提取"""
blurred = cv.GaussianBlur(image, (3, 3), 0)
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
grad_x = cv.Sobel(gray, cv.CV_16SC1, 1, 0)
grad_y = cv.Sobel(gray, cv.CV_16SC1, 0, 1)
# image:要检测的图像,threshold1:阈值1(最小值),threshold2:阈值2(最大值),使用此参数进行明显的边缘检测,
# canny_output2 = cv.Canny(grad_x, grad_y, 30, 150)
canny_output1 = cv.Canny(gray, 50, 150) # 也可以直接传入gray
return canny_output1
def contours(image):
"""轮廓查找"""
binary = canny(image)
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
# 函数 cv2.drawContours() 可以被用来绘制轮廓。它可以根据你提供的边界点绘制任何形状。
# 它的第一个参数是原始图像,第二个参数是轮廓,一个 Python 列表。
# 第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设 置为 -1 时绘制所有轮廓)。
# 接下来的参数是轮廓的颜色和厚度等。
cv.drawContours(image, contours, i, (0, 0, 255), 2) # 2为像素大小,-1时填充轮廓
print(i)
cv.imshow("detect contours", image)
def image_contour(image):
"""轮廓查找并描点"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) # 图像二值化
print("threshold value: %s" % ret) # 输出阈值
# cv.imshow("binary image", binary)
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
cv.drawContours(image, contours, i, (0, 0, 255), 2) # 用红色线条画出轮廓
epsilon = 0.01 * cv.arcLength(contour, True)
approx = cv.approxPolyDP(contour, epsilon, True)
cv.drawContours(image, approx, -1, (255, 0, 0), 10)
cv.imshow("contour_approx", image)
注意:
参考链接:
此函数利用格林公式计算轮廓的面积。对于具有自交点的轮廓,该函数几乎肯定会给出错误的结果。
contourArea(contour[, oriented]) -> retval
计算轮廓周长或曲线长度
arcLength(curve, closed) -> retval
用一个最小的矩形,把找到的形状包起来
boundingRect(array) -> retval
返回四个值,分别是x,y,w,h;
计算多边形或栅格化形状的所有三阶矩
moments(array[, binaryImage]) -> retval
def image_measure(image):
"""对象测量"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) # 图像二值化
# print("threshold value: %s" % ret)
# cv.imshow("binary image", binary)
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours):
cv.drawContours(image, contours, i, (0, 255, 255), 1) # 用黄色线条画出轮廓
area = cv.contourArea(contour) # 计算轮廓面积
print("contour area:", area)
# 轮廓周长,第二参数可以用来指定对象的形状是闭合的(True),还是打开的(一条曲线)。
perimeter = cv.arcLength(contour, True)
print("contour perimeter:", perimeter)
x, y, w, h = cv.boundingRect(contour) # 用矩形框出轮廓
cv.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2) # 画出矩形
rate = min(w, h) / max(w, h) # 计算矩阵宽高比
print("rectangle rate", rate)
mm = cv.moments(contour) # 函数 cv2.moments() 会将计算得到的矩以一个字典的形式返回
print(mm)
# 计算出对象的重心
cx = mm['m10'] / mm['m00']
cy = mm['m01'] / mm['m00']
cv.circle(image, (np.int(cx), np.int(cy)), 2, (0, 255, 255), -1) # 用实心圆画出重心
cv.imshow("measure_object", image)
参考链接: