/** * Performs an exhaustive search centered around (cx,cy) for the region in 'curr' which is the * best match for the template. Results are written into 'flow' */ protected float findFlow(int cx, int cy, T curr, ImageFlow.D flow) { float bestScore = Float.MAX_VALUE; int bestFlowX = 0, bestFlowY = 0; for (int i = -searchRadius; i <= searchRadius; i++) { int y = cy + i; for (int j = -searchRadius; j <= searchRadius; j++) { int x = cx + j; float error = computeError(x, y, curr); if (error < bestScore) { bestScore = error; bestFlowX = j; bestFlowY = i; } else if (error == bestScore) { // Pick solution with the least motion when ambiguous float m0 = j * j + i * i; float m1 = bestFlowX * bestFlowX + bestFlowY * bestFlowY; if (m0 < m1) { bestFlowX = j; bestFlowY = i; } } } } if (bestScore <= maxError) { flow.valid = true; flow.x = bestFlowX; flow.y = bestFlowY; return bestScore; } else { flow.valid = false; return Float.NaN; } }
@Test public void checkNeighbors() { int r = 3; Dummy alg = new Dummy(r, 2, 200, ImageUInt8.class); alg.scores = new float[20 * 30]; ImageFlow flows = new ImageFlow(20, 30); ImageFlow.D tmp = new ImageFlow.D(); tmp.valid = true; tmp.x = -1; tmp.y = 2; // checks to see if a pixel is invalid that it's flow is always set // if a pixel is valid then the score is only set if the score is better flows.get(6, 5).valid = true; alg.scores[5 * 20 + 6] = 10; flows.get(5, 5).valid = true; alg.scores[5 * 20 + 5] = 4; // same score, but more motion flows.get(5, 6).valid = true; alg.scores[6 * 20 + 5] = 5; flows.get(5, 6).x = 2; flows.get(5, 6).y = 2; // same score, but less motion flows.get(6, 6).valid = true; alg.scores[6 * 20 + 6] = 5; flows.get(6, 6).x = 0; flows.get(6, 6).y = 1; alg.checkNeighbors(6, 7, tmp, flows, 5); for (int i = -r; i <= r; i++) { for (int j = -r; j <= r; j++) { int x = j + 6; int y = i + 7; ImageFlow.D f = flows.get(x, y); assertTrue(f.valid); if (x == 5 && y == 5) { assertEquals(4, alg.scores[y * 20 + x], 1e-4); assertEquals(0, f.x, 1e-4); assertEquals(0, f.y, 1e-4); } else if (x == 6 && y == 6) { assertEquals(5, alg.scores[y * 20 + x], 1e-4); assertEquals(0, f.x, 1e-4); assertEquals(1, f.y, 1e-4); } else { assertEquals(x + " " + y, 5, alg.scores[y * 20 + x], 1e-4); assertEquals(-1, f.x, 1e-4); assertEquals(2, f.y, 1e-4); } } } }
/** * Examines every pixel inside the region centered at (cx,cy) to see if their optical flow has a * worse score the one specified in 'flow' */ protected void checkNeighbors(int cx, int cy, ImageFlow.D flow, ImageFlow image, float score) { for (int i = -searchRadius; i <= searchRadius; i++) { int index = image.width * (cy + i) + (cx - searchRadius); for (int j = -searchRadius; j <= searchRadius; j++, index++) { float s = scores[index]; ImageFlow.D f = image.data[index]; if (!f.valid || s > score) { f.set(flow); scores[index] = score; } else if (s == score) { // Pick solution with the least motion when ambiguous float m0 = f.x * f.x + f.y * f.y; float m1 = flow.x * flow.x + flow.y * flow.y; if (m1 < m0) { f.set(flow); scores[index] = score; } } } } }