Подсчитайте количество пикселей одного цвета в помеченном объекте в opencv - PullRequest
1 голос
/ 22 сентября 2019

Я пытаюсь сегментировать изображение камней и получаю приличный результат.Но теперь мне нужно посчитать пиксели в самом крупном цветном объекте.Segmented image

На рисунке выше показано сегментированное изображение груды камней, и я хочу подсчитать количество зеленых пикселей, обозначающих самый большой камень на изображении.А затем также посчитать 2-го по величине, то есть желтый.После подсчета я хотел бы сравнить его с основополагающей правдой, чтобы сравнить мои результаты.

Код для получения сегментированного изображения ссылается на Сегментация водораздела opencv .Часть моего кода также приведена ниже:

  cv::findContours(peaks_8u, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

  // Create the marker image for the watershed algorithm
  // CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
  cv::Mat markers = cv::Mat::zeros(input_image.size(), CV_32S);
  // Draw the foreground markers
  for (size_t i = 0; i < contours.size(); i++)
  {
    cv::drawContours(markers, contours, static_cast<int>(i), cv::Scalar(static_cast<int>(i) + 1), -1);
  }

  // Draw the background marker
  cv::circle(markers, cv::Point(5, 5), 3, cv::Scalar(255), -1);



  cv::watershed(in_sharpened_image, markers);



  // Generate random colors; result of watershed
  std::vector<cv::Vec3b> colors;
  for (size_t i = 0; i < contours.size(); i++)
  {
    int b = cv::theRNG().uniform(0, 256); //0,256
    int g = cv::theRNG().uniform(0, 256);
    int r = cv::theRNG().uniform(0, 256);
    colors.push_back(cv::Vec3b((uchar)b, (uchar)g, (uchar)r));
  }

  // Create the result image
  cv::Mat dst = cv::Mat::zeros(markers.size(), CV_8UC3);
  // Fill labeled objects with random colors
  for (int i = 0; i < markers.rows; i++)
  {
    for (int j = 0; j < markers.cols; j++)
    {
      int index = markers.at<int>(i, j);
      if (index > 0 && index <= static_cast<int>(contours.size()))
      {
        dst.at<cv::Vec3b>(i, j) = colors[index - 1];
      }
    }
  }

Вопрос: Существует ли эффективный способ подсчета пикселей внутри самого большого / маркера в opencv?

Ответы [ 2 ]

3 голосов
/ 22 сентября 2019

Вы можете вычислить гистограмму markers, используя cv :: calcHist с диапазоном от 0 до contours.size() + 1 и найти наибольшее значение в нем, начиная с индекса 1.

1 голос
/ 22 сентября 2019

Вместо подсчета пикселей вы можете использовать contourArea () для вашего наибольшего контура.Это будет работать намного быстрее.

Примерно так.

    cv::Mat mask;

    // numOfSegments - number of your labels (colors)
    for (int i = 0; i < numOfSegments; i++) {
                std::vector<cv::Vec4i> hierarchy;

                // this "i + 2" may be different for you
                // depends on your labels allocation.
                // This is thresholding to get mask with
                // contour of your @i label (color)
                cv::inRange(markers, i + 2, i + 2, mask);

                contours.clear();
                findContours(mask, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);

                double area = cv::contourArea(contours[0]);
    }

Также хорошо иметь контуры в руках, потому что после водораздела () они будут довольно "шумными" с множеством маленьких пиков ине подходит для большинства случаев использования в «сыром» виде.Имея контур, вы можете сгладить его с помощью гаусса или приблизительно, и т. Д., А также проверить наличие важных свойств или формы контура, если вам это нужно.

...