提取轮廓特征:边缘检测之后,二值图像中显现的是边缘像素(一个个像素点)。之后,连接边缘像素形成轮廓(闭合曲线)。
API函数:
查找轮廓:findContours()函数
void findContours(InputOutputArray image,//输入图像,8位单通道,
OutputArrayOfArrays contours,//输出轮廓图,每个轮廓存储为一组点向量
int mode,//轮廓检索模式,看cv::RetrievalModes
int method,//轮廓近似方法,看cv::ContourApproximationModes
Point offset = Point());//默认
绘制轮廓:drawContours()函数
void drawContours(InputOutputArray image,//目标图像
InputArrayOfArrays contours,//所有输入轮廓
int contourIdx,//轮廓索引,画索引指的那个轮廓。如果是负值,绘制所有轮廓。
const Scalar& color,//线的颜色
int thickness = 1,//线宽
int lineType = LINE_8,//线型,看cv::LineTypes
InputArray hierarchy = noArray(),//默认
int maxLevel = INT_MAX, Point offset = Point());//默认
一、c++示例代码
//包含头文件
#include <opencv2/opencv.hpp>
//命名空间
using namespace cv;
using namespace std;
//全局函数声明部分
//主函数
int main()
{
//【1】载入图像
Mat image = imread("G:\\opencvtest\\testImage\\beauty.png");
//【2】检查是否载入成功
if (image.empty())
{
printf("读取图片错误,请确认目录下是否有imread函数指定图片存在! \n ");
return 0;
}
//【3】转换为灰度图像
Mat grayImage;
cvtColor(image, grayImage, COLOR_BGR2GRAY);
//【4】图像平滑降噪
Mat result;
blur(grayImage, result, Size(3, 3));
//【5】Canny算子进行边缘检测
Mat edge;
Canny(result, edge, 20, 60, 3);
//【6】阈值化处理生成二值图像
Mat binaryImage;
threshold(edge, binaryImage, 20, 255, THRESH_BINARY_INV);
//【7】从二值边缘图像中查找轮廓
vector<vector<Point>> contours;
findContours(binaryImage, contours, RETR_LIST, CHAIN_APPROX_NONE);
//【8】在白色图像上画黑色轮廓
Mat dstImage(image.size(), CV_8U, Scalar(255));
drawContours(dstImage, contours, -1, Scalar(0), 1);
//【9】显示图像
imshow("20-轮廓图", dstImage);
//【10】保持窗口显示
waitKey(0);
return 0;
}
二、运行截图
1.Canny边缘检测图
2.提取轮廓特征图
三、数字图像处理知识
1.边缘连接
边缘连接的意义——边缘检测算法的后处理
由于噪音的原因,边界的特征很少能够被完整地描述,在亮度不一致的地方会中断。
因此典型的边检测算法后面总要跟随着连接过程和其它边界检测过程,用来归整边缘像素,成为有意义的边。
2.连接处理的原理:
对做过边缘检测的图像的每个点(x,y)的特性进行分析。
分析在一个小的邻域(3x3或5x5)中进行。
所有相似的点被连接,形成一个享有共同特性像素的边缘 。
用比较梯度算子的响应强度和梯度方向确定两个点是否同属一条边。(具体实现过程看论文吧)