twain3测试版本,代码问题暂未处理

This commit is contained in:
masayume 2021-10-20 19:54:29 +08:00
parent 26bb7a7156
commit 2d07d227a9
782 changed files with 464038 additions and 0 deletions

31
CMakeLists.txt Normal file
View File

@ -0,0 +1,31 @@
# CMake
cmake_minimum_required (VERSION 2.8)
# VCPKG_ROOT
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
message($ENV{PATH})
if(WIN32)
if(${CMAKE_GENERATOR_PLATFORM} STREQUAL "x64")
set(platform x64)
else()
set(platform x86)
endif()
# VCPKG_ROOT
set(CMAKE_TOOLCHAIN_FILE "$ENV{Vcpkg_BuildSystemPath}/vcpkg.cmake")
set(VCPKG_TARGET_TRIPLET "${platform}-windows-static-md")
message(${VCPKG_TARGET_TRIPLET})
endif()
#
project(huagaotwain)
add_subdirectory(huagao)
add_subdirectory(device)
add_subdirectory(ImageProcess)
add_subdirectory(gpdf)
add_subdirectory(Tirdparty)
add_subdirectory(ui)

22
ImageProcess/.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
################################################################################
# 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
################################################################################
/.vs
/opencv
/imageprocess.pro.user
/debug
/release
/Win32/Debug
/.qmake.stash
/Makefile.Release
/Makefile.Debug
/Makefile
/imageprocess.vcxproj.filters
/imageprocess.vcxproj
/imageprocess.sln
/ImageMatQueue.cpp
/ImageMatQueue.h
/gpdf
/ImageApplyColorCorrect.cpp.autosave
/imageprocess.vcxproj.user

View File

@ -0,0 +1,12 @@
project(gimgproc)
file(GLOB IMGPROC_HEADS ${PROJECT_SOURCE_DIR}/*.h)
aux_source_directory(${PROJECT_SOURCE_DIR} IMGPROC_SRCS)
find_package(OpenCV)
add_library(${PROJECT_NAME} ${IMGPROC_SRCS} ${IMGPROC_HEADS})
target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS)
target_include_directories(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/Tirdparty/3rdparty/nick)
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCV_LIBS} gpdf hg::zxing hg::zbar)

10
ImageProcess/IMulti.cpp Normal file
View File

@ -0,0 +1,10 @@
#include "IMulti.h"
IMulti::IMulti(void)
{
}
IMulti::~IMulti(void)
{
}

12
ImageProcess/IMulti.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#include <opencv2/opencv.hpp>
#include <vector>
#include "imgprocdefs.h"
class IMulti
{
public:
IMulti(void);
virtual ~IMulti(void);
virtual std::vector<cv::Mat> apply(cv::Mat& pDib) = 0;
};

View File

@ -0,0 +1,9 @@
#include "ImageApply.h"
CImageApply::CImageApply(void)
{
}
CImageApply::~CImageApply(void)
{
}

27
ImageProcess/ImageApply.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef IMAGE_APPLY_H
#define IMAGE_APPLY_H
//#define LOG
#include <vector>
#include <memory>
#include <opencv2/opencv.hpp>
#if defined(LOG)
#include "Device/filetools.h"
#endif
class CImageApply
{
public:
CImageApply(void);
virtual ~CImageApply(void);
virtual void apply(cv::Mat& pDib,int side) = 0;
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide) = 0;
};
typedef std::shared_ptr<CImageApply> ImageApplyPtr;
#endif //!IMAGE_APPLY_H

View File

@ -0,0 +1,90 @@
#include "ImageApplyAdjustColors.h"
CImageApplyAdjustColors::CImageApplyAdjustColors(void)
: m_brightness(0)
, m_contrast(0)
, m_gamma(1.0f)
, lut(1, 256, CV_8UC1)
{
update_lutData();
}
CImageApplyAdjustColors::CImageApplyAdjustColors(int brightness, int contrast, float gamma)
: lut(1, 256, CV_8UC1)
{
setAdjustColors(brightness, contrast, gamma);
}
CImageApplyAdjustColors::~CImageApplyAdjustColors(void)
{
}
void CImageApplyAdjustColors::apply(cv::Mat& pDib,int side)
{
(void)side;
if (pDib.empty()) return;
if (m_brightness != 0 || m_contrast != 0 || m_gamma < 0.999999f || m_gamma > 1.000001f)
cv::LUT(pDib, lut, pDib);
}
void CImageApplyAdjustColors::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if(!var.empty())
apply(var, 0);
i++;
}
}
void CImageApplyAdjustColors::setAdjustColors(int brightness, int contrast, float gamma)
{
m_brightness = cv::max(-255, cv::min(brightness, 255));
m_contrast = cv::max(-127, cv::min(contrast, 127));
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
update_lutData();
}
void CImageApplyAdjustColors::setBrightness(int brightness)
{
m_brightness = cv::max(-255, cv::min(brightness, 255));
update_lutData();
}
void CImageApplyAdjustColors::setContrast(int contrast)
{
m_contrast = cv::max(-127, cv::min(contrast, 127));
update_lutData();
}
void CImageApplyAdjustColors::setGamma(float gamma)
{
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
update_lutData();
}
void CImageApplyAdjustColors::update_lutData()
{
unsigned char* ptr = lut.data;
uchar buffer[256];
for (int i = 0; i < 256; i++)
{
//update brightness
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i + m_brightness, 255)));
//update contrast
if (ptr[i] < 128)
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(ptr[i] - m_contrast, 127)));
else
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(ptr[i] + m_contrast, 255)));
}
float g = 1.0f / m_gamma;
for (int i = 0; i < 256; i++)
ptr[i] = static_cast<unsigned char>(cv::min(255, static_cast<int>(cv::pow(static_cast<float>(ptr[i]) / 255.0f, g) * 255.0f + 0.5f)));
}

View File

@ -0,0 +1,53 @@
#ifndef IMAGE_APPLY_ADJUST_COLOR_H
#define IMAGE_APPLY_ADJUST_COLOR_H
#include "ImageApply.h"
class CImageApplyAdjustColors : public CImageApply
{
public:
CImageApplyAdjustColors(void);
/*
* brightness [in]: [-255, 255]
* constrast [in]: [-128 127]
* gamma [in]: [0.1, 5.0]
*/
CImageApplyAdjustColors(int brightness, int contrast, float gamma);
virtual ~CImageApplyAdjustColors(void);
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
void setAdjustColors(int brightness, int contrast, float gamma);
int getContrast() { return m_contrast; }
int getBrightness() { return m_brightness; }
double getGamma() { return m_gamma; }
void setBrightness(int brightness);
void setContrast(int contrast);
void setGamma(float gamma);
private:
void update_lutData();
private:
int m_brightness;
int m_contrast;
float m_gamma;
cv::Mat lut;
};
#endif // !IMAGE_APPLY_ADJUST_COLOR_H

View File

@ -0,0 +1,43 @@
#include "ImageApplyAutoContrast.h"
#include <vector>
using namespace std;
using namespace cv;
CImageApplyAutoContrast::CImageApplyAutoContrast()
{
}
CImageApplyAutoContrast::~CImageApplyAutoContrast()
{
}
void CImageApplyAutoContrast::apply(cv::Mat& pDib, int side)
{
(void)side;
if (pDib.empty()) return;
if(pDib.channels() == 1)
cv::equalizeHist(pDib,pDib);
else
{
std::vector<cv::Mat> mats(3);
cv::split(pDib,mats);
for(size_t i = 0; i < mats.size(); i++)
if(!mats[i].empty())
cv::equalizeHist(mats[i], mats[i]);
cv::merge(mats,pDib);
}
}
void CImageApplyAutoContrast::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,32 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_AUTO_CONTRAST_H
#define IMAGE_APPLY_AUTO_CONTRAST_H
#include "ImageApply.h"
class CImageApplyAutoContrast : public CImageApply
{
public:
CImageApplyAutoContrast();
virtual ~CImageApplyAutoContrast();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
};
#endif // !IMAGE_APPLY_AUTO_CONTRAST_H

View File

@ -0,0 +1,229 @@
#include "ImageApplyAutoCrop.h"
#include "ImageProcess_Public.h"
CImageApplyAutoCrop::CImageApplyAutoCrop()
: m_isCrop(false)
, m_isDesaskew(false)
, m_isFillBlank(false)
, m_isConvexHull(true)
, m_isFillColor(false)
, m_threshold(40)
, m_noise(2)
, m_indent(5)
{
}
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, double threshold, int noise, int indent)
: m_isCrop(isCrop)
, m_isDesaskew(isDesaskew)
, m_isFillBlank(isFillBlank)
, m_isConvexHull(isConvex)
, m_isFillColor(isFillColor)
, m_threshold(threshold)
, m_noise(noise)
, m_indent(indent)
, m_fixedSize(fixedSize)
{
}
CImageApplyAutoCrop::~CImageApplyAutoCrop()
{
}
void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
{
(void)side;
if (pDib.empty()) return;
if (!m_isCrop && !m_isDesaskew && !m_isFillBlank && m_fixedSize.empty()) return;
cv::Mat src = pDib;
cv::Mat thre;
cv::Mat dst;
hg::threshold_Mat(src, thre, m_threshold);
if (m_noise > 0)
{
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_noise, m_noise));
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element);
}
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> contours;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
m_maxContour = hg::getMaxContour(contours, hierarchy);
if (m_maxContour.size() == 0)
{
thre.release();
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
#endif // LOG
return;
}
thre.release();
dst.release();
cv::RotatedRect rect = hg::getBoundingRect(m_maxContour);
cv::Rect boudingRect = cv::boundingRect(m_maxContour);
boudingRect.x -= 1;
boudingRect.y -= 1;
boudingRect.width += 2;
boudingRect.height += 2;
if (m_isDesaskew && rect.angle != 0)
{
cv::Point2f srcTri[4];
cv::Point2f dstTri[3];
rect.points(srcTri);
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
dstTri[1] = cv::Point2f(0, 0);
dstTri[2] = cv::Point2f(rect.size.width - 1, 0);
cv::Mat warp_mat;
warp_mat = cv::getAffineTransform(srcTri, dstTri);
//cv::warpAffine(src, dst, warp_mat, rect.size,cv::INTER_LANCZOS4);
cv::warpAffine(src, dst, warp_mat, rect.size);
}
else
dst = src(boudingRect & cv::Rect(0, 0, src.cols, src.rows));
m_maxContour.clear();
m_maxContour.push_back(cv::Point(-1, dst.rows));
m_maxContour.push_back(cv::Point(-1, -1));
m_maxContour.push_back(cv::Point(dst.cols, -1));
m_maxContour.push_back(cv::Point(dst.cols, dst.rows));
if (m_isFillBlank)
{
cv::Mat thre_dst;
hg::threshold_Mat(dst, thre_dst, m_threshold);
if (m_indent > 0)
{
std::vector<cv::Point> rectEdge{ cv::Point(0, 0) ,cv::Point(thre_dst.cols - 1, 0),
cv::Point(thre_dst.cols - 1, thre_dst.rows - 1), cv::Point(0, thre_dst.rows - 1) };
std::vector<std::vector<cv::Point>> rectEdges{ rectEdge };
cv::drawContours(thre_dst, rectEdges, 0, cv::Scalar::all(0));
cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(m_indent, m_indent));
cv::erode(thre_dst, thre_dst, element, cv::Point(-1, -1), 1);
}
hierarchy.clear();
contours.clear();
m_maxContour.clear();
hg::findContours(thre_dst, contours, hierarchy, cv::RETR_EXTERNAL);
if (m_isConvexHull)
{
m_maxContour = hg::getMaxContour(contours, hierarchy);
hg::convexHull(m_maxContour, m_maxContour);
contours.clear();
contours.push_back(m_maxContour);
}
contours.push_back(std::vector<cv::Point>());
contours[contours.size() - 1].push_back(cv::Point(-1, dst.rows - 1));
contours[contours.size() - 1].push_back(cv::Point(-1, -1));
contours[contours.size() - 1].push_back(cv::Point(dst.cols, -1));
contours[contours.size() - 1].push_back(cv::Point(dst.cols, dst.rows));
hg::fillPolys(dst, contours, m_isFillColor ? getBackGroudColor(pDib, rect.size.area()) : cv::Scalar(255, 255, 255));
}
pDib.release();
if (/*(m_isCrop && side == 0) || (side == 1 && m_fixedSize.width * m_fixedSize.height == 0)*/ m_isCrop)
pDib = dst.clone();
else
{
pDib = cv::Mat(m_fixedSize, dst.type(), m_isFillBlank ? cv::Scalar(255, 255, 255) : cv::Scalar(0, 0, 0));
cv::Rect roi;
roi.x = dst.cols > pDib.cols ? (dst.cols - pDib.cols) / 2 : 0;
roi.width = cv::min(pDib.cols, dst.cols);
roi.y = dst.rows > pDib.rows ? (dst.rows - pDib.rows) / 2 : 0;
roi.height = cv::min(pDib.rows, dst.rows);
cv::Rect rect((pDib.cols - roi.width) / 2, (pDib.rows - roi.height) / 2, roi.width, roi.height);
for (cv::Point& p : m_maxContour)
p += roi.tl();
dst(roi).copyTo(pDib(rect));
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply8");
#endif // LOG
}
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
if (mats.empty()) return;
if (!mats[0].empty()) {
apply(mats[0], 0);
}
if (isTwoSide && mats.size() > 1)
{
cv::Size dSize = m_fixedSize;
if (!mats[0].empty())
m_fixedSize = mats[0].size();
if (!mats[1].empty()) {
apply(mats[1], 1);
}
if (!mats[0].empty())
m_fixedSize = dSize;
}
}
cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int total)
{
if (image.channels() == 3)
{
cv::Mat image_bgr[3];
cv::split(image, image_bgr);
uchar bgr[3];
for (size_t i = 0; i < 3; i++)
bgr[i] = getBackGroudChannelMean(image_bgr[i], total);
return cv::Scalar(bgr[0], bgr[1], bgr[2]);
}
else
return cv::Scalar::all(getBackGroudChannelMean(image, total));
}
uchar CImageApplyAutoCrop::getBackGroudChannelMean(const cv::Mat& gray, int total)
{
cv::Mat image_clone;
cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25);
int threnshold = total / 32;
int channels[] = { 0 };
int nHistSize[] = { 256 };
float range[] = { 0, 256 };
const float* fHistRanges[] = { range };
cv::Mat hist;
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false);
int hist_array[256];
for (int i = 0; i < 256; i++)
hist_array[i] = hist.at<float>(i, 0);
int length = 1;
const int length_max = 255 - m_threshold;
while (length < length_max)
{
for (size_t i = m_threshold + 1; i < 256 - length; i++)
{
int count = 0;
uint pixSum = 0;
for (size_t j = 0; j < length; j++)
{
count += hist_array[j + i];
pixSum += hist_array[j + i] * (i + j);
}
if (count >= threnshold)
return pixSum / count;
}
length++;
}
return 255;
}

View File

@ -0,0 +1,83 @@
#ifndef IMAGE_APPLY_AUTO_CROP_H
#define IMAGE_APPLY_AUTO_CROP_H
#include "ImageApply.h"
class CImageApplyAutoCrop : public CImageApply
{
public:
CImageApplyAutoCrop();
/*
* isCrop [in]:使true自动裁剪false为固定裁剪
* isDesaskew [in]:使true自动纠偏false为不纠偏
* isFillBlank [in]:使true为填充false为不填充
* fixedSize [in]:isCrop为false时生效fixedSize大小输出
* isConvex [in]:,true为凸多边形填充false为凹多边形填充true
* isFillColor [in]:false为白色填充true为自适应文稿底色填充false
* threshold [in]:(0, 255)40
* noise [in]:noise宽度的背景竖条纹干扰40
* indent [in]:indent像素5
*/
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, bool isFillColor = false, double threshold = 40, int noise = 40, int indent = 5);
virtual ~CImageApplyAutoCrop();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
bool isAutoCrop() { return m_isCrop; }
bool isFillBlank() { return m_isFillBlank; }
bool isDesaskew() { return m_isDesaskew; }
bool isConvexHull() { return m_isConvexHull; }
double threshold() { return m_threshold; }
int noise() { return m_noise; }
int indent() { return m_indent; }
cv::Size fixedSize() { return m_fixedSize; }
const std::vector<cv::Point>& maxContour() { return m_maxContour; }
void setAutoCrop(bool enabled) { m_isCrop = enabled; }
void setFillBlank(bool enabled) { m_isFillBlank = enabled; }
void setDesaskew(bool enabled) { m_isDesaskew = enabled; }
void setConvexHull(bool convex) { m_isConvexHull = convex; }
void setThreshold(double value) { m_threshold = value; }
void setNoise(int value) { m_noise = value; }
void setIndent(int value) { m_indent = value; }
void setFixedSize(cv::Size size) { m_fixedSize = size; }
private:
cv::Scalar getBackGroudColor(const cv::Mat& image, int total);
uchar getBackGroudChannelMean(const cv::Mat& gray, int total);
private:
bool m_isCrop;
bool m_isDesaskew;
bool m_isFillBlank;
bool m_isConvexHull;
bool m_isFillColor;
double m_threshold;
int m_noise;
int m_indent;
cv::Size m_fixedSize;
std::vector<cv::Point> m_maxContour;
};
#endif // !IMAGE_APPLY_AUTO_CROP_H

View File

@ -0,0 +1,164 @@
#include "ImageApplyBWBinaray.h"
CImageApplyBWBinaray::CImageApplyBWBinaray(ThresholdType type, int threshold, int blockSize, int constant)
: m_threshold(threshold)
, m_type(type)
, m_blockSize(blockSize)
, m_constant(constant)
, m_table(new uchar[256])
{
memset(m_table, 255, 256);
memset(m_table, 0, static_cast<size_t>(m_threshold));
}
CImageApplyBWBinaray::CImageApplyBWBinaray()
: m_threshold(120)
, m_type(ThresholdType::THRESH_BINARY)
, m_blockSize(25)
, m_constant(5)
, m_table(new uchar[256])
{
memset(m_table, 255, 256);
memset(m_table, 0, static_cast<size_t>(m_threshold));
}
CImageApplyBWBinaray::~CImageApplyBWBinaray(void)
{
delete[] m_table;
}
void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side)
{
(void)side;
if (pDib.empty()) return;
if (pDib.channels() == 3)
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
//20.12.29 修改参数为51 10 30 235
//20.12.30 修改参数为51 20 30 235
// 修改参数为17 20 110 235
cv::Mat integ;
int blockSize = 17;//邻域尺寸
int threshold = 20;
int low = 110;
int up = 235;
int halfSize = blockSize / 2;
int square_blockSize = blockSize * blockSize;
switch (m_type)
{
case ThresholdType::THRESH_BINARY:
cv::integral(pDib, integ, CV_32S);
for (int j = halfSize; j < integ.rows - halfSize - 1; j++)
{
uchar* data = pDib.ptr<uchar>(j);
int* idata1 = integ.ptr<int>(j - halfSize);
int* idata2 = integ.ptr<int>(j + halfSize + 1);
for (int i = halfSize; i < integ.cols - halfSize - 1; i++)
{
if (data[i] < low)
data[i] = 0;
else if (data[i] > up)
data[i] = 255;
else
data[i] = data[i] < ((idata2[i + halfSize + 1] - idata2[i - halfSize] - idata1[i + halfSize + 1] + idata1[i - halfSize]) / square_blockSize - threshold) ? 0 : 255;
}
}
cv::threshold(pDib(cv::Rect(0, 0, halfSize, pDib.rows)), pDib(cv::Rect(0, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY);
cv::threshold(pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), pDib(cv::Rect(pDib.cols - halfSize, 0, halfSize, pDib.rows)), m_threshold, 255, cv::THRESH_BINARY);
cv::threshold(pDib(cv::Rect(0, 0, pDib.cols, halfSize)), pDib(cv::Rect(0, 0, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY);
cv::threshold(pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), pDib(cv::Rect(0, pDib.rows - halfSize, pDib.cols, halfSize)), m_threshold, 255, cv::THRESH_BINARY);
break;
case ThresholdType::THRESH_OTSU:
cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU);
break;
case ThresholdType::ADAPTIVE_GAUSSIAN:
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
break;
case ThresholdType::ADAPTIVE_MEAN:
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
break;
case ThresholdType::ERROR_DIFFUSION:
errorDiffuse(pDib);
break;
default:
break;
}
}
void CImageApplyBWBinaray::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}
void CImageApplyBWBinaray::errorDiffuse(cv::Mat& image)
{
if (image.rows < 3 || image.cols < 3)
{
cv::threshold(image, image, m_threshold, 255, CV_THRESH_BINARY);
return;
}
cv::Mat dst;
image.convertTo(dst, CV_16S);
size_t rows = static_cast<size_t>(image.rows) - 1;
size_t cols = static_cast<size_t>(image.cols) - 1;
short** pixels_dst = new short* [static_cast<size_t>(image.rows)];
for (int i = 0; i < image.rows; i++)
pixels_dst[i] = reinterpret_cast<short*>(dst.data + i * static_cast<int>(dst.step));
short error;
for (size_t y = 0; y < rows; y++)
for (size_t x = 1; x < cols; x++)
{
short dstPix = pixels_dst[y][x];
if (dstPix >= m_threshold)
{
pixels_dst[y][x] = 255;
error = dstPix - 255;
}
else
{
pixels_dst[y][x] = 0;
error = dstPix;
}
pixels_dst[y][x + 1] += error * 1 / 16;
pixels_dst[y + 1][x - 1] += error * 1 / 16;
pixels_dst[y + 1][x] += error * 1 / 16;
pixels_dst[y + 1][x + 1] += error * 1 / 16;
}
image.release();
dst.convertTo(image, CV_8U);
rows++;
uchar* ptr = image.data;
size_t step = image.step;
size_t offset;
for (size_t y = 0; y < rows; y++)
{
offset = y * step;
ptr[offset] = m_table[ptr[offset]];
offset += cols;
ptr[offset] = m_table[ptr[offset]];
}
cols++;
ptr = image.data + step * (rows - 1);
for (size_t x = 0; x < cols; x++)
ptr[x] = m_table[ptr[x]];
delete[] pixels_dst;
}

View File

@ -0,0 +1,86 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/5/28 v1.1
2020/5/29 v1.2
2020/6/19 v1.3
2020/12/21 v1.3.1
2020/12/21 v1.3.2 blockSize,5125
* v1.3.2
* ====================================================
*/
#ifndef IMAGE_APPLY_BW_BINARAY_H
#define IMAGE_APPLY_BW_BINARAY_H
#include "ImageApply.h"
class CImageApplyBWBinaray:public CImageApply
{
public:
enum class ThresholdType
{
THRESH_BINARY = 0, //传统二值化
THRESH_OTSU, //大津阈值
ADAPTIVE_GAUSSIAN, //高斯局部自适应阈值
ADAPTIVE_MEAN, //均值局部自适应阈值
ERROR_DIFFUSION //错误扩散
};
/*
* type [in]:
* threshold [in]:THRESH_OTSU时无效
* blockSize [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效
* constant [in]:ADAPTIVE_GAUSSIAN和ADAPTIVE_MEAN模式有效blockSize形成比例关系
*/
CImageApplyBWBinaray(ThresholdType type, int threshold = 120, int blockSize = 25, int constant = 5);
CImageApplyBWBinaray();
virtual ~CImageApplyBWBinaray(void);
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
double getThreshold() { return m_threshold; }
ThresholdType getThresholdType() { return m_type; }
int getBlockSize() { return m_blockSize; }
double getConstant() { return m_constant; }
void setThreshold(double value) { m_threshold = value; }
void setThresholdType(ThresholdType type) { m_type = type; }
void setBlockSize(int value) { m_blockSize = value; }
void setConstant(double value) { m_constant = value; }
private:
void errorDiffuse(cv::Mat& image);
private:
double m_threshold;
ThresholdType m_type;
int m_blockSize;
double m_constant;
uchar* m_table;
};
#endif //!IMAGE_APPLY_BW_BINARAY_H

View File

@ -0,0 +1,355 @@
#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

View File

@ -0,0 +1,84 @@
#ifndef IMAGE_APPLY_BAR_CODE_RECOGNITION_H
#define IMAGE_APPLY_BAR_CODE_RECOGNITION_H
#include "ImageApply.h"
class CImageApplyBarCodeRecognition : public CImageApply
{
public:
enum class RecognizeMode
{
Single = 0,
Multi
};
enum class Direction
{
Horizontal,
Vertical
};
enum BarCodeType
{
ThreeOfNine = 0,
ThreeOfFiveInterleaved = 1,
ThreeOfFiveNonInterleaved = 2,
Code93 = 3,
Code128 = 4,
Ucc128 = 5,
CodaBar = 6,
Upca = 7,
Upce = 8,
Ean8 = 9,
Ean13 = 10,
Postnet = 11,
Pdf417 = 12,
TwoOfFiveIndustrial = 13,
TwoOfFiveMatrix = 14,
TwoOfFiveDatalogic = 15,
TwoOfFiveIata = 16,
ThreeOfNineFullAscii = 17,
CodaBarWithStartStop = 18,
MaxiCode = 19,
QrCode = 20
};
typedef struct BarCode_Info
{
int barCodeType;
int barCodeLength;
std::string barCodeText;
int barCodeX;
int barCodeY;
int barCodeRotation;
int barCdeConfidence;
}BarCodeInfo;
public:
CImageApplyBarCodeRecognition();
CImageApplyBarCodeRecognition(RecognizeMode mode, Direction dir);
virtual ~CImageApplyBarCodeRecognition(void);
virtual void apply(cv::Mat& pDib, int side);
inline BarCodeInfo result() { return m_result; }
inline std::vector<BarCodeInfo> results() { return m_vector_result; }
private:
int recognize_ZXing(const cv::Mat& image, BarCodeInfo& result);
int recognize_Zbar(const cv::Mat& image, BarCodeInfo& result);
void decode(cv::Mat& image, BarCodeInfo& result);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide) {}
private:
RecognizeMode m_mode;
Direction m_direction;
BarCodeInfo m_result;
std::vector<BarCodeInfo> m_vector_result;
};
#endif // IMAGE_APPLY_BAR_CODE_RECOGNITION_H

View File

@ -0,0 +1,127 @@
#include "ImageApplyChannel.h"
#include "ImageApplyAdjustColors.h"
CImageApplyChannel::CImageApplyChannel()
: m_channel(Invalid)
, colors(new CImageApplyAdjustColors(0, 30, 1.0))
{
}
CImageApplyChannel::CImageApplyChannel(Channel channel)
: m_channel(channel)
, colors(new CImageApplyAdjustColors(0, 30, 1.0))
{
}
CImageApplyChannel::~CImageApplyChannel()
{
if (colors != nullptr) delete colors;
}
void CImageApplyChannel::apply(cv::Mat& pDib,int side)
{
(void)side;
if (pDib.empty()) return;
cv::Mat dst(pDib.rows, pDib.cols, CV_8UC1);
switch (m_channel)
{
case Red:
cv::extractChannel(pDib, dst, 2);
colors->apply(pDib, side);
break;
case Green:
cv::extractChannel(pDib, dst, 1);
break;
case Blue:
cv::extractChannel(pDib, dst, 0);
break;
case All:
colourless(pDib, dst, 80);
break;
case Except_Red:
except_channel(pDib, dst, 2);
break;
case Except_Green:
except_channel(pDib, dst, 1);
break;
case Except_Blue:
except_channel(pDib, dst, 0);
break;
default:
break;
}
pDib.release();
pDib = dst;
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyChannel apply");
#endif // LOG
}
void CImageApplyChannel::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}
void CImageApplyChannel::except_channel(const cv::Mat & src, cv::Mat & dst, int channel)
{
int rows = static_cast<int>(src.total());
cv::Mat src_temp(rows, 3, CV_8UC1, src.data);
cv::Mat dst_temp(rows, 1, CV_8UC1, dst.data);
cv::Mat temp1, temp2;
switch (channel)
{
case 0:
temp1 = src_temp(cv::Rect(1, 0, 1, rows));
temp2 = src_temp(cv::Rect(2, 0, 1, rows));
cv::addWeighted(temp1, 0.587, temp2, 0.299, 0, dst_temp);
break;
case 1:
temp1 = src_temp(cv::Rect(0, 0, 1, rows));
temp2 = src_temp(cv::Rect(2, 0, 1, rows));
cv::addWeighted(temp1, 0.114, temp2, 0.299, 0, dst_temp);
break;
case 2:
temp1 = src_temp(cv::Rect(0, 0, 1, rows));
temp2 = src_temp(cv::Rect(1, 0, 1, rows));
cv::addWeighted(temp1, 0.114, temp2, 0.587, 0, dst_temp);
break;
default:
break;
}
}
void CImageApplyChannel::colourless(const cv::Mat &src, cv::Mat &dst, uchar threshold)
{
if (src.channels() != 3)
{
dst = src;
return;
}
cv::Mat hsv;
cv::cvtColor(src, hsv, cv::COLOR_BGR2HSV_FULL);
cv::Mat mv_hsv[3];
cv::split(hsv, mv_hsv);
size_t total = mv_hsv[1].total();
uchar* ptr_s = mv_hsv[1].data;
uchar* ptr_v = mv_hsv[2].data;
for (size_t i = 0; i < total; i++)
if (ptr_s[i] > threshold)
{
ptr_s[i] = 0;
ptr_v[i] = 255;
}
cv::merge(mv_hsv, 3, hsv);
cv::cvtColor(hsv, hsv, cv::COLOR_HSV2BGR_FULL);
cv::cvtColor(hsv, dst, cv::COLOR_BGR2GRAY);
}

View File

@ -0,0 +1,47 @@
#ifndef IMAGE_APPLY_CHANNEL_H
#define IMAGE_APPLY_CHANNEL_H
#include "ImageApply.h"
class CImageApplyAdjustColors;
class CImageApplyChannel : public CImageApply
{
public:
typedef enum channel
{
Red, //红色通道
Green, //绿色通道
Blue, //蓝色通道
All, //去除所有HSV色彩结构中S大于80的色彩
Invalid, //无效
Except_Red, //绿蓝色通道混合
Except_Green, //红蓝色通道混合
Except_Blue //红绿色通道混合
}Channel;
public:
CImageApplyChannel();
CImageApplyChannel(Channel channel);
virtual ~CImageApplyChannel(void);
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
void except_channel(const cv::Mat& src, cv::Mat& dst, int channel);
void colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold = 80);
private:
Channel m_channel;
CImageApplyAdjustColors* colors;
};
#endif // !IMAGE_APPLY_CHANNEL_H

View File

@ -0,0 +1,126 @@
#include "ImageApplyColorRecognition.h"
#include "ImageApplyHeaders.h"
static CImageApplyBWBinaray m_bw;
static CImageApplyAdjustColors m_ac(0, 50, 1.0f);
/// <summary>
/// 检测图像是否是彩色。当前逻辑仅针对红色像素进行判断,即存在红色像素则为彩色,否则为非彩色
/// </summary>
/// <param name="image">待测图像</param>
/// <returns>true为彩色false为非彩色</returns>
bool isColor(const cv::Mat& image)
{
if (image.channels() != 3) return false;
cv::Mat pDib_resize;
cv::resize(image, pDib_resize, cv::Size(image.cols / 9, image.rows / 9), 0, 0, cv::INTER_AREA);
cv::Mat hsv;
cv::cvtColor(pDib_resize, hsv, cv::COLOR_BGR2HSV_FULL);
std::vector<cv::Mat> hsv_channels;
cv::split(hsv, hsv_channels);
cv::Mat range_h1, range_h2, range_s, range_v;
cv::inRange(hsv_channels[0], 0, 85, range_h1);
cv::inRange(hsv_channels[0], 170, 255, range_h2);
cv::inRange(hsv_channels[1], 60, 255, range_s);
cv::inRange(hsv_channels[2], 100, 255, range_v);
cv::Mat thre = (range_h1 | range_h2) & range_s & range_v;
return (cv::sum(thre)[0] / 255)> 4;
}
bool isGray(const cv::Mat& image)
{
if (image.channels() == 3) return true;
cv::Mat image_clone;
cv::resize(image, image_clone, cv::Size(), 0.25, 0.25);
int channels[] = { 0 };
int histsize[] = { 256 };
float range[] = { 0, 256 };
const float* histRanges[] = { range };
cv::Mat hist;
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, histsize, histRanges, true, false);
float pixel_count0 = hist.at<float>(0, 0);
float pixel_count255 = hist.at<float>(255, 0);
float total = image_clone.total();
return ((pixel_count0 + pixel_count255) / total) > 0.95;
}
CImageApplyColorRecognition::CImageApplyColorRecognition(ColorRecognitionMode mode)
: m_mode(mode)
{
}
CImageApplyColorRecognition::~CImageApplyColorRecognition(void)
{
}
void CImageApplyColorRecognition::apply(cv::Mat& pDib, int side)
{
//先判断是否需要判断是彩色
if (m_mode == AllColor || m_mode == Color_Gray || m_mode == Color_Mono)
{
//如果是彩色,直接退出
if (isColor(pDib))
{
m_result = Color;
return;
}
}
if (pDib.channels() == 3)
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
if (m_mode == Color_Gray)
{
m_result = Gray;
return;
}
if (m_mode == Color_Mono)
{
m_bw.apply(pDib, side);
m_result = Mono;
return;
}
if (isGray(pDib))
m_result = Gray;
else
{
m_bw.apply(pDib, side);
m_result = Mono;
}
}
void CImageApplyColorRecognition::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
m_results.clear();
if (mats.empty()) return;
if (!mats[0].empty())
apply(mats[0], 0);
m_results.push_back(m_result);
if (isTwoSide && mats.size() > 1)
if (!mats[1].empty())
apply(mats[1], 1);
m_results.push_back(m_result);
}
CImageApplyColorRecognition::ColorType CImageApplyColorRecognition::getResult()
{
return m_result;
}
std::vector<CImageApplyColorRecognition::ColorType> CImageApplyColorRecognition::getResults()
{
return m_results;
}

View File

@ -0,0 +1,66 @@
/*
* ====================================================
* 242568 8
*
* 2020/7/17
* 2020/12/15
* v1.0 2020/7/17
* v1.1 2020/12/15
* v1.2 2020/12/16 访
* ====================================================
*/
#ifndef IMAGE_APPLY_COLOR_RECOGNITION_H
#define IMAGE_APPLY_COLOR_RECOGNITION_H
#include "ImageApply.h"
class CImageApplyColorRecognition : public CImageApply
{
public :
//色彩识别模式
enum ColorRecognitionMode
{
AllColor, //全色模式 识别结果可能会是彩色、灰度、黑白
Color_Gray, //彩色灰度模式 识别结果只会是彩色或者灰度
Color_Mono, //彩色黑白模式 识别结果只会是彩色或者黑白
Gray_Mono //灰度黑白模式 识别结果只会是灰度或者黑白
};
//色彩类型
enum ColorType
{
Color, //彩色
Gray, //灰度
Mono //黑白
};
public:
CImageApplyColorRecognition(ColorRecognitionMode mode = AllColor);
virtual ~CImageApplyColorRecognition(void);
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
/// <summary>
/// 获取图片色彩类型。配合void apply(cv::Mat&, int)接口使用
/// </summary>
/// <returns>色彩类型</returns>
ColorType getResult();
/// <summary>
/// 获取图片色彩类型。配合void apply(std::vector<cv::Mat>&, int)接口使用
/// </summary>
/// <returns>色彩类型数组</returns>
std::vector<ColorType> getResults();
private:
ColorType m_result;
std::vector<ColorType> m_results;
ColorRecognitionMode m_mode;
};
#endif // !IMAGE_APPLY_CONCATENATION_H

View File

@ -0,0 +1,107 @@
#include "ImageApplyConcatenation.h"
CImageApplyConcatenation::CImageApplyConcatenation()
: m_direction(autoDirection)
, m_BG_color(255, 255, 255)
{
}
CImageApplyConcatenation::CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& background)
: m_direction(dir)
, m_BG_color(background)
{
}
CImageApplyConcatenation::~CImageApplyConcatenation(void)
{
}
void CImageApplyConcatenation::apply(cv::Mat& pDib, int side)
{
(void)pDib;
(void)side;
}
void CImageApplyConcatenation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
if (mats.size() < 2)
{
mats.clear();
return;
}
ConcatMode direction;
if (m_direction == ConcatMode::autoDirection)
direction = (mats[0].cols > mats[0].rows) ? ConcatMode::vertical : ConcatMode::horizontal;
else
direction = m_direction;
cv::Mat dst = concat(mats[0], mats[1], direction);
mats.clear();
mats.push_back(dst);
}
cv::Mat CImageApplyConcatenation::concat(cv::Mat &front, cv::Mat &back, ConcatMode direction)
{
cv::Mat dst;
if (direction == horizontal)
{
#if 0
int top, bottom;
if (front.rows > back.rows)
{
top = (front.rows - back.rows) / 2;
bottom = front.rows - back.rows - top;
cv::copyMakeBorder(back, back, top, bottom, 0, 0, cv::BORDER_CONSTANT);
}
else if (front.rows < back.rows)
{
top = (back.rows - front.rows) / 2;
bottom = back.rows - front.rows - top;
cv::copyMakeBorder(front, front, top, bottom, 0, 0, cv::BORDER_CONSTANT);
}
cv::hconcat(front, back, dst);
#else
int width = cv::max(front.cols, back.cols) * 2;
int height = cv::max(front.rows, back.rows);
if (front.channels() != back.channels())
cv::cvtColor(front.channels() > back.channels() ? back : front, front.channels() > back.channels() ? back : front, cv::COLOR_GRAY2BGR);
dst = cv::Mat(height, width, front.type(), m_BG_color);
front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows)));
int offset = front.cols;
front.release();
back.copyTo(dst(cv::Rect(offset, 0, back.cols, back.rows)));
back.release();
#endif
}
else if (direction == vertical)
{
#if 0
int left, right;
if (front.cols > back.cols)
{
left = (front.cols - back.cols) / 2;
right = front.cols - back.cols - left;
cv::copyMakeBorder(back, back, 0, 0, left, right, cv::BORDER_CONSTANT);
}
else if (front.cols < back.cols)
{
left = (back.cols - front.cols) / 2;
right = back.cols - front.cols - left;
cv::copyMakeBorder(front, front, 0, 0, left, right, cv::BORDER_CONSTANT);
}
cv::vconcat(front, back, dst);
#else
int width = cv::max(front.cols, back.cols);
int height = cv::max(front.rows, back.rows) * 2;
dst = cv::Mat(height, width, front.type(), m_BG_color);
front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows)));
int offset = front.rows;
front.release();
back.copyTo(dst(cv::Rect(0, offset, back.cols, back.rows)));
back.release();
#endif
}
return dst;
}

View File

@ -0,0 +1,61 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/29
* v1.0 2020/4/21
* v1.1 2020/4/29 : 1m_BG_color接口2
* ====================================================
*/
#ifndef IMAGE_APPLY_CONCATENATION_H
#define IMAGE_APPLY_CONCATENATION_H
#include "ImageApply.h"
class CImageApplyConcatenation : public CImageApply
{
public:
//对折方向
enum ConcatMode
{
horizontal = 0, //左右拼接 吅
vertical, //上下拼接 吕
autoDirection
};
public:
CImageApplyConcatenation(); //默认m_direction = autoDirection;
/*
* dir [in]:
* backgroud [in]:
* */
CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& backgroud = cv::Scalar(0, 0, 0));
virtual ~CImageApplyConcatenation(void);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
inline ConcatMode getConcatDirection() { return m_direction; }
inline void setFildDirection(ConcatMode dir) { m_direction = dir; }
inline cv::Scalar getBackGroundColor() const { return m_BG_color; }
inline void setBackGroundColor(const cv::Scalar& color) { m_BG_color = color; }
private:
virtual void apply(cv::Mat& pDib, int side);
cv::Mat concat(cv::Mat& front, cv::Mat& back, ConcatMode direction = autoDirection);
private:
ConcatMode m_direction;
cv::Scalar m_BG_color;
};
#endif // !IMAGE_APPLY_CONCATENATION_H

View File

@ -0,0 +1,52 @@
#include "ImageApplyCrop.h"
CImageApplyCrop::CImageApplyCrop(void)
{
}
CImageApplyCrop::~CImageApplyCrop(void)
{
}
void CImageApplyCrop::apply(cv::Mat& pDib,int side)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter CImageApplyCrop apply");
#endif // LOG
if (pDib.empty())
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyCrop apply");
#endif // LOG
return;
}
if (m_roi.x < 0 || m_roi.y < 0 || m_roi.br().x >= pDib.cols || m_roi.br().y >= pDib.rows || m_roi.width == 0 || m_roi.height == 0)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyCrop apply");
#endif // LOG
return;
}
pDib = pDib(m_roi).clone();
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyCrop apply");
#endif // LOG
}
void CImageApplyCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
if (mats.empty()) return;
if (!mats[0].empty()) {
apply(mats[0], 0);
}
if (isTwoSide && mats.size() > 1) {
if (!mats[1].empty())
apply(mats[1], 1);
}
}

View File

@ -0,0 +1,28 @@
#ifndef IMAGE_APPLY_CROP_H
#define IMAGE_APPLY_CROP_H
#include "imageapply.h"
class CImageApplyCrop : public CImageApply
{
public:
CImageApplyCrop(void);
virtual ~CImageApplyCrop(void);
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
cv::Rect getROI() { return m_roi; }
void setROI(const cv::Rect& rect) { m_roi = rect; }
private:
cv::Rect m_roi;
};
#endif // !IMAGE_APPLY_CROP_H

View File

@ -0,0 +1,32 @@
#include "ImageApplyCustomCrop.h"
CImageApplyCustomCrop::CImageApplyCustomCrop(const cv::Rect &rect)
: m_rect(rect)
{
}
CImageApplyCustomCrop::~CImageApplyCustomCrop()
{
}
void CImageApplyCustomCrop::apply(cv::Mat &pDib, int side)
{
(void)side;
if(pDib.empty()) return;
pDib = pDib(cv::Rect(0, 0, pDib.cols, pDib.rows) & m_rect).clone();
}
void CImageApplyCustomCrop::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,40 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_CUSTOM_CROP_H
#define IMAGE_APPLY_CUSTOM_CROP_H
#include "ImageApply.h"
class CImageApplyCustomCrop : public CImageApply
{
public:
/*
* rect [in]:
* */
CImageApplyCustomCrop(const cv::Rect& rect);
virtual~ CImageApplyCustomCrop(void);
inline cv::Rect getROI() const { return m_rect; }
inline void setROI(const cv::Rect& roi) { m_rect = roi; }
virtual void apply(cv::Mat &pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
cv::Rect m_rect;
};
#endif // IMAGE_APPLY_CUSTOM_CROP_H

View File

@ -0,0 +1,63 @@
#include "ImageApplyCustomGamma.h"
CImageApplyCustomGamma::CImageApplyCustomGamma(unsigned char* table,int length)
: emptyPtr(false)
{
if(table==nullptr)
emptyPtr = true;
init_gamma_table();
setLUT(table,length == 256 ? 1 : 3);
}
CImageApplyCustomGamma::~CImageApplyCustomGamma()
{
}
void CImageApplyCustomGamma::setLUT(const unsigned char* table, int byteCount)
{
if (emptyPtr)
return;
if (byteCount == 1)
memcpy(m_table_bit8, table, 256);
else if (byteCount == 3)
memcpy(m_table_bit24, table, 768);
}
void CImageApplyCustomGamma::apply(cv::Mat& pDib, int side)
{
(void)side;
if (emptyPtr)
return;
int numOfChannels = pDib.channels();
cv::Mat mat_table(1, 256, CV_8UC(numOfChannels), (numOfChannels == 3) ? m_table_bit24 : m_table_bit8);
cv::LUT(pDib, mat_table, pDib);
}
void CImageApplyCustomGamma::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}
void CImageApplyCustomGamma::setTableData(const unsigned char* data, int length)
{
setLUT(data, length == 256 ? 1 : 3);
}
void CImageApplyCustomGamma::init_gamma_table()
{
for (size_t i = 0; i < 256; ++i)
{
m_table_bit8[i] = static_cast<unsigned char>(i);
m_table_bit24[i * 3] = m_table_bit24[i * 3 + 1] = m_table_bit24[i * 3 + 2] = static_cast<unsigned char>(i);
}
}

View File

@ -0,0 +1,44 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_CUSTOM_CAMMA_H
#define IMAGE_APPLY_CUSTOM_CAMMA_H
#include "ImageApply.h"
class CImageApplyCustomGamma : public CImageApply
{
public:
/*
* table [in]:
* length [in]:256768
* */
CImageApplyCustomGamma(unsigned char* table,int length);
virtual ~CImageApplyCustomGamma();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
void setTableData(const unsigned char* data, int length);
private:
void init_gamma_table();
void setLUT(const unsigned char* table, int byteCount);
bool emptyPtr;
private:
unsigned char m_table_bit8[256];
unsigned char m_table_bit24[768];
};
#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H

View File

@ -0,0 +1,57 @@
#include "ImageApplyCvtColor.h"
CImageApplyCvtColor::CImageApplyCvtColor(ConversionCodes type)
: m_code(type)
{
}
CImageApplyCvtColor::~CImageApplyCvtColor()
{
}
void CImageApplyCvtColor::apply(cv::Mat& pDib, int side)
{
(void)side;
if (pDib.channels() == 1) return;
if (m_code > 3)
cv::cvtColor(pDib, pDib, static_cast<cv::ColorConversionCodes>(m_code));
else
{
cv::Mat gray(pDib.size(), CV_8UC1);
if (m_code == BGR_MAX)
{
for (size_t y = 0, rows = pDib.rows; y < rows; y++)
{
uchar* ptr_y = pDib.ptr(y);
uchar* gray_y = gray.ptr(y);
for (size_t x = 0, cols = pDib.cols; x < cols; x++)
gray_y[x] = cv::max(ptr_y[x * 3], cv::max(ptr_y[x * 3 + 1], ptr_y[x * 3 + 2]));
}
}
else if (m_code == BGR_MIN)
{
for (size_t y = 0, rows = pDib.rows; y < rows; y++)
{
uchar* ptr_y = pDib.ptr(y);
uchar* gray_y = gray.ptr(y);
for (size_t x = 0, cols = pDib.cols; x < cols; x++)
gray_y[x] = cv::min(ptr_y[x * 3], cv::min(ptr_y[x * 3 + 1], ptr_y[x * 3 + 2]));
}
}
pDib.release();
pDib = gray;
}
}
void CImageApplyCvtColor::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,52 @@
/*
* ====================================================
* 1|?<EFBFBD><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD><EFBFBD>?2<EFBFBD><EFBFBD><EFBFBD><EFBFBD>???
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>??<EFBFBD><EFBFBD>o<EFBFBD><EFBFBD>?????
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>??<EFBFBD><EFBFBD>o2020/6/19
* <EFBFBD><EFBFBD>??<EFBFBD><EFBFBD>DT??<EFBFBD><EFBFBD><EFBFBD><EFBFBD>??<EFBFBD><EFBFBD>ov1.0 2020/6/19
v1.1 2020/6/20 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<EFBFBD><EFBFBD>BGR<EFBFBD><EFBFBD>aHSV,<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<EFBFBD><EFBFBD>BGR_MAX<EFBFBD><EFBFBD>?<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?<EFBFBD><EFBFBD>BGR_MIN
* <EFBFBD><EFBFBD>?<EFBFBD><EFBFBD>?o?<EFBFBD><EFBFBD>ov1.1
* ====================================================
*/
#ifndef IMAGE_APPLY_CONVERT_COLOR_H
#define IMAGE_APPLY_CONVERT_COLOR_H
#include "ImageApply.h"
class CImageApplyCvtColor : public CImageApply
{
public:
//<2F><>a???<3F>꨺?
enum ConversionCodes
{
BGR_MAX = 1, //BGR<47><52>?<3F>䨮?<3F>̡<EFBFBD>?<3F><>aGRAY
BGR_MIN = 2, //BGR<47><52>?D??<3F>̡<EFBFBD>?<3F><>aGRAY
BGR2GRAY = 6, //BGR<47><52>aGRAY
BGR2HSV = 40 //BGR<47><52>aHSV
};
/*
* type [in]:<EFBFBD><EFBFBD>?2<EFBFBD><EFBFBD><EFBFBD><EFBFBD>a???<EFBFBD>?<EFBFBD><EFBFBD>???<EFBFBD><EFBFBD>?BGR<EFBFBD><EFBFBD>aGray
* */
CImageApplyCvtColor(ConversionCodes type = BGR2GRAY);
virtual ~CImageApplyCvtColor();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
inline ConversionCodes getConversionCode() { return m_code; }
inline void setConversionCode(ConversionCodes code) { m_code = code; }
private:
ConversionCodes m_code;
};
#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H

View File

@ -0,0 +1,42 @@
#include "ImageApplyDetachNoise.h"
#include "ImageProcess_Public.h"
CImageApplyDetachNoise::CImageApplyDetachNoise(int noise)
: m_noise(noise)
{
}
CImageApplyDetachNoise::~CImageApplyDetachNoise(void)
{
}
void CImageApplyDetachNoise::apply(cv::Mat& pDib, int side)
{
(void)side;
if (pDib.empty()||pDib.channels() != 1)
return;
cv::Mat mask;
cv::threshold(pDib, mask, 127, 255, cv::THRESH_BINARY_INV);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> h;
hg::findContours(mask, contours, h);
for (const std::vector<cv::Point>& contour : contours)
if (contourArea(contour) < m_noise)
fillConvexPoly(pDib, contour, cv::Scalar(255));
}
void CImageApplyDetachNoise::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,38 @@
/*
* ====================================================
* 3*3
*
* 2020/4/21
* 2020/4/21 v1.0
2020/5/29 v1.1 使
* v1.1
* ====================================================
*/
#ifndef IMAGE_APPLY_DETACH_NOISE_H
#define IMAGE_APPLY_DETACH_NOISE_H
#include "ImageApply.h"
class CImageApplyDetachNoise : public CImageApply
{
public:
CImageApplyDetachNoise(int noise = 1);
inline int getNoise() { return m_noise; }
inline void setNoise(int noise) { m_noise = noise; }
virtual ~CImageApplyDetachNoise(void);
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
int m_noise;
};
#endif // !IMAGE_APPLY_DETACH_NOISE_H

View File

@ -0,0 +1,202 @@
#include "ImageApplyDiscardBlank.h"
#include "ImageProcess_Public.h"
CImageApplyDiscardBlank::CImageApplyDiscardBlank(int blockSize, int devTh)
: m_res(false)
, m_dSize(blockSize)
, m_devTh(devTh)
{
}
CImageApplyDiscardBlank::CImageApplyDiscardBlank()
: m_res(false)
, m_dSize(200)
, m_devTh(15, 15, 15, 15)
{
}
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
{
}
int CImageApplyDiscardBlank::processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector<cv::Point>& maxContour,
double scale, double thresh, int blobAreaSize)
{
cv::Mat gray;
int blockCount = 0;
if (image.channels() == 3)
if (scale != 1.0f)
{
cv::Size ResImgSiz = cv::Size(image.cols * scale, image.rows * scale);
resize(image, gray, cv::Size(), scale, scale, 0);
cvtColor(gray, gray, CV_BGR2GRAY);
}
else
cvtColor(image, gray, CV_BGR2GRAY);
else
if (scale != 1.0f)
resize(image, gray, cv::Size(), scale, scale, 0);
else
gray = image;
cv::Mat threshold_img;
threshold(gray, threshold_img, thresh, 255.0, CV_THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> h1;
hg::findContours(threshold_img, contours, h1, CV_CHAIN_APPROX_SIMPLE);
threshold_img.release();
if (contours.size() == 0)
return blockCount;
std::vector<cv::Point2f> list_com;
for (int i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
if (area > blobAreaSize)
{
blockCount++;
for (int j = 0; j < contours[i].size(); j++)
list_com.push_back(contours[i][j]);
}
}
if (list_com.size() == 0)
return blockCount;
rotatedRect = cv::minAreaRect(list_com);
rotatedRect.center.x /= (float)scale;
rotatedRect.center.y /= (float)scale;
rotatedRect.size.width /= (float)scale;
rotatedRect.size.height /= (float)scale;
if (rotatedRect.angle < -45.0f)
{
rotatedRect.angle += 90.0f;
float l_temp = rotatedRect.size.width;
rotatedRect.size.width = rotatedRect.size.height;
rotatedRect.size.height = l_temp;
}
std::vector<int> hull(list_com.size());
cv::convexHull(list_com, hull);
for (int i = 0; i < hull.size(); i++)
{
cv::Point temp = list_com[hull[i]];
int x = (int)(temp.x / scale);
int y = (int)(temp.y / scale);
maxContour.push_back(cv::Point(x, y));
}
return blockCount;
}
bool CImageApplyDiscardBlank::scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2)
{
for (int i = 0; i < 3; i++)
if (val1[i] > val2[i])
return false;
return true;
}
void CImageApplyDiscardBlank::setIntensity(int val)
{
val = cv::max(cv::min(100, val), 2);
m_devTh = cv::Scalar::all(val);
}
cv::Mat CImageApplyDiscardBlank::getRoiMat(const cv::Mat& image)
{
int gap = 100;
cv::RotatedRect rect;
std::vector<cv::Point> contour;
double scale = 0.25;
double thresh = 50;
int blobSize = 200;
processRectR(image, rect, contour, scale, thresh, blobSize);
cv::Rect rect2 = rect.boundingRect();
cv::Rect inRect = rect2 & cv::Rect(0, 0, image.cols, image.rows);
gap = cv::max(inRect.width - rect.size.width, inRect.height - rect.size.height) + 20;
inRect = cv::Rect(inRect.x + gap, inRect.y + gap, inRect.width - gap * 2, inRect.height - gap * 2);
if (inRect.width <= 0 || inRect.height <= 0)
return cv::Mat();
return image(inRect);
}
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
{
if (pDib.empty())
{
return;
}
cv::Scalar mean;
cv::Scalar dev;
cv::Mat image = getRoiMat(pDib);
cv::Rect rect;
cv::Rect imRect(0, 0, image.cols, image.rows);
for(int i = 0; i < image.cols; i+= m_dSize)
for(int j = 0; j < image.rows; j+= m_dSize)
{
rect = cv::Rect(i, j, m_dSize, m_dSize) & imRect;
if(rect != cv::Rect())
{
cv::meanStdDev (image(rect) , mean, dev);
if(!scalar_LE(dev, m_devTh))
{
m_res = false;
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply");
#endif // LOG
return;
}
}
}
m_res = true;
if (m_res)
pDib.release();
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply");
#endif // LOG
}
void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, int blockSize, int devTh)
{
if (pDib.empty())
return true;
cv::Scalar mean;
cv::Scalar dev;
cv::Scalar s_devTh = cv::Scalar::all(devTh);
cv::Mat image = getRoiMat(pDib);
if (image.empty())
return false;
cv::Rect rect;
cv::Rect imRect(0, 0, image.cols, image.rows);
for (int i = 0; i < image.cols; i += blockSize)
for (int j = 0; j < image.rows; j += blockSize)
{
rect = cv::Rect(i, j, blockSize, blockSize) & imRect;
if (rect != cv::Rect())
{
cv::meanStdDev(image(rect), mean, dev);
if (!scalar_LE(dev, s_devTh))
return false;
}
}
return true;
}

View File

@ -0,0 +1,56 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21 v1.0
2020/8/12 v1.1 setIntensity和setMinAreaisNormal标识位setIntensity的设置范围[2, 20][1, 100]
* v1.1
* ====================================================
*/
#ifndef IMAGE_APPLY_DISCARD_BLANK_H
#define IMAGE_APPLY_DISCARD_BLANK_H
#include "ImageApply.h"
class CImageApplyDiscardBlank : public CImageApply
{
public:
CImageApplyDiscardBlank(int blockSize, int devTh);
/*
* isnormal [in]:true标准模式false为票据复写纸模式
* */
CImageApplyDiscardBlank();
virtual ~CImageApplyDiscardBlank(void);
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
void setIntensity(int val);
void setMinArea(int val) { m_dSize = val; }
static bool apply(const cv::Mat& pDib, int blockSize = 200, int devTh = 15);
private:
static int processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector<cv::Point>& maxContour,
double scale, double thresh, int blobAreaSize);
static bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2);
static cv::Mat getRoiMat(const cv::Mat& pDib);
private:
bool m_res;
bool m_isNormalDiscard;
int m_dSize;
cv::Scalar m_devTh;
};
#endif // !IMAGE_APPLY_DISCARD_BLANK_H

View File

@ -0,0 +1,67 @@
#include "ImageApplyDogEarDetection.h"
#include "ImageProcess_Public.h"
CImageApplyDogEarDetection::CImageApplyDogEarDetection()
: m_threshold(40)
, m_zoom(1.0)
, m_distance(50)
, m_result(false)
{
}
CImageApplyDogEarDetection::CImageApplyDogEarDetection(double threshlod, double zoom, double distance)
: m_threshold(threshlod)
, m_zoom(zoom)
, m_distance(distance)
, m_result(false)
{
}
CImageApplyDogEarDetection::~CImageApplyDogEarDetection()
{
}
void CImageApplyDogEarDetection::apply(cv::Mat &pDib, int side)
{
m_result = false;
(void)side;
if (pDib.empty()) return;
cv::Mat src;
if (m_zoom != 1.0)
cv::resize(pDib, src, cv::Size(), m_zoom, m_zoom, cv::INTER_NEAREST);
else
src = pDib;
cv::Mat thre;
hg::threshold_Mat(src, thre, m_threshold);
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> contours;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
if (maxContour.size() == 0)
{
m_result = true;
return;
}
hg::convexHull(maxContour, maxContour);
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
cv::Point2f vertexes[4];
rect.points(vertexes);
for (int i = 0; i < 4; i++)
if ((-cv::pointPolygonTest(maxContour, vertexes[i], true)) > (m_distance * m_zoom))
{
m_result = true;
return;
}
}
void CImageApplyDogEarDetection::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)mats;
(void)isTwoSide;
}

View File

@ -0,0 +1,56 @@
/*
* ====================================================
*
*
* 2020/10/30
* 2020/10/30
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_DOGEAR_DETECTION_H
#define IMAGE_APPLY_DOGEAR_DETECTION_H
#include "ImageApply.h"
class CImageApplyDogEarDetection :public CImageApply
{
public:
/// <summary>
/// 折角检测默认构造函数threshold = 40 zoom = 1.0 distance = 50
/// </summary>
CImageApplyDogEarDetection();
/// <summary>
/// 折角检测构造函数
/// </summary>
/// <param name="threshlod">二值化阈值</param>
/// <param name="zoom">原图缩放比例对于大尺寸图像而言通过zoom缩小图像可减少计算量。默认值1.0(不缩放)</param>
/// <param name="distance">理论顶点到实际轮廓最小距离的阈值大于该阈值则判定为折角默认值50像素</param>
CImageApplyDogEarDetection(double threshlod, double zoom = 1.0, double distance = 50);
virtual ~CImageApplyDogEarDetection(void);
/// <summary>
/// 获取检测结果。该函数须在调用apply之后使用。
/// </summary>
/// <returns>true为折角false为不折角</returns>
inline bool getResult() { return m_result; }
virtual void apply(cv::Mat& pDib, int side);
private:
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
double m_threshold;
double m_zoom;
double m_distance;
bool m_result;
};
#endif // IMAGE_APPLY_DOGEAR_DETECTION_H

View File

@ -0,0 +1,62 @@
#include "ImageApplyFilter.h"
CImageApplyFilter::CImageApplyFilter(FilterMode type)
: m_type(type)
{
m_kSize = (m_type == FilterMode::Sharpen || m_type == FilterMode::AverBlur) ? 5 : 9;
}
CImageApplyFilter::~CImageApplyFilter()
{
}
void CImageApplyFilter::apply(cv::Mat & pDib, int side)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter CImageApplySharpen apply");
#endif // LOG
switch (m_type)
{
case FilterMode::Sharpen:
case FilterMode::Sharpen_More:
sharpen(pDib, m_kSize);
break;
case FilterMode::AverBlur:
case FilterMode::AverBlur_More:
averblur(pDib, static_cast<int>(m_kSize));
break;
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplySharpen apply");
#endif // LOG
}
void CImageApplyFilter::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
if (mats.empty()) return;
if (!mats[0].empty())
apply(mats[0], 0);
if (isTwoSide && mats.size() > 1)
{
if (!mats[1].empty())
apply(mats[1], 1);
}
}
void CImageApplyFilter::averblur(cv::Mat& src, int kSize)
{
cv::blur(src, src, cv::Size(kSize, kSize));
}
void CImageApplyFilter::sharpen(cv::Mat& src, float kSize)
{
float other = (1.0f - kSize) / 4;
float kernel_data[] = { 0, other, 0, other, kSize, other, 0, other, 0 };
cv::Mat kernel(3, 3, CV_32FC1, kernel_data);
cv::filter2D(src, src, src.depth(), kernel);
}

View File

@ -0,0 +1,49 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_FILTER_H
#define IMAGE_APPLY_FILTER_H
#include "ImageApply.h"
class CImageApplyFilter : public CImageApply
{
public:
enum FilterMode
{
None,
Sharpen,
Sharpen_More,
AverBlur,
AverBlur_More
};
/*
* sharpentype [in]:
*/
CImageApplyFilter(FilterMode type);
virtual ~CImageApplyFilter();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
void averblur(cv::Mat& src, int kSize);
void sharpen(cv::Mat& src, float kSize);
private:
int m_type;
float m_kSize;
};
#endif // !IMAGE_APPLY_SHARPEN_H

View File

@ -0,0 +1,144 @@
#include "ImageApplyHSVCorrect.h"
#include <omp.h>
CImageApplyHSVCorrect::CImageApplyHSVCorrect()
: m_table(new uint[256 * 256 * 256])
{
initLUT();
}
CImageApplyHSVCorrect::CImageApplyHSVCorrect(CorrectOption mode)
: m_table(new uint[256 * 256 * 256])
{
initLUT();
switch (mode)
{
case CImageApplyHSVCorrect::Red_Removal:
set_HSV_value(std::pair<uchar, uchar>(0, 63), std::pair<uchar, uchar>(20, 255), std::pair<uchar, uchar>(160, 255), 0x00FFFFFF);
set_HSV_value(std::pair<uchar, uchar>(191, 255), std::pair<uchar, uchar>(20, 255), std::pair<uchar, uchar>(160, 255), 0x00FFFFFF);
break;
default:
break;
}
}
CImageApplyHSVCorrect::~CImageApplyHSVCorrect()
{
delete [] m_table;
}
void CImageApplyHSVCorrect::apply(cv::Mat &pDib, int side)
{
(void)side;
if (pDib.empty() || pDib.channels() != 3) return;
uchar* src = pDib.data;
cv::Mat z = cv::Mat::zeros(pDib.size(), CV_8UC3);
uchar* dst = z.data;
int total = pDib.total();
#pragma omp parallel for
for (int i = 0; i < total; i++)
{
int offset = i * 3;
int index = *reinterpret_cast<uint*>(src + offset) & 0x00ffffff;
uint color = m_table[index];
*reinterpret_cast<uint*>(dst + offset) |= color;
}
pDib = z;
}
void CImageApplyHSVCorrect::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}
void CImageApplyHSVCorrect::initLUT()
{
#if 0
uchar h, s, v;
#endif
for (uint b = 0; b < 256; b++)
for (uint g = 0; g < 256; g++)
for (uint r = 0; r < 256; r++)
{
#if 0
RGB_2_HSV_full(r, g, b, h, s, v);
uint index = b | (g << 8) | (r << 16);
if (h < 12 || h > 245)
m_table[index] = index & 0x00ffffff;
else
m_table[index] = (v | (v << 8) | (v << 16)) & 0x00ffffff;
#else
m_table[b | (g << 8) | (r << 16)] = b | (g << 8) | (r << 16);
#endif
}
}
void CImageApplyHSVCorrect::set_single(const uint src_b, const uint src_g, const uint src_r,
const uint dst_b, const uint dst_g, const uint dst_r)
{
m_table[src_b | (src_g << 8) | (src_r << 16)] = dst_b | (dst_g << 8) | (dst_r << 16);
}
void CImageApplyHSVCorrect::set_HSV_value(const std::pair<uchar, uchar>& range_h,
const std::pair<uchar, uchar>& range_s,
const std::pair<uchar, uchar>& range_v,
uint bgr)
{
uchar h, s, v;
for (int b = 0; b < 256; b++)
for (int g = 0; g < 256; g++)
for (int r = 0; r < 256; r++)
{
RGB_2_HSV_full(r, g, b, h, s, v);
if (contained(h, range_h) && contained(s, range_s) && contained(v, range_v))
m_table[(b | (g << 8) | (r << 16)) & 0x00ffffff] = bgr & 0x00ffffff;
}
}
void CImageApplyHSVCorrect::set_table(const uint* table)
{
memcpy(m_table, table, 256 * 256 * 256);
}
bool CImageApplyHSVCorrect::contained(uchar value, const std::pair<uchar, uchar> &range)
{
return value >= range.first && value <= range.second;
}
void CImageApplyHSVCorrect::RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v)
{
int minn = cv::min(r, cv::min(g, b));
int maxx = cv::max(r, cv::max(g, b));
v = static_cast<uchar>(maxx); //V
int delta = maxx - minn;
float _h;
if (maxx == 0)
{
h = s = v = 0;
return;
}
else
s = static_cast<uchar>(delta * 255 / maxx);
if (r == maxx)
_h = static_cast<float>(g - b) / static_cast<float>(delta);
else if (g == maxx)
_h = 2 + static_cast<float>(b - r) / static_cast<float>(delta);
else
_h = 4 + static_cast<float>(r - g) / static_cast<float>(delta);
float __h = _h * 42.6666666667f;
h = (__h >= 0) ? static_cast<uchar>(__h) : static_cast<uchar>(__h + 256);
}

View File

@ -0,0 +1,87 @@
/*
* ====================================================
* LUT实现BGR查值表HVSBGR原图进行查值校正
*
* 2020/3/21
* v1.0 2020/3/21
v1.1 2020/6/15 HSV取值范围
* v1.1
* ====================================================
*/
#ifndef IMAGE_APPLY_COLOR_CORRECT_H
#define IMAGE_APPLY_COLOR_CORRECT_H
#include "ImageApply.h"
class CImageApplyHSVCorrect : public CImageApply
{
public:
enum CorrectOption
{
Red_Removal //除掉红色。红色定义H:[0, 85][170, 255],S:[10, 255],V:[120,255]
};
public:
CImageApplyHSVCorrect();
/*
* mode [in]:
*/
CImageApplyHSVCorrect(CorrectOption mode);
virtual ~CImageApplyHSVCorrect();
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
/*
* RGBR在高位B在低位32
[00x00FFFFFF]
*/
void initLUT();
/*
* RGB索引值设置为目标值
= src_b | (src_g << 8) | (src_r << 16)
= dst_b | (dst_g << 8) | (dst_r << 16)
* src_b:[in] B通道索引
* src_g:[in] G通道索引
* src_r:[in] R通道索引
* dst_b:[in] B通道值
* dst_g:[in] G通道值
* dst_r:[in] R通道值
*/
void set_single(const uint src_b, const uint src_g, const uint src_r,
const uint dst_b, const uint dst_g, const uint dst_r);
/*
* HSV色彩空间描述色彩范围BGR索引设置为0x00FFFFFF(
* range_h:[in] H分量范围[0, 255]
* range_s:[in] S分量范围[0, 255]
* range_v:[in] V分量范围[0, 255]
* bgr:[in] uint表示BGR值B在低位R在高位
*/
void set_HSV_value(const std::pair<uchar, uchar>& range_h,
const std::pair<uchar, uchar>& range_s,
const std::pair<uchar, uchar>& range_v,
uint bgr = 0x00FFFFFF);
/*
* 256 * 256 * 256 * sizeof(uint
* table:[in]
*/
void set_table(const uint* table);
private:
static bool contained(uchar value, const std::pair<uchar, uchar>& range);
static void RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v);
private:
uint* m_table;
};
#endif

View File

@ -0,0 +1,29 @@
#ifndef IMAGE_APPLY_HEADER_H
#define IMAGE_APPLY_HEADER_H
#include "ImageApply.h"
#include "ImageApplyAdjustColors.h"
#include "ImageApplyAutoCrop.h"
#include "ImageApplyBWBinaray.h"
#include "ImageApplyChannel.h"
#include "ImageApplyCrop.h"
#include "ImageApplyDiscardBlank.h"
#include "ImageApplyOutHole.h"
#include "ImageApplyDogEarDetection.h"
#include "ImageApplyResize.h"
#include "ImageApplyRotation.h"
#include "ImageApplySharpen.h"
#include "ImageApplyConcatenation.h"
#include "ImageApplyHSVCorrect.h"
#include "ImageApplyDetachNoise.h"
#include "ImageApplyColorRecognition.h"
#include "ImageApplyCustomCrop.h"
#include "ImageApplyCustomGamma.h"
#include "ImageApplyRefuseInflow.h"
#include "ImageApplyTextureRemoval.h"
#include "ImageApplyFilter.h"
#include "ImageApplySplit.h"
#include "ImageApplyAutoContrast.h"
#include "ImageMulti.h"
#include "ImageMultiOutputRed.h"
#endif

View File

@ -0,0 +1,315 @@
#include "ImageApplyMarkCrop.h"
#include "ImageProcess_Public.h"
#define RE 2
//#define DRAW
#ifdef NOT_USE
CImageApplyMarkCrop::CImageApplyMarkCrop(CImageApplyMarkCrop::DeviceModel device, bool isCropped, double threshold, int noise, CImageApplyMarkCrop::DPI dpi, DirectionMethod direction)
: m_device(device)
, m_b_isCropped(isCropped)
, m_threshold(120)
, m_noise(noise)
, m_dpi(dpi)
, m_range(30, 55)
, m_direction(direction)
{
}
int CImageApplyMarkCrop::apply(const cv::Mat& src, cv::Mat& dst, Orientation markOri, bool barCode, int& angle)
{
if (src.empty()) return -1;
cv::Mat src_resize;
if (m_device == DeviceModel::G400)
cv::resize(src, src_resize, cv::Size(src.cols / RE, src.rows / RE));
else
cv::resize(src, src_resize, cv::Size(src.cols / 3, src.rows / RE));
cv::Mat scale_mat;
cv::Mat thre(src_resize.size(), CV_8UC1);
hg::threshold_Mat(src_resize, thre, m_threshold);
#ifdef DRAW
cv::imwrite("thre.bmp", thre);
#endif
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> contours;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
float scale = m_device == DeviceModel::G300 ? 3 : RE;
if (maxContour.size() == 0)
{
thre.release();
return -1;
}
//thre.release();
//dst.release();
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
cv::Point2f vertex[4];
rect.points(vertex);
std::vector<std::vector<cv::Point>> marks;
std::vector<cv::RotatedRect> rrects;
hg::threshold_Mat(src_resize, thre, m_threshold);
cv::bitwise_not(thre, thre);
contours.clear();
hierarchy.clear();
hg::findContours(thre, contours, hierarchy, cv::RETR_LIST);
findMarks(contours, rect, cv::Range(m_range.start / RE, m_range.end / RE), marks, rrects);
if (marks.size() < 3) return -2;
#ifdef DRAW
for (int i = 0; i < marks.size(); i++)
cv::circle(thre, marks[i][0], 30, cv::Scalar(255));
cv::imwrite("contour.bmp", thre);
#endif
maxContour.clear();
for (const std::vector<cv::Point>& mark : marks)
for (const cv::Point& p : mark)
maxContour.push_back(p);
if (rrects.size() == 3)
{
double distance1 = hg::distanceP2P(rrects[0].center, rrects[1].center);
double distance2 = hg::distanceP2P(rrects[1].center, rrects[2].center);
double distance3 = hg::distanceP2P(rrects[2].center, rrects[0].center);
if (distance1 > distance2 && distance1 > distance3)
maxContour.push_back(((rrects[0].center + rrects[1].center) / 2 * 3 - rrects[2].center) / 2);
else if (distance2 > distance1 && distance2 > distance3)
maxContour.push_back(((rrects[1].center + rrects[2].center) / 2 * 3 - rrects[0].center) / 2);
else
maxContour.push_back(((rrects[2].center + rrects[0].center) / 2 * 3 - rrects[1].center) / 2);
}
for (cv::Point& item : maxContour)
item *= scale;
rect = hg::getBoundingRect(maxContour);
rect.points(vertex);
cv::Point2f focus;
Orientation ori;
for (size_t i = 0; i < rrects.size(); i++)
for (size_t j = i + 1; j < rrects.size(); j++)
if (rrects[i].size.area() < rrects[j].size.area())
{
cv::RotatedRect rect_remp = rrects[j];
rrects[j] = rrects[i];
rrects[i] = rect_remp;
}
for (cv::RotatedRect& item : rrects)
item.center *= scale;
if (m_direction == DirectionMethod::Multilateral)
{
if (rrects.size() < 4) return -3;
for (int i = 0; i < 5; i++)
focus += rrects[i].center;
focus /= 5;
float dis_top = hg::distanceP2L(focus, vertex[1], vertex[2]);
float dis_bottom = hg::distanceP2L(focus, vertex[0], vertex[3]);
float dis_left = hg::distanceP2L(focus, vertex[0], vertex[1]);
float dis_right = hg::distanceP2L(focus, vertex[2], vertex[3]);
float dis_min = cv::min(dis_top, cv::min(dis_bottom, cv::min(dis_left, dis_right)));
if (dis_top == dis_min)
ori = Top_RB;
else if (dis_bottom == dis_min)
ori = Bottom_LT;
else if (dis_left == dis_min)
ori = Left_RT;
else
ori = Right_LB;
}
else if (m_direction == DirectionMethod::Trilateral_7Net)
{
for (int i = 0; i < 3; i++)
focus += rrects[i].center;
focus /= 3;
float dis_top = hg::distanceP2L(focus, vertex[1], vertex[2]);
float dis_bottom = hg::distanceP2L(focus, vertex[0], vertex[3]);
float dis_left = hg::distanceP2L(focus, vertex[0], vertex[1]);
float dis_right = hg::distanceP2L(focus, vertex[2], vertex[3]);
float dis_min_lr = cv::min(dis_left, dis_right);
float dis_min_tb = cv::min(dis_top, dis_bottom);
if (dis_min_lr == dis_right && dis_min_tb == dis_bottom)
ori = Bottom_LT;
else if (dis_min_lr == dis_left && dis_min_tb == dis_top)
ori = Top_RB;
else if (dis_min_lr == dis_right && dis_min_tb == dis_top)
ori = Right_LB;
else
ori = Left_RT;
}
cv::Point2f srcTri[4];
cv::Point2f dstTri[3];
rect.points(srcTri);
if (m_device == DeviceModel::G300)
for (cv::Point2f& p : srcTri)
p.y = p.y * RE / m_device;
cv::Size temp_size;
float width = rect.size.width;
float height = hg::distanceP2P(srcTri[0], srcTri[1]);
if (markOri == Default || markOri == ori)
{
dstTri[0] = cv::Point2f(0, height - 1);
dstTri[1] = cv::Point2f(0, 0);
dstTri[2] = cv::Point2f(width - 1, 0);
temp_size.width = width;
temp_size.height = height;
angle = 0;
}
else if (markOri - ori == -3 || markOri - ori == 1)
{
dstTri[0] = cv::Point2f(0, 0);
dstTri[1] = cv::Point2f(height - 1, 0);
dstTri[2] = cv::Point2f(height - 1, width - 1);
temp_size.width = height;
temp_size.height = width;
angle = -90;
}
else if (markOri - ori == -2 || markOri - ori == 2)
{
dstTri[0] = cv::Point2f(width - 1, 0);
dstTri[1] = cv::Point2f(width - 1, height - 1);
dstTri[2] = cv::Point2f(0, height - 1);
temp_size.width = width;
temp_size.height = height;
angle = 180;
}
else if (markOri - ori == -1 || markOri - ori == 3)
{
dstTri[0] = cv::Point2f(height - 1, width - 1);
dstTri[1] = cv::Point2f(0, width - 1);
dstTri[2] = cv::Point2f(0, 0);
temp_size.width = height;
temp_size.height = width;
angle = 90;
}
if (m_b_isCropped)
{
cv::Mat warp_mat;
warp_mat = cv::getAffineTransform(srcTri, dstTri);
cv::warpAffine(src, dst, warp_mat, temp_size);
}
else
{
if (angle == 0)
dst = src.clone();
else if (angle == 90)
{
cv::transpose(src, dst);
cv::flip(dst, dst, 0);
}
else if (angle == -90)
{
cv::transpose(src, dst);
cv::flip(dst, dst, 1);
}
else
{
cv::flip(src, dst, 0);
cv::flip(dst, dst, 1);
}
}
//Èç¹ûÐèÒªÅжÏÌõÂë
if (barCode)
{
//cv::imwrite("dst.bmp", dst);
if (dst.cols < 600 || dst.rows < 400)
return -4;
if (!isContainBarCode(dst(cv::Rect(0, 0, 600, 400))))
return -5;
}
return 0;
#ifdef DRAW
cv::imwrite("dst.bmp", dst);
#endif
}
void CImageApplyMarkCrop::findMarks(const std::vector<std::vector<cv::Point>>& contours, const cv::RotatedRect& region,
const cv::Range& range, std::vector<std::vector<cv::Point>>& marks, std::vector<cv::RotatedRect>& rrect)
{
cv::RotatedRect region_outside = region;
cv::RotatedRect region_inside = region;
region_inside.size = cv::Size2f(region.size.width * 0.9, region.size.height * 0.9);
cv::Point2f outside[4], inside[4];
region_outside.points(outside);
region_inside.points(inside);
std::vector<cv::Point> v_outside, v_inside;
for (size_t i = 0; i < 4; i++)
{
v_outside.push_back(cv::Point(outside[i].x, outside[i].y));
v_inside.push_back(cv::Point(inside[i].x, inside[i].y));
}
for (size_t i = 0, length = contours.size(); i < length; i++)
{
std::vector<cv::Point> contour = contours[i];
cv::RotatedRect rect = cv::minAreaRect(contour);
double area = cv::contourArea(contour);
if (rect.size.width < range.start || rect.size.height < range.start || rect.size.width > range.end || rect.size.height > range.end)
continue;
if (rect.size.width * rect.size.height < 40 / RE)
continue;
if (cv::pointPolygonTest(v_outside, rect.center, true) > 0 && cv::pointPolygonTest(v_inside, rect.center, true) < 0)
{
marks.push_back(contour);
rrect.push_back(rect);
}
}
}
bool CImageApplyMarkCrop::isContainBarCode(const cv::Mat& image)
{
cv::Mat thre;
hg::threshold_Mat(image, thre, 127);
cv::bitwise_not(thre, thre);
cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(20, 1));
cv::morphologyEx(thre, thre, cv::MorphTypes::MORPH_DILATE, element);
//cv::imwrite("barCode.bmp", thre);
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> contours;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
for (size_t i = 0; i < contours.size(); i++)
{
cv::Rect rect = cv::boundingRect(contours[i]);
if (rect.width > 250 && rect.height > 50)
return true;
}
return false;
}
#endif //

View File

@ -0,0 +1,116 @@
/*
* ====================================================
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD>Mark<EFBFBD>λ<EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>Ծ<EFBFBD><EFBFBD>е<EFBFBD>mark<EFBFBD><EFBFBD><EFBFBD><EFBFBD>о<EFBFBD>ƫ<EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD>ܲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ܻ<EFBFBD>ʶ<EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD>Ȼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD>ͳ<EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>2020/5/22
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>ʱ<EFBFBD>2020/5/22 v1.0
2020/7/29 v1.1 <EFBFBD>Ż<EFBFBD>Mark<EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
2020/7/30 v1.1.1 <EFBFBD>Ż<EFBFBD>Mark<EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
2020/8/3 v1.2 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Mark<EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>ԭ<EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>
2020/8/12 v1.3 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD>Ծ<EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊָ<EFBFBD><EFBFBD><EFBFBD>Ծ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>Ǵ<EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׼ȷʶ<EFBFBD><EFBFBD>
apply<EFBFBD>ӿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>barCode<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2020/8/12 v1.4 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӳü<EFBFBD><EFBFBD>ӿڣ<EFBFBD><EFBFBD>ɽ<EFBFBD><EFBFBD>вü<EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>ţ<EFBFBD>v1.4
* ====================================================
*/
#ifndef IMAGEMARKCROPAPPLY_H
#define IMAGEMARKCROPAPPLY_H
#include "ImageApply.h"
class CImageApplyMarkCrop
{
public:
//ʶ<><CAB6><EFBFBD>ĸ巽<C4B8><E5B7BD>ʽ
enum DirectionMethod
{
Trilateral_7Net, //<2F><><EFBFBD>߶<EFBFBD>λ<EFBFBD>ĸ巽<C4B8><E5B7BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Multilateral //<2F><>߶<EFBFBD>λ<EFBFBD>ĸ巽<C4B8><E5B7BD>
};
enum DPI : ushort
{
DPI_200 = 200,
DPI_300 = 300
};
enum DeviceModel
{
G400 = 2,
G300 = 3
};
enum Orientation
{
Default = 0,
Left_RT, //<2F><><EFBFBD><EFBFBD>ĸ巽<C4B8><E5B7BD>ʶ<EFBFBD><CAB6>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>7<EFBFBD><37>3markʶ<6B><CAB6>ʱ<EFBFBD><CAB1>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
Top_RB, //<2F><><EFBFBD><EFBFBD>ĸ巽<C4B8><E5B7BD>ʶ<EFBFBD><CAB6>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>7<EFBFBD><37>3markʶ<6B><CAB6>ʱ<EFBFBD><CAB1>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
Right_LB, //<2F><><EFBFBD><EFBFBD>ĸ巽<C4B8><E5B7BD>ʶ<EFBFBD><CAB6>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>7<EFBFBD><37>3markʶ<6B><CAB6>ʱ<EFBFBD><CAB1>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
Bottom_LT //<2F><><EFBFBD><EFBFBD>ĸ巽<C4B8><E5B7BD>ʶ<EFBFBD><CAB6>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>7<EFBFBD><37>3markʶ<6B><CAB6>ʱ<EFBFBD><CAB1>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>
};
public:
CImageApplyMarkCrop(DeviceModel device, bool isCropped = true, double threshold = 20, int noise = 40, DPI dpi = DPI::DPI_200, DirectionMethod direction = DirectionMethod::Multilateral);
/*
* src [in]: ԭͼ
* dst [out]:<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>صĽ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
* markOri [in]: <EFBFBD>ĸ<EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD>ʽ
* barCode [in]: <EFBFBD>Ƿ<EFBFBD><EFBFBD>ж<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD><EFBFBD><EFBFBD>Trilateral_7Netģʽ
* angle [out]:<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><EFBFBD>ƫת<EFBFBD>Ƕȡ<EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><EFBFBD>90<EFBFBD><EFBFBD>180<EFBFBD><EFBFBD>270<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD> 0<EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><EFBFBD><EFBFBD>
-1<EFBFBD><EFBFBD>ԭͼΪ<EFBFBD>գ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD>ҵ<EFBFBD>ͼƬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ô<EFBFBD><EFBFBD>󣩣<EFBFBD>
-2<EFBFBD><EFBFBD>markС<EFBFBD><EFBFBD>3<EFBFBD><EFBFBD>
-3<EFBFBD><EFBFBD>ѡ<EFBFBD><EFBFBD>Multilateralģʽʱ<EFBFBD><EFBFBD>mark<EFBFBD><EFBFBD>С<EFBFBD><EFBFBD>4<EFBFBD><EFBFBD>
-4<EFBFBD><EFBFBD>ʶ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Ŀ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
-5<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
int apply(const cv::Mat& src, cv::Mat& dst, Orientation markOri, bool barCode, int& angle);
inline DeviceModel getDeviceModel() { return m_device; }
inline void setDeviceModel(DeviceModel device) { m_device = device; }
inline bool isCropped() { return m_b_isCropped; }
inline void setCropped(bool cropped) { m_b_isCropped = cropped; }
inline double getThreshold() { return m_threshold; }
inline void setThreshold(double threshold) { m_threshold = threshold; }
inline int getNoise() { return m_noise; }
inline void setNoise(int noise) { m_noise = noise; }
inline DPI getDPI() { return m_dpi; }
inline void setDPI(DPI dpi) { m_dpi = dpi; }
inline const cv::Range getSizeRange() { return m_range; }
inline void setSizeRange(const cv::Range& range) { m_range = range; }
inline void setSizeRange(int low, int up) { m_range = cv::Range(low, up); }
private:
void findMarks(const std::vector<std::vector<cv::Point>>& contours, const cv::RotatedRect& region, const cv::Range& range,
std::vector<std::vector<cv::Point>>& marks, std::vector<cv::RotatedRect>& rrect);
bool isContainBarCode(const cv::Mat& image);
private:
DeviceModel m_device;
bool m_b_isCropped;
double m_threshold;
int m_noise;
DPI m_dpi;
cv::Range m_range;
DirectionMethod m_direction;
};
#endif // IMAGEMARKCROPAPPLY_H

View File

@ -0,0 +1,257 @@
#include "ImageApplyOutHole.h"
#include "ImageProcess_Public.h"
#ifdef LOG
#include "Device/filetools.h"
#endif // LOG
CImageOutHole::CImageOutHole(void)
: CImageApply()
, m_borderSize(200)
, m_edgeScale(0.1f)
, m_threshold(50)
{
}
CImageOutHole::CImageOutHole(float borderSize, float edgeScale, double threshold)
: CImageApply()
, m_borderSize(borderSize)
, m_edgeScale(edgeScale)
, m_threshold(threshold)
{
}
CImageOutHole::~CImageOutHole(void)
{
}
void CImageOutHole::apply(cv::Mat& pDib, int side)
{
(void)pDib;
(void)side;
}
void CImageOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter ImageOutHole apply");
#endif // LOG
if (mats.size() < 2)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
return;
}
if (mats[0].empty() || mats[1].empty())
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
return;
}
//二值化正反面图像
cv::Mat front = mats[0];
cv::Mat back = mats[1];
cv::Mat front_thre, back_thre;
hg::threshold_Mat(front, front_thre, m_threshold);
hg::threshold_Mat(back, back_thre, m_threshold);
//反面二值化图像水平翻转
cv::flip(back_thre, back_thre, 1); //1:Horizontal
//正反面图像寻边
std::vector<std::vector<cv::Point>> contours_front, contours_back;
std::vector<cv::Vec4i> b1_front, b1_back;
hg::findContours(front_thre.clone(), contours_front, b1_front, cv::RETR_EXTERNAL);
hg::findContours(back_thre.clone(), contours_back, b1_back, cv::RETR_EXTERNAL);
//提取正反面图像最大轮廓
std::vector<cv::Point> maxContour_front = hg::getMaxContour(contours_front, b1_front);
std::vector<cv::Point> maxContour_back = hg::getMaxContour(contours_back, b1_back);
cv::RotatedRect rrect_front = hg::getBoundingRect(maxContour_front); //提取正面最大轮廓的最小外接矩形
cv::RotatedRect rrect_back = hg::getBoundingRect(maxContour_back); //提取反面最大轮廓的最小外接矩形
//提取正反面图像重叠部分区域
cv::Rect roi_front, roi_back;
cv::RotatedRect mask_rotatedRect;
getRoi(rrect_front, rrect_back, cv::Size(front.cols, front.rows), roi_front, roi_back, mask_rotatedRect);
cv::Mat roiMat_front(front_thre, roi_front); //在正面二值图像中截取重叠部分
cv::Mat roiMat_back(back_thre, roi_back); //在反面二值图像中截取重叠部分
//正反面二值图像做或运算真正镂空区域保留0其他地方填充为255
cv::Mat mask;
bitwise_or(roiMat_front, roiMat_back, mask); //或运算,正反面二值图像重叠
//二值图像重叠图像颜色取反,膨胀,提取轮廓
std::vector<std::vector<cv::Point>> contours_mask;
std::vector<cv::Vec4i> b1_mask;
bitwise_not(mask, mask); //反色
cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(15, 15));
dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //膨胀算法,增大孔洞连通区域面积
//为了避免孔洞彻底贯穿纸边,人为绘制纸张轮廓,确保所有孔洞为封闭图形,不会与背景粘连
polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(0), 15); //绘制纸张矩形边缘
hg::findContours(mask.clone(), contours_mask, b1_mask, cv::RETR_TREE); //提取重叠图像轮廓
//过滤非孔洞的联通区域
std::vector<std::vector<cv::Point>> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize);
for (size_t i = 0; i < hole_contours.size(); i++)
cv::drawContours(mask, hole_contours, static_cast<int>(i), cv::Scalar(127), 2);
for (size_t i = 0; i < hole_contours.size(); i++)
{
cv::Scalar color = getBackGroudColor(front(roi_front), hole_contours[i]);
cv::Mat temp = front(roi_front);
std::vector<std::vector<cv::Point>> contourss_temp;
contourss_temp.push_back(hole_contours[i]);
hg::fillPolys(temp, contourss_temp, color);
}
if (isTwoSide)
{
int width_ = roi_back.width;
roi_back.x = back.cols - roi_back.width - roi_back.x; //因为之前反面图像翻转所以现在ROI也要进行相应翻转
for (size_t i = 0; i < hole_contours.size(); i++)
{
std::vector<cv::Point> hole_contour;
for (size_t j = 0; j < hole_contours[i].size(); j++)
hole_contour.push_back(cv::Point(width_ - hole_contours[i][j].x - 1, hole_contours[i][j].y));
cv::Scalar color = getBackGroudColor(back(roi_back), hole_contour);
cv::Mat temp = back(roi_back);
std::vector<std::vector<cv::Point>> contours_temp;
contours_temp.push_back(hole_contour);
hg::fillPolys(temp, contours_temp, color);
}
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG
}
void CImageOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize,
cv::Rect& roi_front, cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect)
{
cv::Size size(static_cast<int>(rrect_front.size.width + rrect_back.size.width) / 2, static_cast<int>(rrect_front.size.height + rrect_back.size.height) / 2);
float angle = (rrect_front.angle + rrect_back.angle) / 2;
rrect_front.size = rrect_back.size = size;
rrect_front.angle = rrect_back.angle = angle;
roi_front = rrect_front.boundingRect();
roi_back = rrect_back.boundingRect();
if (roi_front.width != roi_back.width || roi_front.height != roi_back.height)
{
roi_front.height = roi_back.height;
roi_front.width = roi_back.width;
}
cv::Point offset(0, 0);
int top = std::min(roi_front.y, roi_back.y);
if (top < 0)
{
roi_front.y -= top;
roi_back.y -= top;
roi_front.height += top;
roi_back.height += top;
offset.y += top;
}
int left = std::min(roi_front.x, roi_back.x);
if (left < 0)
{
roi_front.x -= left;
roi_back.x -= left;
roi_front.width += left;
roi_back.width += left;
offset.x += left;
}
int right = std::max(roi_front.x + roi_front.width, roi_back.x + roi_back.width);
if (right >= srcSize.width)
{
roi_front.width -= (right - srcSize.width + 1);
roi_back.width -= (right - srcSize.width + 1);
}
int bottom = std::max(roi_front.y + roi_front.height, roi_back.y + roi_back.height);
if (bottom >= srcSize.height)
{
roi_front.height -= (bottom - srcSize.height + 1);
roi_back.height -= (bottom - srcSize.height + 1);
}
mask_rotatedRect.center = cv::Point((roi_front.width + offset.x) / 2, (roi_front.height + offset.y) / 2);
mask_rotatedRect.size = size;
mask_rotatedRect.angle = angle;
}
std::vector<std::vector<cv::Point>> CImageOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m,
cv::RotatedRect roi, float edgeScale, float areaThreshold)
{
edgeScale = std::min(0.49f, std::max(edgeScale, 0.0f));
cv::RotatedRect roi2(roi.center, cv::Size(static_cast<int>(roi.size.width * (1 - edgeScale * 2)),
static_cast<int>(roi.size.height * (1 - edgeScale * 2))), roi.angle);
std::vector<cv::Point> vertices_roi1 = hg::getVertices(roi);
std::vector<cv::Point> vertices_roi2 = hg::getVertices(roi2);
std::vector<std::vector<cv::Point>> hole_contours;
for (size_t i = 0, length = contours.size(); i < length; i++)
{
if (m[i][2] != -1) continue;
cv::RotatedRect rrect = hg::getBoundingRect(contours[i]);
if (rrect.size.width > areaThreshold || rrect.size.height > areaThreshold) continue;
bool enabled = true;
for (size_t j = 0, count = contours[i].size(); j < count; j++)
{
cv::Point p(contours[i][j]);
double temp1 = pointPolygonTest(vertices_roi1, p, false); //判断是否在纸张内 10-1
double temp2 = pointPolygonTest(vertices_roi2, p, false); //判断是否在边缘区域内 10-1
//如果在纸张外,或者边缘内,视为非孔洞
if (temp1 < 0 || temp2 > 0)
{
enabled = false;
break;
}
}
if (enabled)
hole_contours.push_back(contours[i]);
}
return hole_contours;
}
cv::Scalar CImageOutHole::getBackGroudColor(const cv::Mat &image, const std::vector<cv::Point> pixelPoints)
{
if (pixelPoints.empty()) return cv::Scalar(255, 255, 255);
int channels = image.channels();
int temp[3] = { 0 };
for (size_t i = 0, length = pixelPoints.size(); i < length; ++i)
{
int x = cv::min(cv::max(0, pixelPoints[i].x), image.cols - 1);
int y = cv::min(cv::max(0, pixelPoints[i].y), image.rows - 1);
const unsigned char* ptr = image.ptr(y, x);
for (int j = 0; j < channels; ++j)
temp[j] += ptr[j];
}
return cv::Scalar(temp[0] / static_cast<int>(pixelPoints.size()),
temp[1] / static_cast<int>(pixelPoints.size()),
temp[2] / static_cast<int>(pixelPoints.size()));
}

View File

@ -0,0 +1,49 @@
#ifndef IMAGE_APPLY_OUT_HOLE_H
#define IMAGE_APPLY_OUT_HOLE_H
#include "ImageApply.h"
class CImageOutHole : public CImageApply
{
public:
CImageOutHole();
CImageOutHole(float borderSize, float edgeScale, double threshold);
~CImageOutHole(void);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
float getBorderSize() { return m_borderSize; }
float getEdgeScale() { return m_edgeScale; }
double getThreshold() { return m_threshold; }
void setBorderSize(float size) { m_borderSize = size; }
void setEdgeScale(float scale) { m_edgeScale = scale; }
void setThreshold(double threshold) { m_threshold = (std::min)((std::max)(threshold, 1.0), 254.0); }
private:
virtual void apply(cv::Mat& pDib, int side);
void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, cv::Rect& roi_front,
cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect);
std::vector<std::vector<cv::Point> > filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i> &m, cv::RotatedRect roi,
float edgeScale, float areaThreshold);
cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints);
private:
float m_borderSize;
float m_edgeScale;
double m_threshold;
};
#endif // !IMAGE_APPLY_OUT_HOLE_H

View File

@ -0,0 +1,57 @@
#include "ImageApplyRefuseInflow.h"
CImageApplyRefuseInflow::CImageApplyRefuseInflow()
{
}
CImageApplyRefuseInflow::~CImageApplyRefuseInflow()
{
}
void CImageApplyRefuseInflow::apply(cv::Mat& pDib, int side)
{
(void)side;
static unsigned char table_contrast[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 198, 199,
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255 };
static cv::Mat mat_table(1, 256, CV_8UC1, table_contrast);
cv::LUT(pDib, mat_table, pDib);
}
void CImageApplyRefuseInflow::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,29 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_REFUSE_INFLOW_H
#define IMAGE_APPLY_REFUSE_INFLOW_H
#include "ImageApply.h"
class CImageApplyRefuseInflow : public CImageApply
{
public:
CImageApplyRefuseInflow();
virtual ~CImageApplyRefuseInflow();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
};
#endif // !IMAGE_APPLY_REFUSE_INFLOW_H

View File

@ -0,0 +1,47 @@
#include "ImageApplyResize.h"
CImageApplyResize::CImageApplyResize()
: m_fx(1.0)
, m_fy(1.0)
, m_type(ResizeType::RATIO)
{
}
CImageApplyResize::CImageApplyResize(ResizeType type, const cv::Size& size, double fx, double fy)
: m_type(type)
, m_dSize(size)
, m_fx(fx)
, m_fy(fy)
{
}
CImageApplyResize::~CImageApplyResize(void)
{
}
void CImageApplyResize::apply(cv::Mat& pDib,int side)
{
(void)side;
if (pDib.empty()) return;
if (m_type == ResizeType::RATIO)
cv::resize(pDib, pDib, cv::Size(0, 0), m_fx, m_fy);
else
cv::resize(pDib, pDib, m_dSize);
}
void CImageApplyResize::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,57 @@
#ifndef IMAGE_APPLY_RESIZE_H
#define IMAGE_APPLY_RESIZE_H
#include "imageapply.h"
class CImageApplyResize : public CImageApply
{
public:
enum class ResizeType
{
RATIO,
DSIZE
};
public:
CImageApplyResize();
/*
* type [in]:
* size [in]:type为DSIZE时生效
* fx [in]:type为RATIO时生效
* fy [in]:type为RATIO时生效
*/
CImageApplyResize(ResizeType type, const cv::Size& size, double fx, double fy);
virtual ~CImageApplyResize(void);
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
double getFX() { return m_fx; }
double getFY() { return m_fy; }
cv::Size getDSize() { return m_dSize; }
ResizeType getType() { return m_type; }
void setFX(double value) { m_fx = value; }
void setFY(double value) { m_fy = value; }
void setDSize(const cv::Size& size) { m_dSize = size; }
void setType(ResizeType type) { m_type = type; }
private:
double m_fx;
double m_fy;
cv::Size m_dSize;
ResizeType m_type;
};
#endif // !IMAGE_APPLY_RESIZE_H

View File

@ -0,0 +1,131 @@
#include "ImageApplyRotation.h"
//#define USE_TESSERCAT
#ifdef USE_TESSERCAT
//#define HG_GPDF_API_BUILD
#include "hg_gpdf.h"
#endif
CImageApplyRotation::CImageApplyRotation(RotationType rotation, bool isBackTransposed, int dpi, const char* tessdataPath)
: m_rotation(rotation)
, m_backTranspose(isBackTransposed)
, m_dpi(dpi)
, osd(nullptr)
{
if (rotation == RotationType::AutoTextOrientation)
{
#ifdef USE_TESSERCAT
osd = new HG_OCR();
reinterpret_cast<HG_OCR*>(osd)->init(tessdataPath, HG_OCR::RECOGNITION_OSD);
#endif
}
}
CImageApplyRotation::~CImageApplyRotation()
{
#ifdef USE_TESSERCAT
if (osd) delete reinterpret_cast<HG_OCR*>(osd);
#endif
}
void CImageApplyRotation::apply(cv::Mat & pDib, int side)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter CImageApplyRotation apply");
#endif // LOG
if (pDib.empty())
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyRotation apply");
#endif // LOG
return;
}
if (m_rotation == RotationType::AutoTextOrientation) //<2F>Զ<EFBFBD><D4B6>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><CAB6>
{
#ifdef USE_TESSERCAT
if (osd)
{
cv::Mat temp;
if (m_dpi != 200)
{
double scale = 200 / static_cast<double>(m_dpi);
int new_w = static_cast<int>(pDib.cols * scale) / 4 * 4;
int new_h = pDib.rows * scale;
cv::resize(pDib, temp, cv::Size(new_w, new_h));
}
else
temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone();
if (temp.channels() == 3)
cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY);
cv::threshold(temp, temp, 180, 255, cv::THRESH_OTSU);
HG_OCR* ptr_osd = reinterpret_cast<HG_OCR*>(osd);
int orientation = ptr_osd->orientation(temp.data, temp.cols, temp.rows, temp.channels(), 200);
switch (orientation)
{
case 90:
cv::transpose(pDib, pDib);
cv::flip(pDib, pDib, 0);
break;
case 180:
cv::flip(pDib, pDib, 0);
cv::flip(pDib, pDib, 1);
break;
case 270:
cv::transpose(pDib, pDib);
cv::flip(pDib, pDib, 1);
break;
default:
break;
}
}
#endif
}
else if (m_backTranspose && side == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת180
{
if (m_rotation != RotationType::Rotate_180) //<2F><>ת180<38><30>
{
if (m_rotation == RotationType::Rotate_90_clockwise || m_rotation == RotationType::Rotate_90_anti_clockwise) //90<39><30> -90<39><30>
{
transpose(pDib, pDib);
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 1 : 0);
}
else
{
flip(pDib, pDib, 0);
flip(pDib, pDib, 1);
}
}
}
else //zh
{
if (m_rotation == RotationType::Rotate_90_clockwise || m_rotation == RotationType::Rotate_90_anti_clockwise) //90<39><30> -90<39><30>
{
transpose(pDib, pDib);
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 0 : 1);
}
else if (m_rotation == RotationType::Rotate_180)
{
flip(pDib, pDib, 0);
flip(pDib, pDib, 1);
}
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyRotation apply");
#endif // LOG
}
void CImageApplyRotation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (!var.empty()) {
apply(var, i);
i++;
}
}
}

View File

@ -0,0 +1,68 @@
/*
* ====================================================
*
*
* 2020/4/21
* v1.0 2020/4/21
v1.1 2020/8/12 稿BUG
* v1.1
* ====================================================
*/
#ifndef IMAGE_APPLY_ROTATION_H
#define IMAGE_APPLY_ROTATION_H
#include "ImageApply.h"
class CImageApplyRotation : public CImageApply
{
public:
enum class RotationType
{
Invalid, //无效
Rotate_90_clockwise, //顺时针90°
Rotate_180, //180°
Rotate_90_anti_clockwise, //逆时针90°即270°
AutoTextOrientation //自动文稿方向识别旋转
};
public:
/*
* rotation [in]:
* isBackTransposed [in]:true为背面180°
* dpi [in]:DPIrotation为AutoTextOrientation时生效稿200DPI进行识别
* tessadataPath [in]:rotation为AutoTextOrientation时生效
*/
CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr);
virtual ~CImageApplyRotation();
virtual void apply(cv::Mat & pDib, int side) override;
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
bool isBackTransposed() { return m_backTranspose; }
int getDPI() { return m_dpi; }
RotationType getRotationType() { return m_rotation; }
void setBackTransposed(bool enabled) { m_backTranspose = enabled; }
void setDPI(int dpi) { m_dpi = dpi; }
void setRotationType(RotationType type) { m_rotation = type; }
private:
RotationType m_rotation;
bool m_backTranspose;
int m_dpi;
void* osd;
};
#endif // !IMAGE_APPLY_ROTATION_H

View File

@ -0,0 +1,61 @@
#include "ImageApplySharpen.h"
using namespace cv;
CImageApplySharpen::CImageApplySharpen(int sharpentype)
{
sharpenType = sharpentype;
kSize = (sharpentype == FilterMethod::Sharpen || sharpentype == FilterMethod::AverBlur) ? 5 : 9;
}
CImageApplySharpen::~CImageApplySharpen()
{
}
void CImageApplySharpen::apply(cv::Mat & pDib, int side)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter CImageApplySharpen apply");
#endif // LOG
switch (sharpenType)
{
case CImageApplySharpen::Sharpen:
case CImageApplySharpen::Sharpen_More:
sharpen(pDib, kSize);
break;
case CImageApplySharpen::AverBlur:
case CImageApplySharpen::AverBlur_More:
averblur(pDib, static_cast<int>(kSize));
break;
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplySharpen apply");
#endif // LOG
}
void CImageApplySharpen::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
if (mats.empty()) return;
if (!mats[0].empty())
apply(mats[0], 0);
if (isTwoSide && mats.size() > 1) {
if (!mats[1].empty())
apply(mats[1], 1);
}
}
void CImageApplySharpen::averblur(Mat& src, int kSize)
{
blur(src, src, Size(kSize, kSize));
}
void CImageApplySharpen::sharpen(Mat& src, float kSize)
{
float other = (1.0f - kSize) / 4;
float kernel_data[] = { 0, other, 0, other, kSize, other, 0, other, 0 };
Mat kernel(3, 3, CV_32FC1, kernel_data);
filter2D(src, src, src.depth(), kernel);
}

View File

@ -0,0 +1,32 @@
#ifndef IMAGE_APPLY_SHARPEN_H
#define IMAGE_APPLY_SHARPEN_H
#include "ImageApply.h"
class CImageApplySharpen :
public CImageApply
{
public:
enum FilterMethod
{
None,
Sharpen,
Sharpen_More,
AverBlur,
AverBlur_More
};
CImageApplySharpen(int sharpentype);
virtual ~CImageApplySharpen();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
void averblur(cv::Mat& src, int kSize);
void sharpen(cv::Mat& src, float kSize);
private:
int sharpenType;
float kSize;
};
#endif // !IMAGE_APPLY_SHARPEN_H

View File

@ -0,0 +1,110 @@
#include "ImageApplySplit.h"
#include <vector>
#define BPP(type,index)
CImageApplySplit::CImageApplySplit(int multitype,bool split, bool ismulti_filter_red,int colormode) :
m_bmulti_filter_red(ismulti_filter_red)
, m_split(split)
, m_multitype(multitype)
, m_colormode(colormode)
{
}
CImageApplySplit::~CImageApplySplit(void)
{
}
std::vector<MatEx> CImageApplySplit::SplitMats(std::vector<cv::Mat>& mats, bool isTwoSide)
{
std::vector<MatEx> rets;
for (size_t i = 0; i < mats.size(); i++)
{
if (mats[i].empty())
continue;
int bpp = getBpp(i);
if(m_split)//²ð·Ö
{
std::vector<cv::Mat> retmats = apply(mats[i]);
if (bpp != -1) {
}
else {//½ö²ð·Ö
if (m_colormode == 0) bpp = 1;//bw
else if (m_colormode == 1) bpp = 8;
else bpp = 24;
}
for (size_t j = 0; j < retmats.size(); j++)
{
if (!retmats[j].empty()) {
MatEx matex(retmats[j], bpp);
rets.push_back(matex);
}
}
}
else{
MatEx matex(mats[i], bpp);
rets.push_back(matex);
}
}
return rets;
}
std::vector<cv::Mat> CImageApplySplit::apply(cv::Mat& pDib)
{
if (pDib.empty())
return std::vector<cv::Mat>();
std::vector<cv::Mat> retMats;
int heigth = pDib.rows;
int width = pDib.cols;
if (heigth > width)
{
cv::Mat matF = pDib(cv::Rect(0, 0, width, (int)(0.5 * heigth)));
cv::Mat matB = pDib(cv::Rect(0, (int)(0.5 * heigth), width, (int)(0.5 * heigth)));
retMats.push_back(matF);
retMats.push_back(matB);
}
else
{
cv::Mat matF = pDib(cv::Rect(0, 0, (int)(width*0.5), heigth));
cv::Mat matB = pDib(cv::Rect((int)(width*0.5), 0, (int)(width * 0.5), heigth));
retMats.push_back(matF);
retMats.push_back(matB);
}
return retMats;
}
int CImageApplySplit::getBpp(int matIndex)
{
int ret = -1;
if (m_bmulti_filter_red) {
ret = matIndex == 0 ? 24 : 8;
}
else
{
if (m_multitype == -1)
return ret;
switch (m_multitype)
{
case 0://all
if (matIndex == 0) ret = 24;
else if (matIndex == 1) ret = 8;
else ret = 1;
break;
case 1://clolr +gray
if (matIndex == 0) ret = 24;
else ret = 8;
break;
case 2://color+bw
if (matIndex == 0) ret = 24;
else ret = 1;
break;
case 3://gray+bw
if (matIndex == 0) ret = 8;
else ret = 1;
break;
default:
break;
}
}
return ret;
}

View File

@ -0,0 +1,36 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#include "IMulti.h"
#ifndef IMAGE_APPLY_SPLIT_H
#define IMAGE_APPLY_SPLIT_H
#include "MatEx.h"
#include <vector>
#include "imgprocdefs.h"
class CImageApplySplit :public IMulti
{
public:
CImageApplySplit(int multitype=-1,bool split=false,bool ismulti_filter_red=false,int colormode=1);//默认不多流输出 不多流除红 灰度
~CImageApplySplit(void);
std::vector<MatEx> SplitMats(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
std::vector<cv::Mat> apply(cv::Mat& pDib);
int getBpp(int matIndex);
private://field
bool m_bmulti_filter_red;
int m_multitype;
int m_colormode;
bool m_split;
};
#endif // !IMAGE_APPLY_SPLIT_H

View File

@ -0,0 +1,172 @@
#include "ImageApplyTextureRemoval.h"
//交换对角线
void zero_to_center(cv::Mat& image, int colToCut, int rowToCut)
{
cv::Mat q1(image, cv::Rect(0, 0, colToCut, rowToCut));
cv::Mat q2(image, cv::Rect(colToCut, 0, colToCut, rowToCut));
cv::Mat q3(image, cv::Rect(0, rowToCut, colToCut, rowToCut));
cv::Mat q4(image, cv::Rect(colToCut, rowToCut, colToCut, rowToCut));
//第二象限和第四象限进行交换
cv::Mat tmpImg;
q1.copyTo(tmpImg);
q4.copyTo(q1);
tmpImg.copyTo(q4);
//第一象限和第三象限进行交换
q2.copyTo(tmpImg);
q3.copyTo(q2);
tmpImg.copyTo(q3);
}
//创建光谱
cv::Mat create_spectrum(cv::Mat* matArray, double scale = 1.5)
{
cv::Mat dst;
cv::magnitude(matArray[0], matArray[1], dst);
#if 1
cv::divide(dst, dst.cols * dst.rows, dst, scale);
//imshow("频谱", dst);
#else
dst += Scalar::all(1);
log(dst, dst);
normalize(dst, dst, 1, 0, CV_MINMAX);
#endif
#if 0
imshow("频谱", dst);
#endif
return dst;
}
//反傅里叶变换
void inverseFourierTransform(const cv::Mat& src, cv::Mat& dst)
{
cv::Mat complexIDFT;
cv::Mat matArray[2];
cv::idft(src, complexIDFT);
cv::split(complexIDFT, matArray);
cv::magnitude(matArray[0], matArray[1], dst);
cv::normalize(dst, dst, 0, 1, CV_MINMAX);
}
//制作陷波滤波器
cv::Mat createFilter(const cv::Mat& spectrum, int dilateSize, int erodeSize)
{
cv::Mat temp;
spectrum.convertTo(temp, CV_8UC1, 255);
cv::threshold(temp, temp, 0, 255, CV_THRESH_OTSU);
//imshow("二值化", temp);
cv::Mat element1 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(dilateSize, dilateSize));
cv::Mat element2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(erodeSize, erodeSize));
cv::dilate(temp, temp, element1);
cv::erode(temp, temp, element2);
cv::floodFill(temp, cv::Point(temp.cols / 2, temp.rows / 2), cv::Scalar(0)); //漫水填充中心区域
cv::medianBlur(~temp, temp, 3); //中值滤波
//temp = ~temp;
//cv::imshow("二值化", temp);
//陷波滤波器复制
cv::Mat filter;
temp.convertTo(filter, CV_32FC1);
cv::normalize(filter, filter, 1, 0.01, CV_MINMAX);
std::vector<cv::Mat> mv;
mv.push_back(filter);
mv.push_back(filter);
cv::merge(mv, filter);
return filter;
}
void CImageApplyTextureRemoval::textureRemovalGray(cv::Mat& img)
{
//得到DFT的最佳尺寸2的指数以加速计算
cv::Mat paddedImg;
int m = cv::getOptimalDFTSize(img.rows);
int n = cv::getOptimalDFTSize(img.cols);
//填充图像的下端和右端
cv::copyMakeBorder(img, paddedImg, 0, m - img.rows, 0, n - img.cols,
cv::BORDER_CONSTANT, cv::Scalar::all(0));
//将填充的图像组成一个复数的二维数组两个通道的Mat用于DFT
cv::Mat matArray[] = { cv::Mat_<float>(paddedImg), cv::Mat::zeros(paddedImg.size(), CV_32F) };
cv::Mat complexInput, complexOutput;
cv::merge(matArray, 2, complexInput);
cv::dft(complexInput, complexOutput);
cv::split(complexOutput, matArray); //计算幅度谱(傅里叶谱)
//滤波
//将实部和虚部按照频谱图的方式换位
//低频在图像中心,用于滤波
zero_to_center(matArray[0], complexOutput.cols / 2, complexOutput.rows / 2);
zero_to_center(matArray[1], complexOutput.cols / 2, complexOutput.rows / 2);
cv::Mat spectrum = create_spectrum(matArray);
//创建滤波器
cv::Mat filter = createFilter(spectrum, m_dilateSize, m_erodeSize);
cv::merge(matArray, 2, complexOutput);
cv::multiply(complexOutput, filter, filter);
//IDFT得到滤波结果
cv::Size imgSize = img.size();
inverseFourierTransform(filter, img);
img = img(cv::Rect(cv::Point(0, 0), imgSize));
img *= 255;
img.convertTo(img, CV_8UC1);
}
CImageApplyTextureRemoval::CImageApplyTextureRemoval()
: CImageApply()
, m_dilateSize(5)
, m_erodeSize(3)
{
}
CImageApplyTextureRemoval::CImageApplyTextureRemoval(int dilateSize, int erodeSize)
: CImageApply()
, m_dilateSize(dilateSize)
, m_erodeSize(erodeSize)
{
}
CImageApplyTextureRemoval::~CImageApplyTextureRemoval()
{
}
void CImageApplyTextureRemoval::apply(cv::Mat &pDib, int side)
{
(void)side;
if (pDib.channels() == 1)
textureRemovalGray(pDib);
else
{
std::vector<cv::Mat> rgb(3);
cv::split(pDib, rgb);
for (cv::Mat& var : rgb)
textureRemovalGray(var);
cv::merge(rgb, pDib);
}
pDib *= 1.15;
}
void CImageApplyTextureRemoval::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -0,0 +1,50 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_APPLY_TEXTURE_REMOVAL_H
#define IMAGE_APPLY_TEXTURE_REMOVAL_H
#include "ImageApply.h"
class CImageApplyTextureRemoval : public CImageApply
{
public:
CImageApplyTextureRemoval(void);
/*
* dilateSize [in]:
* erodeSize [in]:
*/
CImageApplyTextureRemoval(int dilateSize, int erodeSize);
virtual ~CImageApplyTextureRemoval(void);
virtual void apply(cv::Mat& pDib,int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
int getDilateSize() {return m_dilateSize;}
int getErodeSize() {return m_erodeSize;}
void setDilateSize(int size) {m_dilateSize = size;}
void setErodeSize(int size) {m_erodeSize = size;}
private:
void textureRemovalGray(cv::Mat& img);
private:
int m_dilateSize;
int m_erodeSize;
};
#endif

View File

@ -0,0 +1,186 @@
#include "ImageApplyUVMerge.h"
#include "ImageProcess_Public.h"
using namespace cv;
#define SCA 50
CImageApplyUVMerge::CImageApplyUVMerge(): lut(1, 256, CV_8UC1)
{
}
CImageApplyUVMerge::~CImageApplyUVMerge()
{
}
void CImageApplyUVMerge::update_lutData(int contrast)
{
unsigned char* ptr = lut.data;
int m_contrast = cv::max(-127, cv::min(contrast, 127));
for (int i = 0; i < 256; i++)
{
//update contrast
if (i < 128)
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i - m_contrast, 127)));
else
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(i + m_contrast, 255)));
}
}
void CImageApplyUVMerge::Apply(cv::Mat& image, const cv::Mat& uv, int dpi, int thresh)
{
update_lutData(12);
cv::LUT(uv, lut, uv);
Mat uv_resize;
cv::resize(uv, uv_resize, cv::Size(uv.cols * SCA / dpi, uv.rows * SCA / dpi));
if (uv_resize.channels() == 3)
cv::cvtColor(uv_resize, uv_resize, cv::COLOR_BGR2GRAY);
cv::threshold(uv_resize, uv_resize, 0, 255, THRESH_OTSU);
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1500 / dpi, 1500 / dpi));
cv::dilate(uv_resize, uv_resize, element);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
hg::findContours(uv_resize, contours, hierarchy, cv::RETR_EXTERNAL);
std::map<int, cv::Scalar> map_color;
for (int i = 0; i < contours.size(); i++)
{
cv::Rect roi = cv::boundingRect(contours[i]);
roi.x *= dpi / SCA;
roi.y *= dpi / SCA;
roi.width *= dpi / SCA;
roi.height *= dpi / SCA;
purgeQR_kernal(image, roi, map_color, dpi, thresh);
}
}
cv::Mat CImageApplyUVMerge::Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle)
{
if (uvRoi.size.width == 0) return cv::Mat();
cv::RotatedRect uvRoi_clone = uvRoi;
cv::Mat dst = cv::Mat::zeros(image.rows > image.cols ? image.rows : (image.rows * 2), image.cols > image.rows ? image.cols : (image.cols * 2), image.type());
image.copyTo(dst(cv::Rect(0, 0, image.cols, image.rows)));
cv::Mat dst_uv = dst(cv::Rect(image.rows > image.cols ? image.cols : 0, image.rows > image.cols ? 0 : image.rows, image.cols, image.rows));
if (isDesaskew)
{
cv::Point2f srcTri[4];
cv::Point2f dstTri[3];
uvRoi_clone.points(srcTri);
if (angle == 90)
{
dstTri[0] = cv::Point2f(0, 0);
dstTri[1] = cv::Point2f(dst_uv.cols - 1, 0);
dstTri[2] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
}
else if (angle == 180)
{
dstTri[0] = cv::Point2f(dst_uv.cols - 1, 0);
dstTri[1] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
dstTri[2] = cv::Point2f(0, dst_uv.rows - 1);
}
else if (angle == 270)
{
dstTri[0] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
dstTri[1] = cv::Point2f(0, dst_uv.rows - 1);
dstTri[2] = cv::Point2f(0, 0);
}
else
{
dstTri[0] = cv::Point2f(0, dst_uv.rows - 1);
dstTri[1] = cv::Point2f(0, 0);
dstTri[2] = cv::Point2f(dst_uv.cols - 1, 0);
}
cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
if (uv.channels() == 1 && dst_uv.channels() == 3)
{
cv::Mat uv_temp;
cv::warpAffine(uv, uv_temp, warp_mat, dst_uv.size());
cv::cvtColor(uv_temp, dst_uv, cv::COLOR_GRAY2BGR);
}
else
cv::warpAffine(uv, dst_uv, warp_mat, dst_uv.size());
}
else
{
cv::Rect uvBoundingRect = uvRoi_clone.boundingRect();
cv::Rect roi_dst_right;
roi_dst_right.x = dst_uv.cols > uvBoundingRect.width ? (dst_uv.cols - uvBoundingRect.width) / 2 : 0;
roi_dst_right.width = cv::min(dst_uv.cols, uvBoundingRect.width);
roi_dst_right.y = dst_uv.rows > uvBoundingRect.height ? (dst_uv.rows - uvBoundingRect.height) / 2 : 0;
roi_dst_right.height = cv::min(dst_uv.rows, uvBoundingRect.height);
cv::Rect roi_uv_BoundingRect((uvBoundingRect.width - roi_dst_right.width) / 2,
(uvBoundingRect.height - roi_dst_right.height) / 2, roi_dst_right.width, roi_dst_right.height);
Mat uvCrop = (uv(uvBoundingRect))(roi_uv_BoundingRect);
if (uvCrop.channels() == 1 && dst_uv.channels() == 3)
cv::cvtColor(uvCrop, uvCrop, cv::COLOR_GRAY2BGR);
uvCrop.copyTo(dst_uv(roi_dst_right));
}
return dst;
}
void CImageApplyUVMerge::purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map<int, cv::Scalar> map_color, int dpi, int threshold)
{
cv::Mat image_roi = image(roi);
cv::Mat mask;
cv::cvtColor(image_roi, mask, cv::COLOR_BGR2GRAY);
cv::threshold(mask, mask, 127, 255, cv::THRESH_OTSU);
cv::Mat image_resize;
cv::resize(image, image_resize, cv::Size(image.cols, 800));
for (int i = 0, cols = image_roi.cols, rows = image_roi.rows; i < cols; i++)
{
cv::Scalar color_fill;
if (map_color.find(i + roi.x) == map_color.end())
{
color_fill = getColor(image_resize, roi.x + i, threshold);
map_color[i + roi.x] = color_fill;
}
else
color_fill = map_color[i + roi.x];
for (int j = 0; j < rows; j++)
{
if (*mask.ptr<uchar>(j, i))
{
uchar* color = image_roi.ptr<uchar>(j, i);
color[0] = color_fill[0];
color[1] = color_fill[1];
color[2] = color_fill[2];
}
}
}
}
cv::Scalar CImageApplyUVMerge::getColor(const cv::Mat& image, int col, int threshold)
{
cv::Scalar color(0, 0, 0);
int num = 0;
for (int i = 0, length = image.rows; i < length; i++)
{
const uchar* ptr = image.ptr<uchar>(i, col);
int gray = (ptr[0] * 30 + ptr[1] * 59 + ptr[2] * 11) / 100;
if (gray > threshold)
{
color[0] += ptr[0];
color[1] += ptr[1];
color[2] += ptr[2];
num++;
}
}
if (num)
color /= num;
else
color[0] = color[1] = color[2] = 255;
return color;
}

View File

@ -0,0 +1,33 @@
/*
* ====================================================
* ¹¦ÄÜ£ºUVͼÓëԭͼºÏ²¢¡£¸ù¾Ýԭͼ¾ÀÆ«¡¢²Ã¼ôÒÔ¼°ÐýתÇé¿ö£¬UV¸´ÖÆԭͼµÄ´¦Àí£¬²¢ÇÒÓëԭͼƴ½ÓΪһÕÅͼ¡£
¸Ã¹¦ÄÜÓÃÓÚUVÒ»Ìå»úÖС£
* ×÷ÕߣºÁõ¡Î¬
* Éú³Éʱ¼ä£º2020/7/20
* ×î½üÐÞ¸Äʱ¼ä£º2020/7/20
* °æ±¾ºÅ£ºv1.0 2020/7/20
* ====================================================
*/
#ifndef IMAGE_APPLY_UV_MERGE_H
#define IMAGE_APPLY_UV_MERGE_H
#include "ImageApply.h"
class CImageApplyUVMerge
{
public:
CImageApplyUVMerge();
~CImageApplyUVMerge();
void Apply(cv::Mat& image, const cv::Mat& uv, int dpi = 200, int thresh = 100);
static cv::Mat Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle);
private:
void purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map<int, cv::Scalar> map_color, int dpi, int threshold);
cv::Scalar getColor(const cv::Mat& image, int col, int threshold);
void update_lutData(int contrast);
cv::Mat lut;
};
#endif // !IMAGE_APPLY_UV_MERGE_H

View File

@ -0,0 +1,72 @@
#include "ImageMulti.h"
IMageMulti::IMageMulti(int multiType,int thre)
{
m_multiType = multiType;
m_thre = thre;
}
IMageMulti::~IMageMulti(void)
{
}
std::vector<cv::Mat> IMageMulti::apply(cv::Mat& pDib)
{
std::vector<cv::Mat> retMats;
if (pDib.empty())
return retMats;
retMats.push_back(pDib);
switch (m_multiType)
{
case ALL:
{
if (pDib.channels() == 3){
cv::Mat dst;
cv::cvtColor(pDib, dst,cv::COLOR_BGR2GRAY);
retMats.push_back(dst);
}
cv::Mat dstThre;
cv::cvtColor(pDib, dstThre,cv::COLOR_BGR2GRAY);
//cv::threshold(dstThre, dstThre, m_thre, 255, cv::THRESH_BINARY);
cv::adaptiveThreshold(dstThre,dstThre,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,25,5);
if (!dstThre.empty())
{
retMats.push_back(dstThre);
}
}
break;
case COLORGRAY:
{
if (pDib.channels() == 3) {
cv::Mat dstGray;
cv::cvtColor(pDib, dstGray, cv::COLOR_BGR2GRAY);
retMats.push_back(dstGray);
}
}
break;
case COLORBW:
{
if (pDib.channels() == 3) {
cv::Mat dstGray;
cv::cvtColor(pDib, dstGray, cv::COLOR_BGR2GRAY);
cv::Mat dstBW;
cv::adaptiveThreshold(dstGray,dstBW,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,25,5);
retMats.push_back(dstBW);
}
}
break;
case GRAYBW://pDib should be GreyImage(channels() == 1)
{
cv::Mat dstBW;
cv::adaptiveThreshold(pDib,dstBW,255,cv::ADAPTIVE_THRESH_GAUSSIAN_C,cv::THRESH_BINARY,25,5);
if (!dstBW.empty())
{
retMats.push_back(dstBW);
}
}
break;
default:
break;
}
return retMats;
}

26
ImageProcess/ImageMulti.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef IMAGE_MULTI_H
#define IMAGE_MULTI_H
#include "IMulti.h"
class IMageMulti
:public IMulti
{
public:
enum MultiOutput
{
NONE=-1,
ALL,
COLORGRAY,
COLORBW,
GRAYBW
};
public:
IMageMulti(int multiType = 0,int thre = 128);
virtual ~IMageMulti(void);
virtual std::vector<cv::Mat> apply(cv::Mat& pDib);
private:
int m_multiType;
int m_thre;
};
#endif // !IMAGE_MULTI_H

View File

@ -0,0 +1,63 @@
#include "ImageMultiOutputRed.h"
#include <vector>
using namespace std;
ImageMultiOutputRed::ImageMultiOutputRed(short channelIndex)
{
m_channelIndex = channelIndex;
}
ImageMultiOutputRed::~ImageMultiOutputRed(void)
{
}
std::vector<cv::Mat> ImageMultiOutputRed::apply(cv::Mat& pDib)
{
std::vector<cv::Mat> retMats;
if (pDib.empty())
return retMats;
retMats.push_back(pDib);
cv::Mat mat = FilterColor(pDib, m_channelIndex);
if (!mat.empty())
retMats.push_back(mat);
return retMats;
}
cv::Mat ImageMultiOutputRed::FilterColor(cv::Mat image, short channel)
{
cv::Mat dstImage(image.rows, image.cols, CV_8UC1);
int channels = image.channels();
if (channel > channels - 1)
{
return cv::Mat();
}
if ((channel == 3) && (channels != 4) && (channels != 8))
{
return cv::Mat();
}
if (channels <= 4)
{
int srcOffset = image.step - image.cols * channels;
int dstOffset = dstImage.step - dstImage.cols;
unsigned char *src = image.data;
unsigned char *dst = dstImage.data;
src += channel;
for (int y = 0; y < image.rows; y++)
{
for (int x = 0; x < image.cols; x++, src += channels, dst++)
{
unsigned short pix = *src;
if (pix >= 130)
{
pix = 255;
}
*dst = pix;
}
src += srcOffset;
dst += dstOffset;
}
}
return dstImage;
}

View File

@ -0,0 +1,17 @@
#ifndef IMAGE_MULTI_OUTPUT_RED_H
#define IMAGE_MULTI_OUTPUT_RED_H
#include "IMulti.h"
class ImageMultiOutputRed
:public IMulti
{
public:
ImageMultiOutputRed(short channelIndex);
virtual ~ImageMultiOutputRed(void);
virtual std::vector<cv::Mat> apply(cv::Mat& pDib) override;
private:
short m_channelIndex;
cv::Mat FilterColor(cv::Mat image, short channel);
};
#endif //!IMAGE_MULTI_OUTPUT_RED_H

View File

@ -0,0 +1,328 @@
#include "ImageProcess_Public.h"
namespace hg
{
void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise)
{
CvMemStorage* storage = cvCreateMemStorage(); //
CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage
//
for (const cv::Point& item : src)
{
CvPoint p;
p.x = item.x;
p.y = item.y;
cvSeqPush(ptseq, &p);
}
//μhullstorage
CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0);
//dst
dst.clear();
for (int i = 0, hullCount = hull->total; i < hullCount; i++)
dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i));
//storage
cvReleaseMemStorage(&storage);
}
#define R_COLOR 255
void fillConvexHull(cv::Mat& image, const std::vector<cv::Point>& points)
{
uint index_top = 0;
uint index_bottom = 0;
for (size_t i = 0, length = points.size(); i < length; i++)
{
if (points[i].y < points[index_top].y)
index_top = i;
if (points[i].y > points[index_bottom].y)
index_bottom = i;
}
std::vector<cv::Point> edge_left;
uint temp = index_top;
while (temp != index_bottom)
{
edge_left.push_back(points[temp]);
temp = (temp + points.size() - 1) % points.size();
}
edge_left.push_back(points[index_bottom]);
std::vector<cv::Point> edge_right;
temp = index_top;
while (temp != index_bottom)
{
edge_right.push_back(points[temp]);
temp = (temp + points.size() + 1) % points.size();
}
edge_right.push_back(points[index_bottom]);
std::vector<int> left_edge_x;
std::vector<int> left_edge_y;
for (size_t i = 0, length = edge_left.size() - 1; i < length; i++)
{
int y_top = edge_left[i].y;
int x_top = edge_left[i].x;
int y_bottom = edge_left[i + 1].y;
int x_bottom = edge_left[i + 1].x;
for (int y = y_top; y < y_bottom; y++)
if (y >= 0 && y_top != y_bottom && y < image.rows)
{
left_edge_x.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top));
left_edge_y.push_back(y);
}
}
size_t step = image.step;
unsigned char* ptr;
ptr = image.data + static_cast<uint>(left_edge_y[0]) * step;
for (size_t i = 0, length = left_edge_x.size(); i < length; i++)
{
int pix = left_edge_x[i];
if (pix < image.cols - 1 && pix > 0)
memset(ptr + i * step, R_COLOR, static_cast<size_t>((pix + 1) * image.channels()));
}
std::vector<int> right_edge_x;
std::vector<int> right_edge_y;
for (size_t i = 0, length = edge_right.size() - 1; i < length; i++)
{
int y_top = edge_right[i].y;
int x_top = edge_right[i].x;
int y_bottom = edge_right[i + 1].y;
int x_bottom = edge_right[i + 1].x;
for (int y = y_top; y < y_bottom; y++)
if (y_top != y_bottom && y < image.rows && y >= 0)
{
right_edge_x.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top));
right_edge_y.push_back(y);
}
}
ptr = image.data + static_cast<uint>(right_edge_y[0]) * step;
for (size_t i = 0, length = right_edge_x.size(); i < length; i++)
{
int pix = right_edge_x[i];
if (pix < image.cols - 1 && pix > 0)
memset(ptr + i * step + pix * image.channels(), R_COLOR, step - static_cast<size_t>(pix * image.channels()));
}
if (edge_left[0].y > 0)
memset(image.data, R_COLOR, static_cast<size_t>(edge_left[0].y) * step);
if (edge_left.back().y < image.rows - 1)
memset(image.data + static_cast<size_t>(edge_left.back().y) * step, R_COLOR,
static_cast<size_t>(image.rows - edge_left.back().y) * step);
}
void fillPolys(cv::Mat& image, const std::vector<std::vector<cv::Point>>& contours, const cv::Scalar& color)
{
if (contours.empty()) return;
size_t count = contours.size();
cv::Point** pointss = new cv::Point*[count];
int* npts = new int[count];
for (size_t i = 0; i < count; i++)
{
size_t length = contours[i].size();
npts[i] = length;
pointss[i] = new cv::Point[length];
for (size_t j = 0; j < length; j++)
pointss[i][j] = contours[i][j];
}
cv::fillPoly(image, const_cast<const cv::Point**>(pointss), npts, count, color);
for (size_t i = 0; i < count; i++)
delete[] pointss[i];
delete[] pointss;
delete[] npts;
}
void findContours(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;
CV_DbgAssert(src.dims <= 2);
c_image = cvMat(src.rows, src.dims == 1 ? 1 : src.cols, src.type(), src.data);
c_image.step = int(src.step[0]);
c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x,offset.y });
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();
}
cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour)
{
if (contour.empty()) return {};
cv::RotatedRect rect = minAreaRect(contour);
if (rect.angle < -45)
{
rect.angle += 90;
float temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
}
return rect;
}
std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy)
{
std::vector<cv::Point> maxContour;
if (contours.size() < 1) return {};
for (size_t i = 0, length = hierarchy.size(); i < length; i++)
if (hierarchy[i][3] == -1)
for (const auto &item : contours[i])
maxContour.push_back(item);
return maxContour;
}
std::vector<cv::Point> getVertices(const cv::RotatedRect& rect)
{
cv::Point2f box[4];
rect.points(box);
std::vector<cv::Point> points;
for (int i = 0; i < 4; i++)
points.push_back(cv::Point(box[i]));
return points;
}
void polyIndent(std::vector<cv::Point>& points, const cv::Point& center, int indent)
{
static cv::Point zero(0, 0);
for (cv::Point& item : points)
{
#if 0
cv::Point vec = item - center;
if (vec != zero)
{
int length = vec.x * vec.x + vec.y * vec.y;
float x = cv::sqrt(static_cast<float>(vec.x * vec.x / length)) * indent;
float y = cv::sqrt(static_cast<float>(vec.y * vec.y / length)) * indent;
if (vec.x < 0) x *= -1.0f;
if (vec.y < 0) y *= -1.0f;
item.x -= static_cast<int>(x);
item.y -= static_cast<int>(y);
}
#else
if (item.x > center.x)
item.x -= indent;
else
item.x += indent;
if (item.y > center.y)
item.y -= indent;
else
item.y += indent;
#endif
}
}
cv::Mat transforColor(const cv::Mat& src)
{
if (src.channels() == 1) return src.clone();
std::vector<cv::Mat> channels(3);
cv::split(src, channels);
cv::Mat temp, dst;
bitwise_or(channels[0], channels[1], temp);
bitwise_or(channels[2], temp, dst);
temp.release();
for (cv::Mat& index : channels)
index.release();
return dst;
}
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
{
if (src.channels() == 3)
{
#ifdef USE_ONENCL
if (cl_res.context)
transforColor_threshold_opencl(src, dst, static_cast<uchar>(thre));
else
#endif
{
cv::Mat gray = transforColor(src);
cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY);
gray.release();
}
}
else
cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY);
}
cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat)
{
double src_data[3] = { static_cast<double>(p.x), static_cast<double>(p.y), 1 };
cv::Mat src(3, 1, warp_mat.type(), src_data); //warp_mat.type() == CV_64FC1
cv::Mat dst = warp_mat * src;
double* ptr = reinterpret_cast<double*>(dst.data);
return cv::Point(static_cast<int>(ptr[0]), static_cast<int>(ptr[1]));
}
int distanceP2P(const cv::Point& p1, const cv::Point& p2)
{
return cv::sqrt(cv::pow(p1.x - p2.x, 2) + cv::pow(p1.y - p2.y, 2));
}
float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2)
{
//求直线方程
int A = 0, B = 0, C = 0;
A = l1.y - l2.y;
B = l2.x - l1.x;
C = l1.x * l2.y - l1.y * l2.x;
//代入点到直线距离公式
return ((float)abs(A * p.x + B * p.y + C)) / ((float)sqrtf(A * A + B * B));
}
}

View File

@ -0,0 +1,123 @@
/*
* ====================================================
* ImageProcess里面多个类反复使用
*
* 2020/4/21
* 2020/4/21
* v1.0
* ====================================================
*/
#ifndef IMAGE_PROCESS_PUBLIC_H
#define IMAGE_PROCESS_PUBLIC_H
#include "opencv2/opencv.hpp"
#include <vector>
namespace hg
{
/*
*
* src:
* dst:
* clockwise: true为顺时针排序false为逆时针排序
*/
void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise = false);
/*
*
* image:
* points:
*/
void fillConvexHull(cv::Mat& image, const std::vector<cv::Point>& points);
/*
*
* image:
* contours:
* color:
*/
void fillPolys(cv::Mat& image, const std::vector<std::vector<cv::Point>>& contours, const cv::Scalar& color);
/*
*
* src:
* contours:
* hierarchy: contours的数量对应retr选项不同
* retr:
* method:
* offset: 0,0
*/
void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy,
int retr = cv::RETR_LIST, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0));
cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour);
/*
* :
* contours:
* hierarchy: contours对应
* :
*/
std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy);
/*
* :
* contours:
* hierarchy: contours对应
* :
*/
std::vector<cv::Point> getVertices(const cv::RotatedRect& rect);
/*
* :
* points:
* center: center点缩进
* indent:
*/
void polyIndent(std::vector<cv::Point>& points, const cv::Point& center, int indent);
/*
* : src为彩色图像时
* src:
* dst:
* thre:
*/
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre);
/*
* :
* src:
* :
*/
cv::Mat transforColor(const cv::Mat& src);
/*
* : 仿
* p:
* warp_mat: 仿
* :
*/
cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat);
/*
* :
* p1: 1
* p2: 2
* :
*/
int distanceP2P(const cv::Point& p1, const cv::Point& p2);
/*
* : 线
* p:
* l1: 线1
* l2: 线2
* : 线
*/
float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2);
}
#endif // !IMAGE_PROCESS_C_H

22
ImageProcess/MatEx.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <opencv2/opencv.hpp>
class MatEx {
public:
MatEx() :
mat(cv::Mat())
, Bpp(-1) {
};
MatEx(cv::Mat mat, int bpp) :
mat(cv::Mat())
, Bpp(bpp)
{
this->mat = mat.clone();
this->Bpp = bpp;
}
public:
int Bpp;
cv::Mat mat;
};

View File

@ -0,0 +1,141 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-12-29T09:49:19
#
#-------------------------------------------------
QT += core
TARGET = gimgproc
TEMPLATE = lib
DEFINES += GIMGPROC_LIBRARY
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
INCLUDEPATH += $$PWD/../Tirdparty/3rdparty/nick
DEPENDPATH += $$PWD/../Tirdparty/3rdparty/nick
INCLUDEPATH += $$PWD/../gpdf
DEPENDPATH += $$PWD/../gpdf
win32 {
DEFINES += _WIN32
INCLUDEPATH += $$PWD/../Tirdparty/3party/3rdparty/win/hgOCR/include
DEPENDPATH += $$PWD/../Tirdparty/3rdparty/win/hgOCR/include
INCLUDEPATH += $$PWD/../Tirdparty/3rdparty/win/opencv/include
DEPENDPATH += $$PWD/../Tirdparty/3rdparty/win/opencv/include
LIBS += -L$$PWD/../Tirdparty/3rdparty/win/hgOCR/x86/lib
INCLUDEPATH += $$PWD/include
contains(QT_ARCH, i386) {
CONFIG(release, debug|release) {
DESTDIR += ../bin/x86/release
LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346
LIBS += -L$$PWD/../bin/x86/release -lhg_gpdf
LIBS += -L$$PWD/lib/release -lzxing -lzbar
LIBS += -lwinmm
}
CONFIG(debug, debug|release) {
DESTDIR += ../bin/x86/debug
LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346d
LIBS += -L$$PWD/../bin/x86/debug -lhg_gpdf
LIBS += -L$$PWD/lib/debug -lzxing -lzbar
LIBS += -lwinmm
}
} else {
CONFIG(release, debug|release) {
DESTDIR += ../bin/x64/release
LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346
LIBS += -L$$PWD/../bin/x64/release -lhg_gpdf
}
CONFIG(debug, debug|release) {
DESTDIR += ../bin/x64/debug
LIBS += -L$$PWD/../Tirdparty/3rdparty/win/opencv/x86/lib/ -lopencv_world346d
LIBS += -L$$PWD/../bin/x64/debug -lhg_gpdf
}
}
}
else:unix:!macx: {
LIBS += -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs #linux系统上面需安装opencv3.4.6
CONFIG(debug, debug|release) {
DESTDIR += ../bin/x86/debug
LIBS += -L$$PWD/../bin/x86/debug -lhg_gpdf
}
CONFIG(release, debug|release) {
DESTDIR += ../bin/x86/release
LIBS += -L$$PWD/../bin/x86/release -lhg_gpdf
}
}
SOURCES += \
ImageApply.cpp \
IMulti.cpp\
ImageApplyAdjustColors.cpp \
ImageApplyAutoContrast.cpp \
ImageApplyAutoCrop.cpp \
ImageApplyBWBinaray.cpp \
ImageApplyBarCodeRecognition.cpp \
ImageApplyChannel.cpp \
ImageApplyConcatenation.cpp \
ImageApplyCustomCrop.cpp \
ImageApplyCustomGamma.cpp \
ImageApplyDetachNoise.cpp \
ImageApplyDiscardBlank.cpp \
ImageApplyFilter.cpp \
ImageApplyHSVCorrect.cpp \
ImageApplyOutHole.cpp \
ImageApplyRefuseInflow.cpp \
ImageApplyResize.cpp \
ImageApplyRotation.cpp \
ImageApplySplit.cpp \
ImageApplyTextureRemoval.cpp \
ImageMulti.cpp \
ImageMultiOutputRed.cpp \
ImageProcess_Public.cpp
HEADERS += \
ImageApply.h \
IMulti.h\
ImageApplyAdjustColors.h \
ImageApplyAutoContrast.h \
ImageApplyAutoCrop.h \
ImageApplyBWBinaray.h \
ImageApplyBarCodeRecognition.h \
ImageApplyChannel.h \
ImageApplyConcatenation.h \
ImageApplyCustomCrop.h \
ImageApplyCustomGamma.h \
ImageApplyDetachNoise.h \
ImageApplyDiscardBlank.h \
ImageApplyFilter.h \
ImageApplyHSVCorrect.h \
ImageApplyHeaders.h \
ImageApplyOutHole.h \
ImageApplyRefuseInflow.h \
ImageApplyResize.h \
ImageApplyRotation.h \
ImageApplySplit.h \
ImageApplyTextureRemoval.h \
ImageMulti.h \
ImageMultiOutputRed.h \
ImageProcess_Public.h \
imgprocdefs.h
#VERSION = 1.0.0.0
QMAKE_TARGET_PRODUCT = "gimgproc"
QMAKE_TARGET_COMPANY = "huagaoscan"
QMAKE_TARGET_DESCRIPTION = "文件描述"
QMAKE_TARGET_COPYRIGHT = "版权"

View File

@ -0,0 +1,23 @@
#ifndef IMAGE_PROCESS_DEFINES_H
#define IMAGE_PROCESS_DEFINES_H
#define _DIRECT_BUILD
#if defined(_MSC_VER)
# define HT_DECL_EXPORT __declspec(dllexport)
# define HT_DECL_IMPORT __declspec(dllimport)
#elif defined(__linux__) || defined(__linux)
# define HT_DECL_EXPORT __attribute__((visibility("default")))
# define HT_DECL_IMPORT __attribute__((visibility("default")))
# define HT_DECL_HIDDEN __attribute__((visibility("hidden")))
#endif
#if defined(GIMGPROC_LIBRARY_BUILD)
#define GIMGPROC_LIBRARY_API HT_DECL_EXPORT
#elif defined(_DIRECT_BUILD)
#define GIMGPROC_LIBRARY_API
#else
#define GIMGPROC_LIBRARY_API HT_DECL_IMPORT
#endif
#endif // !IMAGE_PROCESS_DEFINES_H

View File

@ -0,0 +1,215 @@
#ifndef BIGINTEGER_H
#define BIGINTEGER_H
#include "BigUnsigned.hh"
/* A BigInteger object represents a signed integer of size limited only by
* available memory. BigUnsigneds support most mathematical operators and can
* be converted to and from most primitive integer types.
*
* A BigInteger is just an aggregate of a BigUnsigned and a sign. (It is no
* longer derived from BigUnsigned because that led to harmful implicit
* conversions.) */
class BigInteger {
public:
typedef BigUnsigned::Blk Blk;
typedef BigUnsigned::Index Index;
typedef BigUnsigned::CmpRes CmpRes;
static const CmpRes
less = BigUnsigned::less ,
equal = BigUnsigned::equal ,
greater = BigUnsigned::greater;
// Enumeration for the sign of a BigInteger.
enum Sign { negative = -1, zero = 0, positive = 1 };
protected:
Sign sign;
BigUnsigned mag;
public:
// Constructs zero.
BigInteger() : sign(zero), mag() {}
// Copy constructor
BigInteger(const BigInteger &x) : sign(x.sign), mag(x.mag) {};
// Assignment operator
void operator=(const BigInteger &x);
// Constructor that copies from a given array of blocks with a sign.
BigInteger(const Blk *b, Index blen, Sign s);
// Nonnegative constructor that copies from a given array of blocks.
BigInteger(const Blk *b, Index blen) : mag(b, blen) {
sign = mag.isZero() ? zero : positive;
}
// Constructor from a BigUnsigned and a sign
BigInteger(const BigUnsigned &x, Sign s);
// Nonnegative constructor from a BigUnsigned
BigInteger(const BigUnsigned &x) : mag(x) {
sign = mag.isZero() ? zero : positive;
}
// Constructors from primitive integer types
BigInteger(unsigned long x);
BigInteger( long x);
BigInteger(unsigned int x);
BigInteger( int x);
BigInteger(unsigned short x);
BigInteger( short x);
/* Converters to primitive integer types
* The implicit conversion operators caused trouble, so these are now
* named. */
unsigned long toUnsignedLong () const;
long toLong () const;
unsigned int toUnsignedInt () const;
int toInt () const;
unsigned short toUnsignedShort() const;
short toShort () const;
protected:
// Helper
template <class X> X convertToUnsignedPrimitive() const;
template <class X, class UX> X convertToSignedPrimitive() const;
public:
// ACCESSORS
Sign getSign() const { return sign; }
/* The client can't do any harm by holding a read-only reference to the
* magnitude. */
const BigUnsigned &getMagnitude() const { return mag; }
// Some accessors that go through to the magnitude
Index getLength() const { return mag.getLength(); }
Index getCapacity() const { return mag.getCapacity(); }
Blk getBlock(Index i) const { return mag.getBlock(i); }
bool isZero() const { return sign == zero; } // A bit special
// COMPARISONS
// Compares this to x like Perl's <=>
CmpRes compareTo(const BigInteger &x) const;
// Ordinary comparison operators
bool operator ==(const BigInteger &x) const {
return sign == x.sign && mag == x.mag;
}
bool operator !=(const BigInteger &x) const { return !operator ==(x); };
bool operator < (const BigInteger &x) const { return compareTo(x) == less ; }
bool operator <=(const BigInteger &x) const { return compareTo(x) != greater; }
bool operator >=(const BigInteger &x) const { return compareTo(x) != less ; }
bool operator > (const BigInteger &x) const { return compareTo(x) == greater; }
// OPERATORS -- See the discussion in BigUnsigned.hh.
void add (const BigInteger &a, const BigInteger &b);
void subtract(const BigInteger &a, const BigInteger &b);
void multiply(const BigInteger &a, const BigInteger &b);
/* See the comment on BigUnsigned::divideWithRemainder. Semantics
* differ from those of primitive integers when negatives and/or zeros
* are involved. */
void divideWithRemainder(const BigInteger &b, BigInteger &q);
void negate(const BigInteger &a);
/* Bitwise operators are not provided for BigIntegers. Use
* getMagnitude to get the magnitude and operate on that instead. */
BigInteger operator +(const BigInteger &x) const;
BigInteger operator -(const BigInteger &x) const;
BigInteger operator *(const BigInteger &x) const;
BigInteger operator /(const BigInteger &x) const;
BigInteger operator %(const BigInteger &x) const;
BigInteger operator -() const;
void operator +=(const BigInteger &x);
void operator -=(const BigInteger &x);
void operator *=(const BigInteger &x);
void operator /=(const BigInteger &x);
void operator %=(const BigInteger &x);
void flipSign();
// INCREMENT/DECREMENT OPERATORS
void operator ++( );
void operator ++(int);
void operator --( );
void operator --(int);
};
// NORMAL OPERATORS
/* These create an object to hold the result and invoke
* the appropriate put-here operation on it, passing
* this and x. The new object is then returned. */
inline BigInteger BigInteger::operator +(const BigInteger &x) const {
BigInteger ans;
ans.add(*this, x);
return ans;
}
inline BigInteger BigInteger::operator -(const BigInteger &x) const {
BigInteger ans;
ans.subtract(*this, x);
return ans;
}
inline BigInteger BigInteger::operator *(const BigInteger &x) const {
BigInteger ans;
ans.multiply(*this, x);
return ans;
}
inline BigInteger BigInteger::operator /(const BigInteger &x) const {
if (x.isZero()) throw "BigInteger::operator /: division by zero";
BigInteger q, r;
r = *this;
r.divideWithRemainder(x, q);
return q;
}
inline BigInteger BigInteger::operator %(const BigInteger &x) const {
if (x.isZero()) throw "BigInteger::operator %: division by zero";
BigInteger q, r;
r = *this;
r.divideWithRemainder(x, q);
return r;
}
inline BigInteger BigInteger::operator -() const {
BigInteger ans;
ans.negate(*this);
return ans;
}
/*
* ASSIGNMENT OPERATORS
*
* Now the responsibility for making a temporary copy if necessary
* belongs to the put-here operations. See Assignment Operators in
* BigUnsigned.hh.
*/
inline void BigInteger::operator +=(const BigInteger &x) {
add(*this, x);
}
inline void BigInteger::operator -=(const BigInteger &x) {
subtract(*this, x);
}
inline void BigInteger::operator *=(const BigInteger &x) {
multiply(*this, x);
}
inline void BigInteger::operator /=(const BigInteger &x) {
if (x.isZero()) throw "BigInteger::operator /=: division by zero";
/* The following technique is slightly faster than copying *this first
* when x is large. */
BigInteger q;
divideWithRemainder(x, q);
// *this contains the remainder, but we overwrite it with the quotient.
*this = q;
}
inline void BigInteger::operator %=(const BigInteger &x) {
if (x.isZero()) throw "BigInteger::operator %=: division by zero";
BigInteger q;
// Mods *this by x. Don't care about quotient left in q.
divideWithRemainder(x, q);
}
// This one is trivial
inline void BigInteger::flipSign() {
sign = Sign(-sign);
}
#endif

View File

@ -0,0 +1,25 @@
#ifndef BIGINTEGERALGORITHMS_H
#define BIGINTEGERALGORITHMS_H
#include "BigInteger.hh"
/* Some mathematical algorithms for big integers.
* This code is new and, as such, experimental. */
// Returns the greatest common divisor of a and b.
BigUnsigned gcd(BigUnsigned a, BigUnsigned b);
/* Extended Euclidean algorithm.
* Given m and n, finds gcd g and numbers r, s such that r*m + s*n == g. */
void extendedEuclidean(BigInteger m, BigInteger n,
BigInteger &g, BigInteger &r, BigInteger &s);
/* Returns the multiplicative inverse of x modulo n, or throws an exception if
* they have a common factor. */
BigUnsigned modinv(const BigInteger &x, const BigUnsigned &n);
// Returns (base ^ exponent) % modulus.
BigUnsigned modexp(const BigInteger &base, const BigUnsigned &exponent,
const BigUnsigned &modulus);
#endif

View File

@ -0,0 +1,8 @@
// This header file includes all of the library header files.
#include "NumberlikeArray.hh"
#include "BigUnsigned.hh"
#include "BigInteger.hh"
#include "BigIntegerAlgorithms.hh"
#include "BigUnsignedInABase.hh"
#include "BigIntegerUtils.hh"

View File

@ -0,0 +1,72 @@
#ifndef BIGINTEGERUTILS_H
#define BIGINTEGERUTILS_H
#include "BigInteger.hh"
#include <string>
#include <iostream>
/* This file provides:
* - Convenient std::string <-> BigUnsigned/BigInteger conversion routines
* - std::ostream << operators for BigUnsigned/BigInteger */
// std::string conversion routines. Base 10 only.
std::string bigUnsignedToString(const BigUnsigned &x);
std::string bigIntegerToString(const BigInteger &x);
BigUnsigned stringToBigUnsigned(const std::string &s);
BigInteger stringToBigInteger(const std::string &s);
// Creates a BigInteger from data such as `char's; read below for details.
template <class T>
BigInteger dataToBigInteger(const T* data, BigInteger::Index length, BigInteger::Sign sign);
// Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'.
std::ostream &operator <<(std::ostream &os, const BigUnsigned &x);
// Outputs x to os, obeying the flags `dec', `hex', `bin', and `showbase'.
// My somewhat arbitrary policy: a negative sign comes before a base indicator (like -0xFF).
std::ostream &operator <<(std::ostream &os, const BigInteger &x);
// BEGIN TEMPLATE DEFINITIONS.
/*
* Converts binary data to a BigInteger.
* Pass an array `data', its length, and the desired sign.
*
* Elements of `data' may be of any type `T' that has the following
* two properties (this includes almost all integral types):
*
* (1) `sizeof(T)' correctly gives the amount of binary data in one
* value of `T' and is a factor of `sizeof(Blk)'.
*
* (2) When a value of `T' is casted to a `Blk', the low bytes of
* the result contain the desired binary data.
*/
template <class T>
BigInteger dataToBigInteger(const T* data, BigInteger::Index length, BigInteger::Sign sign) {
// really ceiling(numBytes / sizeof(BigInteger::Blk))
unsigned int pieceSizeInBits = 8 * sizeof(T);
unsigned int piecesPerBlock = sizeof(BigInteger::Blk) / sizeof(T);
unsigned int numBlocks = (length + piecesPerBlock - 1) / piecesPerBlock;
// Allocate our block array
BigInteger::Blk *blocks = new BigInteger::Blk[numBlocks];
BigInteger::Index blockNum, pieceNum, pieceNumHere;
// Convert
for (blockNum = 0, pieceNum = 0; blockNum < numBlocks; blockNum++) {
BigInteger::Blk curBlock = 0;
for (pieceNumHere = 0; pieceNumHere < piecesPerBlock && pieceNum < length;
pieceNumHere++, pieceNum++)
curBlock |= (BigInteger::Blk(data[pieceNum]) << (pieceSizeInBits * pieceNumHere));
blocks[blockNum] = curBlock;
}
// Create the BigInteger.
BigInteger x(blocks, numBlocks, sign);
delete [] blocks;
return x;
}
#endif

View File

@ -0,0 +1,418 @@
#ifndef BIGUNSIGNED_H
#define BIGUNSIGNED_H
#include "NumberlikeArray.hh"
/* A BigUnsigned object represents a nonnegative integer of size limited only by
* available memory. BigUnsigneds support most mathematical operators and can
* be converted to and from most primitive integer types.
*
* The number is stored as a NumberlikeArray of unsigned longs as if it were
* written in base 256^sizeof(unsigned long). The least significant block is
* first, and the length is such that the most significant block is nonzero. */
class BigUnsigned : protected NumberlikeArray<unsigned long> {
public:
// Enumeration for the result of a comparison.
enum CmpRes { less = -1, equal = 0, greater = 1 };
// BigUnsigneds are built with a Blk type of unsigned long.
typedef unsigned long Blk;
typedef NumberlikeArray<Blk>::Index Index;
using NumberlikeArray<Blk>::N;
protected:
// Creates a BigUnsigned with a capacity; for internal use.
BigUnsigned(int, Index c) : NumberlikeArray<Blk>(0, c) {}
// Decreases len to eliminate any leading zero blocks.
void zapLeadingZeros() {
while (len > 0 && blk[len - 1] == 0)
len--;
}
public:
// Constructs zero.
BigUnsigned() : NumberlikeArray<Blk>() {}
// Copy constructor
BigUnsigned(const BigUnsigned &x) : NumberlikeArray<Blk>(x) {}
// Assignment operator
void operator=(const BigUnsigned &x) {
NumberlikeArray<Blk>::operator =(x);
}
// Constructor that copies from a given array of blocks.
BigUnsigned(const Blk *b, Index blen) : NumberlikeArray<Blk>(b, blen) {
// Eliminate any leading zeros we may have been passed.
zapLeadingZeros();
}
// Destructor. NumberlikeArray does the delete for us.
~BigUnsigned() {}
// Constructors from primitive integer types
BigUnsigned(unsigned long x);
BigUnsigned( long x);
BigUnsigned(unsigned int x);
BigUnsigned( int x);
BigUnsigned(unsigned short x);
BigUnsigned( short x);
protected:
// Helpers
template <class X> void initFromPrimitive (X x);
template <class X> void initFromSignedPrimitive(X x);
public:
/* Converters to primitive integer types
* The implicit conversion operators caused trouble, so these are now
* named. */
unsigned long toUnsignedLong () const;
long toLong () const;
unsigned int toUnsignedInt () const;
int toInt () const;
unsigned short toUnsignedShort() const;
short toShort () const;
protected:
// Helpers
template <class X> X convertToSignedPrimitive() const;
template <class X> X convertToPrimitive () const;
public:
// BIT/BLOCK ACCESSORS
// Expose these from NumberlikeArray directly.
using NumberlikeArray<Blk>::getCapacity;
using NumberlikeArray<Blk>::getLength;
/* Returns the requested block, or 0 if it is beyond the length (as if
* the number had 0s infinitely to the left). */
Blk getBlock(Index i) const { return i >= len ? 0 : blk[i]; }
/* Sets the requested block. The number grows or shrinks as necessary. */
void setBlock(Index i, Blk newBlock);
// The number is zero if and only if the canonical length is zero.
bool isZero() const { return NumberlikeArray<Blk>::isEmpty(); }
/* Returns the length of the number in bits, i.e., zero if the number
* is zero and otherwise one more than the largest value of bi for
* which getBit(bi) returns true. */
Index bitLength() const;
/* Get the state of bit bi, which has value 2^bi. Bits beyond the
* number's length are considered to be 0. */
bool getBit(Index bi) const {
return (getBlock(bi / N) & (Blk(1) << (bi % N))) != 0;
}
/* Sets the state of bit bi to newBit. The number grows or shrinks as
* necessary. */
void setBit(Index bi, bool newBit);
// COMPARISONS
// Compares this to x like Perl's <=>
CmpRes compareTo(const BigUnsigned &x) const;
// Ordinary comparison operators
bool operator ==(const BigUnsigned &x) const {
return NumberlikeArray<Blk>::operator ==(x);
}
bool operator !=(const BigUnsigned &x) const {
return NumberlikeArray<Blk>::operator !=(x);
}
bool operator < (const BigUnsigned &x) const { return compareTo(x) == less ; }
bool operator <=(const BigUnsigned &x) const { return compareTo(x) != greater; }
bool operator >=(const BigUnsigned &x) const { return compareTo(x) != less ; }
bool operator > (const BigUnsigned &x) const { return compareTo(x) == greater; }
/*
* BigUnsigned and BigInteger both provide three kinds of operators.
* Here ``big-integer'' refers to BigInteger or BigUnsigned.
*
* (1) Overloaded ``return-by-value'' operators:
* +, -, *, /, %, unary -, &, |, ^, <<, >>.
* Big-integer code using these operators looks identical to code using
* the primitive integer types. These operators take one or two
* big-integer inputs and return a big-integer result, which can then
* be assigned to a BigInteger variable or used in an expression.
* Example:
* BigInteger a(1), b = 1;
* BigInteger c = a + b;
*
* (2) Overloaded assignment operators:
* +=, -=, *=, /=, %=, flipSign, &=, |=, ^=, <<=, >>=, ++, --.
* Again, these are used on big integers just like on ints. They take
* one writable big integer that both provides an operand and receives a
* result. Most also take a second read-only operand.
* Example:
* BigInteger a(1), b(1);
* a += b;
*
* (3) Copy-less operations: `add', `subtract', etc.
* These named methods take operands as arguments and store the result
* in the receiver (*this), avoiding unnecessary copies and allocations.
* `divideWithRemainder' is special: it both takes the dividend from and
* stores the remainder into the receiver, and it takes a separate
* object in which to store the quotient. NOTE: If you are wondering
* why these don't return a value, you probably mean to use the
* overloaded return-by-value operators instead.
*
* Examples:
* BigInteger a(43), b(7), c, d;
*
* c = a + b; // Now c == 50.
* c.add(a, b); // Same effect but without the two copies.
*
* c.divideWithRemainder(b, d);
* // 50 / 7; now d == 7 (quotient) and c == 1 (remainder).
*
* // ``Aliased'' calls now do the right thing using a temporary
* // copy, but see note on `divideWithRemainder'.
* a.add(a, b);
*/
// COPY-LESS OPERATIONS
// These 8: Arguments are read-only operands, result is saved in *this.
void add(const BigUnsigned &a, const BigUnsigned &b);
void subtract(const BigUnsigned &a, const BigUnsigned &b);
void multiply(const BigUnsigned &a, const BigUnsigned &b);
void bitAnd(const BigUnsigned &a, const BigUnsigned &b);
void bitOr(const BigUnsigned &a, const BigUnsigned &b);
void bitXor(const BigUnsigned &a, const BigUnsigned &b);
/* Negative shift amounts translate to opposite-direction shifts,
* except for -2^(8*sizeof(int)-1) which is unimplemented. */
void bitShiftLeft(const BigUnsigned &a, int b);
void bitShiftRight(const BigUnsigned &a, int b);
/* `a.divideWithRemainder(b, q)' is like `q = a / b, a %= b'.
* / and % use semantics similar to Knuth's, which differ from the
* primitive integer semantics under division by zero. See the
* implementation in BigUnsigned.cc for details.
* `a.divideWithRemainder(b, a)' throws an exception: it doesn't make
* sense to write quotient and remainder into the same variable. */
void divideWithRemainder(const BigUnsigned &b, BigUnsigned &q);
/* `divide' and `modulo' are no longer offered. Use
* `divideWithRemainder' instead. */
// OVERLOADED RETURN-BY-VALUE OPERATORS
BigUnsigned operator +(const BigUnsigned &x) const;
BigUnsigned operator -(const BigUnsigned &x) const;
BigUnsigned operator *(const BigUnsigned &x) const;
BigUnsigned operator /(const BigUnsigned &x) const;
BigUnsigned operator %(const BigUnsigned &x) const;
/* OK, maybe unary minus could succeed in one case, but it really
* shouldn't be used, so it isn't provided. */
BigUnsigned operator &(const BigUnsigned &x) const;
BigUnsigned operator |(const BigUnsigned &x) const;
BigUnsigned operator ^(const BigUnsigned &x) const;
BigUnsigned operator <<(int b) const;
BigUnsigned operator >>(int b) const;
// OVERLOADED ASSIGNMENT OPERATORS
void operator +=(const BigUnsigned &x);
void operator -=(const BigUnsigned &x);
void operator *=(const BigUnsigned &x);
void operator /=(const BigUnsigned &x);
void operator %=(const BigUnsigned &x);
void operator &=(const BigUnsigned &x);
void operator |=(const BigUnsigned &x);
void operator ^=(const BigUnsigned &x);
void operator <<=(int b);
void operator >>=(int b);
/* INCREMENT/DECREMENT OPERATORS
* To discourage messy coding, these do not return *this, so prefix
* and postfix behave the same. */
void operator ++( );
void operator ++(int);
void operator --( );
void operator --(int);
// Helper function that needs access to BigUnsigned internals
friend Blk getShiftedBlock(const BigUnsigned &num, Index x,
unsigned int y);
// See BigInteger.cc.
template <class X>
friend X convertBigUnsignedToPrimitiveAccess(const BigUnsigned &a);
};
/* Implementing the return-by-value and assignment operators in terms of the
* copy-less operations. The copy-less operations are responsible for making
* any necessary temporary copies to work around aliasing. */
inline BigUnsigned BigUnsigned::operator +(const BigUnsigned &x) const {
BigUnsigned ans;
ans.add(*this, x);
return ans;
}
inline BigUnsigned BigUnsigned::operator -(const BigUnsigned &x) const {
BigUnsigned ans;
ans.subtract(*this, x);
return ans;
}
inline BigUnsigned BigUnsigned::operator *(const BigUnsigned &x) const {
BigUnsigned ans;
ans.multiply(*this, x);
return ans;
}
inline BigUnsigned BigUnsigned::operator /(const BigUnsigned &x) const {
if (x.isZero()) throw "BigUnsigned::operator /: division by zero";
BigUnsigned q, r;
r = *this;
r.divideWithRemainder(x, q);
return q;
}
inline BigUnsigned BigUnsigned::operator %(const BigUnsigned &x) const {
if (x.isZero()) throw "BigUnsigned::operator %: division by zero";
BigUnsigned q, r;
r = *this;
r.divideWithRemainder(x, q);
return r;
}
inline BigUnsigned BigUnsigned::operator &(const BigUnsigned &x) const {
BigUnsigned ans;
ans.bitAnd(*this, x);
return ans;
}
inline BigUnsigned BigUnsigned::operator |(const BigUnsigned &x) const {
BigUnsigned ans;
ans.bitOr(*this, x);
return ans;
}
inline BigUnsigned BigUnsigned::operator ^(const BigUnsigned &x) const {
BigUnsigned ans;
ans.bitXor(*this, x);
return ans;
}
inline BigUnsigned BigUnsigned::operator <<(int b) const {
BigUnsigned ans;
ans.bitShiftLeft(*this, b);
return ans;
}
inline BigUnsigned BigUnsigned::operator >>(int b) const {
BigUnsigned ans;
ans.bitShiftRight(*this, b);
return ans;
}
inline void BigUnsigned::operator +=(const BigUnsigned &x) {
add(*this, x);
}
inline void BigUnsigned::operator -=(const BigUnsigned &x) {
subtract(*this, x);
}
inline void BigUnsigned::operator *=(const BigUnsigned &x) {
multiply(*this, x);
}
inline void BigUnsigned::operator /=(const BigUnsigned &x) {
if (x.isZero()) throw "BigUnsigned::operator /=: division by zero";
/* The following technique is slightly faster than copying *this first
* when x is large. */
BigUnsigned q;
divideWithRemainder(x, q);
// *this contains the remainder, but we overwrite it with the quotient.
*this = q;
}
inline void BigUnsigned::operator %=(const BigUnsigned &x) {
if (x.isZero()) throw "BigUnsigned::operator %=: division by zero";
BigUnsigned q;
// Mods *this by x. Don't care about quotient left in q.
divideWithRemainder(x, q);
}
inline void BigUnsigned::operator &=(const BigUnsigned &x) {
bitAnd(*this, x);
}
inline void BigUnsigned::operator |=(const BigUnsigned &x) {
bitOr(*this, x);
}
inline void BigUnsigned::operator ^=(const BigUnsigned &x) {
bitXor(*this, x);
}
inline void BigUnsigned::operator <<=(int b) {
bitShiftLeft(*this, b);
}
inline void BigUnsigned::operator >>=(int b) {
bitShiftRight(*this, b);
}
/* Templates for conversions of BigUnsigned to and from primitive integers.
* BigInteger.cc needs to instantiate convertToPrimitive, and the uses in
* BigUnsigned.cc didn't do the trick; I think g++ inlined convertToPrimitive
* instead of generating linkable instantiations. So for consistency, I put
* all the templates here. */
// CONSTRUCTION FROM PRIMITIVE INTEGERS
/* Initialize this BigUnsigned from the given primitive integer. The same
* pattern works for all primitive integer types, so I put it into a template to
* reduce code duplication. (Don't worry: this is protected and we instantiate
* it only with primitive integer types.) Type X could be signed, but x is
* known to be nonnegative. */
template <class X>
void BigUnsigned::initFromPrimitive(X x) {
if (x == 0)
; // NumberlikeArray already initialized us to zero.
else {
// Create a single block. blk is NULL; no need to delete it.
cap = 1;
blk = new Blk[1];
len = 1;
blk[0] = Blk(x);
}
}
/* Ditto, but first check that x is nonnegative. I could have put the check in
* initFromPrimitive and let the compiler optimize it out for unsigned-type
* instantiations, but I wanted to avoid the warning stupidly issued by g++ for
* a condition that is constant in *any* instantiation, even if not in all. */
template <class X>
void BigUnsigned::initFromSignedPrimitive(X x) {
if (x < 0)
throw "BigUnsigned constructor: "
"Cannot construct a BigUnsigned from a negative number";
else
initFromPrimitive(x);
}
// CONVERSION TO PRIMITIVE INTEGERS
/* Template with the same idea as initFromPrimitive. This might be slightly
* slower than the previous version with the masks, but it's much shorter and
* clearer, which is the library's stated goal. */
template <class X>
X BigUnsigned::convertToPrimitive() const {
if (len == 0)
// The number is zero; return zero.
return 0;
else if (len == 1) {
// The single block might fit in an X. Try the conversion.
X x = X(blk[0]);
// Make sure the result accurately represents the block.
if (Blk(x) == blk[0])
// Successful conversion.
return x;
// Otherwise fall through.
}
throw "BigUnsigned::to<Primitive>: "
"Value is too big to fit in the requested type";
}
/* Wrap the above in an x >= 0 test to make sure we got a nonnegative result,
* not a negative one that happened to convert back into the correct nonnegative
* one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again,
* separated to avoid a g++ warning. */
template <class X>
X BigUnsigned::convertToSignedPrimitive() const {
X x = convertToPrimitive<X>();
if (x >= 0)
return x;
else
throw "BigUnsigned::to(Primitive): "
"Value is too big to fit in the requested type";
}
#endif

View File

@ -0,0 +1,122 @@
#ifndef BIGUNSIGNEDINABASE_H
#define BIGUNSIGNEDINABASE_H
#include "NumberlikeArray.hh"
#include "BigUnsigned.hh"
#include <string>
/*
* A BigUnsignedInABase object represents a nonnegative integer of size limited
* only by available memory, represented in a user-specified base that can fit
* in an `unsigned short' (most can, and this saves memory).
*
* BigUnsignedInABase is intended as an intermediary class with little
* functionality of its own. BigUnsignedInABase objects can be constructed
* from, and converted to, BigUnsigneds (requiring multiplication, mods, etc.)
* and `std::string's (by switching digit values for appropriate characters).
*
* BigUnsignedInABase is similar to BigUnsigned. Note the following:
*
* (1) They represent the number in exactly the same way, except that
* BigUnsignedInABase uses ``digits'' (or Digit) where BigUnsigned uses
* ``blocks'' (or Blk).
*
* (2) Both use the management features of NumberlikeArray. (In fact, my desire
* to add a BigUnsignedInABase class without duplicating a lot of code led me to
* introduce NumberlikeArray.)
*
* (3) The only arithmetic operation supported by BigUnsignedInABase is an
* equality test. Use BigUnsigned for arithmetic.
*/
class BigUnsignedInABase : protected NumberlikeArray<unsigned short> {
public:
// The digits of a BigUnsignedInABase are unsigned shorts.
typedef unsigned short Digit;
// That's also the type of a base.
typedef Digit Base;
protected:
// The base in which this BigUnsignedInABase is expressed
Base base;
// Creates a BigUnsignedInABase with a capacity; for internal use.
BigUnsignedInABase(int, Index c) : NumberlikeArray<Digit>(0, c) {}
// Decreases len to eliminate any leading zero digits.
void zapLeadingZeros() {
while (len > 0 && blk[len - 1] == 0)
len--;
}
public:
// Constructs zero in base 2.
BigUnsignedInABase() : NumberlikeArray<Digit>(), base(2) {}
// Copy constructor
BigUnsignedInABase(const BigUnsignedInABase &x) : NumberlikeArray<Digit>(x), base(x.base) {}
// Assignment operator
void operator =(const BigUnsignedInABase &x) {
NumberlikeArray<Digit>::operator =(x);
base = x.base;
}
// Constructor that copies from a given array of digits.
BigUnsignedInABase(const Digit *d, Index l, Base base);
// Destructor. NumberlikeArray does the delete for us.
~BigUnsignedInABase() {}
// LINKS TO BIGUNSIGNED
BigUnsignedInABase(const BigUnsigned &x, Base base);
operator BigUnsigned() const;
/* LINKS TO STRINGS
*
* These use the symbols ``0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'' to
* represent digits of 0 through 35. When parsing strings, lowercase is
* also accepted.
*
* All string representations are big-endian (big-place-value digits
* first). (Computer scientists have adopted zero-based counting; why
* can't they tolerate little-endian numbers?)
*
* No string representation has a ``base indicator'' like ``0x''.
*
* An exception is made for zero: it is converted to ``0'' and not the
* empty string.
*
* If you want different conventions, write your own routines to go
* between BigUnsignedInABase and strings. It's not hard.
*/
operator std::string() const;
BigUnsignedInABase(const std::string &s, Base base);
public:
// ACCESSORS
Base getBase() const { return base; }
// Expose these from NumberlikeArray directly.
using NumberlikeArray<Digit>::getCapacity;
using NumberlikeArray<Digit>::getLength;
/* Returns the requested digit, or 0 if it is beyond the length (as if
* the number had 0s infinitely to the left). */
Digit getDigit(Index i) const { return i >= len ? 0 : blk[i]; }
// The number is zero if and only if the canonical length is zero.
bool isZero() const { return NumberlikeArray<Digit>::isEmpty(); }
/* Equality test. For the purposes of this test, two BigUnsignedInABase
* values must have the same base to be equal. */
bool operator ==(const BigUnsignedInABase &x) const {
return base == x.base && NumberlikeArray<Digit>::operator ==(x);
}
bool operator !=(const BigUnsignedInABase &x) const { return !operator ==(x); }
};
#endif

View File

@ -0,0 +1,177 @@
#ifndef NUMBERLIKEARRAY_H
#define NUMBERLIKEARRAY_H
// Make sure we have NULL.
#ifndef NULL
#define NULL 0
#endif
/* A NumberlikeArray<Blk> object holds a heap-allocated array of Blk with a
* length and a capacity and provides basic memory management features.
* BigUnsigned and BigUnsignedInABase both subclass it.
*
* NumberlikeArray provides no information hiding. Subclasses should use
* nonpublic inheritance and manually expose members as desired using
* declarations like this:
*
* public:
* NumberlikeArray< the-type-argument >::getLength;
*/
template <class Blk>
class NumberlikeArray {
public:
// Type for the index of a block in the array
typedef unsigned int Index;
// The number of bits in a block, defined below.
static const unsigned int N;
// The current allocated capacity of this NumberlikeArray (in blocks)
Index cap;
// The actual length of the value stored in this NumberlikeArray (in blocks)
Index len;
// Heap-allocated array of the blocks (can be NULL if len == 0)
Blk *blk;
// Constructs a ``zero'' NumberlikeArray with the given capacity.
NumberlikeArray(Index c) : cap(c), len(0) {
blk = (cap > 0) ? (new Blk[cap]) : NULL;
}
/* Constructs a zero NumberlikeArray without allocating a backing array.
* A subclass that doesn't know the needed capacity at initialization
* time can use this constructor and then overwrite blk without first
* deleting it. */
NumberlikeArray() : cap(0), len(0) {
blk = NULL;
}
// Destructor. Note that `delete NULL' is a no-op.
~NumberlikeArray() {
delete [] blk;
}
/* Ensures that the array has at least the requested capacity; may
* destroy the contents. */
void allocate(Index c);
/* Ensures that the array has at least the requested capacity; does not
* destroy the contents. */
void allocateAndCopy(Index c);
// Copy constructor
NumberlikeArray(const NumberlikeArray<Blk> &x);
// Assignment operator
void operator=(const NumberlikeArray<Blk> &x);
// Constructor that copies from a given array of blocks
NumberlikeArray(const Blk *b, Index blen);
// ACCESSORS
Index getCapacity() const { return cap; }
Index getLength() const { return len; }
Blk getBlock(Index i) const { return blk[i]; }
bool isEmpty() const { return len == 0; }
/* Equality comparison: checks if both objects have the same length and
* equal (==) array elements to that length. Subclasses may wish to
* override. */
bool operator ==(const NumberlikeArray<Blk> &x) const;
bool operator !=(const NumberlikeArray<Blk> &x) const {
return !operator ==(x);
}
};
/* BEGIN TEMPLATE DEFINITIONS. They are present here so that source files that
* include this header file can generate the necessary real definitions. */
template <class Blk>
const unsigned int NumberlikeArray<Blk>::N = 8 * sizeof(Blk);
template <class Blk>
void NumberlikeArray<Blk>::allocate(Index c) {
// If the requested capacity is more than the current capacity...
if (c > cap) {
// Delete the old number array
delete [] blk;
// Allocate the new array
cap = c;
blk = new Blk[cap];
}
}
template <class Blk>
void NumberlikeArray<Blk>::allocateAndCopy(Index c) {
// If the requested capacity is more than the current capacity...
if (c > cap) {
Blk *oldBlk = blk;
// Allocate the new number array
cap = c;
blk = new Blk[cap];
// Copy number blocks
Index i;
for (i = 0; i < len; i++)
blk[i] = oldBlk[i];
// Delete the old array
delete [] oldBlk;
}
}
template <class Blk>
NumberlikeArray<Blk>::NumberlikeArray(const NumberlikeArray<Blk> &x)
: len(x.len) {
// Create array
cap = len;
blk = new Blk[cap];
// Copy blocks
Index i;
for (i = 0; i < len; i++)
blk[i] = x.blk[i];
}
template <class Blk>
void NumberlikeArray<Blk>::operator=(const NumberlikeArray<Blk> &x) {
/* Calls like a = a have no effect; catch them before the aliasing
* causes a problem */
if (this == &x)
return;
// Copy length
len = x.len;
// Expand array if necessary
allocate(len);
// Copy number blocks
Index i;
for (i = 0; i < len; i++)
blk[i] = x.blk[i];
}
template <class Blk>
NumberlikeArray<Blk>::NumberlikeArray(const Blk *b, Index blen)
: cap(blen), len(blen) {
// Create array
blk = new Blk[cap];
// Copy blocks
Index i;
for (i = 0; i < len; i++)
blk[i] = b[i];
}
template <class Blk>
bool NumberlikeArray<Blk>::operator ==(const NumberlikeArray<Blk> &x) const {
if (len != x.len)
// Definitely unequal.
return false;
else {
// Compare corresponding blocks one by one.
Index i;
for (i = 0; i < len; i++)
if (blk[i] != x.blk[i])
return false;
// No blocks differed, so the objects are equal.
return true;
}
}
#endif

View File

@ -0,0 +1,14 @@
#ifndef _LIBICONV_H
#define _LIBICONV_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef void* iconv_t;
iconv_t iconv_open(const char *tocode, const char *fromcode);
int iconv_close(iconv_t cd);
size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
#ifdef __cplusplus
}
#endif
#endif//_LIBICONV_H

View File

@ -0,0 +1,247 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]

File diff suppressed because it is too large Load Diff

1498
ImageProcess/include/zbar.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,202 @@
//------------------------------------------------------------------------
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_DECODER_H_
#define _ZBAR_DECODER_H_
/// @file
/// Decoder C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Decoder.h"
#endif
#include <string>
namespace zbar {
/// low-level bar width stream decoder interface.
/// identifies symbols and extracts encoded data
class Decoder {
public:
/// Decoder result handler.
/// applications should subtype this and pass an instance to
/// set_handler() to implement result processing
class Handler {
public:
virtual ~Handler() { }
/// invoked by the Decoder as decode results become available.
virtual void decode_callback(Decoder &decoder) = 0;
};
/// constructor.
Decoder ()
: _handler(NULL)
{
_decoder = zbar_decoder_create();
}
~Decoder ()
{
zbar_decoder_destroy(_decoder);
}
/// clear all decoder state.
/// see zbar_decoder_reset()
void reset ()
{
zbar_decoder_reset(_decoder);
}
/// mark start of a new scan pass.
/// see zbar_decoder_new_scan()
void new_scan ()
{
zbar_decoder_new_scan(_decoder);
}
/// process next bar/space width from input stream.
/// see zbar_decode_width()
zbar_symbol_type_t decode_width (unsigned width)
{
return(zbar_decode_width(_decoder, width));
}
/// process next bar/space width from input stream.
/// see zbar_decode_width()
Decoder& operator<< (unsigned width)
{
zbar_decode_width(_decoder, width);
return(*this);
}
/// retrieve color of @em next element passed to Decoder.
/// see zbar_decoder_get_color()
zbar_color_t get_color () const
{
return(zbar_decoder_get_color(_decoder));
}
/// retrieve last decoded symbol type.
/// see zbar_decoder_get_type()
zbar_symbol_type_t get_type () const
{
return(zbar_decoder_get_type(_decoder));
}
/// retrieve string name of last decoded symbol type.
/// see zbar_get_symbol_name()
const char *get_symbol_name () const
{
return(zbar_get_symbol_name(zbar_decoder_get_type(_decoder)));
}
/// retrieve string name for last decode addon.
/// see zbar_get_addon_name()
/// @deprecated in 0.11
const char *get_addon_name () const
{
return(zbar_get_addon_name(zbar_decoder_get_type(_decoder)));
}
/// retrieve last decoded data in ASCII format as a char array.
/// see zbar_decoder_get_data()
const char *get_data_chars() const
{
return(zbar_decoder_get_data(_decoder));
}
/// retrieve last decoded data as a std::string.
/// see zbar_decoder_get_data()
const std::string get_data_string() const
{
return(std::string(zbar_decoder_get_data(_decoder),
zbar_decoder_get_data_length(_decoder)));
}
/// retrieve last decoded data as a std::string.
/// see zbar_decoder_get_data()
const std::string get_data() const
{
return(get_data_string());
}
/// retrieve length of decoded binary data.
/// see zbar_decoder_get_data_length()
int get_data_length() const
{
return(zbar_decoder_get_data_length(_decoder));
}
/// retrieve last decode direction.
/// see zbar_decoder_get_direction()
/// @since 0.11
int get_direction() const
{
return(zbar_decoder_get_direction(_decoder));
}
/// setup callback to handle result data.
void set_handler (Handler &handler)
{
_handler = &handler;
zbar_decoder_set_handler(_decoder, _cb);
zbar_decoder_set_userdata(_decoder, this);
}
/// set config for indicated symbology (0 for all) to specified value.
/// @see zbar_decoder_set_config()
/// @since 0.4
int set_config (zbar_symbol_type_t symbology,
zbar_config_t config,
int value)
{
return(zbar_decoder_set_config(_decoder, symbology, config, value));
}
/// set config parsed from configuration string.
/// @see zbar_decoder_parse_config()
/// @since 0.4
int set_config (std::string cfgstr)
{
return(zbar_decoder_parse_config(_decoder, cfgstr.c_str()));
}
private:
friend class Scanner;
zbar_decoder_t *_decoder;
Handler *_handler;
static void _cb (zbar_decoder_t *cdcode)
{
Decoder *dcode = (Decoder*)zbar_decoder_get_userdata(cdcode);
if(dcode && dcode->_handler)
dcode->_handler->decode_callback(*dcode);
}
};
}
#endif

View File

@ -0,0 +1,187 @@
//------------------------------------------------------------------------
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_EXCEPTION_H_
#define _ZBAR_EXCEPTION_H_
/// @file
/// C++ Exception definitions
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Exception.h"
#endif
#include <exception>
#include <new>
namespace zbar {
/// base class for exceptions defined by this API.
class Exception : public std::exception {
public:
/// create exception from C library error
Exception (const void *obj = NULL)
: std::exception(),
_obj(obj)
{ }
~Exception () throw() { }
/// retrieve error message
virtual const char* what () const throw()
{
if(!_obj)
return("zbar library unspecified generic error");
return(_zbar_error_string(_obj, 0));
}
private:
const void *_obj;
};
/// internal library error.
class InternalError : public Exception {
public:
/// create exception from C library error
InternalError (const void *obj)
: Exception(obj)
{ }
};
/// unsupported request.
class UnsupportedError : public Exception {
public:
/// create exception from C library error
UnsupportedError (const void *obj)
: Exception(obj)
{ }
};
/// invalid request.
class InvalidError : public Exception {
public:
/// create exception from C library error
InvalidError (const void *obj)
: Exception(obj)
{ }
};
/// failed system call.
class SystemError : public Exception {
public:
/// create exception from C library error
SystemError (const void *obj)
: Exception(obj)
{ }
};
/// locking error.
class LockingError : public Exception {
public:
/// create exception from C library error
LockingError (const void *obj)
: Exception(obj)
{ }
};
/// all resources busy.
class BusyError : public Exception {
public:
/// create exception from C library error
BusyError (const void *obj)
: Exception(obj)
{ }
};
/// X11 display error.
class XDisplayError : public Exception {
public:
/// create exception from C library error
XDisplayError (const void *obj)
: Exception(obj)
{ }
};
/// X11 protocol error.
class XProtoError : public Exception {
public:
/// create exception from C library error
XProtoError (const void *obj)
: Exception(obj)
{ }
};
/// output window is closed.
class ClosedError : public Exception {
public:
/// create exception from C library error
ClosedError (const void *obj)
: Exception(obj)
{ }
};
/// image format error
class FormatError : public Exception {
// FIXME needs c equivalent
virtual const char* what () const throw()
{
// FIXME what format?
return("unsupported format");
}
};
/// @internal
/// extract error information and create exception.
static __inline std::exception throw_exception (const void *obj)
{
switch(_zbar_get_error_code(obj)) {
case ZBAR_ERR_NOMEM:
throw std::bad_alloc();
case ZBAR_ERR_INTERNAL:
throw InternalError(obj);
case ZBAR_ERR_UNSUPPORTED:
throw UnsupportedError(obj);
case ZBAR_ERR_INVALID:
throw InvalidError(obj);
case ZBAR_ERR_SYSTEM:
throw SystemError(obj);
case ZBAR_ERR_LOCKING:
throw LockingError(obj);
case ZBAR_ERR_BUSY:
throw BusyError(obj);
case ZBAR_ERR_XDISPLAY:
throw XDisplayError(obj);
case ZBAR_ERR_XPROTO:
throw XProtoError(obj);
case ZBAR_ERR_CLOSED:
throw ClosedError(obj);
default:
throw Exception(obj);
}
}
}
#endif

View File

@ -0,0 +1,329 @@
//------------------------------------------------------------------------
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_IMAGE_H_
#define _ZBAR_IMAGE_H_
/// @file
/// Image C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Image.h"
#endif
#include <assert.h>
#include <iterator>
#include "Symbol.h"
#include "Exception.h"
namespace zbar {
class Video;
/// stores image data samples along with associated format and size
/// metadata
class Image {
public:
/// general Image result handler.
/// applications should subtype this and pass an instance to
/// eg. ImageScanner::set_handler() to implement result processing
class Handler {
public:
virtual ~Handler() { }
/// invoked by library when Image should be processed
virtual void image_callback(Image &image) = 0;
/// cast this handler to the C handler
operator zbar_image_data_handler_t* () const
{
return(_cb);
}
private:
static void _cb (zbar_image_t *zimg,
const void *userdata)
{
if(userdata) {
Image *image = (Image*)zbar_image_get_userdata(zimg);
if(image)
((Handler*)userdata)->image_callback(*image);
else {
Image tmp(zimg, 1);
((Handler*)userdata)->image_callback(tmp);
}
}
}
};
class SymbolIterator : public zbar::SymbolIterator {
public:
/// default constructor.
SymbolIterator ()
: zbar::SymbolIterator()
{ }
/// constructor.
SymbolIterator (const SymbolSet &syms)
: zbar::SymbolIterator(syms)
{ }
/// copy constructor.
SymbolIterator (const SymbolIterator& iter)
: zbar::SymbolIterator(iter)
{ }
};
/// constructor.
/// create a new Image with the specified parameters
Image (unsigned width = 0,
unsigned height = 0,
const std::string& format = "",
const void *data = NULL,
unsigned long length = 0)
: _img(zbar_image_create())
{
zbar_image_set_userdata(_img, this);
if(width && height)
set_size(width, height);
if(format.length())
set_format(format);
if(data && length)
set_data(data, length);
}
~Image ()
{
if(zbar_image_get_userdata(_img) == this)
zbar_image_set_userdata(_img, NULL);
zbar_image_ref(_img, -1);
}
/// cast to C image object
operator const zbar_image_t* () const
{
return(_img);
}
/// cast to C image object
operator zbar_image_t* ()
{
return(_img);
}
/// retrieve the image format.
/// see zbar_image_get_format()
unsigned long get_format () const
{
return(zbar_image_get_format(_img));
}
/// specify the fourcc image format code for image sample data.
/// see zbar_image_set_format()
void set_format (unsigned long format)
{
zbar_image_set_format(_img, format);
}
/// specify the fourcc image format code for image sample data.
/// see zbar_image_set_format()
void set_format (const std::string& format)
{
unsigned long fourcc = zbar_fourcc_parse(format.c_str());
zbar_image_set_format(_img, fourcc);
}
/// retrieve a "sequence" (page/frame) number associated with this
/// image.
/// see zbar_image_get_sequence()
/// @since 0.6
unsigned get_sequence () const
{
return(zbar_image_get_sequence(_img));
}
/// associate a "sequence" (page/frame) number with this image.
/// see zbar_image_set_sequence()
/// @since 0.6
void set_sequence (unsigned sequence_num)
{
zbar_image_set_sequence(_img, sequence_num);
}
/// retrieve the width of the image.
/// see zbar_image_get_width()
unsigned get_width () const
{
return(zbar_image_get_width(_img));
}
/// retrieve the height of the image.
/// see zbar_image_get_height()
unsigned get_height () const
{
return(zbar_image_get_height(_img));
}
/// retrieve both dimensions of the image.
/// see zbar_image_get_size()
/// @since 0.11
void get_size (unsigned &width,
unsigned &height) const
{
zbar_image_get_size(_img, &width, &height);
}
/// specify the pixel size of the image.
/// see zbar_image_set_size()
void set_size (unsigned width,
unsigned height)
{
zbar_image_set_size(_img, width, height);
}
/// retrieve the scan crop rectangle.
/// see zbar_image_get_crop()
void get_crop (unsigned &x,
unsigned &y,
unsigned &width,
unsigned &height) const
{
zbar_image_get_crop(_img, &x, &y, &width, &height);
}
/// set the scan crop rectangle.
/// see zbar_image_set_crop()
void set_crop (unsigned x,
unsigned y,
unsigned width,
unsigned height)
{
zbar_image_set_crop(_img, x, y, width, height);
}
/// return the image sample data.
/// see zbar_image_get_data()
const void *get_data () const
{
return(zbar_image_get_data(_img));
}
/// return the size of the image sample data.
/// see zbar_image_get_data_length()
/// @since 0.6
unsigned long get_data_length () const
{
return(zbar_image_get_data_length(_img));
}
/// specify image sample data.
/// see zbar_image_set_data()
void set_data (const void *data,
unsigned long length)
{
zbar_image_set_data(_img, data, length, _cleanup);
}
/// image format conversion.
/// see zbar_image_convert()
Image convert (unsigned long format) const
{
zbar_image_t *img = zbar_image_convert(_img, format);
if(img)
return(Image(img));
throw FormatError();
}
/// image format conversion.
/// see zbar_image_convert()
/// @since 0.11
Image convert (std::string format) const
{
unsigned long fourcc = zbar_fourcc_parse(format.c_str());
return(convert(fourcc));
}
/// image format conversion with crop/pad.
/// see zbar_image_convert_resize()
/// @since 0.4
Image convert (unsigned long format,
unsigned width,
unsigned height) const
{
zbar_image_t *img =
zbar_image_convert_resize(_img, format, width, height);
if(img)
return(Image(img));
throw FormatError();
}
const SymbolSet get_symbols () const {
return(SymbolSet(zbar_image_get_symbols(_img)));
}
void set_symbols (const SymbolSet &syms) {
zbar_image_set_symbols(_img, syms);
}
/// create a new SymbolIterator over decoded results.
SymbolIterator symbol_begin () const {
return(SymbolIterator(get_symbols()));
}
/// return a SymbolIterator suitable for ending iteration.
SymbolIterator symbol_end () const {
return(SymbolIterator());
}
protected:
friend class Video;
/// constructor.
/// @internal
/// create a new Image from a zbar_image_t C object
Image (zbar_image_t *src,
int refs = 0)
: _img(src)
{
if(refs)
zbar_image_ref(_img, refs);
zbar_image_set_userdata(_img, this);
}
/// default data cleanup (noop)
/// @internal
static void _cleanup (zbar_image_t *img)
{
// by default nothing is cleaned
assert(img);
}
private:
zbar_image_t *_img;
};
}
#endif

View File

@ -0,0 +1,130 @@
//------------------------------------------------------------------------
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_IMAGE_SCANNER_H_
#define _ZBAR_IMAGE_SCANNER_H_
/// @file
/// Image Scanner C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/ImageScanner.h"
#endif
#include "Image.h"
namespace zbar {
/// mid-level image scanner interface.
/// reads barcodes from a 2-D Image
class ImageScanner {
public:
/// constructor.
ImageScanner (zbar_image_scanner_t *scanner = NULL)
{
if(scanner)
_scanner = scanner;
else
_scanner = zbar_image_scanner_create();
}
~ImageScanner ()
{
zbar_image_scanner_destroy(_scanner);
}
/// cast to C image_scanner object
operator zbar_image_scanner_t* () const
{
return(_scanner);
}
/// setup result handler callback.
void set_handler (Image::Handler &handler)
{
zbar_image_scanner_set_data_handler(_scanner, handler, &handler);
}
/// set config for indicated symbology (0 for all) to specified value.
/// @see zbar_image_scanner_set_config()
/// @since 0.4
int set_config (zbar_symbol_type_t symbology,
zbar_config_t config,
int value)
{
return(zbar_image_scanner_set_config(_scanner, symbology,
config, value));
}
/// set config parsed from configuration string.
/// @see zbar_image_scanner_parse_config()
/// @since 0.4
int set_config (std::string cfgstr)
{
return(zbar_image_scanner_parse_config(_scanner, cfgstr.c_str()));
}
/// enable or disable the inter-image result cache.
/// see zbar_image_scanner_enable_cache()
void enable_cache (bool enable = true)
{
zbar_image_scanner_enable_cache(_scanner, enable);
}
/// remove previous results from scanner and image.
/// @see zbar_image_scanner_recycle_image()
/// @since 0.10
void recycle_image (Image &image)
{
zbar_image_scanner_recycle_image(_scanner, image);
}
/// retrieve decode results for last scanned image.
/// @see zbar_image_scanner_get_results()
/// @since 0.10
const SymbolSet get_results () const {
return(SymbolSet(zbar_image_scanner_get_results(_scanner)));
}
/// scan for symbols in provided image.
/// see zbar_scan_image()
int scan (Image& image)
{
return(zbar_scan_image(_scanner, image));
}
/// scan for symbols in provided image.
/// see zbar_scan_image()
ImageScanner& operator<< (Image& image)
{
scan(image);
return(*this);
}
private:
zbar_image_scanner_t *_scanner;
};
}
#endif

View File

@ -0,0 +1,223 @@
//------------------------------------------------------------------------
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_PROCESSOR_H_
#define _ZBAR_PROCESSOR_H_
/// @file
/// Processor C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Processor.h"
#endif
#include "Exception.h"
#include "Image.h"
namespace zbar {
/// high-level self-contained image processor.
/// processes video and images for barcodes, optionally displaying
/// images to a library owned output window
class Processor {
public:
/// value to pass for no timeout.
static const int FOREVER = -1;
/// constructor.
Processor (bool threaded = true,
const char *video_device = "",
bool enable_display = true)
{
_processor = zbar_processor_create(threaded);
if(!_processor)
throw std::bad_alloc();
init(video_device, enable_display);
}
~Processor ()
{
zbar_processor_destroy(_processor);
}
/// cast to C processor object.
operator zbar_processor_t* ()
{
return(_processor);
}
/// opens a video input device and/or prepares to display output.
/// see zbar_processor_init()
void init (const char *video_device = "",
bool enable_display = true)
{
if(zbar_processor_init(_processor, video_device, enable_display))
throw_exception(_processor);
}
/// setup result handler callback.
/// see zbar_processor_set_data_handler()
void set_handler (Image::Handler& handler)
{
zbar_processor_set_data_handler(_processor, handler, &handler);
}
/// set config for indicated symbology (0 for all) to specified value.
/// @see zbar_processor_set_config()
/// @since 0.4
int set_config (zbar_symbol_type_t symbology,
zbar_config_t config,
int value)
{
return(zbar_processor_set_config(_processor, symbology,
config, value));
}
/// set config parsed from configuration string.
/// @see zbar_processor_parse_config()
/// @since 0.4
int set_config (std::string cfgstr)
{
return(zbar_processor_parse_config(_processor, cfgstr.c_str()));
}
/// retrieve the current state of the ouput window.
/// see zbar_processor_is_visible()
bool is_visible ()
{
int rc = zbar_processor_is_visible(_processor);
if(rc < 0)
throw_exception(_processor);
return(rc != 0);
}
/// show or hide the display window owned by the library.
/// see zbar_processor_set_visible()
void set_visible (bool visible = true)
{
if(zbar_processor_set_visible(_processor, visible) < 0)
throw_exception(_processor);
}
/// control the processor in free running video mode.
/// see zbar_processor_set_active()
void set_active (bool active = true)
{
if(zbar_processor_set_active(_processor, active) < 0)
throw_exception(_processor);
}
/// retrieve decode results for last scanned image.
/// @see zbar_processor_get_results()
/// @since 0.10
const SymbolSet get_results () const {
return(SymbolSet(zbar_processor_get_results(_processor)));
}
/// wait for input to the display window from the user.
/// see zbar_processor_user_wait()
int user_wait (int timeout = FOREVER)
{
int rc = zbar_processor_user_wait(_processor, timeout);
if(rc < 0)
throw_exception(_processor);
return(rc);
}
/// process from the video stream until a result is available.
/// see zbar_process_one()
void process_one (int timeout = FOREVER)
{
if(zbar_process_one(_processor, timeout) < 0)
throw_exception(_processor);
}
/// process the provided image for barcodes.
/// see zbar_process_image()
void process_image (Image& image)
{
if(zbar_process_image(_processor, image) < 0)
throw_exception(_processor);
}
/// process the provided image for barcodes.
/// see zbar_process_image()
Processor& operator<< (Image& image)
{
process_image(image);
return(*this);
}
/// force specific input and output formats for debug/testing.
/// see zbar_processor_force_format()
void force_format (unsigned long input_format,
unsigned long output_format)
{
if(zbar_processor_force_format(_processor, input_format,
output_format))
throw_exception(_processor);
}
/// force specific input and output formats for debug/testing.
/// see zbar_processor_force_format()
void force_format (std::string& input_format,
std::string& output_format)
{
unsigned long ifourcc = zbar_fourcc_parse(input_format.c_str());
unsigned long ofourcc = zbar_fourcc_parse(output_format.c_str());
if(zbar_processor_force_format(_processor, ifourcc, ofourcc))
throw_exception(_processor);
}
/// request a preferred size for the video image from the device.
/// see zbar_processor_request_size()
/// @since 0.6
void request_size (int width, int height)
{
zbar_processor_request_size(_processor, width, height);
}
/// request a preferred driver interface version for debug/testing.
/// see zbar_processor_request_interface()
/// @since 0.6
void request_interface (int version)
{
zbar_processor_request_interface(_processor, version);
}
/// request a preferred I/O mode for debug/testing.
/// see zbar_processor_request_iomode()
/// @since 0.7
void request_iomode (int iomode)
{
if(zbar_processor_request_iomode(_processor, iomode))
throw_exception(_processor);
}
private:
zbar_processor_t *_processor;
};
}
#endif

View File

@ -0,0 +1,169 @@
//------------------------------------------------------------------------
// Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _QZBAR_H_
#define _QZBAR_H_
/// @file
/// Barcode Reader Qt4 Widget
#include <qwidget.h>
namespace zbar {
class QZBarThread;
/// barcode reader Qt4 widget.
/// embeds a barcode reader directly into a Qt4 based GUI. the widget
/// can process barcodes from a video source (using the QZBar::videoDevice
/// and QZBar::videoEnabled properties) or from individual QImages
/// supplied to the QZBar::scanImage() slot
/// @since 1.5
class QZBar : public QWidget
{
Q_OBJECT
/// the currently opened video device.
///
/// setting a new device opens it and automatically sets
/// QZBar::videoEnabled
///
/// @see videoDevice(), setVideoDevice()
Q_PROPERTY(QString videoDevice
READ videoDevice
WRITE setVideoDevice
DESIGNABLE false)
/// video device streaming state.
///
/// use to pause/resume video scanning.
///
/// @see isVideoEnabled(), setVideoEnabled()
Q_PROPERTY(bool videoEnabled
READ isVideoEnabled
WRITE setVideoEnabled
DESIGNABLE false)
/// video device opened state.
///
/// (re)setting QZBar::videoDevice should eventually cause it
/// to be opened or closed. any errors while streaming/scanning
/// will also cause the device to be closed
///
/// @see isVideoOpened()
Q_PROPERTY(bool videoOpened
READ isVideoOpened
DESIGNABLE false)
public:
/// constructs a barcode reader widget with the given @a parent
QZBar(QWidget *parent = NULL);
~QZBar();
/// retrieve the currently opened video device.
/// @returns the current video device or the empty string if no
/// device is opened
QString videoDevice() const;
/// retrieve the current video enabled state.
/// @returns true if video scanning is currently enabled, false
/// otherwise
bool isVideoEnabled() const;
/// retrieve the current video opened state.
/// @returns true if video device is currently opened, false otherwise
bool isVideoOpened() const;
/// @{
/// @internal
QSize sizeHint() const;
int heightForWidth(int) const;
QPaintEngine *paintEngine() const;
/// @}
public Q_SLOTS:
/// open a new video device.
///
/// use an empty string to close a currently opened device.
///
/// @note since opening a device may take some time, this call will
/// return immediately and the device will be opened asynchronously
void setVideoDevice(const QString &videoDevice);
/// enable/disable video scanning.
/// has no effect unless a video device is opened
void setVideoEnabled(bool videoEnabled = true);
/// scan for barcodes in a QImage.
void scanImage(const QImage &image);
Q_SIGNALS:
/// emitted when when a video device is opened or closed.
///
/// (re)setting QZBar::videoDevice should eventually cause it
/// to be opened or closed. any errors while streaming/scanning
/// will also cause the device to be closed
void videoOpened(bool videoOpened);
/// emitted when a barcode is decoded from an image.
/// the symbol type and contained data are provided as separate
/// parameters.
void decoded(int type, const QString &data);
/// emitted when a barcode is decoded from an image.
/// the symbol type name is prefixed to the data, separated by a
/// colon
void decodedText(const QString &text);
/// @{
/// @internal
protected:
void attach();
void showEvent(QShowEvent*);
void paintEvent(QPaintEvent*);
void resizeEvent(QResizeEvent*);
void changeEvent(QEvent*);
void dragEnterEvent(QDragEnterEvent*);
void dropEvent(QDropEvent*);
protected Q_SLOTS:
void sizeChange();
/// @}
private:
QZBarThread *thread;
QString _videoDevice;
bool _videoEnabled;
bool _attached;
};
};
#endif

View File

@ -0,0 +1,72 @@
//------------------------------------------------------------------------
// Copyright 2008-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _QZBARIMAGE_H_
#define _QZBARIMAGE_H_
/// @file
/// QImage to Image type conversion wrapper
#include <qimage.h>
#include <zbar.h>
namespace zbar {
/// wrap a QImage and convert into a format suitable for scanning.
class QZBarImage
: public Image
{
public:
/// construct a zbar library image based on an existing QImage.
QZBarImage (const QImage &qimg)
: qimg(qimg)
{
QImage::Format fmt = qimg.format();
if(fmt != QImage::Format_RGB32 &&
fmt != QImage::Format_ARGB32 &&
fmt != QImage::Format_ARGB32_Premultiplied)
throw FormatError();
unsigned bpl = qimg.bytesPerLine();
unsigned width = bpl / 4;
unsigned height = qimg.height();
set_size(width, height);
set_format(zbar_fourcc('B','G','R','4'));
unsigned long datalen = qimg.numBytes();
set_data(qimg.bits(), datalen);
if((width * 4 != bpl) ||
(width * height * 4 > datalen))
throw FormatError();
}
private:
QImage qimg;
};
};
#endif

View File

@ -0,0 +1,162 @@
//------------------------------------------------------------------------
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_SCANNER_H_
#define _ZBAR_SCANNER_H_
/// @file
/// Scanner C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Scanner.h"
#endif
#include <stdio.h>
namespace zbar {
/// low-level linear intensity sample stream scanner interface.
/// identifies "bar" edges and measures width between them.
/// optionally passes to bar width Decoder
class Scanner {
public:
/// constructor.
/// @param decoder reference to a Decoder instance which will
/// be passed scan results automatically
Scanner (Decoder& decoder)
{
_scanner = zbar_scanner_create(decoder._decoder);
}
/// constructor.
/// @param decoder pointer to a Decoder instance which will
/// be passed scan results automatically
Scanner (Decoder* decoder = NULL)
{
zbar_decoder_t *zdcode = NULL;
if(decoder)
zdcode = decoder->_decoder;
_scanner = zbar_scanner_create(zdcode);
}
~Scanner ()
{
zbar_scanner_destroy(_scanner);
}
/// clear all scanner state.
/// see zbar_scanner_reset()
void reset ()
{
zbar_scanner_reset(_scanner);
}
/// mark start of a new scan pass.
/// see zbar_scanner_new_scan()
zbar_symbol_type_t new_scan ()
{
_type = zbar_scanner_new_scan(_scanner);
return(_type);
}
/// flush scanner pipeline.
/// see zbar_scanner_flush()
zbar_symbol_type_t flush ()
{
_type = zbar_scanner_flush(_scanner);
return(_type);
}
/// process next sample intensity value.
/// see zbar_scan_y()
zbar_symbol_type_t scan_y (int y)
{
_type = zbar_scan_y(_scanner, y);
return(_type);
}
/// process next sample intensity value.
/// see zbar_scan_y()
Scanner& operator<< (int y)
{
_type = zbar_scan_y(_scanner, y);
return(*this);
}
/// process next sample from RGB (or BGR) triple.
/// see zbar_scan_rgb24()
zbar_symbol_type_t scan_rgb24 (unsigned char *rgb)
{
_type = zbar_scan_rgb24(_scanner, rgb);
return(_type);
}
/// process next sample from RGB (or BGR) triple.
/// see zbar_scan_rgb24()
Scanner& operator<< (unsigned char *rgb)
{
_type = zbar_scan_rgb24(_scanner, rgb);
return(*this);
}
/// retrieve last scanned width.
/// see zbar_scanner_get_width()
unsigned get_width () const
{
return(zbar_scanner_get_width(_scanner));
}
/// retrieve last scanned color.
/// see zbar_scanner_get_color()
zbar_color_t get_color () const
{
return(zbar_scanner_get_color(_scanner));
}
/// retrieve last scan result.
zbar_symbol_type_t get_type () const
{
return(_type);
}
/// cast to C scanner
operator zbar_scanner_t* () const
{
return(_scanner);
}
/// retrieve C scanner
const zbar_scanner_t *get_c_scanner () const
{
return(_scanner);
}
private:
zbar_scanner_t *_scanner;
zbar_symbol_type_t _type;
};
}
#endif

View File

@ -0,0 +1,541 @@
//------------------------------------------------------------------------
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_SYMBOL_H_
#define _ZBAR_SYMBOL_H_
/// @file
/// Symbol C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Symbol.h"
#endif
#include <stdlib.h>
#include <string>
#include <ostream>
#include <assert.h>
namespace zbar {
class SymbolIterator;
/// container for decoded result symbols associated with an image
/// or a composite symbol.
class SymbolSet {
public:
/// constructor.
SymbolSet (const zbar_symbol_set_t *syms = NULL)
: _syms(syms)
{
ref();
}
/// copy constructor.
SymbolSet (const SymbolSet& syms)
: _syms(syms._syms)
{
ref();
}
/// destructor.
~SymbolSet ()
{
ref(-1);
}
/// assignment.
SymbolSet& operator= (const SymbolSet& syms)
{
syms.ref();
ref(-1);
_syms = syms._syms;
return(*this);
}
/// truth testing.
bool operator! () const
{
return(!_syms || !get_size());
}
/// manipulate reference count.
void ref (int delta = 1) const
{
if(_syms)
zbar_symbol_set_ref((zbar_symbol_set_t*)_syms, delta);
}
/// cast to C symbol set.
operator const zbar_symbol_set_t* () const
{
return(_syms);
}
int get_size () const
{
return((_syms) ? zbar_symbol_set_get_size(_syms) : 0);
}
/// create a new SymbolIterator over decoded results.
SymbolIterator symbol_begin() const;
/// return a SymbolIterator suitable for ending iteration.
const SymbolIterator symbol_end() const;
private:
const zbar_symbol_set_t *_syms;
};
/// decoded barcode symbol result object. stores type, data, and
/// image location of decoded symbol
class Symbol {
public:
/// image pixel location (x, y) coordinate tuple.
class Point {
public:
int x; ///< x-coordinate.
int y; ///< y-coordinate.
Point () { }
Point(int x, int y)
: x(x), y(y)
{ }
/// copy constructor.
Point (const Point& pt)
: x(pt.x),
y(pt.y)
{ }
/// assignment.
Point& operator= (const Point& pt)
{
x = pt.x;
y = pt.y;
return(*this);
}
};
/// iteration over Point objects in a symbol location polygon.
class PointIterator
: public std::iterator<std::input_iterator_tag, Point> {
public:
/// constructor.
PointIterator (const Symbol *sym = NULL,
int index = 0)
: _sym(sym),
_index(index)
{
if(sym)
sym->ref(1);
if(!sym ||
(unsigned)_index >= zbar_symbol_get_loc_size(*_sym))
_index = -1;
}
/// copy constructor.
PointIterator (const PointIterator& iter)
: _sym(iter._sym),
_index(iter._index)
{
if(_sym)
_sym->ref();
}
/// destructor.
~PointIterator ()
{
if(_sym)
_sym->ref(-1);
}
/// assignment.
PointIterator& operator= (const PointIterator& iter)
{
if(iter._sym)
iter._sym->ref();
if(_sym)
_sym->ref(-1);
_sym = iter._sym;
_index = iter._index;
return(*this);
}
/// truth testing.
bool operator! () const
{
return(!_sym || _index < 0);
}
/// advance iterator to next Point.
PointIterator& operator++ ()
{
unsigned int i = ++_index;
if(!_sym || i >= zbar_symbol_get_loc_size(*_sym))
_index = -1;
return(*this);
}
/// retrieve currently referenced Point.
const Point operator* () const
{
assert(!!*this);
if(!*this)
return(Point());
return(Point(zbar_symbol_get_loc_x(*_sym, _index),
zbar_symbol_get_loc_y(*_sym, _index)));
}
/// test if two iterators refer to the same Point in the same
/// Symbol.
bool operator== (const PointIterator& iter) const
{
return(_index == iter._index &&
((_index < 0) || _sym == iter._sym));
}
/// test if two iterators refer to the same Point in the same
/// Symbol.
bool operator!= (const PointIterator& iter) const
{
return(!(*this == iter));
}
private:
const Symbol *_sym;
int _index;
};
/// constructor.
Symbol (const zbar_symbol_t *sym = NULL)
: _xmlbuf(NULL),
_xmllen(0)
{
init(sym);
ref();
}
/// copy constructor.
Symbol (const Symbol& sym)
: _sym(sym._sym),
_type(sym._type),
_data(sym._data),
_xmlbuf(NULL),
_xmllen(0)
{
ref();
}
/// destructor.
~Symbol () {
if(_xmlbuf)
free(_xmlbuf);
ref(-1);
}
/// assignment.
Symbol& operator= (const Symbol& sym)
{
sym.ref(1);
ref(-1);
_sym = sym._sym;
_type = sym._type;
_data = sym._data;
return(*this);
}
Symbol& operator= (const zbar_symbol_t *sym)
{
if(sym)
zbar_symbol_ref(sym, 1);
ref(-1);
init(sym);
return(*this);
}
/// truth testing.
bool operator! () const
{
return(!_sym);
}
void ref (int delta = 1) const
{
if(_sym)
zbar_symbol_ref((zbar_symbol_t*)_sym, delta);
}
/// cast to C symbol.
operator const zbar_symbol_t* () const
{
return(_sym);
}
/// test if two Symbol objects refer to the same C symbol.
bool operator== (const Symbol& sym) const
{
return(_sym == sym._sym);
}
/// test if two Symbol objects refer to the same C symbol.
bool operator!= (const Symbol& sym) const
{
return(!(*this == sym));
}
/// retrieve type of decoded symbol.
zbar_symbol_type_t get_type () const
{
return(_type);
}
/// retrieve the string name of the symbol type.
const std::string get_type_name () const
{
return(zbar_get_symbol_name(_type));
}
/// retrieve the string name for any addon.
/// @deprecated in 0.11
const std::string get_addon_name () const
{
return(zbar_get_addon_name(_type));
}
/// retrieve data decoded from symbol.
const std::string get_data () const
{
return(_data);
}
/// retrieve length of binary data
unsigned get_data_length () const
{
return((_sym) ? zbar_symbol_get_data_length(_sym) : 0);
}
/// retrieve inter-frame coherency count.
/// see zbar_symbol_get_count()
/// @since 0.5
int get_count () const
{
return((_sym) ? zbar_symbol_get_count(_sym) : -1);
}
/// retrieve loosely defined relative quality metric.
/// see zbar_symbol_get_quality()
/// @since 0.11
int get_quality () const
{
return((_sym) ? zbar_symbol_get_quality(_sym) : 0);
}
SymbolSet get_components () const
{
return(SymbolSet((_sym) ? zbar_symbol_get_components(_sym) : NULL));
}
/// create a new PointIterator at the start of the location
/// polygon.
PointIterator point_begin() const
{
return(PointIterator(this));
}
/// return a PointIterator suitable for ending iteration.
const PointIterator point_end() const
{
return(PointIterator());
}
/// see zbar_symbol_get_loc_size().
int get_location_size () const
{
return((_sym) ? zbar_symbol_get_loc_size(_sym) : 0);
}
/// see zbar_symbol_get_loc_x().
int get_location_x (unsigned index) const
{
return((_sym) ? zbar_symbol_get_loc_x(_sym, index) : -1);
}
/// see zbar_symbol_get_loc_y().
int get_location_y (unsigned index) const
{
return((_sym) ? zbar_symbol_get_loc_y(_sym, index) : -1);
}
/// see zbar_symbol_get_orientation().
/// @since 0.11
int get_orientation () const
{
return(zbar_symbol_get_orientation(_sym));
}
/// see zbar_symbol_xml().
const std::string xml () const
{
if(!_sym)
return("");
return(zbar_symbol_xml(_sym, (char**)&_xmlbuf, (unsigned*)&_xmllen));
}
protected:
/// (re)initialize Symbol from C symbol object.
void init (const zbar_symbol_t *sym = NULL)
{
_sym = sym;
if(sym) {
_type = zbar_symbol_get_type(sym);
_data = std::string(zbar_symbol_get_data(sym),
zbar_symbol_get_data_length(sym));
}
else {
_type = ZBAR_NONE;
_data = "";
}
}
private:
const zbar_symbol_t *_sym;
zbar_symbol_type_t _type;
std::string _data;
char *_xmlbuf;
unsigned _xmllen;
};
/// iteration over Symbol result objects in a scanned Image or SymbolSet.
class SymbolIterator
: public std::iterator<std::input_iterator_tag, Symbol> {
public:
/// default constructor.
SymbolIterator ()
{ }
/// constructor.
SymbolIterator (const SymbolSet &syms)
: _syms(syms)
{
const zbar_symbol_set_t *zsyms = _syms;
if(zsyms)
_sym = zbar_symbol_set_first_symbol(zsyms);
}
/// copy constructor.
SymbolIterator (const SymbolIterator& iter)
: _syms(iter._syms)
{
const zbar_symbol_set_t *zsyms = _syms;
if(zsyms)
_sym = zbar_symbol_set_first_symbol(zsyms);
}
~SymbolIterator ()
{
}
/// assignment.
SymbolIterator& operator= (const SymbolIterator& iter)
{
_syms = iter._syms;
_sym = iter._sym;
return(*this);
}
bool operator! () const
{
return(!_syms || !_sym);
}
/// advance iterator to next Symbol.
SymbolIterator& operator++ ()
{
if(!!_sym)
_sym = zbar_symbol_next(_sym);
else if(!!_syms)
_sym = zbar_symbol_set_first_symbol(_syms);
return(*this);
}
/// retrieve currently referenced Symbol.
const Symbol operator* () const
{
return(_sym);
}
/// access currently referenced Symbol.
const Symbol* operator-> () const
{
return(&_sym);
}
/// test if two iterators refer to the same Symbol
bool operator== (const SymbolIterator& iter) const
{
// it is enough to test the symbols, as they belong
// to only one set (also simplifies invalid case)
return(_sym == iter._sym);
}
/// test if two iterators refer to the same Symbol
bool operator!= (const SymbolIterator& iter) const
{
return(!(*this == iter));
}
const SymbolIterator end () const {
return(SymbolIterator());
}
private:
SymbolSet _syms;
Symbol _sym;
};
__inline SymbolIterator SymbolSet::symbol_begin () const {
return(SymbolIterator(*this));
}
__inline const SymbolIterator SymbolSet::symbol_end () const {
return(SymbolIterator());
}
/// @relates Symbol
/// stream the string representation of a Symbol.
static __inline std::ostream& operator<< (std::ostream& out,
const Symbol& sym)
{
out << sym.get_type_name() << ":" << sym.get_data();
return(out);
}
}
#endif

View File

@ -0,0 +1,170 @@
//------------------------------------------------------------------------
// Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_VIDEO_H_
#define _ZBAR_VIDEO_H_
/// @file
/// Video Input C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Video.h"
#endif
#include "Image.h"
namespace zbar {
/// mid-level video source abstraction.
/// captures images from a video device
class Video {
public:
/// constructor.
Video (zbar_video_t *video = NULL)
{
if(video)
_video = video;
else
_video = zbar_video_create();
}
/// constructor.
Video (std::string& device)
{
_video = zbar_video_create();
open(device);
}
~Video ()
{
zbar_video_destroy(_video);
}
/// cast to C video object.
operator zbar_video_t* () const
{
return(_video);
}
/// open and probe a video device.
void open (std::string& device)
{
if(zbar_video_open(_video, device.c_str()))
throw_exception(_video);
}
/// close video device if open.
void close ()
{
if(zbar_video_open(_video, NULL))
throw_exception(_video);
}
/// initialize video using a specific format for debug.
/// see zbar_video_init()
void init (unsigned long fourcc)
{
if(zbar_video_init(_video, fourcc))
throw_exception(_video);
}
/// initialize video using a specific format for debug.
/// see zbar_video_init()
void init (std::string& format)
{
unsigned int fourcc = zbar_fourcc_parse(format.c_str());
if(zbar_video_init(_video, fourcc))
throw_exception(_video);
}
/// retrieve file descriptor associated with open *nix video device.
/// see zbar_video_get_fd()
int get_fd ()
{
return(zbar_video_get_fd(_video));
}
/// retrieve current output image width.
/// see zbar_video_get_width()
int get_width ()
{
return(zbar_video_get_width(_video));
}
/// retrieve current output image height.
/// see zbar_video_get_height()
int get_height ()
{
return(zbar_video_get_height(_video));
}
/// start/stop video capture.
/// see zbar_video_enable()
void enable (bool enable = true)
{
if(zbar_video_enable(_video, enable))
throw_exception(_video);
}
/// retrieve next captured image.
/// see zbar_video_next_image()
Image next_image ()
{
zbar_image_t *img = zbar_video_next_image(_video);
if(!img)
throw_exception(_video);
return(Image(img));
}
/// request a preferred size for the video image from the device.
/// see zbar_video_request_size()
/// @since 0.6
void request_size (int width, int height)
{
zbar_video_request_size(_video, width, height);
}
/// request a preferred driver interface version for debug/testing.
/// see zbar_video_request_interface()
/// @since 0.6
void request_interface (int version)
{
zbar_video_request_interface(_video, version);
}
/// request a preferred I/O mode for debug/testing.
/// see zbar_video_request_iomode()
/// @since 0.7
void request_iomode (int iomode)
{
if(zbar_video_request_iomode(_video, iomode))
throw_exception(_video);
}
private:
zbar_video_t *_video;
};
}
#endif

View File

@ -0,0 +1,136 @@
//------------------------------------------------------------------------
// Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
//
// This file is part of the ZBar Bar Code Reader.
//
// The ZBar Bar Code Reader is free software; you can redistribute it
// and/or modify it under the terms of the GNU Lesser Public License as
// published by the Free Software Foundation; either version 2.1 of
// the License, or (at your option) any later version.
//
// The ZBar Bar Code Reader is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser Public License for more details.
//
// You should have received a copy of the GNU Lesser Public License
// along with the ZBar Bar Code Reader; if not, write to the Free
// Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA
//
// http://sourceforge.net/projects/zbar
//------------------------------------------------------------------------
#ifndef _ZBAR_WINDOW_H_
#define _ZBAR_WINDOW_H_
/// @file
/// Output Window C++ wrapper
#ifndef _ZBAR_H_
# error "include zbar.h in your application, **not** zbar/Window.h"
#endif
#include "Image.h"
namespace zbar {
/// mid-level output window abstraction.
/// displays images to user-specified platform specific output window
class Window {
public:
/// constructor.
Window (zbar_window_t *window = NULL)
{
if(window)
_window = window;
else
_window = zbar_window_create();
}
/// constructor.
Window (void *x11_display_w32_hwnd,
unsigned long x11_drawable)
{
_window = zbar_window_create();
attach(x11_display_w32_hwnd, x11_drawable);
}
~Window ()
{
zbar_window_destroy(_window);
}
/// cast to C window object.
operator zbar_window_t* () const
{
return(_window);
}
/// associate reader with an existing platform window.
/// see zbar_window_attach()
void attach (void *x11_display_w32_hwnd,
unsigned long x11_drawable = 0)
{
if(zbar_window_attach(_window,
x11_display_w32_hwnd, x11_drawable) < 0)
throw_exception(_window);
}
/// control content level of the reader overlay.
/// see zbar_window_set_overlay()
void set_overlay (int level)
{
zbar_window_set_overlay(_window, level);
}
/// retrieve current content level of reader overlay.
/// see zbar_window_get_overlay()
/// draw a new image into the output window.
/// see zbar_window_draw()
void draw (Image& image)
{
if(zbar_window_draw(_window, image) < 0)
throw_exception(_window);
}
/// clear the image from the output window.
/// see zbar_window_draw()
void clear ()
{
if(zbar_window_draw(_window, NULL) < 0)
throw_exception(_window);
}
/// redraw the last image.
/// zbar_window_redraw()
void redraw ()
{
if(zbar_window_redraw(_window) < 0)
throw_exception(_window);
}
/// resize the image window.
/// zbar_window_resize()
void resize (unsigned width, unsigned height)
{
if(zbar_window_resize(_window, width, height) < 0)
throw_exception(_window);
}
private:
zbar_window_t *_window;
};
/// select a compatible format between video input and output window.
/// see zbar_negotiate_format()
static inline void negotiate_format (Video& video, Window& window)
{
if(zbar_negotiate_format(video, window) < 0)
throw_exception(video);
}
}
#endif

View File

@ -0,0 +1,215 @@
/*------------------------------------------------------------------------
* Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
#ifndef __ZBAR_GTK_H__
#define __ZBAR_GTK_H__
/** SECTION:ZBarGtk
* @short_description: barcode reader GTK+ 2.x widget
* @include: zbar/zbargtk.h
*
* embeds a barcode reader directly into a GTK+ based GUI. the widget
* can process barcodes from a video source (using the
* #ZBarGtk:video-device and #ZBarGtk:video-enabled properties) or
* from individual GdkPixbufs supplied to zbar_gtk_scan_image()
*
* Since: 1.5
*/
#include <glib.h>
#include <glib-object.h>
#include <gtk/gtktable.h>
#include <zbar.h>
G_BEGIN_DECLS
#define ZBAR_TYPE_GTK (zbar_gtk_get_type())
#define ZBAR_GTK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), ZBAR_TYPE_GTK, ZBarGtk))
#define ZBAR_GTK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), ZBAR_TYPE_GTK, ZBarGtkClass))
#define ZBAR_IS_GTK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), ZBAR_TYPE_GTK))
#define ZBAR_IS_GTK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), ZBAR_TYPE_GTK))
#define ZBAR_GTK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), ZBAR_TYPE_GTK, ZBarGtkClass))
typedef struct _ZBarGtk ZBarGtk;
typedef struct _ZBarGtkClass ZBarGtkClass;
struct _ZBarGtk {
GtkWidget widget;
gpointer *_private;
/* properties */
/**
* ZBarGtk:video-device:
*
* the currently set video device.
*
* setting a new device opens it and automatically sets
* #ZBarGtk:video-enabled. set the empty string ("") or NULL to
* close.
*/
/**
* ZBarGtk:video-enabled:
*
* video device streaming state.
*
* use to pause/resume video scanning.
*/
/**
* ZBarGtk:video-opened:
*
* video device opened state.
*
* (re)setting #ZBarGtk:video-device should eventually cause it
* to be opened or closed. any errors while streaming/scanning
* will also cause the device to be closed
*/
};
struct _ZBarGtkClass {
GtkWidgetClass parent_class;
/* signals */
/**
* ZBarGtk::decoded:
* @widget: the object that received the signal
* @symbol_type: the type of symbol decoded (a zbar_symbol_type_t)
* @data: the data decoded from the symbol
*
* emitted when a barcode is decoded from an image.
* the symbol type and contained data are provided as separate
* parameters
*/
void (*decoded) (ZBarGtk *zbar,
zbar_symbol_type_t symbol_type,
const char *data);
/**
* ZBarGtk::decoded-text:
* @widget: the object that received the signal
* @text: the decoded data prefixed by the string name of the
* symbol type (separated by a colon)
*
* emitted when a barcode is decoded from an image.
* the symbol type name is prefixed to the data, separated by a
* colon
*/
void (*decoded_text) (ZBarGtk *zbar,
const char *text);
/**
* ZBarGtk::scan-image:
* @widget: the object that received the signal
* @image: the image to scan for barcodes
*/
void (*scan_image) (ZBarGtk *zbar,
GdkPixbuf *image);
};
GType zbar_gtk_get_type(void) G_GNUC_CONST;
/**
* zbar_gtk_new:
* create a new barcode reader widget instance.
* initially has no associated video device or image.
*
* Returns: a new #ZBarGtk widget instance
*/
GtkWidget *zbar_gtk_new(void);
/**
* zbar_gtk_scan_image:
*
*/
void zbar_gtk_scan_image(ZBarGtk *zbar,
GdkPixbuf *image);
/** retrieve the currently opened video device.
*
* Returns: the current video device or NULL if no device is opened
*/
const char *zbar_gtk_get_video_device(ZBarGtk *zbar);
/** open a new video device.
*
* @video_device: the platform specific name of the device to open.
* use NULL to close a currently opened device.
*
* @note since opening a device may take some time, this call will
* return immediately and the device will be opened asynchronously
*/
void zbar_gtk_set_video_device(ZBarGtk *zbar,
const char *video_device);
/** retrieve the current video enabled state.
*
* Returns: true if video scanning is currently enabled, false otherwise
*/
gboolean zbar_gtk_get_video_enabled(ZBarGtk *zbar);
/** enable/disable video scanning.
* @video_enabled: true to enable video scanning, false to disable
*
* has no effect unless a video device is opened
*/
void zbar_gtk_set_video_enabled(ZBarGtk *zbar,
gboolean video_enabled);
/** retrieve the current video opened state.
*
* Returns: true if video device is currently opened, false otherwise
*/
gboolean zbar_gtk_get_video_opened(ZBarGtk *zbar);
/** set video camera resolution.
* @width: width in pixels
* @height: height in pixels
*
* @note this call must be made before video is initialized
*/
void zbar_gtk_request_video_size(ZBarGtk *zbar,
int width,
int height);
/**
* utility function to populate a zbar_image_t from a GdkPixbuf.
* @image: the zbar library image destination to populate
* @pixbuf: the GdkPixbuf source
*
* Returns: TRUE if successful or FALSE if the conversion could not be
* performed for some reason
*/
gboolean zbar_gtk_image_from_pixbuf(zbar_image_t *image,
GdkPixbuf *pixbuf);
G_END_DECLS
#endif

View File

@ -0,0 +1,58 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __BARCODE_FORMAT_H__
#define __BARCODE_FORMAT_H__
/*
* BarcodeFormat.h
* zxing
*
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace zxing {
class BarcodeFormat {
public:
// if you update the enum, update BarcodeFormat.cpp
enum Value {
NONE,
AZTEC,
CODABAR,
CODE_39,
CODE_93,
CODE_128,
DATA_MATRIX,
EAN_8,
EAN_13,
ITF,
MAXICODE,
PDF_417,
QR_CODE,
RSS_14,
RSS_EXPANDED,
UPC_A,
UPC_E,
UPC_EAN_EXTENSION
};
BarcodeFormat(Value v) : value(v) {}
const Value value;
operator Value () const { return value; }
static char const* barcodeFormatNames[];
};
}
#endif // __BARCODE_FORMAT_H__

View File

@ -0,0 +1,49 @@
#ifndef BINARIZER_H_
#define BINARIZER_H_
/*
* Binarizer.h
* zxing
*
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zxing/LuminanceSource.h>
#include <zxing/common/BitArray.h>
#include <zxing/common/BitMatrix.h>
#include <zxing/common/Counted.h>
namespace zxing {
class Binarizer : public Counted {
private:
Ref<LuminanceSource> source_;
public:
Binarizer(Ref<LuminanceSource> source);
virtual ~Binarizer();
virtual Ref<BitArray> getBlackRow(int y, Ref<BitArray> row) = 0;
virtual Ref<BitMatrix> getBlackMatrix() = 0;
Ref<LuminanceSource> getLuminanceSource() const;
virtual Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source) = 0;
int getWidth() const;
int getHeight() const;
};
}
#endif /* BINARIZER_H_ */

View File

@ -0,0 +1,55 @@
#ifndef __BINARYBITMAP_H__
#define __BINARYBITMAP_H__
/*
* BinaryBitmap.h
* zxing
*
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zxing/common/Counted.h>
#include <zxing/common/BitMatrix.h>
#include <zxing/common/BitArray.h>
#include <zxing/Binarizer.h>
namespace zxing {
class BinaryBitmap : public Counted {
private:
Ref<Binarizer> binarizer_;
public:
BinaryBitmap(Ref<Binarizer> binarizer);
virtual ~BinaryBitmap();
Ref<BitArray> getBlackRow(int y, Ref<BitArray> row);
Ref<BitMatrix> getBlackMatrix();
Ref<LuminanceSource> getLuminanceSource() const;
int getWidth() const;
int getHeight() const;
bool isRotateSupported() const;
Ref<BinaryBitmap> rotateCounterClockwise();
bool isCropSupported() const;
Ref<BinaryBitmap> crop(int left, int top, int width, int height);
};
}
#endif /* BINARYBITMAP_H_ */

View File

@ -0,0 +1,34 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __CHECKSUM_EXCEPTION_H__
#define __NOT_FOUND_EXCEPTION_H__
/*
* Copyright 20011 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zxing/ReaderException.h>
namespace zxing {
class ChecksumException : public ReaderException {
typedef ReaderException Base;
public:
ChecksumException() throw();
ChecksumException(const char* msg) throw();
~ChecksumException() throw();
};
}
#endif // __CHECKSUM_EXCEPTION_H__

View File

@ -0,0 +1,85 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __DECODEHINTS_H_
#define __DECODEHINTS_H_
/*
* DecodeHintType.h
* zxing
*
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zxing/BarcodeFormat.h>
#include <zxing/ResultPointCallback.h>
namespace zxing {
typedef unsigned int DecodeHintType;
class DecodeHints;
DecodeHints operator | (DecodeHints const&, DecodeHints const&);
class DecodeHints {
private:
DecodeHintType hints;
Ref<ResultPointCallback> callback;
public:
static const DecodeHintType AZTEC_HINT = 1 << BarcodeFormat::AZTEC;
static const DecodeHintType CODABAR_HINT = 1 << BarcodeFormat::CODABAR;
static const DecodeHintType CODE_39_HINT = 1 << BarcodeFormat::CODE_39;
static const DecodeHintType CODE_93_HINT = 1 << BarcodeFormat::CODE_93;
static const DecodeHintType CODE_128_HINT = 1 << BarcodeFormat::CODE_128;
static const DecodeHintType DATA_MATRIX_HINT = 1 << BarcodeFormat::DATA_MATRIX;
static const DecodeHintType EAN_8_HINT = 1 << BarcodeFormat::EAN_8;
static const DecodeHintType EAN_13_HINT = 1 << BarcodeFormat::EAN_13;
static const DecodeHintType ITF_HINT = 1 << BarcodeFormat::ITF;
static const DecodeHintType MAXICODE_HINT = 1 << BarcodeFormat::MAXICODE;
static const DecodeHintType PDF_417_HINT = 1 << BarcodeFormat::PDF_417;
static const DecodeHintType QR_CODE_HINT = 1 << BarcodeFormat::QR_CODE;
static const DecodeHintType RSS_14_HINT = 1 << BarcodeFormat::RSS_14;
static const DecodeHintType RSS_EXPANDED_HINT = 1 << BarcodeFormat::RSS_EXPANDED;
static const DecodeHintType UPC_A_HINT = 1 << BarcodeFormat::UPC_A;
static const DecodeHintType UPC_E_HINT = 1 << BarcodeFormat::UPC_E;
static const DecodeHintType UPC_EAN_EXTENSION_HINT = 1 << BarcodeFormat::UPC_EAN_EXTENSION;
static const DecodeHintType TRYHARDER_HINT = 1 << 31;
static const DecodeHintType CHARACTER_SET = 1 << 30;
// static const DecodeHintType ALLOWED_LENGTHS = 1 << 29;
// static const DecodeHintType ASSUME_CODE_39_CHECK_DIGIT = 1 << 28;
static const DecodeHintType ASSUME_GS1 = 1 << 27;
// static const DecodeHintType NEED_RESULT_POINT_CALLBACK = 1 << 26;
static const DecodeHints PRODUCT_HINT;
static const DecodeHints ONED_HINT;
static const DecodeHints DEFAULT_HINT;
DecodeHints();
DecodeHints(DecodeHintType init);
void addFormat(BarcodeFormat toadd);
bool containsFormat(BarcodeFormat tocheck) const;
bool isEmpty() const { return (hints == 0); }
void clear() { hints = 0; }
void setTryHarder(bool toset);
bool getTryHarder() const;
void setResultPointCallback(Ref<ResultPointCallback> const&);
Ref<ResultPointCallback> getResultPointCallback() const;
friend DecodeHints operator | (DecodeHints const&, DecodeHints const&);
};
}
#endif

View File

@ -0,0 +1,51 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
/*
* Exception.h
* ZXing
*
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <exception>
namespace zxing {
class Exception : public std::exception {
private:
char const* const message;
public:
Exception() throw() : message(0) {}
Exception(const char* msg) throw() : message(copy(msg)) {}
Exception(Exception const& that) throw() : std::exception(that), message(copy(that.message)) {}
~Exception() throw() {
if (message) {
deleteMessage();
}
}
char const* what() const throw() { return message ? message : ""; }
private:
static char const* copy(char const*);
void deleteMessage();
};
}
#endif // __EXCEPTION_H__

View File

@ -0,0 +1,37 @@
#ifndef __FORMAT_EXCEPTION_H__
#define __FORMAT_EXCEPTION_H__
/*
* FormatException.h
* zxing
*
* Copyright 2010 ZXing authors All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zxing/ReaderException.h>
namespace zxing {
class FormatException : public ReaderException {
public:
FormatException();
FormatException(const char* msg);
~FormatException() throw();
static FormatException const& getFormatInstance();
};
}
#endif // __FORMAT_EXCEPTION_H__

View File

@ -0,0 +1,35 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __ILLEGAL_STATE_EXCEPTION_H__
#define __ILLEGAL_STATE_EXCEPTION_H__
/*
* Copyright 20011 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may illegal use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zxing/ReaderException.h>
namespace zxing {
class IllegalStateException : public ReaderException {
public:
IllegalStateException() throw() {}
IllegalStateException(const char* msg) throw() : ReaderException(msg) {}
~IllegalStateException() throw() {}
};
}
#endif // __ILLEGAL_STATE_EXCEPTION_H__

Some files were not shown because too many files have changed in this diff Show More