轮廓检测

使用轮廓检测,我们可以检测目标的边界,并在图像中定位它们。轮廓检测有着很多应用场景,例如图像前景提取,图像分割、检测和识别等等。

1.什么是图像的轮廓?

当我们连接图像中某个目标边界上的所有点时,就得到了一个轮廓。通常轮廓是指具有相同颜色和强度的边界像素。

在之前我们有学过Canny边缘检测, 那么边缘和轮廓的区别在哪里呢?通常来说,轮廓是一系列相连的点组成的曲线,描绘了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续

原图像
轮廓检测

2.使用OpenCV进行轮廓检测

使用OpenCV进行轮廓检测非常简单 。步骤如下:

1) 读取图像并将其转换为灰度格式
读取图像并将图像转换为灰度格式。将图像转换为单通道灰度图像是为了方便做阈值处理,这是轮廓检测算法的第一步。

2) 应用二进制阈值
在寻找轮廓时,首先总是对灰度图像应用二值阈值或 Canny 边缘检测。在这里,我们使用二值阈值。

这会将彩色图像转换为二值图像,使轮廓检测算法变得容易。边缘检测使图像中对象的边界完全变白,所有像素都具有相同的强度。该算法现在可以从这些白色像素中检测对象的边界。

此时,可能会出现一个问题。如果我们使用 R(红色)、G(绿色)或 B(蓝色)等单通道而不是灰度(阈值)图像会怎样?答案是在这种情况下,轮廓检测算法将无法正常工作。Canny边缘检测算是利用像素强度(亮度)的值来检测出边界的。而通常灰度图比单个 (RGB) 颜色通道图像更好地提供亮度信息。

3) 找到轮廓
使用findContours()函数检测图像中的轮廓。

4) 在原始 图像上绘制轮廓。
识别轮廓后,使用该drawContours()函数将轮廓叠加在原始 RGB 图像上。

3.OpenCV代码演示
#include<opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main() {
    //读取原始图片
    Mat image = imread("C:/Users/LeLe/Desktop/opencv/images/car.jpeg");

    //转换为灰度图
    Mat img_gray;
    cvtColor(image, img_gray, COLOR_BGR2GRAY);
    imshow("origin", image);

    //通过阈值转换为二值图像
    //注意这里对于不同的图像,可以不断调整阈值来得到更好的二值图像。这里我设置的阈值是150。
    Mat thresh;
    threshold(img_gray, thresh, 150, 255, THRESH_BINARY);

    //边缘检测
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(thresh, contours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE);

    //将检测到的边缘画在原始图像上
    Mat image_copy = image.clone();
    drawContours(image_copy, contours, -1, Scalar(0, 255, 0), 2);
    imshow("None approximation", image_copy);

    waitKey(0);
}

结果显示。左边和右边分别为原始图像和原始图像叠加轮廓的图像。


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容