Repository: sz3/libcimbar
File: src/lib/cimb_translator/CimbReader.cpp (C++)

Code before:
	cv::Mat kernel()
	{
		static const cv::Mat k = (cv::Mat_<float>(3,3) <<  -1, -1, -1, -1, 8.5, -1, -1, -1, -1);
		return k;
	}

	template <typename MAT>
	void sharpenSymbolGrid(const MAT& img, cv::Mat& out)
	{
		cv::filter2D(img, out, -1, kernel());
	}

	template <typename MAT>
	cv::Mat preprocessSymbolGrid(const MAT& img, bool needs_sharpen, bool needs_threshold)
	{
		cv::Mat symbols;
		if (needs_sharpen)
		{
			sharpenSymbolGrid(img, symbols);
			cv::cvtColor(symbols, symbols, cv::COLOR_BGR2GRAY);
		}
		else
			cv::cvtColor(img, symbols, cv::COLOR_BGR2GRAY);

		if (needs_threshold)
			cv::adaptiveThreshold(symbols, symbols, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 5, 0);
		return symbols;
	}
}

CimbReader::CimbReader(const cv::Mat& img, const CimbDecoder& decoder, bool needs_sharpen)
    : _image(img)
    , _cellSize(Config::cell_size() + 2)
    , _positions(Config::cell_spacing(), Config::num_cells(), Config::cell_size(), Config::corner_padding())
    , _decoder(decoder)
{
	_grayscale = preprocessSymbolGrid(img, needs_sharpen, decoder.expects_binary_threshold());
}

CimbReader::CimbReader(const cv::UMat& img, const CimbDecoder& decoder, bool needs_sharpen)
    : _image(img.getMat(cv::ACCESS_READ))
    , _cellSize(Config::cell_size() + 2)
    , _positions(Config::cell_spacing(), Config::num_cells(), Config::cell_size(), Config::corner_padding())
    , _decoder(decoder)
{
	_grayscale = preprocessSymbolGrid(img, needs_sharpen, decoder.expects_binary_threshold());
}

unsigned CimbReader::read(unsigned& bits)
{
	if (_positions.done())

Review comment (performance):
Have said this elsewhere, but one more time: these seem more or less interchangeable. It's probable that one performs better under some scenario, but I've yet to find that scenario. For now, I'm preferring the lower number for hypothetical performance reasons.

Code after:
	cv::Mat kernel()
	{
		static const cv::Mat k = (cv::Mat_<float>(3,3) <<  -1, -1, -1, -1, 8.5, -1, -1, -1, -1);
		return k;
	}

	template <typename MAT>
	void sharpenSymbolGrid(const MAT& img, cv::Mat& out)
	{
		cv::filter2D(img, out, -1, kernel());
	}

	template <typename MAT>
	cv::Mat preprocessSymbolGrid(const MAT& img, bool needs_sharpen, bool needs_threshold)
	{
		cv::Mat symbols;
		if (needs_sharpen)
		{
			sharpenSymbolGrid(img, symbols);
			cv::cvtColor(symbols, symbols, cv::COLOR_BGR2GRAY);
		}
		else
			cv::cvtColor(img, symbols, cv::COLOR_BGR2GRAY);

		if (needs_threshold)
			cv::adaptiveThreshold(symbols, symbols, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 3, 0);
		return symbols;
	}
}

CimbReader::CimbReader(const cv::Mat& img, const CimbDecoder& decoder, bool needs_sharpen)
    : _image(img)
    , _cellSize(Config::cell_size() + 2)
    , _positions(Config::cell_spacing(), Config::num_cells(), Config::cell_size(), Config::corner_padding())
    , _decoder(decoder)
{
	_grayscale = preprocessSymbolGrid(img, needs_sharpen, decoder.expects_binary_threshold());
}

CimbReader::CimbReader(const cv::UMat& img, const CimbDecoder& decoder, bool needs_sharpen)
    : _image(img.getMat(cv::ACCESS_READ))
    , _cellSize(Config::cell_size() + 2)
    , _positions(Config::cell_spacing(), Config::num_cells(), Config::cell_size(), Config::corner_padding())
    , _decoder(decoder)
{
	_grayscale = preprocessSymbolGrid(img, needs_sharpen, decoder.expects_binary_threshold());
}

unsigned CimbReader::read(unsigned& bits)
{
	if (_positions.done())