twain3/ImageProcess/ImageApplyBarCodeRecognitio...

355 lines
12 KiB
C++
Raw Normal View History

#include "ImageApplyBarCodeRecognition.h"
#ifndef _NOT_USE
#include <memory.h>
#include "zxing/BinaryBitmap.h"
#include "zxing/DecodeHints.h"
#include "zxing/common/GlobalHistogramBinarizer.h"
#include "zxing/LuminanceSource.h"
#include "zxing/MultiFormatReader.h"
#include "zxing/Result.h"
#include "zxing/multi/GenericMultipleBarcodeReader.h"
#include "zbar.h"
class ImageWrapper : public zxing::LuminanceSource
{
public:
ImageWrapper(const cv::Mat& sourceImage)
: LuminanceSource(sourceImage.cols, sourceImage.rows)
, m_image(sourceImage) {}
virtual ~ImageWrapper() = default;
// Callers take ownership of the returned memory and must call delete [] on it themselves.
zxing::ArrayRef<char> getRow(int y, zxing::ArrayRef<char> row) const
{
int width = getWidth();
if (row->size() != width)
row.reset(zxing::ArrayRef<char>(width));
for (int x = 0; x < width; ++x)
row[x] = m_image.at<char>(y, x);
return row;
}
zxing::ArrayRef<char> getMatrix() const
{
int width = m_image.cols;
int height = m_image.rows;
char* matrix = new char[width * height];
char* m = matrix;
for (int y = 0; y < height; ++y)
{
zxing::ArrayRef<char> tmpRow;
tmpRow = getRow(y, zxing::ArrayRef<char>(width));
#if __cplusplus > 199711L
memcpy(m, tmpRow->values().data(), width);
#else
memcpy(m, &tmpRow->values()[0], width);
#endif
m += width * sizeof(unsigned char);
//delete tmpRow;
}
zxing::ArrayRef<char> arr = zxing::ArrayRef<char>(matrix, width * height);
if (matrix) delete[] matrix;
return arr;
}
private:
cv::Mat m_image;
};
static std::string WstringToString(const std::wstring& wstr)
{
std::string str;
std::mbstate_t state = {};
const wchar_t* data = wstr.data();
size_t len = std::wcsrtombs(nullptr, &data, 0, &state);
if (static_cast<size_t>(-1) != len)
{
std::unique_ptr<char[]> buff(new char[len + 1]);
len = std::wcsrtombs(buff.get(), &data, len, &state);
if (static_cast<size_t>(-1) != len)
str.assign(buff.get(), len);
}
return str;
}
int CImageApplyBarCodeRecognition::recognize_ZXing(const cv::Mat& image, BarCodeInfo& result)
{
zxing::Ref<zxing::Result> res;
auto ciw = new ImageWrapper(image);
zxing::Ref<zxing::LuminanceSource> imageRef(ciw);
zxing::GlobalHistogramBinarizer* binz = new zxing::GlobalHistogramBinarizer(imageRef);
zxing::Ref< zxing::Binarizer > bz(binz);
zxing::BinaryBitmap* bb = new zxing::BinaryBitmap(bz);
zxing::Ref< zxing::BinaryBitmap > ref(bb);
zxing::MultiFormatReader decoder_;
try
{
res = decoder_.decode(ref, static_cast<zxing::DecodeHints>(static_cast<unsigned int>(
zxing::DecodeHints::QR_CODE_HINT |
zxing::DecodeHints::AZTEC_HINT |
zxing::DecodeHints::CODABAR_HINT |
zxing::DecodeHints::CODE_39_HINT |
zxing::DecodeHints::CODE_93_HINT |
zxing::DecodeHints::CODE_128_HINT |
zxing::DecodeHints::DATA_MATRIX_HINT |
zxing::DecodeHints::EAN_8_HINT |
zxing::DecodeHints::EAN_13_HINT |
zxing::DecodeHints::ITF_HINT |
zxing::DecodeHints::MAXICODE_HINT |
zxing::DecodeHints::PDF_417_HINT |
zxing::DecodeHints::QR_CODE_HINT |
zxing::DecodeHints::RSS_14_HINT |
zxing::DecodeHints::RSS_EXPANDED_HINT |
zxing::DecodeHints::UPC_A_HINT |
zxing::DecodeHints::UPC_E_HINT |
zxing::DecodeHints::UPC_EAN_EXTENSION_HINT)));
result.barCodeText = res->getText()->getText();
result.barCodeLength = result.barCodeText.length();
if (!result.barCodeText.empty())
{
result.barCodeType = -1;
switch (res->getBarcodeFormat())
{
case zxing::BarcodeFormat::NONE:
result.barCodeType = -1;
break;
case zxing::BarcodeFormat::AZTEC:
break;
case zxing::BarcodeFormat::CODABAR:
result.barCodeType = BarCodeType::CodaBar;
break;
case zxing::BarcodeFormat::CODE_39:
break;
case zxing::BarcodeFormat::CODE_93:
result.barCodeType = BarCodeType::Code93;
break;
case zxing::BarcodeFormat::CODE_128:
result.barCodeType = BarCodeType::Code128;
break;
case zxing::BarcodeFormat::DATA_MATRIX:
break;
case zxing::BarcodeFormat::EAN_8:
result.barCodeType = BarCodeType::Ean8;
break;
case zxing::BarcodeFormat::EAN_13:
result.barCodeType = BarCodeType::Ean13;
break;
case zxing::BarcodeFormat::ITF:
break;
case zxing::BarcodeFormat::MAXICODE:
result.barCodeType = BarCodeType::MaxiCode;
break;
case zxing::BarcodeFormat::PDF_417:
result.barCodeType = BarCodeType::Pdf417;
break;
case zxing::BarcodeFormat::QR_CODE:
result.barCodeType = BarCodeType::QrCode;
break;
case zxing::BarcodeFormat::RSS_14:
break;
case zxing::BarcodeFormat::RSS_EXPANDED:
break;
case zxing::BarcodeFormat::UPC_A:
break;
case zxing::BarcodeFormat::UPC_EAN_EXTENSION:
break;
default:
result.barCodeType = -1;
}
}
}
catch (zxing::Exception& e)
{
std::cout << e.what() << std::endl;
return -1;
}
return 0;
}
int CImageApplyBarCodeRecognition::recognize_Zbar(const cv::Mat& image, BarCodeInfo& result)
{
zbar::ImageScanner scanner;
zbar::Image img(image.cols, image.rows, "Y800", reinterpret_cast<void*>(image.data), image.total());
scanner.scan(img);
for (zbar::Image::SymbolIterator symbol = img.symbol_begin(); symbol != img.symbol_end(); ++symbol)
{
result.barCodeText = symbol->get_data();
result.barCodeLength = result.barCodeText.length();
if (!result.barCodeText.empty())
{
result.barCodeType = -1;
switch (symbol->get_type())
{
case zbar::zbar_symbol_type_t::ZBAR_NONE:
result.barCodeType = -1;
break;
case zbar::zbar_symbol_type_t::ZBAR_PARTIAL:
break;
case zbar::zbar_symbol_type_t::ZBAR_EAN8:
result.barCodeType = BarCodeType::Ean8;
break;
case zbar::zbar_symbol_type_t::ZBAR_UPCE:
break;
case zbar::zbar_symbol_type_t::ZBAR_ISBN10:
break;
case zbar::zbar_symbol_type_t::ZBAR_UPCA:
break;
case zbar::zbar_symbol_type_t::ZBAR_EAN13:
result.barCodeType = BarCodeType::Ean13;
break;
case zbar::zbar_symbol_type_t::ZBAR_ISBN13:
break;
case zbar::zbar_symbol_type_t::ZBAR_I25:
break;
case zbar::zbar_symbol_type_t::ZBAR_CODE39:
break;
case zbar::zbar_symbol_type_t::ZBAR_PDF417:
result.barCodeType = BarCodeType::Pdf417;
break;
case zbar::zbar_symbol_type_t::ZBAR_QRCODE:
result.barCodeType = BarCodeType::QrCode;
break;
case zbar::zbar_symbol_type_t::ZBAR_CODE128:
result.barCodeType = BarCodeType::Code128;
break;
case zbar::zbar_symbol_type_t::ZBAR_SYMBOL:
break;
case zbar::zbar_symbol_type_t::ZBAR_ADDON2:
break;
case zbar::zbar_symbol_type_t::ZBAR_ADDON5:
break;
case zbar::zbar_symbol_type_t::ZBAR_ADDON:
break;
default:
result.barCodeType = -1;
}
}
break;
}
return 0;
}
void CImageApplyBarCodeRecognition::decode(cv::Mat& image, CImageApplyBarCodeRecognition::BarCodeInfo& result)
{
if (image.empty()) return;
cv::Mat temp;
if (image.channels() == 3)
{
cv::cvtColor(image, temp, cv::COLOR_BGR2GRAY);
cv::threshold(temp, temp, 127, 255, cv::THRESH_OTSU);
}
else
cv::threshold(image, temp, 127, 255, cv::THRESH_OTSU);
//cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(m_direction == Direction::Horizontal ? 1 : 5, m_direction == Direction::Horizontal ? 5 : 1));
//cv::morphologyEx(temp, temp, cv::MORPH_ERODE, element);
recognize_Zbar(temp, result);
if (result.barCodeText.empty())
recognize_ZXing(temp, result);
}
CImageApplyBarCodeRecognition::CImageApplyBarCodeRecognition()
: m_mode(RecognizeMode::Single)
, m_direction(Direction::Horizontal)
{
}
CImageApplyBarCodeRecognition::CImageApplyBarCodeRecognition(RecognizeMode mode, Direction dir)
: m_mode(mode)
, m_direction(dir)
{
}
CImageApplyBarCodeRecognition::~CImageApplyBarCodeRecognition()
{
}
void CImageApplyBarCodeRecognition::apply(cv::Mat& pDib, int side)
{
(void)side;
m_result = BarCodeInfo();
cv::Mat temp = pDib.clone();
decode(temp, m_result);
if (!m_result.barCodeText.empty()) return;
cv::transpose(pDib, temp);
cv::flip(temp, temp, 0);
decode(temp, m_result);
if (!m_result.barCodeText.empty()) return;
cv::flip(pDib, temp, 0);
cv::flip(temp, temp, 1);
decode(temp, m_result);
if (!m_result.barCodeText.empty()) return;
cv::transpose(pDib, temp);
cv::flip(temp, temp, 1);
decode(temp, m_result);
}
void findContours1(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
{
CvMat c_image = cvMat(src);
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, cvPoint(offset));
if (!_ccontours)
{
contours.clear();
return;
}
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
size_t total = all_contours.size();
contours.resize(total);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
int count = c->total;
int* data = new int[static_cast<size_t>(count * 2)];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
{
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
}
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
}
storage.release();
}
#endif //_NOT_USE