OpenCV轮廓相关操作 C++

2023-05-16

参考
参考

轮廓的基本概念

在OpenCV中,可以通过cv::findContours()函数,在灰度图中寻找轮廓。

函数原型

void findContours( InputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset = Point());

void findContours( InputArray image, OutputArrayOfArrays contours,
                              int mode, int method, Point offset = Point());

参数image是输入的灰度图(注意背景要是黑的,物体是白的);contours是找到的轮廓(每个轮廓由点集表示),其类型一般为std::vector<std::vector<Point> >hierarchy是每个轮廓对应的属性(例如拓扑信息);mode是轮廓的检索模式;method是寻找轮廓时使用的近似算法(cv::CHAIN_APPROX_NONE把轮廓上所有的点存储;cv::CHAIN_APPROX_SIMPLE只存储轮廓上的拐点,例如矩形就只保存四个顶点;cv::CHAIN_APPROX_TC89_L1cv::CHAIN_APPROX_TC89_KCOS为使用"teh-Chinl chain"近似算法)。

检索模式的种类
原图为:在这里插入图片描述
cv::RETR_EXTERNAL仅检索所有外部轮廓,不包含子级轮廓。
效果为:
cv::RETR_LIST检索所有轮廓,不创建任何父子关系。
效果为:在这里插入图片描述
cv::RETR_CCOMP检索所有轮廓并将它们排列为2级层次结构,所有外轮廓为1级,所有子级轮廓为2级。
效果为:在这里插入图片描述
cv::RETR_TREE检索所有轮廓不创建完整的层次列表,如父级、子级、孙子级等。
效果为:在这里插入图片描述
常用的的是cv::RETR_EXTERNALcv::RETR_TREE选项。

轮廓的相关操作

画轮廓
可以通过cv::drawContours()函数,进行画轮廓。
函数原型:

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

参数image是输入输出图片;contourscv::findContours()检测到的所有轮廓;contourIdx是取第几个轮廓;color是轮廓的颜色;thickness是轮廓的线宽(注意这个参数为-1时会填充整个轮廓);lineType是线的形式;hierarchy为关于层级的可选参数,只有绘制部分轮廓时才会用到;maxLevel为绘制轮廓的最高级别,这个参数只有hierarchy有效的时候才有效(maxLevel=0,绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓、maxLevel=1, 绘制与输入轮廓同一等级的所有轮廓与其子节点、maxLevel=2,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点);offset为轮廓偏移量,配合ROI使用。
例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	for (int i = 0; i < contours.size(); ++i) {  //绘制所有轮廓
		cv::drawContours(dst, contours, i, cv::Scalar(0, 255, 0), -1);  //thickness为-1时为填充整个轮廓
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

效果为:
计算轮廓的长度、面积
可以通过cv::contourArea()来获取轮廓的面积;可以通过cv::arcLength()来获取轮廓的长度。
函数原型:

double contourArea( InputArray contour, bool oriented = false );
double arcLength( InputArray curve, bool closed );

contour表示单个轮廓构成的点集;oriented为面积的方向性,true表示面积具有方向性,false表示不具有方向性。
curve表示单个轮廓构成的点集或任意二维点集;closed表示点集是否闭合,对应找到的轮廓此值应为true。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	for (int i = 0; i < contours.size(); ++i) {  //遍历所有轮廓
		printf("第%d个轮廓的面积为%lf 长度为%lf\n", i,
			cv::contourArea(contours[i]), cv::arcLength(contours[i], true));
	}

	return 0;
}

输出:
第0个轮廓的面积为31110.000000 长度为706.0000001个轮廓的面积为32569.000000 长度为767.910811

获取轮廓的最小外接矩形
可以通过cv::minAreaRect()来获取轮廓的最小外接矩形。
函数原型:

RotatedRect minAreaRect( InputArray points );

其返回值是一个矩形(矩形包含了四个角点的信息,以及相对于x轴的旋转角度),参数points是单个轮廓。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	std::vector<cv::RotatedRect> minAreaRects(contours.size());  //存储轮廓的最小外接矩形

	cv::Point2f ps[4];  //外接矩形四个端点的集合
	for (int i = 0; i < contours.size(); ++i) {  //遍历所有轮廓
		minAreaRects[i] = cv::minAreaRect(contours[i]);  //获取轮廓的最小外接矩形
		minAreaRects[i].points(ps);  //将最小外接矩形的四个端点复制给ps数组

		for (int j = 0; j < 4; j++) {  //绘制最小外接轮廓的四条边
			line(dst, cv::Point(ps[j]), cv::Point(ps[(j + 1) % 4]), cv::Scalar(0, 255, 0), 2);
			cv::putText(dst, std::to_string(j), ps[j], 0, 1, cv::Scalar(0, 0, 255), 2);  //将点集按顺序显示在图上
		}

		printf("minAreaRects[%d]的旋转角度为%f\n", i, minAreaRects[i].angle);  //输出旋转角度
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

输出:
minAreaRects[0]的旋转角度为90.000000
minAreaRects[1]的旋转角度为52.678967

效果为:在这里插入图片描述
获取轮廓的最小外接长方形
一般的图像操作都要求在方正的图像中进行,因此一般情况下需要轮廓的最小外接长方形。
可以通过cv::boundingRect()获取轮廓的最小外接长方形。
函数原型:

Rect boundingRect( InputArray array );

其返回值是一个长方形,参数array是单个轮廓。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	std::vector<cv::RotatedRect> minAreaRects(contours.size());  //存储轮廓的最小外接矩形
	std::vector<cv::Rect> boundingRect(contours.size());  //存储轮廓的最小外接矩形

	cv::Point2f ps[4];  //外接矩形四个端点的集合
	for (int i = 0; i < contours.size(); ++i) {  //遍历所有轮廓
		minAreaRects[i] = cv::minAreaRect(contours[i]);  //获取轮廓的最小外接矩形
		minAreaRects[i].points(ps);  //将最小外接矩形的四个端点复制给rect数组

		for (int j = 0; j < 4; j++) {  //绘制最小外接轮廓的四条边
			line(dst, cv::Point(ps[j]), cv::Point(ps[(j + 1) % 4]), cv::Scalar(0, 255, 0), 8);
		}

		boundingRect[i] = cv::boundingRect(contours[i]);  //获取轮廓的最小外接长方形
		cv::rectangle(dst, boundingRect[i], cv::Scalar(255, 0, 0), 2);  //绘制最小外接长方形
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

效果为:在这里插入图片描述
获取轮廓的图像矩
轮廓矩指图像的某些特定像素灰度的加权平均值,或者是图像具有类似功能或意义的属性。可以通过图像的矩来获得图像的部分性质,包括面积(或总体亮度),以及有关几何中心和方向的信息。它可以被用来获得相对于特定变换的不变性(平移、缩放、旋转不变性) 。
通过轮廓矩可以获得轮廓的面积和几何中心。
二值图像的面积或灰度图像的像素总和,可以表示为 M 00 \mathrm{M}_{00} M00
图像的几何中心可以表示为 { x ‾ , y ‾ } = { M 10 M 00 , M 01 M 00 } \{\overline{\mathrm{x}}, \overline{\mathrm{y}}\}=\left\{\frac{\mathrm{M}_{10}}{\mathrm{M}_{00}}, \frac{\mathrm{M}_{01}}{\mathrm{M}_{00}}\right\} {x,y}={M00M10,M00M01}

可以通过cv::moments()来获取轮廓的轮廓矩。
函数原型:

Moments moments( InputArray array, bool binaryImage = false );

array是轮廓点集或任意二维点集,binaryImage图片是否为二值图像,二值图像是指灰度值只有0或255两种取值的图像。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	std::vector<cv::Moments> mv(contours.size());  //存储所以轮廓的轮廓矩
	for (int i = 0; i < contours.size(); ++i) {  //遍历所有轮廓
		mv[i] = cv::moments(contours[i]);  //求轮廓矩
		cv::circle(dst, cv::Point(mv[i].m10 / mv[i].m00, mv[i].m01 / mv[i].m00), 5, cv::Scalar(0, 255, 0), -1);  //绘制轮廓几何中心
		printf("第%d个轮廓的面积为%lf   %lf\n", i, mv[i].m00, cv::contourArea(contours[i]));  //计算轮廓的面积,可知cv::contourArea()其实就是通过轮廓矩获得的
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

输出:
第0个轮廓的面积为31110.000000   31110.0000001个轮廓的面积为32569.000000   32569.000000

效果为:在这里插入图片描述
获取轮廓的最小外接圆
可以通过cv::minEnclosingCircle()来获取轮廓的最小外接矩形。
函数原型:

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

points为传入的轮廓点集或任意二维点集;center是返回的圆心;radius为返回的圆半径。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	for (int i = 0; i < contours.size(); ++i) {  //遍历所有轮廓
		cv::Point2f center;
		float radius = 0.0f;
		cv::minEnclosingCircle(contours[i], center, radius);  //获取轮廓的最小外接圆

		cv::circle(dst, center, radius, cv::Scalar(0, 0, 255), 2);
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

效果为:在这里插入图片描述
获取轮廓的凸包
可以通过cv::convexHull()获取轮廓的凸包。
凸包即拟合出来的最小外接多边形。
效果为:
函数原型:

void convexHull( InputArray points, OutputArray hull,
                              bool clockwise = false, bool returnPoints = true );

points即输入的二维点集;hull为输出的二维点集;clockwise决定出来的轮廓是否为顺时针方向,为true时为顺时针方向;returnPoints标志,为true时,hull将返回点集,此时为std::vector<cv::Point>类型,为false时,hull将返回返回对应于外壳点的轮廓点的索引。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_0.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	std::vector<std::vector<cv::Point>> Hulls(contours.size());

	for (int i = 0; i < contours.size(); ++i) {  //遍历所有轮廓
		cv::convexHull(contours[i], Hulls[i], true, true);  //寻找轮廓的凸包,输出点集为顺时针

		cv::drawContours(dst, Hulls, i, cv::Scalar(0, 255, 0), 2);
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

获取逼近后的轮廓
可以通过cv::approxPolyDP()来获取逼近后的轮廓。

函数原型:

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

curve为输入的点集;approxCurve为逼近后的输出的点集;epsilon为逼近精度,此值越大,逼近后输出的点越少;closed为是否封闭,若封闭此值为true。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_11.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	std::vector<std::vector<cv::Point>> approxCurves(contours.size());
	for (int i = 0; i < contours.size(); ++i) {  //绘制逼近后的轮廓
		double epsilon = 0.1 * cv::arcLength(contours[i], true);
		cv::approxPolyDP(contours[i], approxCurves[i], epsilon, true);

		cv::drawContours(dst, approxCurves, i, cv::Scalar(0, 255, 0), 2);
	}

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

原图为
在这里插入图片描述
原始轮廓为
在这里插入图片描述
逼近后的轮廓为
在这里插入图片描述
判断一个点和轮廓之间的关系,并获取轮廓的最大内接圆
点和轮廓的关系有3种,在轮廓外、在轮廓内、在轮廓上。
可以通过cv::pointPolygonTest()来获取点和轮廓的关系,此函数会计算得到一个点距离多边形的距离,如果点是轮廓点或者属于轮廓多边形上的点,距离是零,如果是多边形内部的点是是正数,如果是负数返回表示点是外部。

函数原型:

double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );

返回值表示点到轮廓的距离。
contour是输入的点集;pt是输入的点;measureDist标志,为true时,返回每个点到轮廓的距离,为false时,返回+1,0,-1三个值,其中+1表示点在轮廓内部,0表示点在轮廓上,-1表示点在轮廓外。

例子:

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_11.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	cv::Point pt(100, 50);
	int res = cv::pointPolygonTest(contours[0], pt, false);  //只和第0个轮廓进行比较
	if (res == 0) {
		std::cout << "点在轮廓上" << std::endl;
	}
	else if (res == -1) {
		std::cout << "点在轮廓外" << std::endl;
	}
	else if (res == 1) {
		std::cout << "点在轮廓内" << std::endl;
	}

	cv::drawContours(dst, contours, 0, cv::Scalar(0, 0, 255), 2);
	cv::circle(dst, pt, 5, cv::Scalar(0, 255, 0), -1);
	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

输出:
点在轮廓内

效果:
在这里插入图片描述
通过这个判定,可以获取轮廓的最大内接圆,其思路是,遍历所有点(当然可以自定义ROI),计算所有点到轮廓的距离,仅比较轮廓内的点到轮廓的距离,其中距离最大的轮廓内的点即为最大内接圆的圆心。

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

int main() {
	cv::Mat src = cv::imread("1_11.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	cv::Point center;  //记录最大内接圆的圆心
	float radius = 0.0f;  //记录最大内接圆的半径

	//遍历所有点
	for (int i = 0; i < src.cols; ++i) {
		for (int j = 0; j < src.rows; ++j) {
			double res = cv::pointPolygonTest(contours[0], cv::Point(i, j), true);  //在轮廓内的点,返回的距离是正数
			if (res > 0.0f) {  //只关注轮廓内的点
				if (res > radius) {  //当当前点距离大于记录的点时,更新
					radius = res;
					center = { i, j };
				}
			}
		}
	}

	cv::drawContours(dst, contours, 0, cv::Scalar(0, 0, 255), 2);  //绘制轮廓
	cv::circle(dst, center, radius, cv::Scalar(0, 255, 0), -1);  //绘制最大内接圆
	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

效果:
在这里插入图片描述
缩小、放大轮廓
这个函数还不完善,但可以试试。
建议将轮廓转为凸包后再使用,且cv::findContours()的最后一个参数必须选择为 cv::CHAIN_APPROX_SIMPLE,且需要轮廓为顺时针的。

#include <iostream>
#include <vector>

#include <opencv2\opencv.hpp>

//函数功能:对cv::findContours(...,cv::CHAIN_APPROX_SIMPLE)找到的轮廓进行放大、缩小处理(注意最后的参数必须为cv::CHAIN_APPROX_SIMPLE)
//in为输入轮廓;out为输出轮廓;scalar负数为内缩,正数为外扩
static void contours_handle(std::vector<cv::Point>& in, std::vector<cv::Point>& out, const float scalar) {
	float SAFELINE = scalar;

	std::vector<cv::Point2f> dpList, ndpList;
	int count = in.size();
	for (int i = 0; i < count; ++i) {
		int next = (i == (count - 1) ? 0 : (i + 1));
		dpList.emplace_back(in.at(next) - in.at(i));
		float unitLen = 1.0f / sqrt(dpList.at(i).dot(dpList.at(i)));
		ndpList.emplace_back(dpList.at(i) * unitLen);
	}

	for (int i = 0; i < count; ++i) {
		int startIndex = (i == 0 ? (count - 1) : (i - 1));
		int endIndex = i;
		float sinTheta = ndpList.at(startIndex).cross(ndpList.at(endIndex));
		cv::Point2f orientVector = ndpList.at(endIndex) - ndpList.at(startIndex);  //i.e. PV2-V1P=PV2+PV1
		if (std::isinf(SAFELINE / sinTheta * orientVector.x) || std::isinf(SAFELINE / sinTheta * orientVector.y)) {  //过滤掉离谱数据
			continue;
		}
		out.emplace_back(cv::Point2f(in.at(i).x + SAFELINE / sinTheta * orientVector.x, in.at(i).y + SAFELINE / sinTheta * orientVector.y));
	}

	return;
}

int main() {
	cv::Mat src = cv::imread("1_11.png", -1);

	std::vector<std::vector<cv::Point>> contours;
	std::vector<cv::Vec4i> hierarchy;
	cv::findContours(src, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);  //只找最外层轮廓

	cv::Mat dst;  //用于绘制结果
	cv::cvtColor(src, dst, cv::COLOR_GRAY2BGR);

	std::vector<std::vector<cv::Point>> Hulls(contours.size());  //保存凸包
	cv::convexHull(contours[0], Hulls[0], true, true);  //寻找轮廓的凸包,输出点集为顺时针

	std::vector <std::vector<cv::Point>> outs(contours.size());  //保存放大、缩小后的轮廓
	contours_handle(Hulls[0], outs[0], -15.0f);  //将轮廓缩小15个像素

	cv::drawContours(dst, contours, 0, cv::Scalar(0, 0, 255), 2);  //绘制原始轮廓
	cv::drawContours(dst, Hulls, 0, cv::Scalar(0, 255, 0), 2);  //绘制轮廓的凸包
	cv::drawContours(dst, outs, 0, cv::Scalar(255, 0, 0), 2);  //绘制缩小后的轮廓

	cv::imshow("dst", dst);
	cv::waitKey();

	cv::destroyAllWindows();
	return 0;
}

效果:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV轮廓相关操作 C++ 的相关文章

  • 在OpenCV Python中编写4通道以上图像

    这对我来说是一个持续的挑战 我正在尝试使用 openCV 将两个 3 RGB 图像组合成一个 6 通道 TIFF 图像 到目前为止我的代码如下 import cv2 import numpy as np im1 cv2 imread im1
  • OpenCV 中更新窗口的 waitKey() 的替代方法

    到目前为止我见过的所有示例和书籍都建议使用 waitKey 1 来强制重新绘制 OpenCV 窗口 这看起来很奇怪而且太老套了 不必要的时候为什么还要等待 1 毫秒呢 还有其他选择吗 我尝试了 cv updateWindow 但它似乎需要
  • OpenCV:处理每一帧

    我想使用 OpenCV 编写一个跨平台应用程序进行视频捕获 在所有示例中 我发现来自相机的帧是使用抓取功能进行处理并等待一段时间 我想处理序列中的每一帧 我想定义自己的回调函数 每次当一个新帧准备好处理时都会执行该函数 例如直播对于 Win
  • ECC 导致多光谱图像的图像对齐失败

    我正在尝试将 RGB 图像与 IR 图像 单通道 对齐 目标是创建 4 通道图像 R G B IR 为了做到这一点 我正在使用cv2 findTransformECC如中所述这个非常简洁的指南 https learnopencv com i
  • 针对不同相机(RGB 和红外)的 StereoCalibrate

    我在校准两个摄像头时遇到问题 第一个是 RGB 第二个是红外 它们有不同的分辨率 我调整了大小并裁剪了更大的图像 焦距等等 例子 RGB 1920x1080 Infrared 512x424 如何相互校准它们 我应该在stereoCalib
  • 构建 OpenCV 时出错 :: MonitorFromRect 未在此范围内声明

    我试图建立OpenCV version 2 4 8与它一起使用CodeBlocks and MinGw 我按照以下指示进行操作here http kevinhughes ca tutorials opencv install on wind
  • 附加信息:OpenCV:使用 c# 的不同大小的对象

    目前 我的 EmguCV c 代码面临问题 我试图从数据库中识别我的图像 但它不起作用 一旦检测到我的脸 它就会崩溃 然后会出现此错误 附加信息 OpenCV 不同大小的对象 我尝试寻找这个错误 但我一无所知 这是我的代码 Action f
  • OpenCV非旋转图像拼接

    我正在 OpenCV 中进行图像拼接 从不同位置拍摄平面场景的照片并尝试构图全景图 我修改了缝合示例以满足我的需要 openCV 拼接管道的问题是 它假设相机纯粹旋转 但对我来说情况并非如此 当拍摄的照片与场景完全正交时 没有相机旋转 只是
  • 从单应性估计 R/T

    我一直在尝试计算 2 个图像中的特征 然后将这些特征传递回CameraParams R没有运气 特征已成功计算并匹配 但是问题是将它们传递回R t 我明白你必须分解Homography为了使这一点成为可能 我已经使用如下方法完成了 http
  • 从索贝尔确定图像梯度方向?

    我正在尝试使用 openCV 的 Sobel 方法的结果来确定图像梯度方向 我知道这应该是一个非常简单的任务 我从此处复制了许多资源和答案中的方法 但无论我做什么 所得方向始终在 0 57 度之间 我希望范围为 0 360 我相信所有的深度
  • 有没有办法检测图像是否模糊? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道是否有一种方法可以通过分析图像数据来确定图像是否模糊 估计图像清晰度的另一种非常简单的方法是使用拉普拉斯 或 LoG 滤波器并
  • OpenCV 中“IplImage”和“CvMat”的全称是什么?

    有一个IplImage and CvMat在 OpenCV 中 他们的全名是什么 IPL in IplImage代表英特尔处理库 这是Intel维护OpenCV时的残余 CV in cvMat代表计算机视觉矩阵 这是图形中常用的数据结构 I
  • OpenCV:视频录制太快

    我有一个简单的录像机 录制来自网络摄像头的视频 theVideoWriter open filename countAsString ext CV FOURCC X V I D 30 Size 1920 1080 true while re
  • ValueError:当数组不是序列时设置带有序列的数组元素

    您好 此代码旨在存储使用 open cv 绘制的矩形的坐标 并将结果编译为单个图像 import numpy as np import cv2 im cv2 imread 1 jpg im3 im copy gray cv2 cvtColo
  • OpenCV 旋转图像而不裁剪澄清

    我想扩展这个主题 参考用户 Lars Schillingmann 给出的这个 SO 问题和接受的答案 在 C 中的 OpenCV 中旋转图像而不裁剪 https stackoverflow com questions 22041699 ro
  • VideoCapture 未检测到 uEye 摄像头

    我的 uEye 相机遇到了一个问题 使用我的笔记本电脑摄像头 id 0 或 USB 上的网络摄像头 id 1 此行完美运行 TheVideoCapturer open 1 TheVideoCapturer 属于 VideoCapture 类
  • OpenCV 读取视频文件时内存不足

    此示例从文件中读取视频cv2 VideoCapture在 python OpenCV 中内存不足 import cv2 cap cv2 VideoCapture file mp4 while True ret frame cap read
  • 使用opencv+picamera流IO用树莓派捕获视频

    我使用 Raspberry 来简单地显示一个视频 目前仅此 为此 我必须使用 opencv cv2 我尝试了很多解决方案 但现在我想使用 Picamera 库捕获视频 我将向您展示我的代码 import io import time imp
  • 计数物体和更好的填充孔的方法

    我是 OpenCV 新手 正在尝试计算物体的数量在图像中 我在使用 MATLAB 图像处理工具箱之前已经完成了此操作 并在 OpenCV Android 中也采用了相同的方法 第一步是将图像转换为灰度 然后对其进行阈值计算 然后计算斑点的数
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码

随机推荐