RegionGrow算法-PS魔棒

ps里面的魔棒工具非常好用,是图像处理中非常常用的一个工具,它现在已经是我的c++工具箱中很重要的一员了,我会在以后的时间里把我的工具箱逐渐介绍给大家。

魔棒工具的核心算法是RegionGrow区域成长法,它的概念很简单,首先在要处理的图片上选取一个种子点,然后以此点为起点,向四周辐射形成一个区域。最初成长区域只有种子点这一个点,然后不断把周围的点归并入该成长区域,条件是该点的值与成长区域边界点的值之差小于阈值。当成长区域不能再继续扩大时,算法停止。

r_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);
				}
			}
		}
	}


打赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.