Commit 0ab422e2 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

removing foreground bridges

parent 971dd284
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -284,7 +284,7 @@ public class Conflicts {
		final int stilesY =       (tilesY + superTileSize -1)/superTileSize;
		final int nStiles =       stilesX * stilesY;
		final int [][][] conflicts = new int [st.getPlanes().length][][];
		final TileSurface.TileNeibs tnSurface = st.getTileSurface().new TileNeibs(stilesX, stilesY);
		final TileNeibs tnSurface = new TileNeibs(stilesX, stilesY);
		final Thread[] threads = ImageDtt.newThreadArray(st.getTileProcessor().threadsMax);
		final AtomicInteger ai = new AtomicInteger(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
@@ -343,7 +343,7 @@ public class Conflicts {
			HashMap<Integer,Integer> replacement_tiles, // null is OK
			int [][][]    replacement_neibs,               // null OK if  replacement_tiles == null
			double [][][] replacement_val_weights,
			TileSurface.TileNeibs tnSurface)
			TileNeibs tnSurface)
	{
		TilePlanes.PlaneData [][] planes = st.getPlanes();
		// generate conflicts if not provided
@@ -405,7 +405,7 @@ public class Conflicts {
			HashMap<Integer,Integer> replacement_tiles, // null is OK
			int [][][]    replacement_neibs,               // null OK if  replacement_tiles == null
			ConnectionCosts connectionCosts,
			TileSurface.TileNeibs tnSurface)
			TileNeibs tnSurface)
	{
		TilePlanes.PlaneData [][] planes = st.getPlanes();
		// generate conflicts if not provided
@@ -465,7 +465,7 @@ public class Conflicts {
			int nsTile0,
			HashMap<Integer,Integer> replacement_tiles, // null is OK - will use only planes data
			int [][][] replacement_neibs,               // null OK if  replacement_tiles == null
			TileSurface.TileNeibs tnSurface)
			TileNeibs tnSurface)
	{
		TilePlanes.PlaneData [][] planes = st.getPlanes();
		ArrayList<Conflict> conflicts_list= new ArrayList<Conflict>();
+6 −6
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import java.util.HashSet;
public class ConnectionCosts {
	TilePlanes.PlaneData [][] planes =  null;
	boolean preferDisparity = false;
	TileSurface.TileNeibs tnSurface;
	TileNeibs tnSurface;
	double         orthoWeight;
	double         diagonalWeight;
	double         starPwr;    // Divide cost by number of connections to this power
@@ -57,7 +57,7 @@ public class ConnectionCosts {
			double         starValPwr, //  Raise value of each tile before averaging
			int            steps,
			TilePlanes.PlaneData [][] planes,
			TileSurface.TileNeibs tnSurface,
			TileNeibs tnSurface,
			boolean preferDisparity)
	{
		this.planes =          planes;
@@ -481,7 +481,7 @@ public class ConnectionCosts {
			double diagonalWeight,
			double starPwr,    // Divide cost by number of connections to this power
			double   starWeightPwr,    // Use this power of tile weight when calculating connection cost
			TileSurface.TileNeibs tnSurface,
			TileNeibs tnSurface,
			boolean preferDisparity,
			int    debugLevel)
	{
@@ -506,7 +506,7 @@ public class ConnectionCosts {
			double diagonalWeight,
			double starPwr,    // Divide cost by number of connections to this power
			double   starWeightPwr,    // Use this power of tile weight when calculating connection cost
			TileSurface.TileNeibs tnSurface,
			TileNeibs tnSurface,
			boolean preferDisparity,
			int    debugLevel)
	{
@@ -566,7 +566,7 @@ public class ConnectionCosts {
			double   diagonalWeight,
			double   starPwr,    // Divide cost by number of connections to this power
			double   starWeightPwr,    // Use this power of tile weight when calculating connection cost
			TileSurface.TileNeibs tnSurface,
			TileNeibs tnSurface,
			boolean preferDisparity,
			int     debugLevel)
	{
@@ -594,7 +594,7 @@ public class ConnectionCosts {
			double   diagonalWeight,
			double   starPwr,    // Divide cost by number of connections to this power
			double   starWeightPwr,    // Use this power of tile weight when calculating connection cost
			TileSurface.TileNeibs tnSurface,
			TileNeibs tnSurface,
			boolean preferDisparity,
			int     debugLevel)
	{
+16 −5
Original line number Diff line number Diff line
@@ -813,6 +813,17 @@ public class LinkPlanes {
		ImageDtt.startAndJoin(threads);
	}

	/**
	 * Merge the supertile planes with agreeing neighbors, non-exclusively (no considering other planes
	 * of the same supertile. Start with the best fit, then goes to lower quality, until the individual
	 * merge quality falls below scaled quality of the best, pre-set minimum or the merged plane becomes
	 * too thick
	 * Separately calculates merged weighted plane and with equal weights of the neighbors
	 * @param planes array of plane instances for the same supertile
	 * @param debugLevel
	 * @param dbg_X
	 * @param dbg_Y
	 */
	public void setNonExclusive(
			final TilePlanes.PlaneData [][] planes,
			final int     debugLevel,
@@ -834,7 +845,7 @@ public class LinkPlanes {
		//				final int debug_stile = 9 * stilesX + 26;
		final int debug_stile = dbg_Y * stilesX + dbg_X;

		final Thread[] threads = ImageDtt.newThreadArray(st.tileProcessor.threadsMax);
		final Thread[] threads = ImageDtt.newThreadArray((debugLevel > 1)? 1 : st.tileProcessor.threadsMax);
		final AtomicInteger ai = new AtomicInteger(0);

		for (int ithread = 0; ithread < threads.length; ithread++) {
@@ -2426,7 +2437,7 @@ public class LinkPlanes {
		final int stilesX =       (tilesX + superTileSize -1)/superTileSize;  
		final int stilesY =       (tilesY + superTileSize -1)/superTileSize;
		final int nStiles =       stilesX * stilesY; 
		final TileSurface.TileNeibs tnSurface = st.tileSurface.new TileNeibs(stilesX, stilesY);
		final TileNeibs tnSurface = new TileNeibs(stilesX, stilesY);
		final Thread[] threads = ImageDtt.newThreadArray(st.tileProcessor.threadsMax);
		final AtomicInteger ai = new AtomicInteger(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
@@ -2441,7 +2452,7 @@ public class LinkPlanes {
							starValPwr,     //double          starValPwr, //  Raise value of each tile before averaging
							steps,          // int            steps,
							planes,         // TilePlanes.PlaneData [][] planes,
							tnSurface,      // TileSurface.TileNeibs tnSurface,
							tnSurface,      // TileNeibs tnSurface,
							preferDisparity); // boolean preferDisparity)
					int [] mod_supertiles = new int[1];
					for (int nsTile = ai.getAndIncrement(); nsTile < nStiles; nsTile = ai.getAndIncrement()) {
@@ -2484,7 +2495,7 @@ public class LinkPlanes {
		//				final int tileSize =      tileProcessor.getTileSize();
		final int stilesX =       (tilesX + superTileSize -1)/superTileSize;  
		final int stilesY =       (tilesY + superTileSize -1)/superTileSize;
		final TileSurface.TileNeibs tnSurface = st.tileSurface.new TileNeibs(stilesX, stilesY);
		final TileNeibs tnSurface = new TileNeibs(stilesX, stilesY);
		final Thread[] threads = ImageDtt.newThreadArray(st.tileProcessor.threadsMax);
		final AtomicInteger ai = new AtomicInteger(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
@@ -2499,7 +2510,7 @@ public class LinkPlanes {
							starValPwr,      //double     starValPwr, //  Raise value of each tile before averaging
							steps,          // int            steps,
							planes,         // TilePlanes.PlaneData [][] planes,
							tnSurface,      // TileSurface.TileNeibs tnSurface,
							tnSurface,      // TileNeibs tnSurface,
							preferDisparity); // boolean preferDisparity)
					int [] supertiles = new int[1];
					for (int isTile = ai.getAndIncrement(); isTile < mod_supertiles.length; isTile = ai.getAndIncrement()) {
+154 −489

File changed.

Preview size limit exceeded, changes collapsed.

+366 −0
Original line number Diff line number Diff line
import java.util.ArrayList;
import java.util.Arrays;

/**
 ** TileNeibs - handles walking inside rectangular area
 **
 ** Copyright (C) 2017 Elphel, Inc.
 **
 ** -----------------------------------------------------------------------------**
 **  
 **  TileNeibs.java is free software: you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 of the License, or
 **  (at your option) any later version.
 **
 **  This program is distributed in the hope that it will be useful,
 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 **  GNU General Public License for more details.
 **
 **  You should have received a copy of the GNU General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ** -----------------------------------------------------------------------------**
 **
 */

public class TileNeibs{
	int sizeX;
	int sizeY;
	public int dirs = 8;
	public TileNeibs(int size){
		this.sizeX = size;
		this.sizeY = size;
	}
	public TileNeibs(int sizeX, int sizeY){
		this.sizeX = sizeX;
		this.sizeY = sizeY;
	}
	public int numNeibs() // TODO: make configurable to 
	{
		return dirs;
	}
	public int opposite(int dir){
		return (dir + dirs / 2) % dirs;
	}

	/**
	 * Get x,y pair from index
	 * @param indx element index
	 * @return array of {x,y}
	 */
	
	int [] getXY(int indx)
	{
		int [] xy = {indx % sizeX ,indx / sizeX};
		return xy;
	}
	
	/**
	 * Get element index from x and y
	 * @param x horizontal position
	 * @param y vertical position
	 * @return element linescan index
	 */
	
	int getIndex(int x, int y){
		return y * sizeX + x;
	}
	
	/**
	 * Get 2d element index after step N, NE, ... NW. Returns -1 if leaving array   
	 * @param indx start index
	 * @param dir step direction (CW from up)
	 * @return new index or -1 if leaving 
	 */
	int getNeibIndex(int indx, int dir)
	{
		int y = indx / sizeX;
		int x = indx % sizeX;
		if (dir < 0) return indx;
		switch (dir % dirs){
		case 0: return (y == 0) ?                                    -1 : (indx - sizeX); 
		case 1: return ((y == 0)           || ( x == (sizeX - 1))) ? -1 : (indx - sizeX + 1); 
		case 2: return (                      ( x == (sizeX - 1))) ? -1 : (indx        + 1); 
		case 3: return ((y == (sizeY - 1)) || ( x == (sizeX - 1))) ? -1 : (indx + sizeX + 1); 
		case 4: return ((y == (sizeY - 1))                       ) ? -1 : (indx + sizeX); 
		case 5: return ((y == (sizeY - 1)) || ( x == 0))           ? -1 : (indx + sizeX - 1); 
		case 6: return (                      ( x == 0))           ? -1 : (indx        - 1); 
		case 7: return ((y == 0)           || ( x == 0))           ? -1 : (indx - sizeX - 1); 
		default: return indx;
		}
	}
	
	/**
	 * Return tile segment for 50% overlap. -1 - center, 0 N, 1 - NE,... 7 - NW
	 * @param indx element index
	 * @return which of the 9 areas this element belongs
	 */
	int getSegment(int indx)
	{
		int s1x = sizeX / 4;
		int s3x = 3 * sizeX / 4;
		int s1y = sizeY / 4;
		int s3y = 3 * sizeY / 4;
		int x = indx % sizeX;
		int y = indx / sizeX;
		boolean up = y < s1y;
		boolean down = y >= s3y;
		boolean left = x < s1x;
		boolean right = x >= s3x;
		if (up){
			if (left) return 7;
			if (right) return 1;
			return 0;
		}
		if (down){
			if (left) return 5;
			if (right) return 3;
			return 4;
		}
		if (left) return 6;
		if (right) return 2;
		return -1;
	}

	/**
	 * Find if the step leaves the center half of all area
	 * @param indx start point
	 * @param dir direction
	 * @return direction to the new tile (assuming 50% overlap) or -1 if did not cross the border
	 */
	int leaveOvderlapedCenter(int indx, int dir)
	{
		int segm = getSegment(indx);
		int indx1 = getNeibIndex(indx, dir);
		if (indx1 < 0 ) {
			return -1; // should not happen
		}
		int segm1 = getSegment(indx1);
		if (segm1 == segm) return -1;
		if (segm == -1) return segm1;
		int [][] dxy = {
				{ 0, 0},
				{-1, 0},
				{-1, 1},
				{ 0, 1},
				{ 1, 1},
				{ 1, 0},
				{ 1,-1},
				{ 0,-1},
				{-1,-1}};
		int dx = dxy[segm1 + 1][1] - dxy[segm + 1][1]; 
		int dy = dxy[segm1 + 1][0] - dxy[segm + 1][0];
		for (int dp1 = 0; dp1 <=8; dp1++) {
			int sdx = (dx > 0) ? 1: ( (dx < 0) ? -1 : 0);
			int sdy = (dy > 0) ? 1: ( (dy < 0) ? -1 : 0);
			if ((dxy[dp1][0] == sdy) && (dxy[dp1][1] == sdx)){
				return dp1 -1;
			}
		}
		return -1; // should not happen
	}
	
	public void growSelection(
			int        grow,           // grow tile selection by 1 over non-background tiles 1: 4 directions, 2 - 8 directions, 3 - 8 by 1, 4 by 1 more
			boolean [] tiles,
			boolean [] prohibit)
	{
		boolean [] src_tiles = tiles.clone(); // just in case
		// grow
		boolean hor = true;
		for (; grow > 0; grow--){
			boolean single = (grow ==1) && hor;
			src_tiles = tiles.clone();
			int num_new = 0;
			if (hor){
				for (int tileY = 0; tileY < sizeY; tileY++){
					for (int tileX = 0; tileX < (sizeX - 1); tileX++){
						int tindx = tileY * sizeX + tileX;
						if ((prohibit == null) || (!prohibit[tindx] && !prohibit[tindx + 1])) {
							if (!tiles[tindx + 1] && src_tiles[tindx]){
								num_new++;
							}
							tiles[tindx + 1] |= src_tiles[tindx];  
						}

					}
					for (int tileX = 1; tileX < sizeX; tileX++){
						int tindx = tileY * sizeX + tileX;
						if ((prohibit == null) || (!prohibit[tindx] && !prohibit[tindx - 1])) {
							if (!tiles[tindx - 1] && src_tiles[tindx]){
								num_new++;
							}
							tiles[tindx - 1] |= src_tiles[tindx];
						}
					}
				}
			}
			if (!hor || single){ // do vertically, but from previous state
				for (int tileX = 0; tileX < sizeX; tileX++){
					for (int tileY = 0; tileY < (sizeY - 1); tileY++){
						int tindx = tileY * sizeX + tileX;
						if ((prohibit == null) || (!prohibit[tindx] && !prohibit[tindx + sizeX])) {
							if (!tiles[tindx + sizeX] && src_tiles[tindx]){
								num_new++;
							}
							tiles[tindx + sizeX] |= src_tiles[tindx];
						}

					}
					for (int tileY = 1; tileY < sizeY; tileY++){
						int tindx = tileY * sizeX + tileX;
						if ((prohibit == null) || (!prohibit[tindx] && !prohibit[tindx - sizeX])) {
							if (!tiles[tindx - sizeX] && src_tiles[tindx]){
								num_new++;
							}
							tiles[tindx - sizeX] |= src_tiles[tindx];
						}
					}
				}
			}
			hor = !hor;
			if (num_new == 0){
				break;
			}
		}
	}
	
	public boolean [] boundShape(
			boolean [] selection,
			boolean octo)
	{
		boolean [] bound_shape = new boolean [selection.length];
		int min_x=-1, max_x=-1, min_y=-1, max_y=-1; 
		int min_s=-1, max_s=-1, min_d=-1, max_d=-1; 
		boolean is_set = false;
		for (int i = 0; i < selection.length; i++) if (selection[i]){
			int [] xy = getXY(i);
			int [] sd = {xy[0]+xy[1],xy[0]-xy[1]};
			if (!is_set) {
				min_x = xy[0];
				max_x = xy[0];
				min_y = xy[1];
				max_y = xy[1];
				if (octo) {
				min_s = sd[0];
				max_s = sd[0];
				min_d = sd[1];
				max_d = sd[1];
				}
				is_set = true;
			} else {
				if      (xy[0] < min_x) min_x = xy[0];
				else if (xy[0] > max_x) max_x = xy[0]; 
				if      (xy[1] < min_y) min_y = xy[1];
				else if (xy[1] > max_y) max_y = xy[1];
				if (octo) {
					if      (sd[0] < min_s) min_s = sd[0];
					else if (sd[0] > max_s) max_s = sd[0]; 
					if      (sd[1] < min_d) min_d = sd[1];
					else if (sd[1] > max_d) max_d = sd[1];
				}
				
			}
		}
		for (int y = min_y; y <= max_y; y++){
			for (int x = min_x; x <= max_x; x++){
				if (!octo ||
				(((x + y) >= min_s) && ((x + y) <= max_s) && ((x - y) >= min_d) && ((x - y) <= max_d))) {
					bound_shape[getIndex(x,y)] = true; 
					
				}
			}
		}
		return bound_shape;
	}
	
	
	/**
	 * Enumerate clusters on rectangular area
	 * @param tiles   selected tiles, size should be sizeX * sizeY
	 * @param ordered if true, order tiles from largest to smallest5
	 * @return integer array, where 0 is unused, 1+ cluster it belongs to
	 */
	
	
	public int [] enumerateClusters(
			boolean [] tiles,
			boolean ordered)
	{
		int [] waves = new int [tiles.length];
		for (int i = 0; i < tiles.length; i++) waves[i] = tiles[i] ? 0: -1;
		ArrayList<Integer> front = new ArrayList<Integer>();
		int [] enum_clust = new int[tiles.length];
		int numClust = 0;
		for (int start_indx = 0; start_indx < tiles.length; start_indx++) if (waves[start_indx] == 0){ // found first pixel of a new cluster
			numClust ++;
			Integer ipx = start_indx;
			Integer ipx1;
			front.clear();
			int area = 1;
			waves[ipx] = area;
			enum_clust[ipx] = numClust;
			front.add(ipx);
			while (!front.isEmpty()) {
				ipx = front.remove(0);// get oldest element
				for (int d = 0; d < dirs; d++){
					ipx1 = 	getNeibIndex(ipx, d);
					if (ipx1 >= 0){
						if (waves[ipx1] == 0) {
							area++;
							waves[ipx1] = area;
							enum_clust[ipx1] = numClust;
							front.add(ipx1);
						}
					}
				}
			}
		}
		if (!ordered) {
			return enum_clust;
		}
		
		// count cluster
		int []clustSizes = new int [numClust];
		for (int i = 0; i < clustSizes.length; i++) clustSizes[i] = 0;
		for (int i = 0; i < enum_clust.length; i++) if (enum_clust[i] > 0) clustSizes[enum_clust[i]-1]++;

		class Pair implements Comparable<Pair> {
			public final int index;
			public final int value;

			public Pair(int index, int value) {
				this.index = index;
				this.value = value;
			}

			@Override
			public int compareTo(Pair other) {
				return Integer.valueOf(this.value).compareTo(other.value);
			}
		}

		Pair[] pairs = new Pair[numClust];
		for (int i = 0; i < clustSizes.length; i++) pairs [i] = new Pair (i, clustSizes[i]);
		Arrays.sort(pairs);
		int [] revIndex = new int [numClust];
		for (int i = 0; i < revIndex.length; i++) revIndex [pairs[i].index] = (numClust - i); // array was in accending order
		int [] enum_clust_ordered = new int[tiles.length];
		for (int i=0; i < enum_clust_ordered.length; i++){
			enum_clust_ordered[i] = (enum_clust[i] > 0) ? revIndex[enum_clust[i] - 1] : 0; 
		}
		return enum_clust_ordered;  
	}
	public int getMax(
			int [] data)
	{
		int mx = data[0];
		for (int i = 1; i < data.length; i++){
			if (data[i] > mx){
				mx= data[i];
			}
		}
		return mx;
	}
}
Loading