2014-09-04 48 views
5

Tôi muốn tính toán bán kính vòng tròn màu đỏ (hình 2). Tôi gặp khó khăn khi tìm những vòng tròn này bằng cách sử dụng HoughCircles từ OpenCV. Như bạn thấy trong hình. 2 Tôi chỉ có thể tìm thấy các vòng tròn nhỏ ở trung tâm được thể hiện bằng màu đen bằng cách sử dụng HoughCircles.Tìm các vòng tròn chồng chéo/phức tạp với OpenCV

gốc pic1 vả 2. red

Kể từ khi tôi biết trung tâm của vòng tròn màu đỏ (mà cũng giống như những cái màu đỏ), có cách nào để tính toán đơn giản là bán kính của vòng tròn màu đỏ?

là nó cũng có thể có một cách chung chung của bán kính của vòng tròn tính toán trên một hình ảnh phức tạp hơn như thế này một:

example 2

Edit: Đây là phần thú vị của mã của tôi sau khi có vả 2 :

threshold(maskedImage, maskedImage, thresh, 255, THRESH_BINARY_INV | THRESH_OTSU); 
    std::vector<Vec3f> circles; 
// Canny(maskedImage, maskedImage, thresh, thresh * 2, 3); 

HoughCircles(maskedImage, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/4, cannyThreshold, accumulatorThreshold, 0, 0); 

Mat display = src_display.clone(); 
for (size_t i = 0; i < circles.size(); i++) 
{ 
    Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); 
    int radius = cvRound(circles[i][2]); 
    // circle center 
    circle(display, center, 3, Scalar(0, 255, 0), -1, 8, 0); 
    // circle outline 
    circle(display, center, radius, Scalar(0, 0, 255), 3, 8, 0); 
} 

tôi đã cố gắng sử dụng chơi với cannyThreshold và ác quy mà không kết quả. Hình ảnh thực tế là 5x biggers. Ở đây a link ví dụ 1 sau ngưỡng.

Cảm ơn

+0

bạn có thể hiển thị mã HoughCircles của mình không? chồng chéo/halfcircles vv thường không phải là một vấn đề cho HoughCircles afaik. – Micka

+0

Cảm ơn bạn Micka Tôi chỉ cần thêm một số mã – coincoin

+1

Bạn có thể lưu maskedImage vào một tệp ('imwrite (" maskedImage.jpg ", maskedImage)') và đăng liên kết không? –

Trả lời

5

Bạn đã biết các vòng tròn nhỏ hơn trong hình ảnh (bạn đã vẽ màu đen).

  • Chuẩn bị hình ảnh mặt nạ bằng các vòng kết nối này để các khu vực có vòng tròn nhỏ hơn sẽ có pixel khác 0. Chúng tôi sẽ gọi nó là mặt nạ:

enter image description here

  • Trong ảnh gốc, điền các khu vực vòng tròn trong một màu tối (nói màu đen). Điều này sẽ dẫn đến một hình ảnh như vả của bạn 2. Chúng tôi sẽ gọi nó là điền
  • Ngưỡng điền hình ảnh để có được các vùng tối. Chúng tôi sẽ gọi nó là nhị phân. Bạn có thể sử dụng Otsu thresholding cho việc này. Kết quả sẽ giống như thế này:

enter image description here

  • Hãy khoảng cách biến đổi của nhị phân hình ảnh này. Sử dụng một phương pháp ước lượng khoảng cách chính xác cho việc này. Chúng tôi sẽ gọi số điện thoại này dist. Nó sẽ trông như thế này Một màu chỉ là một map nhiệt cho rõ ràng hơn:

enter image description hereenter image description here

  • Sử dụng mặt nạ để có được những vùng đỉnh từ quận. Giá trị tối đa của mỗi khu vực như vậy sẽ cung cấp cho bạn bán kính của vòng tròn lớn hơn. Bạn cũng có thể thực hiện một số quá trình xử lý trên các vùng này để có được giá trị hợp lý hơn cho bán kính chứ không phải chỉ cần chọn tối đa.
  • Đối với việc lựa chọn các khu vực, bạn có thể tìm thấy các đường viền của mặt nạ và sau đó trích xuất khu vực mà từ quận hình ảnh, hay, kể từ khi bạn đã biết các vòng tròn nhỏ từ việc áp dụng hough vòng tròn biến đổi, chuẩn bị một mặt nạ từ mỗi vòng kết nối đó và trích xuất vùng đó từ dist hình ảnh. Tôi không chắc chắn nếu bạn có thể tính toán số liệu thống kê tối đa hoặc khác bằng cách đưa ra một mặt nạ. Max chắc chắn sẽ hoạt động vì phần còn lại của pixel là 0. Bạn có thể tính toán số liệu thống kê của khu vực nếu bạn trích xuất các pixel đó sang một mảng khác.

Hình bên dưới hiển thị mặt nạ như vậy và vùng được trích xuất từ ​​dist. Đối với điều này tôi nhận được tối đa khoảng 29, phù hợp với bán kính của vòng tròn đó. Lưu ý rằng hình ảnh không được chia tỷ lệ.

mặt nạ cho một vòng tròn, khu vực chiết xuất từ ​​quận

enter image description hereenter image description here

Dưới đây là đoạn code (tôi không sử dụng hough-circles transform):

Mat im = imread(INPUT_FOLDER_PATH + string("ex1.jpg")); 

    Mat gray; 
    cvtColor(im, gray, CV_BGR2GRAY); 

    Mat bw; 
    threshold(gray, bw, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU); 
    // filtering smaller circles: not using hough-circles transform here. 
    // you can replace this part with you hough-circles code. 
    vector<int> circles; 
    vector<vector<Point>> contours; 
    vector<Vec4i> hierarchy; 
    findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 
    for(int idx = 0; idx >= 0; idx = hierarchy[idx][0]) 
    { 
     Rect rect = boundingRect(contours[idx]); 
     if (abs(1.0 - ((double)rect.width/rect.height) < .1)) 
     { 
      Mat mask = Mat::zeros(im.rows, im.cols, CV_8U); 
      drawContours(mask, contours, idx, Scalar(255, 255, 255), -1); 
      double area = sum(mask).val[0]/255; 
      double rad = (rect.width + rect.height)/4.0; 
      double circArea = CV_PI*rad*rad; 
      double dif = abs(1.0 - area/circArea); 
      if (dif < .5 && rad < 50 && rad > 30) // restrict the radius 
      { 
       circles.push_back(idx); // store smaller circle contours 
       drawContours(gray, contours, idx, Scalar(0, 0, 0), -1); // fill circles 
      } 
     } 
    } 

    threshold(gray, bw, 0, 255, CV_THRESH_BINARY_INV|CV_THRESH_OTSU); 

    Mat dist, distColor, color; 
    distanceTransform(bw, dist, CV_DIST_L2, 5); 
    double max; 
    Point maxLoc; 
    minMaxLoc(dist, NULL, &max); 
    dist.convertTo(distColor, CV_8U, 255.0/max); 
    applyColorMap(distColor, color, COLORMAP_JET); 
    imshow("", color); 
    waitKey(); 

    // extract dist region corresponding to each smaller circle and find max 
    for(int idx = 0; idx < (int)circles.size(); idx++) 
    { 
     Mat masked; 
     Mat mask = Mat::zeros(im.rows, im.cols, CV_8U); 
     drawContours(mask, contours, circles[idx], Scalar(255, 255, 255), -1); 
     dist.copyTo(masked, mask); 
     minMaxLoc(masked, NULL, &max, NULL, &maxLoc); 
     circle(im, maxLoc, 4, Scalar(0, 255, 0), -1); 
     circle(im, maxLoc, (int)max, Scalar(0, 0, 255), 2); 
     cout << "rad: " << max << endl; 
    } 
    imshow("", im); 
    waitKey(); 

Kết quả (quy mô):

enter image description hereenter image description here

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn đó là một ý tưởng hay. Tôi đã thu được kết quả tương tự bạn đã sử dụng distanceTransform. (Bằng cách làm thế nào để bạn tô màu bản đồ khoảng cách applyColorMap dường như không làm việc cho tôi). Tuy nhiên tôi không thấy làm thế nào tôi có thể phân biệt bán kính vòng tròn và tính toán hiệu quả các giá trị tối đa này? – coincoin

+1

Trong OpenCV, kết quả biến đổi khoảng cách sẽ là loại phao. Hãy thử mở rộng phạm vi từ 0-255 và chuyển đổi thành loại uint8. Sau đó applyColorMap sẽ hoạt động. Để lấy giá trị tối đa, hãy xem bài đăng đã chỉnh sửa của tôi để xem tôi có trả lời câu hỏi của bạn ở đó không. – dhanushka

+0

Cảm ơn bạn đã trả lời có giá trị. Tôi đã nhận được màu bản đồ nhưng tôi gặp khó khăn trong việc hiểu cách tôi có thể trích xuất vùng bằng cách sử dụng hình ảnh mặt nạ và trung tâm của các vòng tròn nhỏ. Bạn có thể nêu chi tiết phần này không? – coincoin

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