use of org.ddogleg.struct.GrowQueue_I32 in project BoofCV by lessthanoptimal.
the class RemoveWatersheds method remove.
/**
* Removes watersheds from the segmented image. The input image must be the entire original
* segmented image and assumes the outside border is filled with values < 0. To access
* this image call {@link boofcv.alg.segmentation.watershed.WatershedVincentSoille1991#getOutputBorder()}.
* Each watershed is assigned the value of an arbitrary neighbor. 4-connect rule is used for neighbors.
* Doesn't matter if initial segmented was done using another connectivity rule. The value of each region i
* s reduced by one at the very end.
*
* @param segmented Entire segmented image (including border of -1 values) with watersheds
*/
public void remove(GrayS32 segmented) {
// very quick sanity check
if (segmented.get(0, 0) >= 0)
throw new IllegalArgumentException("The segmented image must contain a border of -1 valued pixels. See" + " JavaDoc for important details you didn't bother to read about.");
open.reset();
connect[0] = -1;
connect[1] = 1;
connect[2] = segmented.stride;
connect[3] = -segmented.stride;
// step through the inner pixels and find watershed pixels
for (int y = 1; y < segmented.height - 1; y++) {
int index = y * segmented.stride + 1;
for (int x = 1; x < segmented.width - 1; x++, index++) {
if (segmented.data[index] == 0) {
open.add(index);
}
}
}
// assign region values to watersheds until they are all assigned
while (open.size != 0) {
open2.reset();
for (int i = 0; i < open.size; i++) {
int index = open.get(i);
// assign it to the first valid region it finds
for (int j = 0; j < 4; j++) {
// the outside border in the enlarged segmented image will have -1 and watersheds are 0
int r = segmented.data[index + connect[j]];
if (r > 0) {
segmented.data[index] = r;
break;
}
}
// see if it was not assigned a region
if (segmented.data[index] == 0) {
open2.add(index);
}
}
// swap open and open2
GrowQueue_I32 tmp = open;
open = open2;
open2 = tmp;
}
// watershed pixels have a value of 0 and have been removed. So change the region ID numbers by 1
for (int y = 1; y < segmented.height - 1; y++) {
int index = y * segmented.stride + 1;
for (int x = 1; x < segmented.width - 1; x++, index++) {
segmented.data[index]--;
}
}
}
use of org.ddogleg.struct.GrowQueue_I32 in project BoofCV by lessthanoptimal.
the class WatershedVincentSoille1991 method process.
/**
* <p>
* Segments the image using initial seeds for each region. This is often done to avoid
* over segmentation but requires additional preprocessing and/or knowledge on the image structure. Initial
* seeds are specified in the input image 'seeds'. A seed is any pixel with a value > 0. New new regions
* will be created beyond those seeds. The final segmented image is provided by {@link #getOutput()}.
* </p>
*
* <p>
* NOTE: If seeds are used then {@link #getTotalRegions()} will not return a correct solution.
* </p>
*
* @param input (Input) Input image
* @param seeds (Output) Segmented image containing seeds. Note that all seeds should have a value > 0 and have a
* value ≤ numRegions.
*/
public void process(GrayU8 input, GrayS32 seeds) {
InputSanityCheck.checkSameShape(input, seeds);
removedWatersheds = false;
output.reshape(input.width + 2, input.height + 2);
distance.reshape(input.width + 2, input.height + 2);
ImageMiscOps.fill(output, INIT);
ImageMiscOps.fill(distance, 0);
fifo.reset();
// copy the seeds into the output directory
for (int y = 0; y < seeds.height; y++) {
int indexSeeds = seeds.startIndex + y * seeds.stride;
int indexOut = (y + 1) * output.stride + 1;
for (int x = 0; x < seeds.width; x++, indexSeeds++, indexOut++) {
int v = seeds.data[indexSeeds];
if (v > 0) {
output.data[indexOut] = v;
}
}
}
// sort pixels
sortPixels(input);
// perform watershed
for (int i = 0; i < histogram.length; i++) {
GrowQueue_I32 level = histogram[i];
if (level.size == 0)
continue;
// Go through each pixel at this level and mark them according to their neighbors
for (int j = 0; j < level.size; j++) {
int index = level.data[j];
// from its neighbors
if (output.data[index] == INIT) {
output.data[index] = MASK;
assignNewToNeighbors(index);
}
}
currentDistance = 1;
fifo.add(MARKER_PIXEL);
while (true) {
int p = fifo.popHead();
// end of a cycle. Exit the loop if it is done or increase the distance and continue processing
if (p == MARKER_PIXEL) {
if (fifo.isEmpty())
break;
else {
fifo.add(MARKER_PIXEL);
currentDistance++;
p = fifo.popHead();
}
}
// look at its neighbors and see if they have been labeled or belong to a watershed
// and update its distance
checkNeighborsAssign(p);
}
// Ensure that all pixels have a distance of zero
// Could probably do this a bit more intelligently...
ImageMiscOps.fill(distance, 0);
}
}
use of org.ddogleg.struct.GrowQueue_I32 in project BoofCV by lessthanoptimal.
the class WatershedVincentSoille1991 method process.
/**
* Perform watershed segmentation on the provided input image. New basins are created at each local minima.
*
* @param input Input gray-scale image.
*/
public void process(GrayU8 input) {
// input = im_0
removedWatersheds = false;
output.reshape(input.width + 2, input.height + 2);
distance.reshape(input.width + 2, input.height + 2);
ImageMiscOps.fill(output, INIT);
ImageMiscOps.fill(distance, 0);
fifo.reset();
// sort pixels
sortPixels(input);
currentLabel = 0;
for (int i = 0; i < histogram.length; i++) {
GrowQueue_I32 level = histogram[i];
if (level.size == 0)
continue;
// Go through each pixel at this level and mark them according to their neighbors
for (int j = 0; j < level.size; j++) {
int index = level.data[j];
output.data[index] = MASK;
// see if its neighbors has been labeled, if so set its distance and add to queue
assignNewToNeighbors(index);
}
currentDistance = 1;
fifo.add(MARKER_PIXEL);
while (true) {
int p = fifo.popHead();
// end of a cycle. Exit the loop if it is done or increase the distance and continue processing
if (p == MARKER_PIXEL) {
if (fifo.isEmpty())
break;
else {
fifo.add(MARKER_PIXEL);
currentDistance++;
p = fifo.popHead();
}
}
// look at its neighbors and see if they have been labeled or belong to a watershed
// and update its distance
checkNeighborsAssign(p);
}
// see if new minima have been discovered
for (int j = 0; j < level.size; j++) {
int index = level.get(j);
// distance associated with p is reset to 0
distance.data[index] = 0;
if (output.data[index] == MASK) {
currentLabel++;
fifo.add(index);
output.data[index] = currentLabel;
// grow the new region into the surrounding connected pixels
while (!fifo.isEmpty()) {
checkNeighborsMasks(fifo.popHead());
}
}
}
}
}
use of org.ddogleg.struct.GrowQueue_I32 in project BoofCV by lessthanoptimal.
the class SegmentMeanShift method process.
/**
* Performs mean-shift segmentation on the input image. The
* total number of regions can be found by calling {@link #getNumberOfRegions()}.
*
* @param image Image
* @param output Storage for output image. Each pixel is set to the region it belongs to.
*/
public void process(T image, GrayS32 output) {
InputSanityCheck.checkSameShape(image, output);
// long time0 = System.currentTimeMillis();
search.process(image);
// long time1 = System.currentTimeMillis();
FastQueue<float[]> regionColor = search.getModeColor();
GrayS32 pixelToRegion = search.getPixelToRegion();
GrowQueue_I32 regionPixelCount = search.getRegionMemberCount();
FastQueue<Point2D_I32> modeLocation = search.getModeLocation();
merge.process(pixelToRegion, regionPixelCount, regionColor, modeLocation);
// long time2 = System.currentTimeMillis();
segment.process(pixelToRegion, output, regionPixelCount);
if (prune != null)
prune.process(image, output, regionPixelCount, regionColor);
// long time4 = System.currentTimeMillis();
// System.out.println("Search: "+(time1-time0)+" Merge: "+(time2-time1)+
// " segment: "+(time3-time2)+" Prune: "+(time4-time3));
}
use of org.ddogleg.struct.GrowQueue_I32 in project BoofCV by lessthanoptimal.
the class VisOdomDualTrackPnP method addNewTracks.
/**
* Spawns tracks in each image and associates features together.
*/
private void addNewTracks() {
trackerLeft.spawnTracks();
trackerRight.spawnTracks();
List<PointTrack> newLeft = trackerLeft.getNewTracks(null);
List<PointTrack> newRight = trackerRight.getNewTracks(null);
// get a list of new tracks and their descriptions
addNewToList(inputLeft, newLeft, pointsLeft, descLeft);
addNewToList(inputRight, newRight, pointsRight, descRight);
// associate using L2R
assocL2R.setSource(pointsLeft, descLeft);
assocL2R.setDestination(pointsRight, descRight);
assocL2R.associate();
FastQueue<AssociatedIndex> matches = assocL2R.getMatches();
// storage for the triangulated location in the camera frame
Point3D_F64 cameraP3 = new Point3D_F64();
for (int i = 0; i < matches.size; i++) {
AssociatedIndex m = matches.get(i);
PointTrack trackL = newLeft.get(m.src);
PointTrack trackR = newRight.get(m.dst);
// declare additional track information stored in each track. Tracks can be recycled so it
// might not always need to be declared
LeftTrackInfo infoLeft = trackL.getCookie();
if (infoLeft == null)
trackL.cookie = infoLeft = new LeftTrackInfo();
RightTrackInfo infoRight = trackR.getCookie();
if (infoRight == null)
trackR.cookie = infoRight = new RightTrackInfo();
Stereo2D3D p2d3d = infoLeft.location;
// convert pixel observations into normalized image coordinates
leftImageToNorm.compute(trackL.x, trackL.y, p2d3d.leftObs);
rightImageToNorm.compute(trackR.x, trackR.y, p2d3d.rightObs);
// triangulate 3D coordinate in the current camera frame
if (triangulate.triangulate(p2d3d.leftObs, p2d3d.rightObs, leftToRight, cameraP3)) {
// put the track into the current keyframe coordinate system
SePointOps_F64.transform(currToKey, cameraP3, p2d3d.location);
// save a reference to the matching track in the right camera frame
infoLeft.right = trackR;
infoLeft.lastConsistent = infoLeft.lastInlier = tick;
infoRight.left = trackL;
} else {
// triangulation failed, drop track
trackerLeft.dropTrack(trackL);
// TODO need way to mark right tracks which are unassociated after this loop
throw new RuntimeException("This special case needs to be handled!");
}
}
// drop tracks that were not associated
GrowQueue_I32 unassignedRight = assocL2R.getUnassociatedDestination();
for (int i = 0; i < unassignedRight.size; i++) {
int index = unassignedRight.get(i);
// System.out.println(" unassigned right "+newRight.get(index).x+" "+newRight.get(index).y);
trackerRight.dropTrack(newRight.get(index));
}
GrowQueue_I32 unassignedLeft = assocL2R.getUnassociatedSource();
for (int i = 0; i < unassignedLeft.size; i++) {
int index = unassignedLeft.get(i);
trackerLeft.dropTrack(newLeft.get(index));
}
// System.out.println("Total left "+trackerLeft.getAllTracks(null).size()+" right "+trackerRight.getAllTracks(null).size());
// System.out.println("Associated: "+matches.size+" new left "+newLeft.size()+" new right "+newRight.size());
// System.out.println("New Tracks: Total: Left "+trackerLeft.getAllTracks(null).size()+" right "+
// trackerRight.getAllTracks(null).size());
// List<PointTrack> temp = trackerLeft.getActiveTracks(null);
// for( PointTrack t : temp ) {
// if( t.cookie == null )
// System.out.println("BUG!");
// }
// temp = trackerRight.getActiveTracks(null);
// for( PointTrack t : temp ) {
// if( t.cookie == null )
// System.out.println("BUG!");
// }
}
Aggregations