2012-01-23 25 views
5

Có chức năng nào để kết nối hai (hoặc nhiều) đường bao lân cận không? Hãy nhìn vào trong- tôi/ra và bạn sẽ thấy những gì tôi có nghĩa là ...OpenCV C++/Obj-C: Kết nối các đường bao lân cận

Mã của tôi:

[... some processing ...] 

// getting contours 
std::vector<std::vector<cv::Point> > contours; 
findContours(input, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 

// approximate contours 
std::vector<std::vector<cv::Point> > contours_poly(contours.size()); 
for(int i = 0; i < contours.size(); i++) { 
    approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 5, true); 
} 

// debugging 
cv::Scalar colors[3]; 
colors[0] = cv::Scalar(255, 0, 0); 
colors[1] = cv::Scalar(0, 255, 0); 
colors[2] = cv::Scalar(0, 0, 255); 
for (int idx = 0; idx < contours_poly.size(); idx++) { 
    cv::drawContours(output, contours_poly, idx, colors[idx % 3]); 
} 

output output

+2

Bạn có thể làm giãn hình ảnh để làm cho các đường cong được kết nối nếu chúng đủ gần. – Adrian

+0

Bạn đã thực hiện nó với iOS như thế nào? –

+0

Nó hoạt động trên iOS. Chỉ cần lấy một bản sao của phiên bản OpenCV for iOS này tại đây: https://github.com/aptogo/OpenCVForiPhone và quấn đầu của bạn xung quanh nó… – dom

Trả lời

8

tôi đã đưa ra giải pháp này, bởi vì tôi chỉ cần hộp bounding xung quanh toàn bộ đối tượng:

[... some processing ...] 

// getting contours 
std::vector<std::vector<cv::Point> > contours; 
findContours(input, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); 

// approximate contours 
std::vector<std::vector<cv::Point> > contours_poly(contours.size()); 
for(int i = 0; i < contours.size(); i++) { 
    approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 5, true); 
} 

// merge all contours into one vector 
std::vector<cv::Point> merged_contour_points; 
for (int i = 0; i < contours_poly.size(); i++) { 
    for (int j = 0; j < contours_poly[i].size(); j++) { 
    merged_contour_points.push_back(contours_poly[i][j]); 
    } 
} 

// get rotated bounding box 
std::vector<cv::Point> hull; 
cv::convexHull(cv::Mat(merged_contour_points),hull); 
cv::Mat hull_points(hull); 
cv::RotatedRect rotated_bounding_rect = minAreaRect(hull_points); 

Đôi khi loại bỏ tiếng ồn tiêu có thể dẫn đến kết quả tốt hơn:

void removePepperNoise(cv::Mat &mask) 
{ 
    for (int y=2; y<mask.rows-2; y++) { 
     uchar *pUp2 = mask.ptr(y-2); 
     uchar *pUp1 = mask.ptr(y-1); 
     uchar *pThis = mask.ptr(y); 
     uchar *pDown1 = mask.ptr(y+1); 
     uchar *pDown2 = mask.ptr(y+2); 
     pThis += 2; 
     pUp1 += 2; 
     pUp2 += 2; 
     pDown1 += 2; 
     pDown2 += 2; 

     for (int x=2; x<mask.cols-2; x++) { 
      uchar value = *pThis; // Get this pixel value (0 or 255). // Check if this is a black pixel that is surrounded by white pixels 
      if (value == 0) { 
       bool above, left, below, right, surroundings; 
       above = *(pUp2 - 2) && *(pUp2 - 1) && *(pUp2) && *(pUp2 + 1) && *(pUp2 + 2); 
       left = *(pUp1 - 2) && *(pThis - 2) && *(pDown1 - 2); 
       below = *(pDown2 - 2) && *(pDown2 - 1) && *(pDown2) && *(pDown2 + 1) && *(pDown2 + 2); 
       right = *(pUp1 + 2) && *(pThis + 2) && *(pDown1 + 2); 
       surroundings = above && left && below && right; 
       if (surroundings == true) { 
        // Fill the whole 5x5 block as white. Since we know 
        // the 5x5 borders are already white, we just need to 
        // fill the 3x3 inner region. 
        *(pUp1 - 1) = 255; 
        *(pUp1 + 0) = 255; 
        *(pUp1 + 1) = 255; 
        *(pThis - 1) = 255; 
        *(pThis + 0) = 255; 
        *(pThis + 1) = 255; 
        *(pDown1 - 1) = 255; 
        *(pDown1 + 0) = 255; 
        *(pDown1 + 1) = 255; 
        // Since we just covered the whole 5x5 block with 
        // white, we know the next 2 pixels won't be black, 
        // so skip the next 2 pixels on the right. 
        pThis += 2; 
        pUp1 += 2; 
        pUp2 += 2; 
        pDown1 += 2; 
        pDown2 += 2; 
       } 
      } 
      // Move to the next pixel on the right. 
      pThis++; 
      pUp1++; 
      pUp2++; 
      pDown1++; 
      pDown2++; 
     } 
    } 
} 
+0

Tuyệt vời. Chấp nhận câu trả lời này khi bạn có thể. Nhấp vào hộp kiểm gần đó để chọn nó làm câu trả lời chính thức. – karlphillip

+0

@karlphillip Yep, tôi sẽ làm điều đó! – dom

+0

Bất kỳ ai bị giảm giá: Giải thích lý do! – dom

2

Đơn giản chỉ cần đi qua điểm và tìm ra startpoints gần nhất hoặc thiết bị đầu cuối và sau đó kết nối chúng. Thật khó để quyết định trong trường hợp của bạn nếu đường nét nên được kết nối hay không. Nếu morfology như Adrian Popovici nói không giúp bạn phải xác định một số khoảng cách tối đa mà quyết định nếu điểm được kết nối.

Các vấn đề liên quan