ps里面的魔棒工具非常好用,是图像处理中非常常用的一个工具,它现在已经是我的c++工具箱中很重要的一员了,我会在以后的时间里把我的工具箱逐渐介绍给大家。
魔棒工具的核心算法是RegionGrow区域成长法,它的概念很简单,首先在要处理的图片上选取一个种子点,然后以此点为起点,向四周辐射形成一个区域。最初成长区域只有种子点这一个点,然后不断把周围的点归并入该成长区域,条件是该点的值与成长区域边界点的值之差小于阈值。当成长区域不能再继续扩大时,算法停止。
算法说明:
区域成长法的思想很好理解,代码实现对于初学者有一定难度。对于满足条件的像素点,函数会把它们一个个的压入队列的尾部,然后从队列的头部一个个的取出来,形成成长区域。M是一个点名册,用来记录每一个像素是否被处理过。start和end用来记录队列的头和尾,当start==end时,说明所有所有像素已经处理完,函数结束。
附上JAVA实现:
循环实现:
private StarSet getStarRegionByLoop(int y, int x, boolean[][] hasCalced) { StarSet starSet = new StarSet(); StarType star = this.stars[y][x]; Point orgP = new Point(y, x); starSet.getPointSet().add(orgP); starSet.setStar(star); Queue queue = new LinkedList(); queue.offer(orgP); hasCalced[orgP.x][orgP.y] = true; while (queue.peek() != null) { Point p = queue.poll(); Point p1 = new Point(p.x + 1, p.y); Point p2 = new Point(p.x - 1, p.y); Point p3 = new Point(p.x, p.y + 1); Point p4 = new Point(p.x, p.y - 1); addMatchToStarSet(starSet, queue, p1, hasCalced); addMatchToStarSet(starSet, queue, p2, hasCalced); addMatchToStarSet(starSet, queue, p3, hasCalced); addMatchToStarSet(starSet, queue, p4, hasCalced); } return starSet; } private void addMatchToStarSet(StarSet starSet, Queue queue, Point p, boolean[][] hasCalced) { if (p.y < PopStar.X_SIZE && p.x < PopStar.Y_SIZE && p.y >= 0 && p.x >= 0 && hasCalced[p.x][p.y] == false && this.stars[p.x][p.y] == starSet.getStar()) { queue.offer(p); starSet.getPointSet().add(p); hasCalced[p.x][p.y] = true; } }
递归实现:
private StarSet getStarRegion(int y, int x, boolean[][] hasCalced) { StarSet starSet = new StarSet();// 在判断内部初始化对象,可提高效率 starSet.setStar(this.stars[y][x]); if (hasCalced[y][x] == false && StarType.EMPTY != this.stars[y][x]) { this.findStarArea(y, x, starSet, hasCalced); } return starSet; } /** * 计算当前局面下与starSet中的StarType相同且与指定位置邻接的所有点的点集(该点集可能只包含一个点) * * @param y * 开始查找的横向从左至右0起始的位置坐标 * @param x * 开始查找的纵向从下至上0起始的位置坐标 * @param starSet * 包含点集与点集的星星类型 * @param hasCalced2 */ private void findStarArea(int y, int x, StarSet starSet, boolean[][] hasCalced) { if ((y >= 0) && (x >= 0) && (y < this.stars.length) && (x < this.stars[y].length)) { if (starSet.getStar() == this.stars[y][x]) { Point point = new Point(y, x); if (hasCalced[y][x]) { return; } else { hasCalced[y][x] = true; starSet.getPointSet().add(point); this.findStarArea(y + 1, x, starSet, hasCalced); this.findStarArea(y - 1, x, starSet, hasCalced); this.findStarArea(y, x + 1, starSet, hasCalced); this.findStarArea(y, x - 1, starSet, hasCalced); } } } }