2013-07-10 5 views
2

뒤틀린 이미지에서 일반 직사각형을 기꺼이 가져옵니다. 예를 들어OpenCV에서 마름모 모양의 모서리를 찾고 작은 사각형을 잘라내는 방법은?

, 나는 이미지의 이런 종류의 일단 : enter image description here

을 ...하지만 내 코드는 다음과 같습니다 enter image description here

... 나는 다음과 같은 사각형 영역 기자를 자르고 싶습니다을 MY 코드 노호 도시 enter image description here

:

int main(int argc, char** argv) { 
    cv::Mat img = cv::imread(argv[1]); 

    // Convert RGB Mat to GRAY 
    cv::Mat gray; 
    cv::cvtColor(img, gray, CV_BGR2GRAY); 

    // Store the set of points in the image before assembling the bounding box 
    std::vector<cv::Point> points; 
    cv::Mat_<uchar>::iterator it = gray.begin<uchar>(); 
    cv::Mat_<uchar>::iterator end = gray.end<uchar>(); 
    for (; it != end; ++it) { 
     if (*it) 
      points.push_back(it.pos()); 
    } 

    // Compute minimal bounding box 
    Rect box = cv::boundingRect(cv::Mat(points)); 

    // Draw bounding box in the original image (debug purposes) 
    cv::Point2f vertices[4]; 
    vertices[0] = Point2f(box.x, box.y +box.height); 
    vertices[1] = Point2f(box.x, box.y); 
    vertices[2] = Point2f(box.x+ box.width, box.y); 
    vertices[3] = Point2f(box.x+ box.width, box.y +box.height); 

    for (int i = 0; i < 4; ++i) { 
     cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA); 
     cout << "==== vertices (x, y) = " << vertices[i].x << ", " << vertices[i].y << endl; 
    } 

    cv::imshow("box", img); 
    cv::imwrite("box.png", img); 

    waitKey(0); 

    return 0; 
} 
이 큰 프레임을 추출

마름모꼴 모서리를 찾고이를 더 작은 사각형으로 축소하는 방법에 대한 아이디어가 있습니까?

+0

당신은 뒤틀린 이미지를 생성하는 데 사용되는 코너 지점이 일이 있습니까? 그렇게하면이 문제는 훨씬 더 쉽게됩니다. – Aurelius

답변

2

이 문제의 가장 어려운 부분은 실제로 마름모 모서리의 위치를 ​​찾는 것입니다. 실제 사용량의 이미지가 예제와 많이 다른 경우 마름모 모서리를 찾는 특정 절차가 작동하지 않을 수 있습니다. 이 작업이 완료되면 이미지 중심에서 거리를 기준으로 코너 점을 정렬 할 수 있습니다. 이미지 센터에 가장 가까운 점을 찾고 있습니다.

첫째, 당신은 정렬 비교를 위해 펑 (당신이 C++ (11)를 사용할 수있는 경우이 람다 수)를 정의해야합니다

이 실제로 템플릿 operator() 일 필요는 없습니다
struct CenterDistance 
{ 
    CenterDistance(cv::Point2f pt) : center(pt){} 

    template <typename T> bool operator() (cv::Point_<T> p1, cv::Point_<T> p2) const 
    { 
     return cv::norm(p1-center) < cv::norm(p2-center); 
    } 

    cv::Point2f center; 
}; 

, 하지만 그것은 어떤 cv::Point_ 타입에서도 작동합니다.

예제 이미지의 경우 이미지 모서리가 매우 잘 정의되어 있으므로 FAST와 같은 코너 감지기를 사용할 수 있습니다. 그런 다음 cv::convexHull()을 사용하여 마름모 모서리 만있는 외부 점을 가져올 수 있습니다. 대신 라인에서 그려진 사각형을 구성하는 cv::rectangle()을 사용할 수 있습니다

int main(int argc, char** argv) { 
    cv::Mat img = cv::imread(argv[1]); 

    // Convert RGB Mat to GRAY 
    cv::Mat gray; 
    cv::cvtColor(img, gray, CV_BGR2GRAY); 

    // Detect image corners 
    std::vector<cv::KeyPoint> kpts; 
    cv::FAST(gray, kpts, 50); 

    std::vector<cv::Point2f> points; 
    cv::KeyPoint::convert(kpts, points); 
    cv::convexHull(points, points); 

    cv::Point2f center(img.size().width/2.f, img.size().height/2.f); 
    CenterDistance centerDistance(center); 
    std::sort(points.begin(), points.end(), centerDistance); 

    //The two points with minimum distance are what we want 
    cv::rectangle(img, points[0], points[1], cv::Scalar(0,255,0)); 

    cv::imshow("box", img); 
    cv::imwrite("box.png", img); 

    cv::waitKey(0); 

    return 0; 
} 

참고. 결과는 다음과 같습니다

Box result

+0

설명 주셔서 감사합니다, Aurelius. 문제가 있습니다 : 줄에 cv :: FAST (회색, kpts, 50); 그것은 나를 위해 작동하지 않고 실제로 cv :: FAST (thresh, kpts, 250, true)를 사용하고 있습니다. 대신. 나는 약 24 점을 얻었고 예상 한 것뿐만 아니라 4 점을 얻었다. 원하지 않는 점은 원래 위치와 1 또는 2 픽셀 씩 다릅니다. 코너 검출기에 대한 제안 사항이나 여분의 포인트를 제거하기위한 모든 종류의 필터링을 알고 있습니까? – marcelosalloum

+0

게시 한 이미지와 다른 이미지를 사용하고 있습니까? 그렇다면이 방법이 제대로 수행되지 않을 것으로 예상됩니다. 방법을 개선하기 위해 노력하겠습니다. – Aurelius

+0

@marcelosalloum 제 편집을보고 작동 방식을 알려주세요! – Aurelius