2014-01-06 1 views
2

Bacisally 작업 : 하나의 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)); 
,691,363,210

입력 화상 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 배향 상업적 각각 91,363,210

원 중심과 기판의 중심 : 보드 센터 (center)의 위치가 원 중심 반면 image (c)에 따른되는 보드에 따른 위치이다 (t) . 왼쪽은 보드 중심과 원 중심을 통과하는 선의 기울기를 찾는 것입니다.

+0

+1 니스. 여기에 많은 정보가 있습니다 - 전에 해본 적이 있으리라 생각합니다 : –

+1

전에 비슷한 것을했습니다. 제가 여기서 언급하고자하는 것은이 문제에서 그 보드 안에있는 원과 사각형이 모든 것을 단순하게 만들지는 않지만 더 어렵게 만드는 것입니다. – baci

+0

감사합니다! 당신의 대답은 매우 도움이되었습니다. 예,이 모양은 좋은 생각이 아닙니다. 왜냐하면 이동 중에 모아레 효과가 나타납니다. 다른 문제는 부분적으로 프레임의 내부에있을 때 플랫폼의 일부를 감지하는 것입니다. 더 이상 광장이 아니며 어떻게 해결해야할지 모르겠습니다. –