我得到了一个带有connectedComponents
函数C++ OpenCV的标签,如图中所示:
这是ccLabels
变量的输出,它是一个与原始图像大小相同的cv::Mat
。
所以我要做的是:
N
次数,这是“大”的。我的最终目标是计算图像中的洞数,因此我的目标是从(number of 0's / number of 4's)
中推断出洞数。这可能不是最漂亮的方式,但图像是非常均匀的大小和照明,所以它将满足我的需要。
但是我对OpenCV并不熟悉,我不知道如何完成这个任务。
以下是我迄今所做的工作:
cv::Mat1b outImg;
cv::threshold(grayImg, outImg, 150, 255, 0); // Thresholded -binary- image
cv::Mat ccLabels;
cv::connectedComponents(outImg, ccLabels); // Each non-zero pixel is labeled with their connectedComponent ID's
// write the labels to file:
std::ofstream myfile;
myfile.open("ccLabels.txt");
cv::Size s = ccLabels.size();
myfile << "Size: " << s.height << " , " << s.width <<"\n";
for (int r1 = 0; r1 < s.height; r1++) {
for (int c1 = 0; c1 < s.height; c1++) {
myfile << ccLabels.at<int>(r1,c1);
}
myfile << "\n";
}
myfile.close();
因为我知道如何在矩阵中迭代,所以计数数字应该是可以的,但是首先我必须分离(消除/忽略)“背景”像素,它们是之外的0's 连接的组件。那么数数应该很容易。
我如何分割这些“大”组件?也许可以获得一个掩码,并且只考虑mask(x,y) = 1
所在的像素
谢谢你的帮助!
编辑
这是被分割的图像:
这就是我在Canny边缘检测之后得到的结果:
这是实际图像(阈值):
发布于 2015-10-07 10:12:31
这里有一个简单的程序,从你的阈值图像开始,找到骰子上的数字。
结果:
Number: 5
Number: 2
图片:
代码:
#include <opencv2\opencv.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
int main(void)
{
// Grayscale image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Minimum area of the contour
double minContourArea = 10;
// Prepare outpot
Mat3b result;
cvtColor(img, result, COLOR_GRAY2BGR);
// Find contours
vector<vector<Point>> contours;
findContours(img.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); ++i)
{
// Check area
if (contourArea(contours[i]) < minContourArea) continue;
// Black mask
Mat1b mask(img.rows, img.cols, uchar(0));
// Draw filled contour
drawContours(mask, contours, i, Scalar(255), CV_FILLED);
mask = (mask & img) ^ mask;
vector<vector<Point>> cntrs;
findContours(mask, cntrs, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
cout << "Number: " << cntrs.size() << endl;
// Just for showing results
drawContours(result, cntrs, -1, Scalar(0,0,255), CV_FILLED);
}
imshow("Result", result);
waitKey();
return 0;
}
发布于 2015-10-07 08:22:37
更简单的方法是findContours方法。您找到内部轮廓并计算它们的面积(因为内部轮廓将是洞)并相应地处理这些信息。
发布于 2015-10-07 09:44:00
要解决您的第一个问题,请考虑在values.Count中有一组值,即出现的每一个数字。
int m=0;
for(int n=0;n<256;n++)
{
int c=0;
for(int q=0;q<values.size();q++)
{
if(n==values[q])
{
//int c;
c++;
m++;
}
}
cout<<n<<"= "<< c<<endl;
}
cout<<"Total number of elements "<< m<<endl;
要解决第二个问题,使用find等值线在图像中找到最大的轮廓,在其周围画出包围矩形,然后裁剪它。再次使用上面的代码来计数像素值"4“和"0”。您可以在这里找到它的链接,https://stackoverflow.com/a/32998275/3853072。
https://stackoverflow.com/questions/32996963
复制相似问题