opencv学习-常用函数总结

1. findContours

1.1 函数功能

在二值图像(binary image)中寻找轮廓(contour)

1.2 函数声明

cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point())

cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point())

1.3 函数参数

1、InputOutputArray image:参数必须为二值单通道图像,定义黑色为背景,白色为识别目标;

即单通道图像、灰度图像,更常用的为canny边缘检测算子处理后的图像;

2、OutputArrayOfArrays contours:contours参数为检测的轮廓数组,每一个轮廓用一个point类型的vector表示,每一个元素为一个3维数组(其形状为(n,1,2),其中n表示轮廓点个数,2表示像素点坐标),表示一个轮廓;

3、OutputArray hierarchy:hiararchy参数和轮廓个数相同,每个轮廓contours[ i ]对应4个hierarchy元素hierarchy[ i ][ 0 ] ~hierarchy[ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。

4、int mode:mode表示轮廓的检索模式,具体相关如下表所示:
CV_RETR_EXTERNAL:只检测外轮廓
CV_RETR_LIST:检测的轮廓不建立等级关系,都是同级。不存在父轮廓或内嵌轮廓
CV_RETR_CCOMP:建立两个等级的轮廓。上面一层为外边界,里面一层为内孔的边界信息
CV_RETR_TREE:建立一个等级树结构的轮廓

5、int method:method表示为轮廓的近似办法。具体参数如下表所示:

CV_CHAIN_APPROX_NONE:
存储所有的轮廓点,相邻的两个点的像素位置差不超过1。
即max(abs(x1-x2),abs(y2-y1))==1

CV_CHAIN_APPROX_SIMPLE
压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息

CV_CHAIN_APPROX_TC89_L1
使用teh-Chinl chain 近似算法

CV_CHAIN_APPROX_TC89_KCOS
使用teh-Chinl chain 近似算法

6、Point offset=Point():offset:轮廓点的偏移量,格式为tuple,如(-10,10)表示轮廓点沿X负方向偏移10个像素点,沿Y正方向偏移10个像素点。

7、返回值:
contours:std::vector<std::vectorcv::Point>
hiararchy:std::vectorcv::Vec4i

=提示:findContours函数处理后会对输入图像进行修改。若保留原图像,应先copy一份图像,对copy的图像进行处理,这里一般先用Mat来存放一张临时图像。=

2. drawContours

2.1 功能

用来将轮廓绘制出来

2.2 函数声明

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, intthickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

2.3 参数说明

image:表示目标图像,

contours:表示输入的轮廓组,每一组轮廓由点vector构成,

contourIdx:指明画第几个轮廓,如果该参数为负值,则画全部轮廓,

color:为轮廓的颜色,

thickness:为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,

lineType:为线型,

hierarchy:为轮廓结构信息,

maxLevel:为maxLevel

offset:offset:轮廓点的偏移量,格式为tuple,如(-10,10)表示轮廓点沿X负方向偏移10个像素点,沿Y正方向偏移10个像素点。

3. boundingRect

3.1 函数功能

计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的

3.2 函数声明

Rect boundingRect(InputArray points)

3.3 参数说明

points:
二维点集,点的序列或向量 (Mat)

4. approxPolyDP

4.1 函数功能

对图像轮廓点进行多边形拟合

4.2 函数声明

void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)

4.3 参数说明

InputArray curve:一般是由图像的轮廓点组成的点集

OutputArray approxCurve:表示输出的多边形点集

double epsilon:主要表示输出的精度,就是另个轮廓点之间最大距离数,5,6,7,,8,,,,

bool closed:表示输出的多边形是否封闭

5. contourArea

5.1 函数功能

主要用于计算图像轮廓的面积

5.2 函数声明

double contourArea(InputArray contour, bool oriented=false )

5.3 参数说明

InputArray contour:输入的点,一般是图像的轮廓点

bool oriented=false:表示某一个方向上轮廓的的面积值,顺时针或者逆时针,一般选择默认false

6. arcLength

6.1 函数功能

主要是计算图像轮廓的周长

6.2 函数声明

double arcLength(InputArray curve, bool closed)

6.3 参数说明

InputArray curve:表示图像的轮廓

bool closed:表示轮廓是否封闭的

上述函数代码示例:

void MotionAnalyze::MoveObjDetect(cv::Mat& frontGray, cv::Mat& afterGray, std::vector<cv::Rect> &detectResult)
{
    
    
	cv::Mat diff;

	//1 灰度处理 目的 RGB三通道转灰度单通道 压缩到原图片三分之一大小
	
	//2 帧差处理 目的 找到帧与帧之间的差异(正在运动的物体)
	cv::absdiff(frontGray, afterGray, diff);
	//imshow("diff",diff);

	//3 二值化处理 目的 将灰度图继续识别转换为黑白分明的图像
	cv::threshold(diff, diff, 20, 255, CV_THRESH_BINARY);
	//imshow("threshold",diff);

	//4 图像降噪
	//4-1 腐蚀处理 目的 去除白色噪点
	Mat element = cv::getStructuringElement(MORPH_RECT, Size(1, 1));//小于3*3方块的白色噪点都会被腐蚀
	cv::erode(diff, diff, element);
	//imshow("erode",diff);

	//4-2 膨胀 目的 把白色区域变大
	Mat element2 = cv::getStructuringElement(MORPH_RECT, Size(10, 10));
	cv::dilate(diff, diff, element2);
	//imshow("dilate",diff);

	//5 提取关键点
	//5-1 查找特征点
	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	AIUtils::findContours(diff, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));

	//5-2 提取关键点
	//5-3 确定下四个点来用于框选目标物体
	int num = contours.size();
	for (int i = 0; i < num; i++)
	{
    
    
		if (cv::contourArea(contours[i]) < 600)
			continue;
		vector<cv::Point> c_poly(contours[i].size());
		cv::approxPolyDP(Mat(contours[i]), c_poly, 3, true);

		//多边拟合
		cv::Rect rect;
		rect = cv::boundingRect(Mat(c_poly));

		detectResult.push_back(rect);
	}
}

7. minAreaRect

7.1 函数功能

主要求得包含点集最小面积的矩形,,这个矩形是可以有偏转角度的,可以与图像的边界不平行

7.2 函数声明

RotatedRect minAreaRect(InputArray points)

7.3 参数说明

InputArray points:表示输入的点集

返回值:矩形的四个顶点坐标

8. RotatedRect

8.1 函数功能

旋转的长方形

8.2 函数声明

C++:   RotatedRect:: RotatedRect ( )
C++:   RotatedRect:: RotatedRect (const Point2f&  center, const Size2f&  size, float  angle )
C++:   RotatedRect:: RotatedRect (const CvBox2D&  box )
Parameters:	
center – The rectangle mass center.
size – Width and height of the rectangle.
angle – The rotation angle in a clockwise direction. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
box – The rotated rectangle parameters as the obsolete CvBox2D structure.
C++:  void  RotatedRect:: points (Point2f  pts[] )  const //! returns 4 vertices of the rectangle
C++:  Rect  RotatedRect:: boundingRect ( )  const
C++:   RotatedRect:: operator CvBox2D ( )  const
Parameters:	
pts – The points array for storing rectangle vertices.

8.3 代码示例

Mat image(200, 200, CV_8UC3, Scalar(0));
RotatedRect rRect = RotatedRect(Point2f(100,100), Size2f(100,50), 30);

Point2f vertices[4];
rRect.points(vertices);//获取矩形的四个点
for (int i = 0; i < 4; i++)
    line(image, vertices[i], vertices[(i+1)%4], Scalar(0,255,0));

Rect brect = rRect.boundingRect();
rectangle(image, brect, Scalar(255,0,0));

imshow("rectangles", image);
waitKey(0);

9. minEnclosingCircle

9.1 函数功能

得到包含二维点集的最小圆

9.2 函数声明

void minEnclosingCircle(InputArray points, Point2f& center, float& radius)

9.3 参数说明

InputArray points:输入的二维点集

Point2f& center:表示输出的圆形的中心坐标,是float型

float& radius:输出的最小圆的半径,是float型

9.4 代码示例

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
 
using namespace cv;
using namespace std;
 
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
 
/// 函数声明
void thresh_callback(int, void*);
 
/** @主函数 */
int main(int argc, char** argv)
{
    
    
	/// 载入原图像, 返回3通道图像
	src = imread("D:6.jpg", 1);
 
	/// 转化成灰度图像并进行平滑
	cvtColor(src, src_gray, CV_BGR2GRAY);
	blur(src_gray, src_gray, Size(3, 3));
 
	/// 创建窗口
	char* source_window = "Source";
	namedWindow(source_window, CV_WINDOW_AUTOSIZE);
	imshow(source_window, src);
 
	createTrackbar(" Threshold:", "Source", &thresh, max_thresh, thresh_callback);
	thresh_callback(0, 0);
 
	waitKey(0);
	return(0);
}
 
/** @thresh_callback 函数 */
void thresh_callback(int, void*)
{
    
    
	Mat threshold_output;
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
 
	/// 使用Threshold检测边缘
	threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY);
	/// 找到轮廓
	findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
 
	/// 多边形逼近轮廓 + 获取矩形和圆形边界框
	vector<vector<Point> > contours_poly(contours.size());
	vector<Rect> boundRect(contours.size());
	vector<Point2f>center(contours.size());
	vector<float>radius(contours.size());
 
	//for (int i = 0; i < contours.size(); i++)
	//{
    
    
	//	approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
	//	boundRect[i] = boundingRect(Mat(contours_poly[i]));
	//	minEnclosingCircle(contours_poly[i], center[i], radius[i]);
	//}
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true);
		boundRect[i] = boundingRect(Mat(contours[i]));
		minEnclosingCircle(contours[i], center[i], radius[i]);
	}
 
	/// 画多边形轮廓 + 包围的矩形框 + 圆形框
	Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
	for (int i = 0; i< contours.size(); i++)
	{
    
    
		Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
		drawContours(drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());
		rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
		circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);
	}
 
	/// 显示在一个窗口
	namedWindow("Contours", CV_WINDOW_AUTOSIZE);
	imshow("Contours", drawing);
}

参考链接:https://blog.csdn.net/qq_18343569/article/details/48000071

猜你喜欢

转载自blog.csdn.net/wyw0000/article/details/130257916