mirror of http://192.168.1.51:8099/lmh188/twain3
twain3测试版本,代码问题暂未处理
This commit is contained in:
parent
26bb7a7156
commit
2d07d227a9
|
@ -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)
|
|
@ -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
|
|
@ -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)
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "IMulti.h"
|
||||||
|
|
||||||
|
IMulti::IMulti(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IMulti::~IMulti(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "ImageApply.h"
|
||||||
|
|
||||||
|
CImageApply::CImageApply(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CImageApply::~CImageApply(void)
|
||||||
|
{
|
||||||
|
}
|
|
@ -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
|
|
@ -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)));
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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,从原来的51调整到25
|
||||||
|
* 版本号: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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
|
||||||
|
* 功能:色彩识别,将识别会“灰度”的24位图转化为256色8位图, 把识别为“黑白”图转化为二值化的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
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
|
||||||
|
* 功能:拼接,又名对折
|
||||||
|
* 作者:刘丁维
|
||||||
|
* 生成时间:2020/4/21
|
||||||
|
* 最近修改时间:2020/4/29
|
||||||
|
* 版本号:v1.0 2020/4/21
|
||||||
|
* 版本号:v1.1 2020/4/29 : 1、添加m_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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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]:表的长度,灰度表256,彩色表768
|
||||||
|
* */
|
||||||
|
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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
|
||||||
|
* 功能:空白页识别。
|
||||||
|
* 作者:刘丁维
|
||||||
|
* 生成时间:2020/4/21
|
||||||
|
* 最近修改时间:2020/4/21 v1.0
|
||||||
|
2020/8/12 v1.1 开放setIntensity和setMinArea;取消isNormal标识位;扩大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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
|
||||||
|
* 功能:彩色图像,色彩校正。基于LUT实现,预设BGR查值表(表达所有HVS),对BGR原图进行查值校正。
|
||||||
|
* 作者:刘丁维
|
||||||
|
* 生成时间: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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 函数功能:初始化查值表,按照RGB(R在高位,B在低位)的32位数据进行索引,值与索引一致。
|
||||||
|
表中索引范围[0,0x00FFFFFF]。在构造函数中会默认调用该函数。
|
||||||
|
*/
|
||||||
|
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
|
|
@ -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
|
|
@ -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 //
|
|
@ -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
|
|
@ -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); //判断是否在纸张内 1:内;0:上;-1:外
|
||||||
|
double temp2 = pointPolygonTest(vertices_roi2, p, false); //判断是否在边缘区域内 1:内;0:上;-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()));
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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]:当前图像的DPI,该参数在rotation为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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
};
|
|
@ -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 = "版权"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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__
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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__
|
|
@ -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
|
|
@ -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__
|
|
@ -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__
|
|
@ -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
Loading…
Reference in New Issue