Bacially的任務是: 實現可以攜帶一臺FlyCam/GoPro相機的四軸飛行器的自動着陸/起飛。定位應該相對於包括旋轉在內的2D平面上的降落平臺的高度和位置發生。這意味着無人機有一個「頭部」和「尾巴」,應該降落在特定的位置。檢測降落平臺的位置/角度來控制無人機
着陸平臺看起來像這樣
的邊角形狀是在大的距離,並在中心圓小的重複形狀的方向是精確着陸。
你會採取什麼方法來解決這個任務?
Bacially的任務是: 實現可以攜帶一臺FlyCam/GoPro相機的四軸飛行器的自動着陸/起飛。定位應該相對於包括旋轉在內的2D平面上的降落平臺的高度和位置發生。這意味着無人機有一個「頭部」和「尾巴」,應該降落在特定的位置。檢測降落平臺的位置/角度來控制無人機
着陸平臺看起來像這樣
的邊角形狀是在大的距離,並在中心圓小的重複形狀的方向是精確着陸。
你會採取什麼方法來解決這個任務?
這是一個僞代碼,假設您已經完全訪問了電機控制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));
輸入圖像
檢測最大正方形(Mat t
)
檢測最大-不靠近中心的圓內部的最大正方形(conts[0]
)
圓
EDIT分別中心和板中心,用於定向目的:板中心(center
)根據image
而圓心(c
)的位置是根據電路板的位置(t
) 。剩下的只是找到穿過板中心和圓心的線的斜率。
+1不錯。很多信息在這裏 - 我懷疑你之前做過:-) –
我做過一些類似的東西。我想在這裏提到的是,在這個問題中,董事會內部的圓圈和廣場使得一切都變得不那麼簡單,但更難。 – baci
謝謝!你的回答非常有幫助。是的,這些形狀不是好主意,因爲在運動過程中莫爾效應出現在它們上面。其他問題是當它只部分在框架內時檢測平臺的一部分。它不再是一個廣場,我不知道如何解決它。 –
恐怕這個問題不適合Stackoverflow。請參閱[您可以詢問哪些主題](http://stackoverflow.com/help/on-topic)。 – MMM
@MMM:你能解釋一下你爲什麼這麼想嗎?這是一個特定的編程問題,所以在閱讀了兩次鏈接的FAQ頁面之後,我會說它是明確的主題。 – Niki