use of org.ddogleg.struct.DogArray_I32 in project BoofCV by lessthanoptimal.
the class ComputeMeanTuple_MT_U8 method process.
@Override
public void process(LArrayAccessor<TupleDesc_U8> points, DogArray_I32 assignments, FastAccess<TupleDesc_U8> clusters) {
// see if it should run the single thread version instead
if (points.size() < minimumForConcurrent) {
super.process(points, assignments, clusters);
return;
}
if (assignments.size != points.size())
throw new IllegalArgumentException("Points and assignments need to be the same size");
// Compute the sum of all points in each cluster
BoofConcurrency.loopBlocks(0, points.size(), threadData, (data, idx0, idx1) -> {
final TupleDesc_U8 tuple = data.point;
final DogArray<int[]> sums = data.clusterSums;
sums.resize(clusters.size);
for (int i = 0; i < sums.size; i++) {
Arrays.fill(sums.data[i], 0);
}
final DogArray_I32 counts = data.counts;
counts.resize(sums.size, 0);
for (int pointIdx = idx0; pointIdx < idx1; pointIdx++) {
points.getCopy(pointIdx, tuple);
final byte[] point = tuple.data;
int clusterIdx = assignments.get(pointIdx);
counts.data[clusterIdx]++;
int[] sum = sums.get(clusterIdx);
for (int i = 0; i < point.length; i++) {
sum[i] += point[i] & 0xFF;
}
}
});
// Stitch results from threads back together
counts.reset();
counts.resize(clusters.size, 0);
means.resize(clusters.size);
for (int i = 0; i < clusters.size; i++) {
Arrays.fill(means.data[i], 0);
}
for (int threadIdx = 0; threadIdx < threadData.size(); threadIdx++) {
ThreadData data = threadData.get(threadIdx);
for (int clusterIdx = 0; clusterIdx < clusters.size; clusterIdx++) {
int[] a = data.clusterSums.get(clusterIdx);
int[] b = means.get(clusterIdx);
for (int i = 0; i < b.length; i++) {
b[i] += a[i];
}
counts.data[clusterIdx] += data.counts.data[clusterIdx];
}
}
// Divide to get the average value in each cluster
for (int clusterIdx = 0; clusterIdx < clusters.size; clusterIdx++) {
int[] sum = means.get(clusterIdx);
byte[] cluster = clusters.get(clusterIdx).data;
double divisor = counts.get(clusterIdx);
for (int i = 0; i < cluster.length; i++) {
cluster[i] = (byte) (sum[i] / divisor);
}
}
}
use of org.ddogleg.struct.DogArray_I32 in project BoofCV by lessthanoptimal.
the class TestComputeMedianTuple_MT_B method compare.
@Test
void compare() {
int DOF = 510;
int numClusters = 4;
// Create a list of random points
List<TupleDesc_B> list = new ArrayList<>();
var assignments = new DogArray_I32(1000);
for (int i = 0; i < 1000; i++) {
assignments.add(rand.nextInt(numClusters));
var t = new TupleDesc_B(DOF);
for (int j = 0; j < t.data.length; j++) {
t.data[j] = rand.nextInt();
}
list.add(t);
}
var points = new ListAccessor<>(list, (src, dst) -> dst.setTo(src), TupleDesc_B.class);
var clustersSingle = new DogArray<>(() -> new TupleDesc_B(DOF));
var clustersMulti = new DogArray<>(() -> new TupleDesc_B(DOF));
clustersSingle.resize(numClusters);
clustersMulti.resize(numClusters);
var single = new ComputeMedianTuple_B(DOF);
var multi = new ComputeMedianTuple_MT_B(DOF);
single.process(points, assignments, clustersSingle);
multi.process(points, assignments, clustersMulti);
assertEquals(clustersSingle.size, clustersMulti.size);
for (int i = 0; i < numClusters; i++) {
assertArrayEquals(clustersSingle.get(i).data, clustersMulti.get(i).data);
}
}
use of org.ddogleg.struct.DogArray_I32 in project BoofCV by lessthanoptimal.
the class TestRecognitionVocabularyTreeNister2006 method describe.
@Test
void describe() {
HierarchicalVocabularyTree<Point2D_F64> tree = create2x2Tree();
// Add a few features at the leaves
List<Point2D_F64> imageFeatures = new ArrayList<>();
for (int i = 0; i < 3; i++) {
imageFeatures.add(new Point2D_F64(-5, -1));
imageFeatures.add(new Point2D_F64(5, -1));
}
// TF-IDF descriptor
var descWeights = new DogArray_F32();
var descWords = new DogArray_I32();
var alg = new RecognitionVocabularyTreeNister2006<Point2D_F64>();
alg.initializeTree(tree);
alg.describe(imageFeatures, descWeights, descWords);
// See if the description is as expected
assertEquals(4, descWeights.size());
assertEquals(4, descWords.size());
// All the expected nodes should have values
float f1 = descWeights.get(descWords.indexOf(1));
float f2 = descWeights.get(descWords.indexOf(2));
float f3 = descWeights.get(descWords.indexOf(3));
float f5 = descWeights.get(descWords.indexOf(5));
assertTrue(f1 > 0 && f2 > 0 && f3 > 0 && f5 > 0);
assertTrue(f1 < f2);
assertTrue(f3 < f5);
// L2-norm should be 1.0
float norm = (float) Math.sqrt(f1 * f1 + f2 * f2 + f3 * f3 + f5 * f5);
assertEquals(1.0f, norm, UtilEjml.TEST_F32);
}
use of org.ddogleg.struct.DogArray_I32 in project BoofCV by lessthanoptimal.
the class TestComputeMeanTuple_MT_F64 method compare.
@Test
void compare() {
int DOF = 31;
int numClusters = 4;
// Create a list of random points
List<TupleDesc_F64> list = new ArrayList<>();
var assignments = new DogArray_I32(1000);
for (int i = 0; i < 1000; i++) {
assignments.add(rand.nextInt(numClusters));
var t = new TupleDesc_F64(DOF);
for (int j = 0; j < DOF; j++) {
t.data[j] = rand.nextDouble();
}
list.add(t);
}
var points = new ListAccessor<>(list, (src, dst) -> dst.setTo(src), TupleDesc_F64.class);
var clustersSingle = new DogArray<>(() -> new TupleDesc_F64(DOF));
var clustersMulti = new DogArray<>(() -> new TupleDesc_F64(DOF));
clustersSingle.resize(numClusters);
clustersMulti.resize(numClusters);
var single = new ComputeMeanTuple_F64();
var multi = new ComputeMeanTuple_MT_F64(DOF);
single.process(points, assignments, clustersSingle);
multi.process(points, assignments, clustersMulti);
assertEquals(clustersSingle.size, clustersMulti.size);
for (int i = 0; i < numClusters; i++) {
assertArrayEquals(clustersSingle.get(i).data, clustersMulti.get(i).data, UtilEjml.TEST_F64);
}
}
use of org.ddogleg.struct.DogArray_I32 in project BoofCV by lessthanoptimal.
the class ComputeMedianTuple_MT_B method countBitsInEachCluster.
@Override
protected void countBitsInEachCluster(LArrayAccessor<TupleDesc_B> points, DogArray_I32 assignments) {
if (points.size() < minimumForConcurrent) {
super.countBitsInEachCluster(points, assignments);
return;
}
int numClusters = super.assignmentCounts.size;
// Compute the sum of all points in each cluster
BoofConcurrency.loopBlocks(0, points.size(), threadData, (data, idx0, idx1) -> {
final TupleDesc_B tuple = data.point;
final DogArray<int[]> bitCounts = data.bitCounts;
final DogArray_I32 assignmentCounts = data.assignmentCounts;
assignmentCounts.resetResize(numClusters, 0);
bitCounts.resize(numClusters);
for (int i = 0; i < bitCounts.size; i++) {
Arrays.fill(bitCounts.data[i], 0);
}
// Compute the sum of all points in each cluster
for (int pointIdx = idx0; pointIdx < idx1; pointIdx++) {
// See which cluster this point was assigned to and increment its counter
int clusterIdx = assignments.get(pointIdx);
assignmentCounts.data[clusterIdx]++;
points.getCopy(pointIdx, tuple);
// Increment the counter for each "true" bit in the tuple
int[] bitCount = bitCounts.get(clusterIdx);
int bit = 0;
while (bit + 32 < dof) {
// Unroll for speed
int value = tuple.data[bit / 32];
if ((value & 0x00000001) != 0)
bitCount[bit]++;
if ((value & 0x00000002) != 0)
bitCount[bit + 1]++;
if ((value & 0x00000004) != 0)
bitCount[bit + 2]++;
if ((value & 0x00000008) != 0)
bitCount[bit + 3]++;
if ((value & 0x00000010) != 0)
bitCount[bit + 4]++;
if ((value & 0x00000020) != 0)
bitCount[bit + 5]++;
if ((value & 0x00000040) != 0)
bitCount[bit + 6]++;
if ((value & 0x00000080) != 0)
bitCount[bit + 7]++;
if ((value & 0x00000100) != 0)
bitCount[bit + 8]++;
if ((value & 0x00000200) != 0)
bitCount[bit + 9]++;
if ((value & 0x00000400) != 0)
bitCount[bit + 10]++;
if ((value & 0x00000800) != 0)
bitCount[bit + 11]++;
if ((value & 0x00001000) != 0)
bitCount[bit + 12]++;
if ((value & 0x00002000) != 0)
bitCount[bit + 13]++;
if ((value & 0x00004000) != 0)
bitCount[bit + 14]++;
if ((value & 0x00008000) != 0)
bitCount[bit + 15]++;
if ((value & 0x00010000) != 0)
bitCount[bit + 16]++;
if ((value & 0x00020000) != 0)
bitCount[bit + 17]++;
if ((value & 0x00040000) != 0)
bitCount[bit + 18]++;
if ((value & 0x00080000) != 0)
bitCount[bit + 19]++;
if ((value & 0x00100000) != 0)
bitCount[bit + 20]++;
if ((value & 0x00200000) != 0)
bitCount[bit + 21]++;
if ((value & 0x00400000) != 0)
bitCount[bit + 22]++;
if ((value & 0x00800000) != 0)
bitCount[bit + 23]++;
if ((value & 0x01000000) != 0)
bitCount[bit + 24]++;
if ((value & 0x02000000) != 0)
bitCount[bit + 25]++;
if ((value & 0x04000000) != 0)
bitCount[bit + 26]++;
if ((value & 0x08000000) != 0)
bitCount[bit + 27]++;
if ((value & 0x10000000) != 0)
bitCount[bit + 28]++;
if ((value & 0x20000000) != 0)
bitCount[bit + 29]++;
if ((value & 0x40000000) != 0)
bitCount[bit + 30]++;
if ((value & 0x80000000) != 0)
bitCount[bit + 31]++;
bit += 32;
}
// handle the remainder if it doesn't align with 32-bit integers
for (; bit < dof; bit++) {
if (!tuple.isBitTrue(bit))
continue;
bitCount[bit]++;
}
}
});
// stitch all the threads back together
for (int threadIdx = 0; threadIdx < threadData.size(); threadIdx++) {
ThreadData data = threadData.get(threadIdx);
for (int clusterIdx = 0; clusterIdx < numClusters; clusterIdx++) {
super.assignmentCounts.data[clusterIdx] += data.assignmentCounts.data[clusterIdx];
int[] allCounts = super.bitCounts.get(clusterIdx);
int[] threadCounts = data.bitCounts.get(clusterIdx);
for (int bitIdx = 0; bitIdx < dof; bitIdx++) {
allCounts[bitIdx] += threadCounts[bitIdx];
}
}
}
}
Aggregations