我一直在查看自动无人机的代码,并在此存储库中遇到了这个代码:https://github.com/puku0x/cvdrone。我试图理解代码,我是控制器算法和OpenCV的新手。我试过去OpenCV网站并了解功能,但它没有多大帮助。任何帮助将不胜感激。
// Tracking
if (contour_index >= 0) {
// Moments
cv::Moments moments = cv::moments(contours[contour_index], true);
double marker_y = (int)(moments.m01 / moments.m00);
double marker_x = (int)(moments.m10 / moments.m00);
// Show result
cv::Rect rect = cv::boundingRect(contours[contour_index]);
cv::rectangle(image, rect, cv::Scalar(0, 255, 0));
if (track) {
const double kp = 0.005;
vx = kp * (binalized.rows / 2 - marker_y);;
vy = 0.0;
vz = kp;
vr = kp * (binalized.cols / 2 - marker_x);
std::cout << "(vx, vy, vz, vr)" << "(" << vx << "," << vy << "," << vz << "," << vr << ")" << std::endl;
std::cout << "Altitude = " << ardrone.getAltitude() << "%" << std::endl;
}
// Marker tracking
if (track) {
// PID gains
const double kp = 0.001;
const double ki = 0.000;
const double kd = 0.000;
// Errors
double error_x = (binalized.rows / 2 - marker.y); // Error front/back
double error_y = (binalized.cols / 2 - marker.x); // Error left/right
// Time [s]
static int64 last_t = 0.0;
double dt = (cv::getTickCount() - last_t) / cv::getTickFrequency();
last_t = cv::getTickCount();
// Integral terms
static double integral_x = 0.0, integral_y = 0.0;
if (dt > 0.1) {
// Reset
integral_x = 0.0;
integral_y = 0.0;
}
integral_x += error_x * dt;
integral_y += error_y * dt;
// Derivative terms
static double previous_error_x = 0.0, previous_error_y = 0.0;
if (dt > 0.1) {
// Reset
previous_error_x = 0.0;
previous_error_y = 0.0;
}
double derivative_x = (error_x - previous_error_x) / dt;
double derivative_y = (error_y - previous_error_y) / dt;
previous_error_x = error_x;
previous_error_y = error_y;
// Command velocities
vx = kp * error_x + ki * integral_x + kd * derivative_x;
vy = 0.0;//kp * error_y + ki * integral_y + kd * derivative_y;
vz = 0.0;
vr = 0.0;
}
}
// Display the image
cv::putText(image, (track) ? "track on" : "track off", cv::Point(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, (track) ? cv::Scalar(0, 0, 255) : cv::Scalar(0, 255, 0), 1, cv::LINE_AA);
cv::imshow("camera", image);
ardrone.move3D(vx, vy, vz, vr);
}
答案 0 :(得分:2)
您的问题有点笼统,但我会看看能否为您提供一个帮助您入门的概述。 (另请参阅此类似问题:Tracking objects from camera; PID controlling; Parrot AR Drone 2。)
此代码(来自cvdrone
存储库中的sample_tracking.cpp)正在尝试执行以下操作:
它使用OpenCV来完成第一个任务,使用PID来完成第二个任务。
为此,代码从无人机的视频摄像头抓取一个帧,寻找所需颜色的最大斑点,并找到该斑点的中心。
它使用OpenCV通过执行以下操作来实现此目的:
使用InRange
阈值图像,这会打开接近目标颜色的像素,并关闭远处的像素。现在你有一个只包含白色和黑色像素的图像,其中白色像素对应于你正在寻找的颜色。这篇博文有一个很好的例子,可以使用InRange
在魔方的立方体上找到某种颜色的立方体:Color spaces in OpenCV。
将morphologyEx
与MORPH_CLOSE
一起使用可消除图像中的噪点。这应该可以更容易地找到所需的blob。见第4节,&#34;结束&#34;在this page上查看此处理结果的示例。
使用findContours
查找图像中的像素斑点。轮廓是连接所有连续点(沿着边界)的曲线,具有相同的颜色或强度&#34;,因此这将找到图像中所有白色斑点的轮廓。
示例输入:
示例结果:
使用contourArea
按区域查找最大轮廓。这将是无人机将追踪的目标。
使用moments
查找最大轮廓的质心。这是它如何确定对象的图像坐标。 This page documenting contour features提供了有关时刻的更多信息。
所以现在代码具有要跟踪的对象的坐标。接下来是实际移动无人机进行跟踪的部分。
PID控制是一个很大的主题。我只是描述基础知识和这段代码的作用;如果您需要更多信息,可以使用大量介绍性资源,例如本文"Introduction to PID control"或此视频:"PID Control - A brief introduction"。
PID控制器考虑了3件事:
比例术语将您带向目标。当您快速向目标移动时,衍生术语会减慢您的速度,因此您不会超调。当你离目标稍远一点时,积分术语可以帮助推动你。
事实证明,由于以下3行代码,此函数并未真正运行完整的PID控制器:
// PID gains
const double kp = 0.001;
const double ki = 0.000;
const double kd = 0.000;
由于控制器的积分和微分部分的增益为0,这只是一个简单的比例控制器:代码只是查看目标坐标和图像中心之间的差异,并使用它决定如何驾驶无人机。
首先,这是cvdrone
代码uses for the AR.Drone coordinate system:
AR.Drone的前面是X轴,左边是Y轴,上面是Z轴。也 前面是0.0 [rad],每个轴CCW是正的。
X +^- | | Y <-----+ (0,0) Z
在这里计算无人机运动然后命令:
// Command velocities
vx = kp * error_x + ki * integral_x + kd * derivative_x;
vy = 0.0;//kp * error_y + ki * integral_y + kd * derivative_y;
vz = 0.0;
vr = 0.0;
// ...
ardrone.move3D(vx, vy, vz, vr);
因此,代码计算vx
,这是无人机所需的前向/后向速度,为kp * error_x
(其他项为零,因为kd
和{{1}是零)。 ki
是图像中目标的Y坐标与图像的中心Y坐标之间的像素增量。
我不记得AR.Drone相机的实际分辨率,但我们假设它是320x480。这意味着图像的中心位于y = 240。
如果目标的中心靠近图像的顶部,比如说y = 15像素,那么error_x
。然后是error_x = 240 - 15 = 225
。调用vx = kp * error_x = 0.001 * 225 = 0.225
会导致无人机以0.225的速度向前移动。
假设在下一个时间步,无人机向前移动了一点,结果静止跟踪物体在相机的视野中略微向下移动,所以现在中心位于y = 40像素。然后是move3D
和error_x = 240 - 40 = 200
。所以现在调用vx = 0.001 * 200 = 0.200
导致无人机继续向前移动,但比之前更慢。
当无人机向前移动并且目标移近摄像机视野的中心时,无人机将继续减速。很可能无人机将超过目标,并且希望相机会看到目标略低于视野中心,这将导致负move3D
和负error_x
,导致无人机慢慢向后移动。
对于此代码如何使用OpenCV和PID控制器来跟踪对象,这非常快速。通常,您实际上每个轴都有一个单独的PID控制器,您可以将无人机移动到:前进/后向平移,左/右平移,顺时针/逆时针旋转。您可以尝试将vx
和kd
项分别设置为小的负值和小值,以查看它如何改变无人机的行为。 This video是我制作的,演示了使用AR.Drone和两个PID控制器,一个用于前进/后退,一个用于左/右,用于跟踪一系列航路点。
还有其他方法可以使用OpenCV进行对象跟踪。 This video演示了使用camshift / meanshift技术(不是在无人机上)。 This video演示了如何在AR.Drone上使用颜色直方图跟踪。