C# 扫描拍摄目标纸以获得分数
我正在尝试编写一个桌面应用程序,用于计算射击靶场纸的分数。C# 扫描拍摄目标纸以获得分数,c#,opencv,desktop-application,emgucv,image-recognition,C#,Opencv,Desktop Application,Emgucv,Image Recognition,我正在尝试编写一个桌面应用程序,用于计算射击靶场纸的分数。 经过研究,发现一些文章可以帮助,但仍然是如何使用OpenCV或EMGUCV的问题,我擅长C语言,但是C++需要时间去学习。 另一个问题是,检测射击目标中重叠弹孔的最佳方法是什么? 喜欢这张图片 图片在上面。在环7和环8中有两个重叠的弹孔。在这种情况下,很容易通过简单的侵蚀来解决 然而,在圆圈几乎完全重叠的情况下,我不知道如何识别它们 一些链接可以帮助: 您可以通过以下步骤隔离重叠项目符号: 将您的子弹与图像的其余部分隔离 在子弹
经过研究,发现一些文章可以帮助,但仍然是如何使用OpenCV或EMGUCV的问题,我擅长C语言,但是C++需要时间去学习。
另一个问题是,检测射击目标中重叠弹孔的最佳方法是什么?
喜欢这张图片
图片在上面。在环7和环8中有两个重叠的弹孔。在这种情况下,很容易通过简单的侵蚀来解决 然而,在圆圈几乎完全重叠的情况下,我不知道如何识别它们 一些链接可以帮助:
- 将您的子弹与图像的其余部分隔离
- 在子弹上开孔(腐蚀然后膨胀)
- 计算每个白色像素到最近黑色像素的距离
- 应用阈值
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;
}
cv::Mat预处理(常量cv::Mat图像){
显示器(图像,“原件”);
//颜色阈值
cv::标量minColor(141,0,0);
cv::标量maxColor(255、255、124);
cv::Mat过滤;
//隔离有趣的颜色范围
cv::inRange(图像、最小颜色、最大颜色、过滤);
过滤。转换到(过滤,CV_8U);
//应用开口(腐蚀然后扩张)
cv::垫开度;
cv::Mat kernel=cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3));
cv::morphologyEx(过滤、打开、cv::MORPH_打开、内核、cv::Point(-1,-1)、2);
//计算到最近零像素的距离(欧几里德)
cv::垫距;
距离变换(开口,距离,距离L2,5);
cv::规格化(距离,距离,0,1.0,cv::NORM_MINMAX);
显示(距离,“距离”);
//使用最长距离进行阈值化
双最小值,最大值;
cv::minMaxLoc(距离、最小值和最大值);
cv::设定阈值的Mat;
cv::threshold(距离,阈值化,0.7*max,255,cv_threshold_二进制);
阈值转换(阈值化,CV_8U);
//查找连接的组件
cv::垫标签;
int nbLabels=cv::connectedComponents(阈值化的标签);
//为每个标签指定随机颜色
矢量颜色(NB标签,0);
对于(int label=1;label
您可以通过以下步骤隔离重叠项目符号:
- 将您的子弹与图像的其余部分隔离
- 在子弹上开孔(腐蚀然后膨胀)
- 计算每个白色像素到最近黑色像素的距离
- 应用阈值
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;
}
cv::Mat预处理(常量cv::Mat图像){
显示器(图像,“原件”);
//颜色阈值
cv::标量minColor(141,0,0);
cv::标量maxColor(255、255、124);
cv::Mat过滤;
//隔离有趣的颜色范围
cv::inRange(图像、最小颜色、最大颜色、过滤);
过滤。转换到(过滤,CV_8U);
//应用开口(腐蚀然后扩张)
cv::垫开度;
cv::Mat kernel=cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3));
cv::morphologyEx(过滤、打开、cv::MORPH_打开、内核、cv::Point(-1,-1)、2);
//计算到最近零像素的距离(欧几里德)
cv::垫距;
距离变换(开口,距离,距离L2,5);
cv::规格化(距离,距离,0,1.0,cv::NORM_MINMAX);
显示(距离,“距离”);
//使用最长距离进行阈值化
双最小值,最大值;
cv::minMaxLoc(距离、最小值和最大值);
cv::设定阈值的Mat;
cv::threshold(距离,阈值化,0.7*max,255,cv_threshold_二进制);
阈值转换(阈值化,CV_8U);
//查找连接的组件
cv::垫标签;
int nbLabels=cv::connectedComponents(阈值化的标签);
//为每个标签指定随机颜色
矢量颜色(NB标签,0);
对于(int label=1;label
您可以通过两种方式完成任务
有两种方法可以完成任务
对于重叠的圆,您可以