2014-01-06 15 views
2

Bacially的任務是: 實現可以攜帶一臺FlyCam/GoPro相機的四軸飛行器的自動着陸/起飛。定位應該相對於包括旋轉在內的2D平面上的降落平臺的高度和位置發生。這意味着無人機有一個「頭部」和「尾巴」,應該降落在特定的位置。檢測降落平臺的位置/角度來控制無人機

着陸平臺看起來像這樣

enter image description here

的邊角形狀是在大的距離,並在中心圓小的重複形狀的方向是精確着陸。

你會採取什麼方法來解決這個任務?

+0

恐怕這個問題不適合Stackoverflow。請參閱[您可以詢問哪些主題](http://stackoverflow.com/help/on-topic)。 – MMM

+2

@MMM:你能解釋一下你爲什麼這麼想嗎?這是一個特定的編程問題,所以在閱讀了兩次鏈接的FAQ頁面之後,我會說它是明確的主題。 – Niki

回答

2

這是一個僞代碼,假設您已經完全訪問了電機控制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

EDIT分別中心和板中心,用於定向目的:板中心(center)根據image而圓心(c)的位置是根據電路板的位置(t) 。剩下的只是找到穿過板中心和圓心的線的斜率。

+0

+1不錯。很多信息在這裏 - 我懷疑你之前做過:-) –

+1

我做過一些類似的東西。我想在這裏提到的是,在這個問題中,董事會內部的圓圈和廣場使得一切都變得不那麼簡單,但更難。 – baci

+0

謝謝!你的回答非常有幫助。是的,這些形狀不是好主意,因爲在運動過程中莫爾效應出現在它們上面。其他問題是當它只部分在框架內時檢測平臺的一部分。它不再是一個廣場,我不知道如何解決它。 –