Skip to content

Commit

Permalink
sample_rgb impl based on a "min_stack" idea.
Browse files Browse the repository at this point in the history
Will it perform? Who can say
  • Loading branch information
sz3 committed Dec 26, 2023
1 parent 05d5e38 commit 056df8e
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 2 deletions.
57 changes: 55 additions & 2 deletions src/lib/cimb_translator/Cell.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */
#pragma once

#include <opencv2/opencv.hpp>
#include "util/sampling_min_stack.h"

#include <opencv2/opencv.hpp>
#include <tuple>

class Cell
Expand All @@ -26,7 +27,59 @@ class Cell
, _rows(rows)
{}

// it would be nice to use a cropped cv::Mat to get the contiguous memory pointer...
std::tuple<uchar,uchar,uchar> sample_rgb_continuous(bool skip) const
{
/* cmovs everywhere?
* sum += foo
* sum_adj = foo < bar? foo : bar
* sum -= sum_adj
* ... etc, no branches, don't trust the compiler here
* */

sampling_min_stack<uint16_t> blue;
sampling_min_stack<uint16_t> green;
sampling_min_stack<uint16_t> red;
uint16_t count = 0;

int channels = _img.channels();
int index = (_ystart * _img.cols) + _xstart;
const uchar* p = _img.ptr<uchar>(0) + (index * channels);

int increment = 1 + skip;
int toNextCol = channels * (_img.rows - _rows);
if (skip)
toNextCol += channels * _img.rows;

for (int i = 0; i < _cols; i+=increment)
{
for (int j = 0; j < _rows; ++j, ++count)
{
red += p[0];
green += p[1];
blue += p[2];
p += channels;
}
p += toNextCol;
}

if (count <= 4)
return std::tuple<uchar,uchar,uchar>(0, 0, 0);

count -= 4;
return std::tuple<uchar,uchar,uchar>(red.total()/count, green.total()/count, blue.total()/count);
}

std::tuple<uchar,uchar,uchar> sample_rgb(bool skip=false) const
{
int channels = _img.channels();
if (channels < 3)
return std::tuple<uchar,uchar,uchar>(0, 0, 0);
if (_img.isContinuous() and _cols > 0)
return sample_rgb_continuous(skip);

return mean_rgb(skip);
}

std::tuple<uchar,uchar,uchar> mean_rgb_continuous(bool skip) const
{
uint16_t blue = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/lib/util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ set(SOURCES

add_library(util INTERFACE)

if(NOT DEFINED DISABLE_TESTS)
add_subdirectory(test)
endif()

63 changes: 63 additions & 0 deletions src/lib/util/sampling_min_stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include <array>
#include <cstdint>

template <typename Integer=uint16_t>
class sampling_min_stack
{
public:
sampling_min_stack()
: _vals{255, 255, 255, 255}
, _minSum(255*4)
, _totalSum(-_minSum)
{}

Integer min_sum() const
{
return _minSum;
}

Integer avg() const
{
return _minSum >> 2; // /4, the length of _vals
}

Integer total() const
{
return _totalSum;
}

// replace max in _vals with val. Returns previous max value.
// unconditional -- assumes val < avg(), or none of this makes sense
Integer push_pop(Integer replacement)
{
// get max idx
int8_t il = _vals[0] > _vals[1]? 0 : 1;
int8_t ir = _vals[2] > _vals[3]? 2 : 3;
int8_t i = _vals[il] > _vals[ir]? il : ir;

Integer res = _vals[i];
_vals[i] = replacement;
_minSum += replacement - res;
return res;
}

void add(Integer prospect)
{
if (prospect < avg())
prospect = push_pop(prospect);
_totalSum += prospect;
}

sampling_min_stack& operator+=(Integer prospect)
{
add(prospect);
return *this;
}

protected:
std::array<Integer, 4> _vals;
Integer _minSum;
Integer _totalSum;
};
22 changes: 22 additions & 0 deletions src/lib/util/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 2.6)

project(util_test)

set (SOURCES
test.cpp
sampling_min_stackTest.cpp
)

include_directories(
${libcimbar_SOURCE_DIR}/test
${libcimbar_SOURCE_DIR}/test/lib
${CMAKE_CURRENT_SOURCE_DIR}/..
)

add_executable (
util_test
${SOURCES}
)

add_test(util_test util_test)

29 changes: 29 additions & 0 deletions src/lib/util/test/sampling_min_stackTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */
#include "unittest.h"

#include "sampling_min_stack.h"

TEST_CASE( "sample_min_stackTest/testDefault", "[unit]" )
{
sampling_min_stack<uint16_t> blue;
assertEquals(255, blue.avg());

blue += 200;
blue += 200;
blue += 200;
blue += 200;
assertEquals(200, blue.avg());
assertEquals(0, blue.total());

blue += 100;
blue += 250;
blue += 100;
blue += 250;
assertEquals(900, blue.total());

blue += 220;
assertEquals(1120, blue.total());

blue += 60;
assertEquals(1320, blue.total());
}
4 changes: 4 additions & 0 deletions src/lib/util/test/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* This code is subject to the terms of the Mozilla Public License, v.2.0. http://mozilla.org/MPL/2.0/. */
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

0 comments on commit 056df8e

Please sign in to comment.