代码之家  ›  专栏  ›  技术社区  ›  ProgrammingCuber

OpenCV层次结构始终为空

  •  0
  • ProgrammingCuber  · 技术社区  · 9 年前

    我有一张有重叠轮廓的图像,当我找到轮廓时,我一直在尝试使用层次过滤轮廓。我想做的是过滤掉父母不等于-1的轮廓。然而,当我试图获取包含层次结构的信息时,父索引几乎每次都等于null。我不是在寻找正确的信息来获取当前家长的状态吗?这是我的密码。

    List<MatOfPoint> contours = new ArrayList<>();
        List<MatOfPoint> squareContours = new ArrayList<>();
        Mat hierarchy = new Mat();
        //find all contours
        Imgproc.findContours(dilated, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
    
        //Remove contours that aren't close to a square shape.
        for(int i = 0; i < contours.size(); i++){
            if(hierarchy != null){
                double area = Imgproc.contourArea(contours.get(i)); 
                MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
                double perimeter = Imgproc.arcLength(contour2f, true);
                //Found squareness equation on wiki... 
                //https://en.wikipedia.org/wiki/Shape_factor_(image_analysis_and_microscopy)
                double squareness = 4 * Math.PI * area / Math.pow(perimeter, 2);
    
                if(squareness >= 0.7 && squareness <= 0.9 && area >= 2000){
                    squareContours.add(contours.get(i));
                }
            }
        }
        //remove contour if it has a parent 
        List<MatOfPoint> finalContours = new ArrayList<>();
        for(int i = 0; i < squareContours.size();i++){
            if(hierarchy.get(i, 3)[3] == -1){ //this should be checking parent index I think.
                finalContours.add(squareContours.get(i));
            }
        }
    

    这是我打印包含父信息的层次矩阵时程序的输出 Arrays.toString(hierarchy.get(i,3)))

    [-1.0, -1.0, -1.0, 2.0]
    null
    null
    null
    null
    null
    null
    null
    null
    null
    null
    
    2 回复  |  直到 9 年前
        1
  •  5
  •   Dan MaÅ¡ek    9 年前

    当您使用 Mat findContours ,则得到一个数组,其中包含:

    • 一行
    • 每个检测到的轮廓一列
    • 4个通道(下一个、上一个、子和父轮廓的id)
    • 数据类型a 32位有符号整数

    现在,你的问题变得很明显。

    hierarchy.get(i, 3)[3]
    

    get 您使用的方法具有以下特征:

    public double[] get(int row, int col)
    

    请注意,第一个参数是行号。将等高线编号作为行传递,但只有一行。

    接下来,第二个参数是列。您总是会得到第3列--第3个等高线的层次信息。

    hierarchy.get(0, i)[3]
    

    appropriate overload of get .

    int[] current_hierarchy = new int[4];
    for(int i = 0; i < squareContours.size();i++) {
        hierarchy.get(0, i, current_hierarchy);
        if (current_hierarchy[3] == -1) {
            // ... and so on
    

    我注意到还有一个问题。在呼叫之后 hierarchy 对应于 contours 列表但是,首先删除一些等高线(只将其中的一个子集插入另一个列表),而不对层次数据进行任何类似更改。然后迭代该子集,最终由于索引不匹配而使用了错误的层次结构条目。

    为了解决这个问题,我将两个循环合并在一起,可能是这样的:

    List<MatOfPoint> contours = new ArrayList<>();
    Mat hierarchy = new Mat();
    //find all contours
    Imgproc.findContours(dilated, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);
    
    // Remove contours that aren't close to a square shape
    // and remove contour if it has a parent 
    List<MatOfPoint> finalContours = new ArrayList<>();
    int[] current_hierarchy = new int[4];
    for(int i = 0; i < contours.size(); i++){
        double area = Imgproc.contourArea(contours.get(i)); 
        MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
        double perimeter = Imgproc.arcLength(contour2f, true);
        //Found squareness equation on wiki... 
        //https://en.wikipedia.org/wiki/Shape_factor_(image_analysis_and_microscopy)
        double squareness = 4 * Math.PI * area / Math.pow(perimeter, 2);
    
        if(squareness >= 0.7 && squareness <= 0.9 && area >= 2000){
            hierarchy.get(0, i, current_hierarchy);
            if (current_hierarchy[3] == -1) {
                finalContours.add(contours.get(i));
            }
        }
    
    }
    
        2
  •  0
  •   Michal Friedl    6 年前

    List<double[]> listHierarchy = new ArrayList<>();
                    for (int i = 0; i< list.size(); i++){
                        listHierarchy.add(hierarchie.get(0, i));
                    }
    

    然后,当我需要从此列表中删除项目时,我调用此函数:

     List<double[]> deleteHierarchyItem(int position, List<double[]> hierarchy){
        double[] itemHierarchy = hierarchy.get(position);
        double[] workItem;
    
        //doesnt have children?
        if (itemHierarchy[2]!=-1){
            int nextChild =(int) (itemHierarchy[2]);
            do {
                //nacte dite
                workItem = hierarchy.get(nextChild);
                //zmeni rodice v diteti na rodice puvodniho rodice
                workItem[3] = itemHierarchy[3];
                //nastavi nova data v listu
                hierarchy.set(nextChild, workItem);
                //zmeni ukazatel na nove dite
                nextChild = (int)(workItem[2]);
    
            } while (nextChild != -1);
        }
    
        //check for siblings
        boolean hasNextSibling = itemHierarchy[0] != -1;
        boolean hasPreviousSibling = itemHierarchy[1] != -1;
    
        double idPreviousSibling = itemHierarchy[1];
        double idNextSibling = itemHierarchy[0];
    
        //has both siblings
        if (hasPreviousSibling && hasNextSibling){
            //change previous sibling
            workItem = hierarchy.get((int)(idPreviousSibling));
            workItem[0] = idNextSibling;
            hierarchy.set((int)(idPreviousSibling), workItem);
            //change next sibling
            workItem = hierarchy.get((int)(idNextSibling));
            workItem[1] = idPreviousSibling;
            hierarchy.set((int)(idNextSibling), workItem);
        }
    
        //has only previous sibling
        if (hasPreviousSibling && !hasNextSibling){
            workItem = hierarchy.get((int)(idPreviousSibling));
            workItem[0] = -1;
            hierarchy.set((int)(idPreviousSibling), workItem);
        }
    
        //has only next sibling
        if (!hasPreviousSibling && hasNextSibling){
            workItem = hierarchy.get((int)(idNextSibling));
            workItem[1] = -1;
            hierarchy.set((int)(idNextSibling), workItem);
    
            //change of child parametres in parent
            if(itemHierarchy[3]>0)
            {
                workItem = hierarchy.get((int)(itemHierarchy[3]));
                workItem[2]=idNextSibling;
                hierarchy.set((int)(itemHierarchy[3]), workItem);
            }
        }
    
        //check for parent
        if (itemHierarchy[3]!=-1){
            workItem = hierarchy.get((int)(itemHierarchy[3]));
            if (workItem[2]==position){
                workItem[2] = -1;
                hierarchy.set((int)(itemHierarchy[3]), workItem);
            }
        }
    
        //iterate and decrement values
        for (int i = position; i< hierarchy.size();i++){
            workItem = hierarchy.get(i);
            if (workItem[0]>position){
                workItem[0] = workItem[0] - 1;
            }
            if (workItem[1]>position){
                workItem[1] = workItem[1] - 1;
            }
            if (workItem[2]>position){
                workItem[2] = workItem[2] - 1;
            }
            if (workItem[3]>position){
                workItem[3] = workItem[3] - 1;
            }
            hierarchy.set(i, workItem);
        }
        return hierarchy;
    }