2017-01-27 8 views
-1

Я пытаюсь закодировать приложение для настольных компьютеров для подсчета очков стрельбы.
После исследования найти статью может помочь, но проблема заключается в том, как работать с openCv или emguCv, я хорош на C#, но C++ нужно время, чтобы изучить его.
Другое квесто, что лучше всего подходит для обнаружения перекрывающихся пулевых отверстий в цели стрельбы?
нравится это фото
enter image description here Изображение наверху. В кольцах 7 и 8 имеются два пулевых отверстия, перекрывающиеся. В этом случае было бы легко решить это, просто выполнив эрозию.Сканирующая целевая бумага для оценки

Однако в тех случаях, когда круги почти полностью перекрываются, я не вижу, как я могу их идентифицировать.

Некоторые ссылки могут помочь:

+1

Для перекрывающихся кругов вы можете попытаться измерить площадь отверстия и сравнить площадь с одиночным отверстием «станард». Это может быть более надежным, чем эрозия и проще, чем поиск кругов. –

ответ

2

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

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

Original image

thresholded & distances

isolated bullets

код

C++:

cv::Mat preprocess(const cv::Mat image) { 
    display(image, "Original"); 

    // Color thresholds 
    cv::Scalar minColor(141, 0, 0); 
    cv::Scalar maxColor(255, 255, 124); 
    cv::Mat filtered; 

    // Isolate the interesting range of colors 
    cv::inRange(image, minColor, maxColor, filtered); 
    filtered.convertTo(filtered, CV_8U); 

    // Apply opening (erode then dilate) 
    cv::Mat opening; 
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)); 
    cv::morphologyEx(filtered, opening, cv::MORPH_OPEN, kernel, cv::Point(-1,-1), 2); 

    // Compute the distance to the closest zero pixel (euclidian) 
    cv::Mat distance; 
    cv::distanceTransform(opening, distance, CV_DIST_L2, 5); 
    cv::normalize(distance, distance, 0, 1.0, cv::NORM_MINMAX); 

    display(distance, "Distance"); 

    // Thresholding using the longest distance 
    double min, max; 
    cv::minMaxLoc(distance, &min, &max); 
    cv::Mat thresholded; 
    cv::threshold(distance, thresholded, 0.7 * max, 255, CV_THRESH_BINARY); 
    thresholded.convertTo(thresholded, CV_8U); 

    // Find connected components 
    cv::Mat labels; 
    int nbLabels = cv::connectedComponents(thresholded, labels); 

    // Assign a random color to each label 
    vector<int> colors(nbLabels, 0); 
    for (int label = 1; label < nbLabels; ++label) { 
     colors[label] = rand() & 255; 
    } 
    cv::Mat result(distance.size(), CV_8U); 
    for (int r = 0; r < result.rows; ++r) { 
     for (int c = 0; c < result.cols; ++c) { 
      int label = labels.at<int>(r, c); 

      result.at<uchar>(r, c) = colors[label]; 
     } 
    } 

    display(result, "Labels"); 

    return result; 
} 
0

есть два способа, которыми вы можете завершить свою задачу.

  1. Простым методом является вычитание изображений. Возьмите идеальный целевой образ и вычтите его с целевым изображением после каждого попадания или, наконец, после завершения всей съемки.
  2. Другим методом будет выделение цветов. Если цвет пули синий, то вы можете использовать функцию inRange для фильтрации цвета. Вы даже можете создать библиотеку различных цветных пуль, чтобы пользователь мог выбрать ее из опции. Недавно я сделал аналогичный проект на C#. Для получения более подробной информации свяжитесь со мной по электронной почте. ([email protected])
Смежные вопросы