轮廓发现与绘制
有时候,我们希望Canny边缘提取出来的图像是完整的轮廓,但是Canny出来的却是一些边缘的像素信息,并没有向我们提供完整的轮廓
OpenCV中有一组轮廓发现与绘制的函数,能帮助我们发现轮廓与绘制轮廓
轮廓发现
图像的轮廓一般都有啥由一系列的像素点组成的,一般为二值图像,每一组轮廓都是一组像素点,从这些点还可以看出一条曲线上的其他各点,假设图像中有多个轮廓,则会生成多个轮廓描述的数组
函数的Api如下
findContours(Mat image, List<MatOfPoint> contours, Mat hierarchy, int mode, int method, Point offset)
- image:输入图像,必须是8位单通道图像
- conours:是List类型,List里的每一个元素都是一个轮廓对应的像素点集合
- hierarchy:拓扑信息,
- mode:返回宽阔拓扑模式一共有四种
- RETR_EXTERNAL = 0 : 表示捕获最外层最大的轮廓
- RETR_LIST = 1 : 表示获取所有的轮廓,按照List队列顺序组织
- RETR_CCOMP = 2 : 表示获取所有轮廓呈现的双层结构组织,第一层是外边界,第二程是孔边界
- RETR_TREE = 3 : 表示回去的轮廓是按照树形结构进行组织,显示归属于嵌套层次
- method:描述轮廓的方法,一般是基于链式编码
- CHAIN_APPROX_NONE = 1:将链式编码中的所有点都转换为输出
- CHAIN_APPROX_SIMPLE = 2:压缩水平,垂直、倾斜部分的轮廓点输出
- CHAIN_APPROX_TC89_L1 = 3:使用Teh-Chin链式逼近算法中的一种
- CHAIN_APPROX_TC89_KCOS = 4:使用Teh-Chin链式逼近算法中的一种
- offset:是否有位移,默认是(0,0)
轮廓绘制
对发现的轮廓List对象使用循环可以遍历每一个轮廓面对轮廓都可以使用轮廓绘制
下面是轮廓绘制的Api
drawContours(Mat image, List<MatOfPoint> contours, int contourIdx, Scalar color, int thickness)
- image:要绘制的轮廓图像,通常可以创建一张空白的黑色背景图像
- contours:轮廓数据来自轮廓发现的函数输出
- contourIdx:声明要绘制第几个轮廓
- color:绘制轮廓的颜色
- tickness:声明绘制轮廓时使用的线宽,当<0的时候表示填充改轮廓
演示代码
Mat m = Imgcodecs.imread("C:\\test\\tx.jpg",Imgcodecs.IMREAD_REDUCED_COLOR_2);
HighGui.imshow("原始图片",m);
Mat m1 =new Mat();//灰度
Imgproc.cvtColor(m,m1,Imgproc.COLOR_BGR2GRAY);
Mat m2 = new Mat();//二值
Imgproc.threshold(m1,m2,0,255,Imgproc.THRESH_BINARY|Imgproc.THRESH_OTSU);
Mat m3 = new Mat();//轮廓发现
List<MatOfPoint> list = new ArrayList<>();
Imgproc.findContours(m2,list,m3,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_NONE);
//轮廓绘制
Mat m4 = new Mat(m2.size(),m2.type());
for (int i =0;i<list.size();i++){
Imgproc.drawContours(m4,list,i,new Scalar(255,255,255),1);
}
HighGui.imshow("灰度",m1);
HighGui.imshow("二值",m2);
HighGui.imshow("轮廓",m4);