Как рассчитать расстояние двух окружностей на изображении с помощью opencv - PullRequest
1 голос
/ 25 июня 2019

изображение с двумя кружками

enter image description here

У меня есть изображение, содержащее два волокна (представленное в виде двух кружков на изображении).Как я могу рассчитать расстояние двух волокон?

Мне трудно определить положение волокна.Я попытался использовать функцию HoughCircles, но параметры трудно оптимизировать, и в большинстве случаев невозможно точно определить круг.Должен ли я сначала вычесть фон или есть какие-то другие методы?Большое спасибо!

Ответы [ 2 ]

3 голосов
/ 25 июня 2019

К сожалению, вы не показали свои шаги предварительной обработки.В моем подходе я сделаю следующее:

  1. Преобразование входного изображения в оттенки серого (см. cvtColor).
  2. Среднее размытие, поддерживает "ребра "(см. medianBlur).
  3. Адаптивный порог (см. adaptiveTreshold).
  4. Морфологическое отверстие, чтобы избавиться от небольшого шума(см. morphologyEx).
  5. Найти круги по HoughCircles.
  6. Здесь не сделано: Возможные уточнения найденных кругов.Исключите слишком маленькие или слишком большие круги.Используйте всю имеющуюся у вас информацию об этом!Например, насколько большими могут быть круги?

Вот весь мой код:

// Read image.
cv::Mat img = cv::imread("images/i7aJJ.jpg", cv::IMREAD_COLOR);

// Convert to grayscale for processing.
cv::Mat blk;
cv::cvtColor(img, blk, cv::COLOR_BGR2GRAY);

// Median blurring to improve following thresholding.
cv::medianBlur(blk, blk, 11);

// Adaptive thresholding.
cv::adaptiveThreshold(blk, blk, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY, 51, -2);

// Morphological opening to get rid of small noise.
cv::morphologyEx(blk, blk, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3)));

// Find circles using Hough transform.
std::vector<cv::Vec4f> circles;
cv::HoughCircles(blk, circles, cv::HOUGH_GRADIENT, 1.0, 300, 50, 25, 100);

// TODO: Refinement of found circles, if there are more than two.
// For example, calculate areas: Neglect too small or too large areas.
// Compare all areas, and keep the two with nearly matching areas and
// suitable areas.

// Draw circles in input image.
for (Vec4f& circle : circles) {
    cv::circle(img, cv::Point(circle[0], circle[1]), circle[2], cv::Scalar(0, 0, 255), 4);
    cv::circle(img, cv::Point(circle[0], circle[1]), 5, cv::Scalar(0, 255, 0), cv::FILLED);
}

// --- Assuming there are only the two right circles left from here. --- //

// Draw some debug output in input image.
const cv::Point c1 = cv::Point(circles[0][0], circles[0][1]);
const cv::Point c2 = cv::Point(circles[1][0], circles[1][1]);
cv::line(img, c1, c2, cv::Scalar(255, 0, 0), 2);

// Calculate distance, and put in input image.
double dist = cv::norm(c1 - c2);
cv::putText(img, std::to_string(dist), cv::Point((c1.x + c2.x) / 2 + 20, (c1.y + c2.y) / 2 + 20), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255, 0, 0));

Окончательный результат выглядит следующим образом:

Final output

Промежуточное изображение прямо перед операцией HoughCircles выглядит следующим образом:

Intermediate image

В общемЯ не так скептически отношусь к HoughCircles.Вы просто должны обратить внимание на свою предварительную обработку.

Надеюсь, это поможет!

1 голос
/ 25 июня 2019

Это возможно при использовании обнаружения кругов, но вы должны предоставить больше изображений, если вы хотите более стабильное обнаружение.Я просто делаю шум и иду прямо к обнаружению круга.Использование нелокальных средств означает, что шумоподавление довольно хорошо сохраняет края, что, в свою очередь, хорошо для алгоритма гибкого края, включенного в алгоритм грубого круга.

Мой код написан на Python, но может быть легко переведен на C ++.

import cv2 
from matplotlib import pyplot as plt

IM_PATH = 'your image path'
DS = 2 # downsample the image

orig = cv2.imread(IM_PATH, cv2.IMREAD_GRAYSCALE)
orig = cv2.resize(orig, (orig.shape[1] // DS, orig.shape[0] // DS))
img = cv2.fastNlMeansDenoising(orig, h=3, templateWindowSize=20 // DS + 1, searchWindowSize=40 // DS + 1)

plt.imshow(orig, cmap='gray')
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, dp=1, minDist=200 // DS, param1=40 // DS, param2=40 // DS, minRadius=210 // DS, maxRadius=270 // DS)

if circles is not None:
    for x, y, r in circles[0]:
        c = plt.Circle((x, y), r, fill=False, lw=1, ec='C1')
        plt.gca().add_patch(c)
plt.gcf().set_size_inches((12, 8))
plt.show()

Важно

Небольшая обработка изображения - это только первый шаг в хорошем (и стабильном!)обнаружение объекта.Вы должны использовать каждую деталь и свойство, которые вы можете получить, и применять некоторые статистические данные, чтобы улучшить свои результаты.Например:

  • Используйте Подход Ива в качестве дополнения и отфильтруйте все обнаруженные круги, которые не пересекают суставы.
  • Всегда ли один круг под другим?Отфильтруйте горизонтально выровненные пары.
  • Можете ли вы уменьшить ROI (круги всегда находятся в определенной области на вашем изображении или они могут быть везде)?
  • Всегда ли оба круга одинакового размера?Отфильтруйте пары разных размеров.
  • ...

Если вы можете использовать несколько метрик, вы можете применить статистическую модель (например, большинство голосов или кнн), чтобы найти лучшую парукругов.

Опять же: всегда думайте о том, что вы знаете о своем объекте, окружающей среде и его поведении, и пользуйтесь этими знаниями.

...