Java+opencv3.2.0之删除最小连通区域

来源:互联网 发布:java selenium教程 编辑:程序博客网 时间:2024/06/10 17:17

吐槽一下,在网上查了半天opencv3关于删除最小连通区域的方法,结果还是没找到,就自己写了一个,效果还可以,就发出来和大家分享一下。

思路:
1、遍历所有像素点
2、每遍历到一个黑点就去判断是否为连通区域起始点,若是则添加到待检测像素点集合中
3、遍历待检测像素点集合,检测待检测像素点周围(上下左右)的像素点,若是黑点,则添加到待检测像素点集合中,并把当前待检测像素点添加到已检测点集合。若待检测点集合中像素点数小于某个阈值时,就认为这些待检测点区域为最小连通区域。
4、查找到最小连通区域后把已检测点集合中的像素点设置成白点。

代码:

/**     * 判断是否为连通区域起始点(有点问题,有待优化)     * @param i 待检验点的横坐标     * @param j 待检验点的纵坐标     * @param srcImage 源图像     * @return true表示是连通区域起始点,false则反之     */    public boolean isStart(int i, int j, Mat srcImage){        int before = j - 1;        int top = i - 1;        if((before<0||srcImage.get(i, before)[0] == 255.0) && (top<0 || srcImage.get(top, j)[0] == 255.0)){            return true;        }        return false;    }public Mat deleteMinConnectedArea(Mat srcImage,double minarea){        int iw = srcImage.width(); //横向        int ih = srcImage.height(); //纵向        System.out.println("宽和高:"+ iw +" "+ ih);        for (int i = 0; i < ih; i++) {            for (int j = 0; j < iw; j++) {                double[] colors = srcImage.get(i, j);                if(colors[0] < 255.0 && isStart(i, j, srcImage)){                    List<Point> checkPoint = new ArrayList<Point>();                    List<Point> checkedPoint = new ArrayList<Point>();                    checkPoint.add(new Point(i, j));                    ergodic(srcImage, checkPoint, checkedPoint, (int) minarea);                }            }        }        return srcImage;    }/**     * 连通像素计数     * @param i 第一个检测到的像素为0的横坐标     * @param j 第一个检测到的像素为0的纵坐标     * @param iw 源图像像素列数     * @param ih 源图像像素行数     * @param srcImage 源图像     * @param sp 待检测像素点     * @param lp 已检测像素点     */    public void ergodic(Mat srcImage, List<Point> sp, List<Point> lp, int minArea ){        for (int k = 0; k < sp.size(); k++) {            check((int) sp.get(k).x, (int) sp.get(k).y, sp, lp, srcImage);            if(sp.size() >= minArea){                lp.removeAll(lp);                break;            }        }        if(lp.size() < minArea){            for (Point point : lp) {                srcImage.put((int) point.x, (int) point.y, 255.0);            }        }    }/**     * 像素点判断是否已检测过     * @param i 待检验是否已检测像素点横坐标     * @param j 待检验是否已检测像素点纵坐标     * @param lp 已检测点集合     * @return 检测结果  false表示未检测,true表示已检测     */    public boolean isExist(int i, int j, List<Point> lp){        if(lp.size() == 0){            return false;        }        for (Point point : lp) {            if(point.x == i && point.y == j ){                return true;            }        }        return false;    }/**     * 像素点判断是否已被发现(存储在待检测集合)     * @param i 待检验是否已检测像素点横坐标     * @param j 待检验是否已检测像素点纵坐标     * @param sp 已检测点集合     * @return 检测结果  false表示未检测,true表示已检测     */    public boolean isFind(int i, int j, List<Point> sp){        if(sp.size() == 0){            return false;        }        for (Point point : sp) {            if(point.x == i && point.y == j){                return true;            }        }        return false;    }/**     * 检测当前像素点上下左右的像素,并把当前像素点添加到已检测集合     * @param i 检测当前像素点横坐标     * @param j 检测当前像素点纵坐标     * @param sp 待检测点集合     * @param lp 已检测点集合     * @param srcImage 源图像     */    public void check(int i, int j, List<Point> sp, List<Point> lp, Mat srcImage){        int before = j - 1;        int after = j + 1;        int top = i - 1;        int bottom = i + 1;        if(before >= 0 && srcImage.get(i, before)[0] == 0.0){            if(!isExist(i, before, lp) && !isFind(i, before, sp)){                sp.add(new Point(i, before));            }        }        if(after < srcImage.width() && srcImage.get(i, after)[0] == 0.0){            if(!isExist(i, after, lp) && !isFind(i, after, sp)){                sp.add(new Point(i, after));            }        }        if(top >= 0 && srcImage.get(top, j)[0] == 0.0){            if(!isExist(top, j, lp) && !isFind(top, j, sp)){                sp.add(new Point(top, j));            }        }        if(bottom < srcImage.height() && srcImage.get(bottom, j)[0] == 0.0){            if(!isExist(bottom, j, lp) && !isFind(bottom, j, sp)){                sp.add(new Point(bottom, j));            }        }        lp.add(new Point(i,j));    }public static void main(String[] args) {        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);        Mat mat = Imgcodecs.imread("F:\\20170801161034.png");        Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY);         Imgproc.adaptiveThreshold(mat, mat, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 9, 0);        Mat dst = new DeleteMinArea().deleteMinConnectedArea(mat,50);        Imgcodecs.imwrite("F:\\31.jpg", dst);    }

源图片:
这里写图片描述

结果图片:
这里写图片描述

原创粉丝点击