在OpenCV中检测和绘制轮廓的步骤如下所示:
- 读取图像并将其转换为单通道:红色、绿色或蓝色
- 查找对象轮廓
- 绘制对象轮廓
4.1 读取图像并将其转换为单通道
C++:
// read the image
Mat image = imread("../../input/image_1.jpg");
// B, G, R channel splitting
Mat channels[3];
split(image, channels);
Python:
# read the image
image = cv2.imread('../../input/image_1.jpg')
# B, G, R channel splitting
blue, green, red = cv2.split(image)
4.2 查找对象轮廓
C++:
// detect contours using blue channel and without thresholding
vector<vector<Point>> contours1;
vector<Vec4i> hierarchy1;
findContours(channels[0], contours1, hierarchy1, RETR_TREE, CHAIN_APPROX_NONE);
// detect contours using green channel and without thresholding
vector<vector<Point>> contours2;
vector<Vec4i> hierarchy2;
findContours(channels[1], contours2, hierarchy2, RETR_TREE, CHAIN_APPROX_NONE);
// detect contours using red channel and without thresholding
vector<vector<Point>> contours3;
vector<Vec4i> hierarchy3;
findContours(channels[2], contours3, hierarchy3, RETR_TREE, CHAIN_APPROX_NONE);
Python:
# detect contours using blue channel and without thresholding
contours1, hierarchy1 = cv2.findContours(image=blue, mode=cv2.RETR_TREE,
method=cv2.CHAIN_APPROX_NONE)
# detect contours using green channel and without thresholding
contours2, hierarchy2 = cv2.findContours(image=green, mode=cv2.RETR_TREE,
method=cv2.CHAIN_APPROX_NONE)
# detect contours using red channel and without thresholding
contours3, hierarchy3 = cv2.findContours(image=red, mode=cv2.RETR_TREE,
method=cv2.CHAIN_APPROX_NONE)
4.3 绘制对象轮廓
C++:
// draw contours on the original image
Mat image_contour_blue = image.clone();
drawContours(image_contour_blue, contours1, -1, Scalar(0, 255, 0), 2);
imshow("Contour detection using blue channels only", image_contour_blue);
// draw contours on the original image
Mat image_contour_green = image.clone();
drawContours(image_contour_green, contours2, -1, Scalar(0, 255, 0), 2);
imshow("Contour detection using green channels only", image_contour_green);
// draw contours on the original image
Mat image_contour_red = image.clone();
drawContours(image_contour_red, contours3, -1, Scalar(0, 255, 0), 2);
imshow("Contour detection using red channels only", image_contour_red);
Python:
# draw contours on the original image
image_contour_blue = image.copy()
cv2.drawContours(image=image_contour_blue, contours=contours1, contourIdx=-1,
color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
# see the results
cv2.imshow('Contour detection using blue channels only', image_contour_blue)
# draw contours on the original image
image_contour_green = image.copy()
cv2.drawContours(image=image_contour_green, contours=contours2, contourIdx=-1,
color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
# see the results
cv2.imshow('Contour detection using green channels only', image_contour_green)
# draw contours on the original image
image_contour_red = image.copy()
cv2.drawContours(image=image_contour_red, contours=contours3, contourIdx=-1,
color=(0, 255, 0), thickness=2, lineType=cv2.LINE_AA)
# see the results
cv2.imshow('Contour detection using red channels only', image_contour_red)
4.4 效果
在下面的图像中,我们可以看到轮廓检测算法不能正确地找到轮廓。这是因为它不能正确地检测对象的边界,而且像素之间的强度差也没有很好地定义。这就是我们更喜欢使用灰度和二进制阈值图像来检测轮廓的原因。
另外,CHAIN_APPROX_SIMPLE
和CHAIN_APPROX_NONE
并没有差异,同样无法找到轮廓。