例子源于OpenCV官网–为轮廓创建边框和圆圈
(https://docs.opencv.org/4.x/da/d0c/tutorial_bounding_rects_circles.html)
使用OpenCV函数cv::boundingRect
(1.计算灰度图像的点集或非零像素的上-右边界矩形。
2.该函数计算并返回灰度图像中指定的点集或非零像素的最小上下边界矩形。)
使用OpenCV函数cv::minEnclosingCircle
(1.查找包含二维点集的最小面积的圆。
2.该函数使用迭代算法查找二维点集的最小外围圆。)
from __future__ import print_function
import cv2 as cv
import numpy as np
import argparse
import random as rng
rng.seed(12345)
def thresh_callback(val):
threshold = val
#使用cv::Canny检测图像中的边缘。
canny_output = cv.Canny(src_gray, threshold, threshold * 2)
#找到轮廓并保存到向量轮廓和层次结构。
contours, _ = cv.findContours(canny_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
"""
对于每一个发现的轮廓,我们现在对多边形应用精度+-3的近似值,
并说明曲线必须是封闭的。
之后,我们为每个多边形找到一个边界矩形,
并将其保存为边界矩形。
最后求出每个多边形的最小外接圆,
并保存为圆心矢量和半径矢量。
"""
contours_poly = [None]*len(contours)
boundRect = [None]*len(contours)
centers = [None]*len(contours)
radius = [None]*len(contours)
for i, c in enumerate(contours):
contours_poly[i] = cv.approxPolyDP(c, 3, True)
boundRect[i] = cv.boundingRect(contours_poly[i])
centers[i], radius[i] = cv.minEnclosingCircle(contours_poly[i])
#创建新的无符号8位字符Mat,由0填充。它将包含我们将要制作的所有绘图(矩形和圆形)。
drawing = np.zeros((canny_output.shape[0], canny_output.shape[1], 3), dtype=np.uint8)
#对于每个轮廓:随机选择一种颜色,绘制轮廓、边界矩形和最小外接圆。
for i in range(len(contours)):
color = (rng.randint(0,256), rng.randint(0,256), rng.randint(0,256))
cv.drawContours(drawing, contours_poly, i, color)
cv.rectangle(drawing, (int(boundRect[i][0]), int(boundRect[i][1])),
(int(boundRect[i][0]+boundRect[i][2]), int(boundRect[i][1]+boundRect[i][3])), color, 2)
cv.circle(drawing, (int(centers[i][0]), int(centers[i][1])), int(radius[i]), color, 2)
cv.imshow('Contours', drawing)
#加载图像:打开图像,将其转换为灰度,并将其模糊以去除噪声。
parser = argparse.ArgumentParser(description='Code for Creating Bounding boxes and circles for contours tutorial.')
parser.add_argument('--input', help='Path to input image.', default='ball.png')
args = parser.parse_args()
src = cv.imread(cv.samples.findFile(args.input))
if src is None:
print('Could not open or find the image:', args.input)
exit(0)
# Convert image to gray and blur it
src_gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
src_gray = cv.blur(src_gray, (3,3))
#创建一个标题为“Source”的窗口,并在其中显示源文件。
source_window = 'Source'
cv.namedWindow(source_window)
cv.imshow(source_window, src)
"""
在source_window上创建一个trackbar,并给它分配一个回调函数。
通常回调函数是用来响应某种信号的,在我们的例子中,
它是trackbar的状态变化。要同时显示“轮廓”窗口和“源”窗口,
必须显式地一次性调用thresh_callback。
"""
max_thresh = 255
thresh = 100 # initial threshold
cv.createTrackbar('Canny thresh:', source_window, thresh, max_thresh, thresh_callback)
thresh_callback(thresh)
cv.waitKey()
原图:
运行结果:



