首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用BoofCV在Java中分割图像?

如何用BoofCV在Java中分割图像?
EN

Stack Overflow用户
提问于 2018-11-08 16:00:47
回答 1查看 170关注 0票数 1

我试图使用BoofCV在Java中提供的分水岭函数来分割一个简单的图像。因此,我编写了以下代码(复制、编辑和调整):

代码语言:javascript
复制
package alltestshere;

import boofcv.alg.filter.binary.BinaryImageOps;
import boofcv.alg.filter.binary.Contour;
import boofcv.alg.filter.binary.GThresholdImageOps;
import boofcv.gui.ListDisplayPanel;
import boofcv.gui.binary.VisualizeBinaryData;
import boofcv.gui.image.ShowImages;
import boofcv.io.UtilIO;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.io.image.UtilImageIO;
import boofcv.struct.ConnectRule;
import boofcv.struct.image.GrayS32;
import boofcv.struct.image.GrayU8;
import java.awt.image.BufferedImage;
import java.util.List;
import boofcv.alg.segmentation.watershed.WatershedVincentSoille1991;
import boofcv.factory.segmentation.FactorySegmentationAlg;
import boofcv.gui.feature.VisualizeRegions;



public class examp {

   public static void main( String args[] ) {
    // load and convert the image into a usable format
    BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("C:\\\\Users\\\\Caterina\\\\Downloads\\\\boofcv\\\\data\\\\example\\\\shapes\\\\shapes02.png"));
    // convert into a usable format
    GrayU8 input = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class);

//declare some of my working data
    GrayU8 binary = new GrayU8(input.width,input.height);
    GrayS32 markers = new GrayS32(input.width,input.height);

    // Select a global threshold using Otsu's method.
    GThresholdImageOps.threshold(input, binary, GThresholdImageOps.computeOtsu(input, 0, 255),true);

    //through multiple erosion you can obtain the sure foreground and use it as marker in order to segment the image
    GrayU8 filtered = new GrayU8 (input.width, input.height);
    GrayU8 filtered2 = new GrayU8 (input.width, input.height);
    GrayU8 filtered3 = new GrayU8 (input.width, input.height);
    BinaryImageOps.erode8(binary, 1, filtered);
    BinaryImageOps.erode8(filtered, 1, filtered2);
    BinaryImageOps.erode8(filtered2, 1, filtered3);

//count how many markers you have (one for every foreground part +1 for the background
    int numRegions = BinaryImageOps.contour(filtered3, ConnectRule.EIGHT, markers).size()+1 ;


    // Detect foreground imagea using an 8-connect rule
    List<Contour> contours = BinaryImageOps.contour(binary, ConnectRule.EIGHT, markers);

    //Watershed function which takes the original b&w image as input and the markers 
    WatershedVincentSoille1991 watershed = FactorySegmentationAlg.watershed(ConnectRule.FOUR);
    watershed.process(input, markers);

    //get the results of the watershed as output
    GrayS32 output = watershed.getOutput();


    // display the results
    BufferedImage visualBinary = VisualizeBinaryData.renderBinary(input, false, null);
    BufferedImage visualFiltered = VisualizeBinaryData.renderBinary(filtered3, false, null);
    BufferedImage visualLabel = VisualizeBinaryData.renderLabeledBG(markers , contours.size(), null);
    BufferedImage outLabeled = VisualizeBinaryData.renderLabeledBG(output, numRegions, null);


    ListDisplayPanel panel = new ListDisplayPanel();
    panel.addImage(visualBinary, "Binary Original");
    panel.addImage(visualFiltered, "Binary Filtered");
    panel.addImage(visualLabel, "Markers");
    panel.addImage(outLabeled, "Watershed");
    ShowImages.showWindow(panel,"Watershed");
    }

}

然而,这段代码不能很好地工作。具体来说,它不是用不同的颜色来着色前景物体,而是将所有图像分割成区域,而每个区域仅由一个前景对象和背景的某些部分组成,并以相同的颜色绘制所有这部分(图3)。那我做错什么了?

我正在上传原图 标记图分水岭图

谢谢你,卡特琳娜

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-08 16:22:44

您得到这个结果是因为您没有将背景处理为一个区域。你提供给分水岭的标志只是你形状的轮廓。由于背景不是一个区域,分水岭算法将其平分到每个区域。这是同样的,因为你的原始图像中的每个形状到背景的距离是相同的(二值图像)。

如果您想作为另一个区域获取背景,则向分水岭算法提供一些背景点作为标记,例如角点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53211543

复制
相关文章

相似问题

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