gpt4 book ai didi

opencv - 检测着陆平台的位置/角度以引导无人机

转载 作者:太空宇宙 更新时间:2023-11-03 21:37:01 24 4
gpt4 key购买 nike

基本上任务是:实现四轴飞行器的自动降落/起飞,可搭载一个FlyCam/GoPro相机。方向应相对于 2D 平面上着陆平台的高度和位置进行,包括旋转。这意味着无人机有“头”和“尾”,应该降落在特定位置。

登陆平台是这样的

enter image description here

拐角形状用于远距离定位,中心圆中的小重复形状用于精确着陆。

你会采用什么方法来解决这个任务?

最佳答案

这是一个伪代码,假设您已经拥有对电机控制 API 的完全访问权限;也就是说,您已经成功定义了改变高度、向左旋转等所需的内容。

loop
{
if(landing board detected)
{
if(circle including the center point detected)
{
find orientation from corner circles' center
change device's orientation accordingly
}
else
{
lose altitude & move towards the center point
}
}
else
{
move around
}
}

着陆板及其中心:

假设:它是最大且近乎完美的正方形。

1-阈值

2-提取轮廓

3- 将形状(方形)滤镜应用于轮廓

4-找到最大的轮廓

5-找到它的中心

6- 使用此轮廓的边界矩形裁剪图像

Mat image = imread("~\\image.jpg");

// scale down for faster processing
pyrDown(image, image);
pyrDown(image, image);
// safe copy
Mat temp = image.clone();
// noise reduction & thresholding
GaussianBlur(image, image, Size(5,5), 3);
cvtColor(image, image, CV_BGR2GRAY);
threshold(image, image, 127, 255, CV_THRESH_OTSU);

// extract all contours
vector<vector<Point> > contours;
findContours(image, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

// define a perfect square
vector<Point> square;
square.push_back(Point(0,0));
square.push_back(Point(0,10));
square.push_back(Point(10,10));
square.push_back(Point(10,0));

// filter out contours that are not square
bool erased;
for(unsigned int i = 0; i<contours.size(); i++)
{
erased = false;
double x = matchShapes(contours[i], square, CV_CONTOURS_MATCH_I2, 0);
if(x > 0.005)
{
contours.erase(contours.begin() + i);
erased = true;
}
if(erased) i--;
}

// area filtering to find the biggest square contour
vector<double> contourAreas(contours.size());
for(unsigned int i = 0; i<contours.size(); i++)
{
contourAreas[i] = contourArea(contours[i]);
}
int ID = max_element(contourAreas.begin(), contourAreas.end()) - contourAreas.begin();
for(unsigned int i = 0; i<contours.size(); i++)
{
erased = false;
if(i != ID)
{
contours.erase(contours.begin() + i);
erased = true;
ID--;
}
if(erased) i--;
}

// find the bounding rect of this contour and crop the image within that rect
vector<Point> total;
for(unsigned int j = 0; j<contours[0].size(); j++)
{
total.push_back(contours[0][j]);
}
Rect rect = boundingRect(total);

Mat t = Mat(temp, rect);

// find the center of the landing board - to move towards it when necessary
Moments m = moments(contours[0], false);
Point center = Point(cvRound(m.m10/m.m00), cvRound(m.m01/m.m00));

现在我们已经检测到板,我们需要检测角圆的方向。

1-阈值

2-提取轮廓

3- 对轮廓应用形状(圆形)滤镜

4- 过滤掉靠近棋盘中心的圆圈

5-结果圆是角圆,找到它们最大的圆心

// threshold
Mat gray;
cvtColor(t, gray, CV_BGR2GRAY);
threshold(gray, gray, 2187451321, 12186471, CV_THRESH_OTSU);

// extract contours
vector<vector<Point> > conts;
findContours(gray, conts, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

// circularity check
for(unsigned int i = 0; i<conts.size(); i++)
{
erased = false;
if(4*3.14*contourArea(conts[i]) / ((arcLength(conts[i],true) * arcLength(conts[i],true))) < 0.85)
{
conts.erase(conts.begin() + i);
erased = true;
}
if(erased) i--;
}

// position check - filtering out center circle
vector<Moments> mu(conts.size());
vector<Point2f> mc(conts.size());
for(unsigned int i = 0; i<conts.size(); i++ )
{
mu[i] = moments(conts[i], false);
}
for(unsigned int i = 0; i <conts.size(); i++ )
{
mc[i] = Point2f(mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00);
}
for(unsigned int i=0; i<conts.size(); i++)
{
erased = false;
if((((int)mc[i].x > t.cols/3) && ((int)mc[i].x < 2*t.cols/3) && ((int)mc[i].y < 2*t.rows/3) && ((int)mc[i].y > t.rows/3)))
{
mc.erase(mc.begin() + i);
conts.erase(conts.begin() + i);
erased = true;
}
if(erased) i--;
}

// selecting the biggest circle
vector<double> contAreas(conts.size());
for(unsigned int i = 0; i<conts.size(); i++)
{
contAreas[i] = contourArea(conts[i]);
}
ID = max_element(contAreas.begin(), contAreas.end()) - contAreas.begin();
for(unsigned int i = 0; i<conts.size(); i++)
{
erased = false;
if(i != ID)
{
conts.erase(conts.begin() + i);
erased = true;
ID--;
}
if(erased) i--;
}

drawContours(t, conts, -1, Scalar(0,255,255));

// finding its center - this is nothing but current orientation
Moments m2 = moments(conts[0], false);
Point c = Point(cvRound(m2.m10/m2.m00), cvRound(m2.m01/m2.m00));

输入图像 input image

检测到的最大平方(Mat t)

detected biggest-square

检测到最大的 - 不靠近中心圆 - 在那个最大的正方形内 (conts[0]) detected biggest-not close to center-circle-inside that biggest square

圆心和棋盘中心分别用于定位目的 circle center and board center respectively, for orientation purposes

编辑:棋盘中心 (center) 是根据 image 的位置,而圆心 (c) 是根据 image 的位置板(t)。剩下的就是找到通过板心和圆心的直线的斜率。

关于opencv - 检测着陆平台的位置/角度以引导无人机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20951552/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com