-
Notifications
You must be signed in to change notification settings - Fork 344
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Encoder improvements. 118 KB/s #54
Changes from all commits
0de861b
cb84a59
d869656
355ef7c
f6b6496
396939a
a2ffe08
87338c4
a49fe7f
c15ac29
6933d3e
21e39db
0626afc
f979012
4c5f826
5b86c29
a865dd4
e340559
48b2d1a
7247339
f8408b3
bf2c492
206c786
8e5fa90
fc04ea6
61fff8f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,22 +9,32 @@ | |
* There are 4 or 8 possible colors, encoding an additional 2-3 bits per tile. | ||
* These 6-7 bits per tile work out to a maximum of 9300-10850 bytes per barcode, though in practice this number is reduced by error correction. | ||
* The default ecc setting is 30/155, which is how we go from 9300 -> 7500 bytes of real data for a 4-color cimbar image. | ||
* Reed Solomon is not an ideal for this use case -- specifically, it corrects byte errors, and cimbar errors tend to involve 1-3 bits at a time. However, since Reed Solomon implementations are ubiquitous, I used it for this prototype. | ||
* Reed Solomon is not perfect for this use case -- specifically, it corrects byte errors, and cimbar errors tend to involve 1-3 bits at a time. However, since Reed Solomon implementations are ubiquitous, it is currently in use. | ||
|
||
## Current sustained benchmark | ||
|
||
* 4-color cimbar with ecc=30: | ||
* 2,980,556 bytes (after compression) in 36s -> 662 kilobits/s (~82 KB/s) | ||
* 4,717,525 bytes (after compression) in 45s -> 838 kilobits/s (~104 KB/s) | ||
|
||
* 8-color cimbar with ecc=30: | ||
* 2,980,556 bytes in 31s -> 769 kilobits/s (~96 KB/s) | ||
* 4,717,525 bytes in 40s -> 943 kilobits/s (~118 KB/s) | ||
|
||
* details: | ||
* these numbers are use https://github.com/sz3/cfc, running with 4 CPU threads on a Qualcomm Snapdragon 625 | ||
* cimbar has built-in compression using zstd. What's being measured here is bits over the wire, e.g. data after compression is applied. | ||
* these numbers are using https://github.com/sz3/cfc, running with 4 CPU threads on a Qualcomm Snapdragon 625 | ||
* perhaps I will buy a new cell phone to inflate the benchmark numbers. | ||
* the sender commandline is `./cimbar_send /path/to/file -s` | ||
* the `shakycam` option allows cfc to quickly discard ghosted frames, and spend more time decoding real data. | ||
* the sender is the cimbar.org wasm implementation. An equivalent command line is `./cimbar_send /path/to/file -s` | ||
* cimbar.org uses the `shakycam` option to allow the receiver to detect/discard "in between" frames as part of the scan step. This allows it to spend more processing time decoding real data. | ||
* burst rate can be higher (or lower) | ||
* to this end, lower ecc settings *can* provide better burst rates | ||
* 8-color cimbar is considerably more sensitive to lighting conditions. Notably, decoding has some issues with dim screens. | ||
* 4-color cimbar is currently preferred, and will give more consistent transfer speeds. | ||
* 8-color cimbar should be considered a prototype within a prototype. It is considerably more sensitive to lighting conditions and color tints. | ||
|
||
* other notes: | ||
* having better lighting in the frame often leads to better results -- this is why cimbar.org has a (mostly) white background. cfc uses android's auto-exposure, auto-focus, etc (it's a very simple app). Good ambient light -- or a white background -- can lead to more consitent quality frame capture. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Misc notes for how to achieve peak throughput. There may be other stuff, but this is what I know. |
||
* because of the lighting/exposure question, I usually "shoot" in landscape instead of portrait. | ||
* cfc currently has a low resolution, so the cimbar frame should take up as much of the display as possible (trust the guide brackets) | ||
* similarly, it's best to keep the camera angle straight-on -- instead of at an angle -- to decode the whole image successfully. Decodes should still happen at higher angles, but the "smaller" part of the image may have more errors than the ECC can deal with. | ||
* other things to be wary of: | ||
* glare from light sources. | ||
* shaky hands. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,18 +55,11 @@ int main(int argc, char** argv) | |
fps = defaultFps; | ||
unsigned delay = 1000 / fps; | ||
|
||
bool dark = true; | ||
bool use_rotatecam = result.count("rotatecam"); | ||
bool use_shakycam = result.count("shakycam"); | ||
int window_size = 1080; | ||
|
||
cimbar::shaky_cam cam(cimbar::Config::image_size(), 1080, 1080, dark); | ||
// if we don't need the shakycam, we'll just turn it off | ||
// we could use a separate code path (just do a mat copyTo), | ||
// but this is fine. | ||
if (!use_shakycam) | ||
cam.toggle(); | ||
|
||
cimbar::window w(cam.width(), cam.height(), "cimbar_send"); | ||
cimbar::window w(window_size, window_size, "cimbar_send"); | ||
if (!w.is_good()) | ||
{ | ||
std::cerr << "failed to create window :(" << std::endl; | ||
|
@@ -76,21 +69,22 @@ int main(int argc, char** argv) | |
bool running = true; | ||
bool start = true; | ||
|
||
auto draw = [&w, &cam, use_rotatecam, delay, &running, &start] (const cv::Mat& frame, unsigned) { | ||
auto draw = [&w, use_rotatecam, use_shakycam, delay, &running, &start] (const cv::Mat& frame, unsigned) { | ||
if (!start and w.should_close()) | ||
return running = false; | ||
start = false; | ||
|
||
cv::Mat& windowImg = cam.draw(frame); | ||
w.show(windowImg, delay); | ||
w.show(frame, delay); | ||
if (use_rotatecam) | ||
w.rotate(); | ||
if (use_shakycam) | ||
w.shake(); | ||
return true; | ||
}; | ||
|
||
Encoder en(ecc, cimbar::Config::symbol_bits(), colorBits); | ||
while (running) | ||
for (const string& f : infiles) | ||
en.encode_fountain(f, draw, compressionLevel); | ||
en.encode_fountain(f, draw, compressionLevel, 8.0, window_size); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I may go a different direction with this at some point. We're passing in the size here to embed the 1024x1024 image in a larger image -- which will then get passed to the cimbar::window (which won't have to worry about resizing it). This is somewhat silly -- the window should be able to render an image on a larger background. But you know what else is silly? Trying to get transpose and scaling to work in a GLSL shader without hitting weird half-pixel blurring issues. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4-color being over 100 KB/s is very nice.