Хобрук: Ваш путь к мастерству в программировании

найти контуры находит слишком много контуров на смоделированном изображении

Я хочу найти контуры двоичного изображения сегментированных горных пород. Есть некоторые проблемы с функцией findContours из opencv.

  1. Размер контура составляет около 1000, в то время как контуры из двоичного изображения могут быть около 30-50.

  2. Когда я рисую ВСЕ контуры, они кажутся достойным представлением черных границ двоичного изображения. Но когда я рисую только один контур некоторого случайного индекса, он показывает небольшой контур.

Изображения представлены ниже:

  • Двоичное изображение

введите описание изображения здесь

  • Контуры всего индекса

введите описание изображения здесь

  • Контур случайного контурного указателя. Маленький зеленый контур

введите описание изображения здесь

Я хотел бы иметь ровно столько контуров, сколько на двоичном изображении.

Код:

std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(input_image, contours,hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);
  for( int i = 0; i < (int)contours.size(); i++)
  {

      cv::drawContours(input_rgb_image, contours, 512 , cv::Scalar(0,255,0), 1, 8, hierarchy,1);


  }



Ответы:


1

В вашем коде есть две проблемы. Вы получите лучшие результаты, если инвертируете и размываете изображение. Это мои результаты после применения этих двух операций до нахождения контуров:  contours

Функция OpenCV findContours() находит темные контуры на светлом фоне. Если вы хотите найти белые пространства, которые являются камнями, вам нужно сначала инвертировать двоичное изображение. Вы можете инвертировать двоичное изображение следующим образом invertedImage = 255 - binaryImage. Размытие также помогает, потому что оно соединяет пиксели, которые должны быть соединены, но не из-за низкого разрешения. Размытие выполняется кодом blurredImage = cv2.blur(img, (2,2)). Это перевернутое размытое изображение:

инвертировать и размыть

Это код, который я использовал:

import cv2
import random
# Read image
gray = 255-cv2.imread('/home/stephen/Desktop/image.png', 0)
gray = cv2.blur(gray, (2,2))
# Find contours in image
contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
img = cv2.imread('/home/stephen/Desktop/image.png')
for cnt in contours:
    color = random.randint(0,255),random.randint(0,255),random.randint(0,255)
    img = cv2.drawContours(img, [cnt], 0, color, cv2.FILLED)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
23.09.2019

2

Я бы попробовал пару вещей:

  • двусторонний фильтр вместо размытия. Он сглаживает объекты аналогично размытию, но также пытается сохранить границы, что хорошо для сегментации. Недостатки - это дорого с точки зрения вычислений, но вы можете найти "свои" параметры, которые хорошо работают бесплатно.
  • blur + означает сдвиг сегментации до водораздела. Размытие будет действовать точно так же, как ожидалось, а среднее смещение будет усредняться и соединять контуры схожих цветов и, таким образом, уменьшать количество контуров. В зависимости от параметров, meanshift также стоит дорого. Просто поиграйте с этим.

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

  • схожесть гистограммы на некоторых каналах hsv;
  • свойства контуров, например округлость. Если округлость двух объединенных соседей лучше округлости любого из них, то их можно объединить. Что-то вроде этого.

Расчет округлости:

float calcRoundness(std::vector<cv::Point> &contour, double area)
{
        float p = cv::arcLength(contour, true);
        if (p == 0)
                return 0;
        float k = (4 * M_PI * area) / pow(p, 2);

        /* 1 is circle, 0.75 - squared area, etc. */
        return k;
}
23.09.2019
Новые материалы

Учебные заметки JavaScript Object Oriented Labs
Вот моя седьмая неделя обучения программированию. После ruby ​​и его фреймворка rails я начал изучать самый популярный язык интерфейса — javascript. В отличие от ruby, javascript — это более..

Разбор строк запроса в vue.js
Иногда вам нужно получить данные из строк запроса, в этой статье показано, как это сделать. В жизни каждого дизайнера/разработчика наступает момент, когда им необходимо беспрепятственно..

Предсказание моей следующей любимой книги 📚 Благодаря данным Goodreads и машинному обучению 👨‍💻
«Если вы не любите читать, значит, вы не нашли нужную книгу». - J.K. Роулинг Эта статья сильно отличается от тех, к которым вы, возможно, привыкли . Мне очень понравилось поработать над..

Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

Как настроить Selenium в проекте Angular
Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

Аргументы прогрессивного улучшения почти всегда упускают суть
В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

Введение в Джанго Фреймворк
Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..