Skip to content

Commit

Permalink
Merge pull request #114 from sz3/encoder-skip-unextractable-frames
Browse files Browse the repository at this point in the history
Have the (cli) encoder skip unextractable frames
  • Loading branch information
sz3 authored Nov 26, 2024
2 parents 0799842 + 6b540f4 commit 9d4eb6c
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 19 deletions.
2 changes: 1 addition & 1 deletion package-wasm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mkdir build-wasm
cd build-wasm
emcmake cmake .. -DUSE_WASM=1 -DOPENCV_DIR=/usr/src/app/opencv4
make -j5 install
(cd ../web/ && tar -czvf cimbar.wasm.tar.gz cimbar_js.* index.html main.js)
(cd ../web/ && tar -czvf cimbar.wasm.tar.gz cimbar_js.js cimbar_js.wasm index.html main.js)

cd /usr/src/app
mkdir build-asmjs
Expand Down
1 change: 1 addition & 0 deletions src/exe/cimbar/cimbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ template <typename FilenameIterable>
int encode(const FilenameIterable& infiles, const std::string& outpath, int ecc, int color_bits, int compression_level, bool legacy_mode, bool no_fountain)
{
Encoder en(ecc, cimbar::Config::symbol_bits(), color_bits);
en.set_encode_id(109);
if (legacy_mode)
en.set_legacy_mode();
for (const string& f : infiles)
Expand Down
11 changes: 5 additions & 6 deletions src/lib/cimbar_js/cimbar_js.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,11 @@ int next_frame()
if (!_window or !_fes)
return 0;

// we generate 5x the amount of required symbol blocks -- unless everything fits in a single frame.
// color blocks will contribute to this total, but only symbols are used for the initial calculation.
// ... this way, if the color decode is failing, it won't get "stuck" failing to read a single frame.
unsigned required = _fes->blocks_required();
if (required > cimbar::Config::fountain_chunks_per_frame(cimbar::Config::symbol_bits(), _legacyMode))
required = required*5;
// we generate 8x the amount of required symbol blocks.
// this number is somewhat arbitrary, but needs to not be
// *too* low (1-2), or we risk long runs of blocks the decoder
// has already seen.
unsigned required = _fes->blocks_required() * 8;
if (_fes->block_count() > required)
{
_fes->restart();
Expand Down
16 changes: 16 additions & 0 deletions src/lib/encoder/Encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "SimpleEncoder.h"
#include "cimb_translator/Config.h"
#include "extractor/Scanner.h"
#include "serialize/format.h"

#include <opencv2/opencv.hpp>
Expand Down Expand Up @@ -55,12 +56,27 @@ inline unsigned Encoder::encode_fountain(const std::string& filename, const std:
requiredFrames = 1;

unsigned i = 0;
unsigned consecutiveScansFailed = 0;
while (i < requiredFrames)
{
auto frame = encode_next(*fes, canvas_size);
if (!frame)
break;

// some % of generated frames (for the current 8x8 impl)
// will produce random patterns that falsely match as
// corner "anchors" and fail to extract. So:
// if frame fails the scan, skip it.
if (!Scanner::will_it_scan(*frame))
{
if (++consecutiveScansFailed < 5)
continue;

// else, we gotta make forward progress. And it's probably a bug?
std::cerr << fmt::format("generated {} bad frames in a row. This really shouldn't happen, maybe report a bug. :(", consecutiveScansFailed) << std::endl;
}

consecutiveScansFailed = 0;
if (!on_frame(*frame, i))
break;
++i;
Expand Down
1 change: 1 addition & 0 deletions src/lib/encoder/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ add_test(encoder_test encoder_test)
target_link_libraries(encoder_test

cimb_translator
extractor

correct_static
wirehair
Expand Down
2 changes: 1 addition & 1 deletion src/lib/encoder/test/EncoderRoundTripTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ TEST_CASE( "EncoderRoundTripTest/testFountain.Pad", "[unit]" )
Encoder enc(30, 4, 2);
assertEquals( 1, enc.encode_fountain(inputFile, outPrefix) );

uint64_t hash = 0xeecc8800efce8c48;
uint64_t hash = 0xefcc8800efce8c48;
std::string path = fmt::format("{}_0.png", outPrefix);
cv::Mat encodedImg = cv::imread(path);
cv::cvtColor(encodedImg, encodedImg, cv::COLOR_BGR2RGB);
Expand Down
12 changes: 6 additions & 6 deletions src/lib/encoder/test/EncoderTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ TEST_CASE( "EncoderTest/testFountain.4c", "[unit]" )
enc.set_legacy_mode();
assertEquals( 3, enc.encode_fountain(inputFile, outPrefix, 0) );

std::vector<uint64_t> hashes = {0xbb1cc62b662abfe5, 0xf586f6466a5b194, 0x8c2f0f40e6ecb08b};
std::vector<uint64_t> hashes = {0xbb1cc62b662abfe5, 0xf586f6466a5b194, 0x93a3830d042966e1};
for (unsigned i = 0; i < hashes.size(); ++i)
{
DYNAMIC_SECTION( "are we correct? : " << i )
Expand Down Expand Up @@ -93,7 +93,7 @@ TEST_CASE( "EncoderTest/testFountain.Compress", "[unit]" )
Encoder enc(30, 4, 2);
assertEquals( 1, enc.encode_fountain(inputFile, outPrefix) );

uint64_t hash = 0xb36b65402eec434e;
uint64_t hash = 0xa66a666543280e8e;
std::string path = fmt::format("{}_0.png", outPrefix);
cv::Mat img = cv::imread(path);
assertEquals( hash, image_hash::average_hash(img) );
Expand Down Expand Up @@ -131,12 +131,12 @@ TEST_CASE( "EncoderTest/testFountain.Size", "[unit]" )
std::string outPrefix = tempdir.path() / "encoder.fountain";

Encoder enc(30, 4, 2);
assertEquals( 1, enc.encode_fountain(inputFile, outPrefix, 16, 1.6, 1080) );
assertEquals( 1, enc.encode_fountain(inputFile, outPrefix, 16, 1.6, 1024) );

uint64_t hash = 0xbdc232c714226fe6;
uint64_t hash = 0xa66a666543280e8e;
std::string path = fmt::format("{}_0.png", outPrefix);
cv::Mat img = cv::imread(path);
assertEquals( 1080, img.rows );
assertEquals( 1080, img.cols );
assertEquals( 1024, img.rows );
assertEquals( 1024, img.cols );
assertEquals( hash, image_hash::average_hash(img) );
}
35 changes: 30 additions & 5 deletions src/lib/extractor/Scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include "Anchor.h"
#include "Corners.h"
#include "Point.h"
#include "ScanState.h"

Expand All @@ -10,7 +11,6 @@
#include <iostream>
#include <vector>

class Corners;
class Midpoints;

class Scanner
Expand All @@ -33,6 +33,10 @@ class Scanner

static unsigned nextPowerOfTwoPlusOne(unsigned v); // helper

// external helper method
template <typename MAT>
static bool will_it_scan(const MAT& img);

// rest of public interface
std::vector<Anchor> scan();
std::vector<point<int>> scan_edges(const Corners& corners, Midpoints& mps) const;
Expand Down Expand Up @@ -98,6 +102,27 @@ inline unsigned Scanner::nextPowerOfTwoPlusOne(unsigned v)
return std::max(3U, v + 2);
}

template <typename MAT>
inline bool Scanner::will_it_scan(const MAT& unpadded_img)
{
Scanner scanner(unpadded_img);
std::vector<Anchor> points = scanner.scan();
if (points.size() < 4)
return false;

constexpr int limit = 50;
Corners corners(points);
if (corners.top_left().x() > limit or corners.top_left().y() > limit)
return false;
if (corners.top_right().x() < (unpadded_img.cols - limit) or corners.top_right().y() > limit)
return false;
if (corners.bottom_left().x() > limit or corners.bottom_left().y() < (unpadded_img.rows - limit))
return false;
if (corners.bottom_right().x() < (unpadded_img.cols - limit) or corners.bottom_right().y() < (unpadded_img.rows - limit))
return false;
return true;
}

template <typename MAT, typename MAT2>
inline void Scanner::threshold_fast(const MAT& img, MAT2& out)
{
Expand Down Expand Up @@ -141,10 +166,10 @@ inline void Scanner::preprocess_image(const MAT& img, MAT2& out, bool fast)

template <typename MAT>
inline Scanner::Scanner(const MAT& img, bool fast, bool dark, int skip)
: _dark(dark)
, _skip(skip? skip : std::min(img.rows, img.cols) / 60)
, _mergeCutoff(img.cols / 30)
, _anchorSize(30)
: _dark(dark)
, _skip(skip? skip : std::min(img.rows, img.cols) / 60)
, _mergeCutoff(img.cols / 30)
, _anchorSize(30)
{
_img = preprocess_image(img, fast);
}
Expand Down

0 comments on commit 9d4eb6c

Please sign in to comment.