2012-01-23 12 views
5

¿Hay una función para conectar dos (o más) contornos cercanos? Echar un vistazo a mi entrada/salida y verá lo que quiero decir ...OpenCV C++/Obj-C: Conectar contornos cercanos

Mi código:

[... 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

Usted podría dilatar el imagen para hacer las curvas conectadas si están lo suficientemente cerca. – Adrian

+0

¿Cómo lo hiciste con iOS? –

+0

Está trabajando en iOS. Simplemente tome una copia de esta versión de OpenCV para iOS aquí: https://github.com/aptogo/OpenCVForiPhone y concéntrese en ello ... – dom

Respuesta

8

me ocurrió con esta solución, porque sólo necesito la caja alrededor de la totalidad del objeto:

[... 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); 

eliminación veces el ruido de pimienta puede conducir a mejores resultados:

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

Impresionante. Acepta esta respuesta cuando puedas. Haga clic en la casilla de verificación cercana para seleccionarla como la respuesta oficial. – karlphillip

+0

@karlphillip Sí, lo haré! – dom

+0

Quien haya votado negativamente: ¡Explique por qué! – dom

2

sólo tiene que ir a través de puntos y encontrar los puntos finales más cercanos startpoints o y luego conectarlos. Es difícil decidir en su caso si los contornos deberían estar conectados o no. Si la morfología como dijo Adrian Popovici no ayuda, debe especificar una distancia máxima que decida si los puntos deben conectarse.

Cuestiones relacionadas