【问题标题】:finding area and centre of stones寻找石头的区域和中心
【发布时间】:2014-04-05 13:46:55
【问题描述】:

我想找到这些石头的面积和中心。 但其中一些找不到。

这里是代码

I=imread('E:/2.png');
level = graythresh(I);
BW = im2bw(I,level);
se = strel('disk',2);
bw1 = imclose(BW,se);
bw1 = imfill(BW,'holes');

bwa=bwareaopen(bw1,25);
cc = bwconncomp(bwa)
stat = regionprops(cc,'centroid','Area');
ss=[stat.Area];
imshow(I); hold on;
 for x = 1: numel(stat)
    plot(stat(x).Centroid(1),stat(x).Centroid(2), 'wp','MarkerSize',6,'MarkerFaceColor','b');
  end
figure, imshow(bwa)

结果在这里:

这是黑白照片; 这些石头有些是分不开的。 有什么想法吗?

【问题讨论】:

  • 我无法告诉你有多少石头看图片!我建议稍微腐蚀最后一张图片,但你的问题定义不明确,IMO。
  • 有些石头粘在一起,有些不够亮,无法分开。我想知道如何才能分开,
  • 图像处理的圣杯:数石头。
  • 术语“图像分割”可能会引出一些想法..
  • 这基本上是一个图像分割问题。这是多年来一直未解决的问题。没有任何技术可以使每个示例或情况都正确。我会做 chappjc 建议的你应该侵蚀图片的地方。就我个人而言,我会做一个开口来摆脱任何虚假的嘈杂像素。如果要分割出宽度为 40 的岩石,可以将 BoundingBox 指定为 regionprops 函数的附加参数,然后使用宽度参数(最后两个值)来确定是否应该接受或拒绝每个形状。

标签: matlab image-processing


【解决方案1】:

腐蚀石头,直到将它们分开,通过连接的组件(例如 findContours)找到分段,设置中心,然后在原始 BW 图像的中心(侵蚀之前)应用洪水填充播种洪水以优雅地定义分段。 “优雅地”意味着洪水不应“泄漏”到另一个(可能连接的)段,因为它已经被不同的标签填充。您可能想要使用floodFIll 的参数来调整您的细分。我没有时间做这件事。

// separate stones
Mat Ibw = imread("bw.png", 0);
imshow("bw", Ibw);
int w=Ibw.cols, h=Ibw.rows;
int ERODE_SZ = 20;
Mat kernel = getStructuringElement( cv::MORPH_RECT, Size(ERODE_SZ, ERODE_SZ));
Mat Ierode;
erode(Ibw, Ierode, kernel);
imshow("erode", Ierode); imwrite("erode.png", Ierode);
vector<vector<Point> > contours;
Mat hierarchy;
Mat Icc = Ierode.clone();
findContours(Icc, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

// find centers
Mat Icenters = Ibw.clone();
int sz = contours.size();
vector<Point> centers(sz);
for (int i=0; i<sz; ++i) {
     if (i==0)
         centers[i] = Point2f(0.f, 0.f);
     int area = contours[i].size();
     for (int j=0; j<area; j++) {
         centers[i]+=contours[i][j];
     }
     centers[i]*=1.0/area;
     circle(Icenters, centers[i], 3, 100, 3);
}
imshow("centers", Icenters);imwrite("erode.png", Ierode);

// find segments
Mat Iseg = Ibw.clone();
RNG rng( 0xFFFFFFFF );
for (int i=0; i<sz; ++i) {
    floodFill(Iseg, centers[i], rng.uniform(100, 200));
    circle(Iseg, centers[i], 3, 0, 1);
}
imshow("seg", Iseg); imwrite("result.png", Iseg);
waitKey();

【讨论】:

  • 我会试试这个,看看我能找到什么,非常感谢
  • 请记住,这是在 C++ 和 OpenCV 中完成的。但是,事后回顾代码,您可以轻松地在 MATLAB 中重现此代码。
  • 确实如此。我想这里的一个中心思想是开始考虑图像处理是从片段中心并行发生的,而不是依赖于扫描图像的某些过程
  • 作为一项改进,考虑在侵蚀图像上运行洪水填充,将分段标签添加到原始阈值图像,然后继续分水岭
猜你喜欢
  • 2019-12-03
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多