OpenCV-Java-如何删除集群周围的一些像素

OpenCV-Java-如何删除集群周围的一些像素,java,opencv,image-processing,Java,Opencv,Image Processing,我正在做一个项目,我需要确定图像的某些区域。在处理图像并去除所有不必要的东西后,我最终得到了如图所示的区域(绿色圆圈内的区域) 我无法使用OpenCV在该区域周围绘制圆。我目前正在使用OpenCV的Java版本。如果有人能给我指出如何在图像上实现绿色圆圈的正确方向,这将非常有帮助 我试图探测到的东西。 blob探测器-没有取得多大成就。 集群-与blob检测器相同。 HoughCircles-在图像中绘制不必要的圆。 FindContour-没有画任何东西,因为它不是一个完美的圆、椭圆或任何其他

我正在做一个项目,我需要确定图像的某些区域。在处理图像并去除所有不必要的东西后,我最终得到了如图所示的区域(绿色圆圈内的区域)

我无法使用OpenCV在该区域周围绘制圆。我目前正在使用OpenCV的Java版本。如果有人能给我指出如何在图像上实现绿色圆圈的正确方向,这将非常有帮助

我试图探测到的东西。 blob探测器-没有取得多大成就。 集群-与blob检测器相同。 HoughCircles-在图像中绘制不必要的圆。 FindContour-没有画任何东西,因为它不是一个完美的圆、椭圆或任何其他众所周知的多边形

我感谢你的帮助

这里有一个解决方案:

  • 打开以清除所有薄/细长图案中的图像
  • 连接的组件标签,以便计算剩余的模式
  • 每个剩余图案的大小计数
  • 最大的图案是您要圈出的图案

  • 注意:如果您想完美地保留图案,可以通过重建(侵蚀+测地线重建)将洞口替换为洞口。

    我终于找到了解决问题的方法。我使用了OpenCV库中的特征检测器,并为检测器设置了正确的阈值。这对我起了作用。Java中的代码如下所示

    public static void main(String[] args){
        try{
            //Validation whether a file name is passed to the function
            if(args.length == 0){
                System.out.println("here...");
                log.error("No file was passed to the function");
                throw new IOException();
            }
    
            //Read the image from the input
            Mat inputMat = Highgui.imread(args[0],Highgui.CV_LOAD_IMAGE_GRAYSCALE);
    
            //Create a feature detector. In this case we are using SURF (Speeded-Up Robust Features) detector. 
            MatOfKeyPoint objectKeyPoints = new MatOfKeyPoint();
            FeatureDetector featureDetector = FeatureDetector.create(FeatureDetector.SURF);
    
            //A temporary file is created to input Hessian Threshold to the SURF detector
            File tempFile = File.createTempFile("config", ".yml");
            String settings = "%YAML:1.0\nhessianThreshold: 7000.\noctaves: 3\noctaveLayers: 4\nupright: 0\n";
            FileWriter writer = new FileWriter(tempFile, false);
            writer.write(settings);
            writer.close();
    
            //Read the configuration from the temporary file to assign the threshold for the detector
            featureDetector.read(tempFile.getPath());
    
            //Detect the features in the image provided
            featureDetector.detect(inputMat, objectKeyPoints);
    
            //Iterate through the list of key points detected in the previous step and find the Key Point with the largest size
            List<KeyPoint> objectKeyPointList = objectKeyPoints.toList();
            KeyPoint impKeyPoint = new KeyPoint();
    
            for(int i=0; i<objectKeyPointList.size(); i++){
                if(impKeyPoint == null){
                    impKeyPoint = objectKeyPointList.get(i);
                }
                else if(impKeyPoint.size < objectKeyPointList.get(i).size){
                    impKeyPoint = objectKeyPointList.get(i);
                }
            }
    
            //If the size of the Key Point is greater than 120 then reduce the size to 120 and if the size is less than 120 then increase to 120 
            if(impKeyPoint.size > 120){
                KeyPoint tempKeyPoint = new KeyPoint();
                tempKeyPoint = impKeyPoint;
                tempKeyPoint.size = 120;
                impKeyPoint = tempKeyPoint;
            }
            else if(impKeyPoint.size < 120){
                KeyPoint tempKeyPoint = new KeyPoint();
                tempKeyPoint = impKeyPoint;
                tempKeyPoint.size = 120;
                impKeyPoint = tempKeyPoint;
            }
    
            //Convert the Key Point to MatOfKeyPoint since drawKeyPoints accepts only MatOfKeyPoint
            MatOfKeyPoint impMatOfKeyPoint = new MatOfKeyPoint(impKeyPoint);
    
            //Mat for drawing the circle in the image
            Mat outputImage = new Mat(inputMat.rows(), inputMat.cols(), Highgui.CV_LOAD_IMAGE_COLOR);
    
            //Green color for the circle
            Scalar greenCircle = new Scalar(0, 255, 0);
    
            //Draw the circle around the optic nerve when detected
            Features2d.drawKeypoints(inputMat, impMatOfKeyPoint, outputImage, greenCircle, Features2d.DRAW_RICH_KEYPOINTS);
    
            //Write the image to a file
            Highgui.imwrite("surf_keypoints.png", outputImage);
        }catch(Exception e){
            log.fatal(e.getMessage());
        }
    
    }
    
    publicstaticvoidmain(字符串[]args){
    试一试{
    //验证是否将文件名传递给函数
    如果(args.length==0){
    System.out.println(“此处…”);
    log.error(“没有向函数传递任何文件”);
    抛出新IOException();
    }
    //从输入中读取图像
    Mat inputMat=Highgui.imread(args[0],Highgui.CV\u LOAD\u IMAGE\u GRAYSCALE);
    //创建一个特征检测器。在这种情况下,我们使用的是SURF(加速鲁棒特征)检测器。
    MatOfKeyPoint objectKeyPoints=新的MatOfKeyPoint();
    FeatureDetector FeatureDetector=FeatureDetector.create(FeatureDetector.SURF);
    //创建一个临时文件,将Hessian阈值输入到冲浪检测器
    File tempFile=File.createTempFile(“config”,“.yml”);
    String settings=“%YAML:1.0\n高级管理员:7000。\n管理员:3\n管理员:4\n优先级:0\n”;
    FileWriter writer=新的FileWriter(tempFile,false);
    writer.write(设置);
    writer.close();
    //从临时文件中读取配置,为探测器分配阈值
    读取(tempFile.getPath());
    //检测所提供图像中的特征
    特征检测器。检测(inputMat、objectKeyPoints);
    //迭代上一步中检测到的关键点列表,并找到大小最大的关键点
    List objectKeyPointList=objectKeyPoints.toList();
    KeyPoint impKeyPoint=新的KeyPoint();
    对于(int i=0;i 120){
    KeyPoint tempKeyPoint=新的KeyPoint();
    tempKeyPoint=impKeyPoint;
    tempKeyPoint.size=120;
    impKeyPoint=tempKeyPoint;
    }
    否则如果(impKeyPoint.size<120){
    KeyPoint tempKeyPoint=新的KeyPoint();
    tempKeyPoint=impKeyPoint;
    tempKeyPoint.size=120;
    impKeyPoint=tempKeyPoint;
    }
    //将关键点转换为MatOfKeyPoint,因为drawKeyPoints仅接受MatOfKeyPoint
    MatOfKeyPoint impMatOfKeyPoint=新的MatOfKeyPoint(impKeyPoint);
    //用于在图像中绘制圆的垫子
    Mat outputImage=新Mat(inputMat.rows(),inputMat.cols(),Highgui.CV\u LOAD\u IMAGE\u COLOR);
    //圆圈的绿色
    标量绿圈=新标量(0,255,0);
    //检测到时,在视神经周围画一个圆圈
    功能2d.绘制关键点(inputMat、impMatOfKeyPoint、outputImage、绿色圆圈、功能2d.绘制丰富的关键点);
    //将图像写入文件
    imwrite(“surf_keypoints.png”,outputImage);
    }捕获(例外e){
    log.fatal(如getMessage());
    }
    }
    

    希望这对其他人有帮助。

    谢谢您的回复。我可以做第一步。我尝试了第2步,如果连接的组件是2次通过,则需要花费大量时间来处理。你有一些例子的链接,我可以让它更快吗?这是一个链接,指向用Java开发的Union Find算法的法语页面,但是用C++重新实现它非常容易:我将在我的项目中实现它,并让您知道会发生什么。非常感谢。