Skip to content

Commit

Permalink
Drift cooldown?
Browse files Browse the repository at this point in the history
The idea is that if we drift "right" when decoding a given cell, we
should exclude the same drift for the next cell we check. This *might*
help with runaway decode errors?

Tests remain quite scuffed.
  • Loading branch information
sz3 committed Jun 1, 2023
1 parent f3cdabe commit 99e0f51
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 35 deletions.
19 changes: 17 additions & 2 deletions src/lib/cimb_translator/CellDrift.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace {
}

CellDrift::CellDrift(int x, int y)
: _x(x)
, _y(y)
: _x(x)
, _y(y)
{}

int CellDrift::x() const
Expand All @@ -29,3 +29,18 @@ void CellDrift::updateDrift(int dx, int dy)
_y = std::min(_y, _limit);
_y = std::max(_y, 0-_limit);
}

// static
uint8_t CellDrift::calculate_cooldown(uint8_t previous, uint8_t idx)
{
// previous xor idx == 6??
if (previous == 1 and idx == 7)
return 0xFF;
if (previous == 3 and idx == 5)
return 0xFF;
if (previous == 5 and idx == 3)
return 0xFF;
if (previous == 1 and idx == 7)
return 0xFF;
return idx;
}
4 changes: 3 additions & 1 deletion src/lib/cimb_translator/CellDrift.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ class CellDrift
CellDrift(int x=0, int y=0);

inline static const std::array<std::pair<int, int>, 9> driftPairs = {{
{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}
{-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}
}};

static uint8_t calculate_cooldown(uint8_t previous, uint8_t idx);

int x() const;
int y() const;

Expand Down
13 changes: 9 additions & 4 deletions src/lib/cimb_translator/CimbDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ bool CimbDecoder::load_tiles()
return true;
}

unsigned CimbDecoder::get_best_symbol(image_hash::ahash_result& results, unsigned& drift_offset, unsigned& best_distance) const
unsigned CimbDecoder::get_best_symbol(image_hash::ahash_result& results, unsigned& drift_offset, unsigned& best_distance, unsigned cooldown) const
{
drift_offset = 0;
unsigned best_fit = 0;
Expand All @@ -91,6 +91,11 @@ unsigned CimbDecoder::get_best_symbol(image_hash::ahash_result& results, unsigne
// 8, 0, 2, 6 == corners.
for (auto&& [drift_idx, h] : results)
{
// skip over this drift_idx if it matches cooldown
// we could be more clever to check for corners, but for now this is fine
// ~0U is "unset"
if (drift_idx == cooldown and drift_idx != 4) // don't skip the center, obvs
continue;
for (unsigned i = 0; i < _tileHashes.size(); ++i)
{
unsigned distance = image_hash::hamming_distance(h, _tileHashes[i]);
Expand All @@ -107,16 +112,16 @@ unsigned CimbDecoder::get_best_symbol(image_hash::ahash_result& results, unsigne
return best_fit;
}

unsigned CimbDecoder::decode_symbol(const cv::Mat& cell, unsigned& drift_offset, unsigned& best_distance) const
unsigned CimbDecoder::decode_symbol(const cv::Mat& cell, unsigned& drift_offset, unsigned& best_distance, unsigned cooldown) const
{
image_hash::ahash_result results = image_hash::fuzzy_ahash(cell, _ahashThreshold, image_hash::ahash_result::FAST);
return get_best_symbol(results, drift_offset, best_distance);
}

unsigned CimbDecoder::decode_symbol(const bitmatrix& cell, unsigned& drift_offset, unsigned& best_distance) const
unsigned CimbDecoder::decode_symbol(const bitmatrix& cell, unsigned& drift_offset, unsigned& best_distance, unsigned cooldown) const
{
image_hash::ahash_result results = image_hash::fuzzy_ahash(cell, image_hash::ahash_result::FAST);
return get_best_symbol(results, drift_offset, best_distance);
return get_best_symbol(results, drift_offset, best_distance, cooldown);
}

std::tuple<uchar,uchar,uchar> CimbDecoder::fix_color(std::tuple<float,float,float> c, float adjustUp, float down) const
Expand Down
6 changes: 3 additions & 3 deletions src/lib/cimb_translator/CimbDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ class CimbDecoder

void update_color_correction(cv::Matx<float, 3, 3>&& ccm);

unsigned get_best_symbol(image_hash::ahash_result& results, unsigned& drift_offset, unsigned& best_distance) const;
unsigned decode_symbol(const cv::Mat& cell, unsigned& drift_offset, unsigned& best_distance) const;
unsigned decode_symbol(const bitmatrix& cell, unsigned& drift_offset, unsigned& best_distance) const;
unsigned get_best_symbol(image_hash::ahash_result& results, unsigned& drift_offset, unsigned& best_distance, unsigned cooldown=~0U) const;
unsigned decode_symbol(const cv::Mat& cell, unsigned& drift_offset, unsigned& best_distance, unsigned cooldown=~0U) const;
unsigned decode_symbol(const bitmatrix& cell, unsigned& drift_offset, unsigned& best_distance, unsigned cooldown=~0U) const;

unsigned get_best_color(float r, float g, float b) const;
unsigned decode_color(const Cell& cell) const;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/cimb_translator/CimbReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,18 @@ unsigned CimbReader::read(PositionData& pos)
return 0;

// need coordinate, index, and drift from next position
auto [i, xy, drift] = _positions.next();
auto [i, xy, drift, cooldown] = _positions.next();
int x = xy.first + drift.x();
int y = xy.second + drift.y();
bitmatrix cell(_grayscale, _image.cols, _image.rows, x-1, y-1);

unsigned drift_offset = 0;
unsigned error_distance;
unsigned bits = _decoder.decode_symbol(cell, drift_offset, error_distance);
unsigned bits = _decoder.decode_symbol(cell, drift_offset, error_distance, cooldown);

std::pair<int, int> best_drift = CellDrift::driftPairs[drift_offset];
drift.updateDrift(best_drift.first, best_drift.second);
_positions.update(i, drift, error_distance);
_positions.update(i, drift, error_distance, CellDrift::calculate_cooldown(cooldown, drift_offset));

pos.i = i;
pos.x = x + best_drift.first;
Expand Down
14 changes: 7 additions & 7 deletions src/lib/cimb_translator/FloodDecodePositions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void FloodDecodePositions::reset()
for (unsigned i = 0; i < _positions.size(); ++i)
{
_remaining.push_back(true);
_instructions.push_back({CellDrift(), 0xFF});
_instructions.push_back({CellDrift(), 0xFF, 0xFF});
}

// seed
Expand Down Expand Up @@ -58,24 +58,24 @@ FloodDecodePositions::iter FloodDecodePositions::next()

needsDecode = false;
++_count;
auto [drift, __] = _instructions[i];
return {i, _positions[i], drift};
auto [drift, __, cooldown] = _instructions[i];
return {i, _positions[i], drift, cooldown};
}

return {0, {0, 0}, CellDrift()};
return {0, {0, 0}, CellDrift(), 0xFF};
}

int FloodDecodePositions::update(unsigned index, const CellDrift& drift, unsigned error_distance)
int FloodDecodePositions::update(unsigned index, const CellDrift& drift, unsigned error_distance, uint8_t cooldown)
{
std::array<int,4> adj = _cellFinder.find(index);
for (int next : adj)
{
if (next < 0 or !_remaining[next])
continue;
decode_instructions& di = _instructions[next];
if (di.second <= error_distance)
if (std::get<1>(di) <= error_distance)
continue;
di = {drift, error_distance};
di = {drift, error_distance, cooldown};
_heap.push({next, error_distance});
}
return 0;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/cimb_translator/FloodDecodePositions.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
class FloodDecodePositions
{
public:
using iter = std::tuple<unsigned, CellPositions::coordinate, CellDrift>;
using decode_instructions = std::pair<CellDrift, uint8_t>; // drift, best_prio
using iter = std::tuple<unsigned, CellPositions::coordinate, CellDrift, uint8_t>;
using decode_instructions = std::tuple<CellDrift, uint8_t, uint8_t>; // drift, best_prio, cooldown_pos
using decode_prio = std::tuple<uint16_t, uint8_t>; // index, prio

class PrioCompare
Expand All @@ -33,7 +33,7 @@ class FloodDecodePositions

bool done() const;
iter next();
int update(unsigned index, const CellDrift& drift, unsigned error_distance);
int update(unsigned index, const CellDrift& drift, unsigned error_distance, uint8_t cooldown);

protected:
unsigned _index;
Expand Down
19 changes: 10 additions & 9 deletions src/lib/cimb_translator/test/FloodDecodePositionsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ TEST_CASE( "FloodDecodePositionsTest/testSimple", "[unit]" )
unsigned i;
CellPositions::coordinate xy;
CellDrift drift;
uint8_t cooldown;

// validate seed points
unsigned count = 0;
for (int c = 0; c < 4; ++c)
{
// 0
std::tie(i, xy, drift) = cells.next();
std::tie(i, xy, drift, cooldown) = cells.next();
assertEquals(0, drift.x());
assertEquals(0, drift.y());

Expand All @@ -38,25 +39,25 @@ TEST_CASE( "FloodDecodePositionsTest/testSimple", "[unit]" )
assertEquals(62, xy.first);
assertEquals(8, xy.second);
drift.updateDrift(1, 1);
cells.update(i, drift, 1);
cells.update(i, drift, 1, cooldown);
}
else if (i == 99)
{
assertEquals(953, xy.first);
assertEquals(8, xy.second);
cells.update(i, drift, 2);
cells.update(i, drift, 2, cooldown);
}
else if (i == 12300)
{
assertEquals(62, xy.first);
assertEquals(1007, xy.second);
cells.update(i, drift, 2);
cells.update(i, drift, 2, cooldown);
}
else if (i == 12399)
{
assertEquals(953, xy.first);
assertEquals(1007, xy.second);
cells.update(i, drift, 2);
cells.update(i, drift, 2, cooldown);
}
else
FAIL("i ?= " << i);
Expand All @@ -68,7 +69,7 @@ TEST_CASE( "FloodDecodePositionsTest/testSimple", "[unit]" )
// we did "update(..., 1) for index=1. So the next cells should be the ones adjacent to 0: 1, 100.
for (int c = 0; c < 2; ++c)
{
std::tie(i, xy, drift) = cells.next();
std::tie(i, xy, drift, cooldown) = cells.next();
if (i == 1)
{
assertEquals(71, xy.first);
Expand All @@ -85,16 +86,16 @@ TEST_CASE( "FloodDecodePositionsTest/testSimple", "[unit]" )
assertEquals(1, drift.x());
assertEquals(1, drift.y());

cells.update(i, drift, 3);
cells.update(i, drift, 3, cooldown);
remainingPos.erase(i);
++count;
}

// as for the rest... we'll just make sure we hit them all
while (!cells.done())
{
std::tie(i, xy, drift) = cells.next();
cells.update(i, drift, 1);
std::tie(i, xy, drift, cooldown) = cells.next();
cells.update(i, drift, 1, cooldown);
remainingPos.erase(i);
++count;
}
Expand Down
6 changes: 3 additions & 3 deletions src/lib/image_hash/ahash_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ahash_result
// 5, 7, 3, 1 == sides.
// 8, 0, 2, 6 == corners.
// mode=FAST will discard the corner checks.
static constexpr std::array<int, 9> _ORDER = {4, 5, 7, 3, 1, 8, 0, 2, 6};
static constexpr std::array<unsigned, 9> _ORDER = {4, 5, 7, 3, 1, 8, 0, 2, 6};

public:
class iterator
Expand All @@ -31,9 +31,9 @@ class ahash_result
, _i(i)
{}

std::pair<int, uint64_t> operator*()
std::pair<unsigned, uint64_t> operator*()
{
int idx = _hr._ORDER[_i];
unsigned idx = _hr._ORDER[_i];
return {idx, _hr._results[idx]};
}

Expand Down

0 comments on commit 99e0f51

Please sign in to comment.