首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扫描投篮靶纸以获取分数

扫描投篮靶纸以获取分数
EN

Stack Overflow用户
提问于 2017-01-27 18:18:27
回答 2查看 1.8K关注 0票数 0

我正试图编写一个桌面应用程序,用于计算射击靶场纸的得分。

经过研究,发现一些文章可以帮助,但仍然是如何使用openCv或emguCv的问题,我擅长C#,但C++需要时间来学习它。

另一个问题是,在射击目标中发现重叠弹孔的最佳方法是什么?

就像这张照片

图像在上面。在环7和8中有两个弹孔重叠。在这种情况下,很容易通过简单的腐蚀来解决这个问题。

然而,在圆圈几乎完全重叠的情况下,我不知道如何识别它们。

一些链接可以帮助:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-28 12:40:15

您可以通过以下步骤隔离重叠的子弹:

  • 将子弹与图像的其余部分隔离开来。
  • 在子弹上涂上开口(腐蚀后扩张)。
  • 计算每个白色像素到最近的黑色像素的距离。
  • 应用阈值

C++代码:

代码语言:javascript
复制
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;
}
票数 2
EN

Stack Overflow用户

发布于 2017-02-07 05:38:13

有两种方法可以完成你的任务。

  1. 更简单的方法是减去图像。取一幅理想的目标图像,每次击中后或完成整个拍摄后,用目标图像减去它。
  2. 另一种方法是分离颜色。如果子弹的颜色是蓝色,那么我们可以使用inRange函数过滤掉颜色。您甚至可以使用不同颜色的符号创建一个库,这样用户就可以从选项中选择它。我最近在C#做了类似的项目。欲知更多详情,请联系我的电子邮件。(rajkumarm704@gmail.com)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41900518

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档