算法更新

This commit is contained in:
13038267101 2022-07-29 16:41:34 +08:00
parent 53174686f7
commit 186a2c3165
270 changed files with 28362 additions and 4901 deletions

View File

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

View File

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

View File

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

View File

@ -1,21 +1,34 @@
#ifndef IMAGE_APPLY_H /*
#define IMAGE_APPLY_H * ====================================================
#include <vector> *
#include <memory> *
#include <opencv2/opencv.hpp> * 2020/4/21
* 2020/4/21
class CImageApply * v1.0
{
public: * ====================================================
CImageApply(void); */
virtual ~CImageApply(void);
#ifndef IMAGE_APPLY_H
virtual void apply(cv::Mat& pDib,int side) = 0; #define IMAGE_APPLY_H
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide) = 0; #include <memory>
}; #include <vector>
#include <opencv2/opencv.hpp>
typedef std::shared_ptr<CImageApply> ImageApplyPtr; #include "imgprocdefs.h"
#endif //!IMAGE_APPLY_H class GIMGPROC_LIBRARY_API CImageApply
{
public:
CImageApply(void);
virtual ~CImageApply(void);
virtual void apply(cv::Mat& pDib,int side) = 0;
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide) = 0;
};
typedef std::shared_ptr<CImageApply> ImageApplyPtr;
#endif // !IMAGE_APPLY_H

View File

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

View File

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

View File

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

View File

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

View File

@ -1,393 +1,330 @@
#include "ImageApplyAutoCrop.h" #include "ImageApplyAutoCrop.h"
#include "ImageProcess_Public.h" #include "ImageProcess_Public.h"
#include <iostream>
CImageApplyAutoCrop::CImageApplyAutoCrop() #include <opencv2/imgproc/hal/hal.hpp>
: m_isCrop(false) #include "ImageApplyDispersion.h"
, m_isDesaskew(false)
, m_isFillBlank(false) CImageApplyAutoCrop::CImageApplyAutoCrop()
, m_isConvexHull(true) : m_isCrop(false)
, m_isFillColor(false) , m_isDesaskew(false)
, m_threshold(40) , m_isFillBlank(false)
, m_noise(8) , m_isConvexHull(true)
, m_indent(5) , m_isFillColor(false)
, m_normalCrop(false) , m_threshold(40)
{ , m_noise(8)
} , m_indent(5)
, m_normalCrop(false)
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, , m_isDispersion(true)
double threshold, int noise, int indent, bool normalCrop) {
: m_isCrop(isCrop) }
, m_isDesaskew(isDesaskew)
, m_isFillBlank(isFillBlank) CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor,
, m_isConvexHull(isConvex) double threshold, int noise, int indent, bool normalCrop, bool dispersion)
, m_isFillColor(isFillColor) : m_isCrop(isCrop)
, m_threshold(threshold) , m_isDesaskew(isDesaskew)
, m_noise(noise) , m_isFillBlank(isFillBlank)
, m_indent(indent) , m_isConvexHull(isConvex)
, m_fixedSize(fixedSize) , m_isFillColor(isFillColor)
, m_normalCrop(normalCrop) , m_threshold(threshold)
{ , m_noise(noise)
} , m_indent(indent)
, m_fixedSize(fixedSize)
CImageApplyAutoCrop::~CImageApplyAutoCrop() , m_normalCrop(normalCrop)
{ , m_isDispersion(dispersion)
} {
}
void matmul(double* mul1, double* mul2, double* dst)
{ CImageApplyAutoCrop::~CImageApplyAutoCrop()
dst[0] = mul1[0] * mul2[0] + mul1[1] * mul2[3] + mul1[2] * mul2[6]; {
dst[1] = mul1[0] * mul2[1] + mul1[1] * mul2[4] + mul1[2] * mul2[7]; }
dst[2] = mul1[0] * mul2[2] + mul1[1] * mul2[5] + mul1[2] * mul2[8];
dst[3] = mul1[3] * mul2[0] + mul1[4] * mul2[3] + mul1[5] * mul2[6]; void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
dst[4] = mul1[3] * mul2[1] + mul1[4] * mul2[4] + mul1[5] * mul2[7]; {
dst[5] = mul1[3] * mul2[2] + mul1[4] * mul2[5] + mul1[5] * mul2[8]; cv::Mat dst;
dst[6] = mul1[6] * mul2[0] + mul1[7] * mul2[3] + mul1[8] * mul2[6]; autoCrop_desaskew_fillBlank(pDib, dst, m_isCrop, m_isDesaskew, m_isFillBlank, m_fixedSize.width, m_fixedSize.height,
dst[7] = mul1[6] * mul2[1] + mul1[7] * mul2[4] + mul1[8] * mul2[7]; m_isConvexHull, m_isFillColor, m_threshold, m_noise, m_indent, m_normalCrop, m_isDispersion);
dst[8] = mul1[6] * mul2[2] + mul1[7] * mul2[5] + mul1[8] * mul2[8]; pDib = dst;
} }
cv::Mat concatenateMatrix(const cv::Mat& first, const cv::Mat& second) void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{ {
double buffer1[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1} ; (void)isTwoSide;
double buffer2[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1} ; int i = 0;
cv::Mat mul1(3, 3, CV_64FC1, buffer1); //cv::Mat::eye(3, 3, CV_64F); for (cv::Mat& var : mats) {
cv::Mat mul2(3, 3, CV_64FC1, buffer2); //cv::Mat::eye(3, 3, CV_64F); if (i != 0 && isTwoSide == false)
cv::Mat mul_r; break;
first.convertTo(mul_r, CV_64F); if (!var.empty())
mul_r.row(0).copyTo(mul1.row(0)); apply(var, 0);
mul_r.row(1).copyTo(mul1.row(1)); i++;
}
second.convertTo(mul_r, CV_64F); }
mul_r.row(0).copyTo(mul2.row(0));
mul_r.row(1).copyTo(mul2.row(1)); #define FRONT_TOP 70
#define FX_FY 0.5f
//mul1 = mul2 * mul1;
cv::Mat temp(3, 3, CV_64FC1); void myWarpAffine(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _M0, cv::Size dsize, int flags, int borderType, const cv::Scalar& borderValue)
matmul(buffer2, buffer1, (double*)temp.data); {
mul1 = temp; int interpolation = flags;
mul_r = first.clone(); cv::Mat src = _src.getMat(), M0 = _M0.getMat();
mul1.row(0).copyTo(mul_r.row(0)); cv::Mat dst = _dst.getMat();
mul1.row(1).copyTo(mul_r.row(1));
return mul_r; if (dst.data == src.data)
} src = src.clone();
std::vector<cv::Mat> comMat() double M[6] = { 0 };
{ cv::Mat matM(2, 3, CV_64F, M);
std::vector<cv::Mat> mats; if (interpolation == cv::INTER_AREA)
cv::Point2f srcTri[3]; interpolation = cv::INTER_LINEAR;
srcTri[0] = cv::Point2f(1, 1);
srcTri[1] = cv::Point2f(1, 0); M0.convertTo(matM, matM.type());
srcTri[2] = cv::Point2f(0, 1);
const float fact = 0.33f; if (!(flags & cv::WARP_INVERSE_MAP))
{
float pos[] = { 0, 2 * fact, fact }; double D = M[0] * M[4] - M[1] * M[3];
cv::Point2f dstTri[3]; D = D != 0 ? 1. / D : 0;
dstTri[0] = cv::Point2f(1, 1); double A11 = M[4] * D, A22 = M[0] * D;
dstTri[1] = cv::Point2f(1, 0.5); M[0] = A11; M[1] *= -D;
dstTri[2] = cv::Point2f(0, 1); M[3] *= -D; M[4] = A22;
double b1 = -M[0] * M[2] - M[1] * M[5];
for (int i = 0; i < 3; i++) double b2 = -M[3] * M[2] - M[4] * M[5];
{ M[2] = b1; M[5] = b2;
dstTri[0] = cv::Point2f(1, 1 + pos[i]); }
dstTri[1] = cv::Point2f(1, pos[i]);
dstTri[2] = cv::Point2f(0, 1 + pos[i]); cv::hal::warpAffine(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows,
M, interpolation, borderType, borderValue.val);
mats.push_back(cv::getAffineTransform(srcTri, dstTri)); }
}
return mats; uchar getBackGroudChannelMean(const cv::Mat& gray, int total, int threshold)
} {
cv::Mat image_clone;
void brightSharp(cv::Mat& src) cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25);
{
const float a = -0.49f; int threnshold = total / 32;
const float b = 3.0f; int channels[] = { 0 };
//float kernel_data[] = { int nHistSize[] = { 256 };
// a, 0, 0, 0, a, float range[] = { 0, 256 };
// 0, 0, a, 0, 0, const float* fHistRanges[] = { range };
// 0, a, b, a, 0, cv::Mat hist;
// 0, 0, a, 0, 0, cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false);
// a, 0, 0, 0, a };
int hist_array[256];
float kernel_data[] = { for (int i = 0; i < 256; i++)
0, a, 0, hist_array[i] = hist.at<float>(i, 0);
a, b, a,
0, a, 0 int length = 1;
}; const int length_max = 255 - threshold;
cv::Mat kernel(3, 3, CV_32FC1, kernel_data); while (length < length_max)
cv::filter2D(src, src, src.depth(), kernel); {
} for (size_t i = threshold + 1; i < 256 - length; i++)
{
void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side) int count = 0;
{ uint pixSum = 0;
(void)side; for (size_t j = 0; j < length; j++)
if (pDib.empty()) return; {
count += hist_array[j + i];
if (m_normalCrop) pixSum += hist_array[j + i] * (i + j);
{ }
cv::Rect roi = cv::Rect((pDib.cols - m_fixedSize.width) / 2, side == 0 ? 75 : 145, m_fixedSize.width, m_fixedSize.height) & cv::Rect(0, 0, pDib.cols, pDib.rows);
pDib = pDib(roi).clone(); if (count >= threnshold)
m_rect = cv::RotatedRect(cv::Point2f(roi.x + roi.width / 2, roi.y + roi.height / 2), cv::Size2f(roi.width, roi.height), 0.0f); return pixSum / count;
return; }
} length++;
}
if (!m_isCrop && !m_isDesaskew && !m_isFillBlank && m_fixedSize.empty()) return; return 255;
}
cv::Mat src = pDib;
cv::Mat thre; cv::Scalar getBackGroudColor(const cv::Mat& image, int total, int threshold)
cv::Mat dst; {
hg::threshold_Mat(src, thre, m_threshold); if (image.channels() == 3)
{
if (m_noise > 0) cv::Mat image_bgr[3];
{ cv::split(image, image_bgr);
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_noise, 1));
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element); uchar bgr[3];
} for (size_t i = 0; i < 3; i++)
bgr[i] = getBackGroudChannelMean(image_bgr[i], total, threshold);
if (m_indent > 0) return cv::Scalar(bgr[0], bgr[1], bgr[2]);
{ }
cv::Mat element = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(m_indent, m_indent)); else
cv::morphologyEx(thre, thre, cv::MORPH_ERODE, element); return cv::Scalar::all(getBackGroudChannelMean(image, total, threshold));
} }
std::vector<cv::Vec4i> hierarchy; CImageApplyDispersion dispersion_apply;
std::vector<std::vector<cv::Point>> contours; #define COLOR_SCALE_THRE 0.5
void autoCrop_desaskew_fillBlank(const cv::Mat& src, cv::Mat& dst, bool isAutoCrop, bool isDesaskew, bool isFillBlank, int dWidth, int dHeight,
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); bool isConvex, bool isColorBlank, double threshold, int noise, int indent, bool isNormalCrop, bool dispersion)
m_maxContour = hg::getMaxContour(contours, hierarchy); {
if (src.empty()) return;
if (m_maxContour.size() == 0)
{ if (isNormalCrop)
thre.release(); {
// cv::Rect roi = cv::Rect((src.cols - dWidth) / 2, FRONT_TOP, dWidth, dHeight) & cv::Rect(0, 0, src.cols, src.rows);
if (!m_isCrop) dst = src(roi).clone();
pDib = pDib(cv::Rect((pDib.cols - m_fixedSize.width) / 2, (pDib.rows - m_fixedSize.height) / 2, m_fixedSize.width, m_fixedSize.height) & cv::Rect(0, 0, pDib.cols, pDib.rows)).clone(); return;
#ifdef LOG }
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
#endif // LOG if (!isAutoCrop && !isDesaskew && !isFillBlank && (dWidth <= 0 || dHeight <= 0))
return; {
} dst = src.clone();
return;
thre.release(); }
dst.release();
cv::Mat resizeMat;
cv::RotatedRect rect = hg::getBoundingRect(m_maxContour); cv::Mat thre;
m_rect = rect;
cv::Rect boudingRect = cv::boundingRect(m_maxContour); cv::resize(src, resizeMat, cv::Size(), FX_FY, FX_FY, cv::INTER_NEAREST);
boudingRect.x -= 1; hg::threshold_Mat(resizeMat, thre, threshold);
boudingRect.y -= 1;
boudingRect.width += 2; if (noise > 0)
boudingRect.height += 2; cv::morphologyEx(thre, thre, cv::MORPH_OPEN, getStructuringElement(cv::MORPH_RECT, cv::Size(noise * FX_FY, 1)),
cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
if (m_isDesaskew && rect.angle != 0)
{ std::vector<cv::Vec4i> hierarchy;
cv::Point2f srcTri[4], srcTri_temp[3], dstTri[3]; std::vector<std::vector<cv::Point>> contours;
rect.points(srcTri);
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
dstTri[1] = cv::Point2f(0, 0); for (std::vector<cv::Point>& sub : contours)
dstTri[2] = cv::Point2f(rect.size.width - 1, 0); for (cv::Point& p : sub)
p /= FX_FY;
srcTri_temp[0] = dstTri[0];
srcTri_temp[1] = dstTri[1]; std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
srcTri_temp[2] = dstTri[2];
cv::Mat warp_mat; if (maxContour.empty())
warp_mat = cv::getAffineTransform(srcTri, dstTri); {
if (src.channels() == 1) if (isAutoCrop)
{ dst = src.clone();
cv::warpAffine(src, dst, warp_mat, rect.size, cv::INTER_LINEAR); else
} {
else cv::Rect roi = cv::Rect((src.cols - dWidth) / 2, FRONT_TOP, dWidth, dHeight) & cv::Rect(0, 0, src.cols, src.rows);
{ dst = src(roi).clone();
cv::Mat bgr[3]; }
cv::split(src, bgr); return;
auto mats = comMat(); }
warp_mat = cv::getAffineTransform(srcTri, dstTri);
warp_mat = concatenateMatrix(mats[0], warp_mat); cv::RotatedRect rect = hg::getBoundingRect(maxContour);
cv::warpAffine(bgr[0], bgr[0], warp_mat, rect.size, cv::INTER_LINEAR); if (dispersion)
{
warp_mat = cv::getAffineTransform(srcTri, dstTri); cv::Mat mat_dispersion = src(cv::boundingRect(maxContour));
warp_mat = concatenateMatrix(mats[1], warp_mat); dispersion_apply.apply(mat_dispersion, 0);
cv::warpAffine(bgr[1], bgr[1], warp_mat, rect.size, cv::INTER_LINEAR); }
warp_mat = cv::getAffineTransform(srcTri, dstTri); cv::Scalar blankColor;
warp_mat = concatenateMatrix(mats[2], warp_mat); if (isFillBlank)
cv::warpAffine(bgr[2], bgr[2], warp_mat, rect.size, cv::INTER_LINEAR); if (isColorBlank)
blankColor = getBackGroudColor(resizeMat, rect.size.area() * FX_FY * FX_FY, COLOR_SCALE_THRE);
cv::merge(bgr, 3, dst); else
} blankColor = cv::Scalar::all(255);
else
double* ptr_m = reinterpret_cast<double*>(warp_mat.data); blankColor = cv::Scalar::all(0);
double a = ptr_m[0];
double b = ptr_m[1]; if (isAutoCrop)
double c = ptr_m[2]; if (isDesaskew)
double d = ptr_m[3]; dst = cv::Mat(cv::Size(rect.size), src.type(), blankColor);
double e = ptr_m[4]; else
double f = ptr_m[5]; dst = cv::Mat(rect.boundingRect().size(), src.type(), blankColor);
else
for (cv::Point& p : m_maxContour) dst = cv::Mat(dHeight, dWidth, src.type(), blankColor);
{
p.x = static_cast<int>(a * p.x + b * p.y + c); cv::Mat dstROI;
p.y = static_cast<int>(d * p.x + e * p.y + f); if (isDesaskew && rect.angle != 0)
} {
cv::Point2f srcTri[4], dstTri[3];
for (std::vector<cv::Point>& sub : contours) rect.points(srcTri);
for (cv::Point& p : sub) srcTri[0].x -= 1;
{ srcTri[1].x -= 1;
p.x = static_cast<int>(a * p.x + b * p.y + c); srcTri[2].x -= 1;
p.y = static_cast<int>(d * p.x + e * p.y + f);
} int w = rect.size.width;
} int h = rect.size.height;
else int x = (dst.cols - w) / 2;
{ int y = (dst.rows - h) / 2;
auto t_rect = boudingRect & cv::Rect(0, 0, src.cols, src.rows); dstTri[0] = cv::Point2f(0, h);
dst = src(t_rect); dstTri[1] = cv::Point2f(0, 0);
if (dst.channels() == 3) dstTri[2] = cv::Point2f(w, 0);
{
cv::Mat bgr[3]; dstROI = dst(cv::Rect(x, y, w, h) & cv::Rect(0, 0, dst.cols, dst.rows));
cv::split(dst, bgr); myWarpAffine(src, dstROI, cv::getAffineTransform(srcTri, dstTri), dstROI.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(0));
auto mats = comMat(); }
for (int i = 0; i < 3; i++) else
cv::warpAffine(bgr[i], bgr[i], mats[i], t_rect.size(), cv::INTER_LINEAR); {
cv::merge(bgr, 3, dst); cv::Rect bounding = cv::boundingRect(maxContour);
}
} if (bounding.width > dst.cols)
{
cv::Scalar autoBGColor; bounding.x += (bounding.width - dst.cols) / 2;
if (m_isFillBlank) bounding.width = dst.cols;
{ }
if (m_isConvexHull)
{ if (bounding.height > dst.rows)
if (m_maxContour.size() == 0) {
{ bounding.y += (bounding.height - dst.rows) / 2;
thre.release(); bounding.height = dst.rows;
//<2F><><EFBFBD><EFBFBD>ǹ̶<C7B9><CCB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ز<EFBFBD><D8B2>к<EFBFBD>ijߴ<C4B3> }
if (!m_isCrop)
pDib = pDib(cv::Rect((pDib.cols - m_fixedSize.width) / 2, (pDib.rows - m_fixedSize.height) / 2, m_fixedSize.width, m_fixedSize.height) & cv::Rect(0, 0, pDib.cols, pDib.rows)).clone(); dstROI = dst(cv::Rect((dst.cols - bounding.width) / 2, (dst.rows - bounding.height) / 2, bounding.width, bounding.height));
return; src(bounding).copyTo(dstROI);
} }
hg::convexHull(m_maxContour, m_maxContour);
contours.clear(); if (isFillBlank)
contours.push_back(m_maxContour); {
} if (isConvex)
{
contours.push_back(std::vector<cv::Point>()); hg::convexHull(maxContour, maxContour);
contours[contours.size() - 1].push_back(cv::Point(-1, dst.rows - 1)); contours.clear();
contours[contours.size() - 1].push_back(cv::Point(-1, -1)); contours.push_back(maxContour);
contours[contours.size() - 1].push_back(cv::Point(dst.cols, -1)); }
contours[contours.size() - 1].push_back(cv::Point(dst.cols, dst.rows));
cv::Point2f srcTri[4], dstTri[3];
autoBGColor = m_isFillColor ? getBackGroudColor(pDib, rect.size.area()) : cv::Scalar(255, 255, 255); int w, h;
hg::fillPolys(dst, contours, autoBGColor); if (isDesaskew && rect.angle != 0)
} {
else rect.points(srcTri);
{ srcTri[0].x -= 1;
m_maxContour.clear(); srcTri[1].x -= 1;
m_maxContour.push_back(cv::Point(-1, dst.rows)); srcTri[2].x -= 1;
m_maxContour.push_back(cv::Point(-1, -1)); w = rect.size.width;
m_maxContour.push_back(cv::Point(dst.cols, -1)); h = rect.size.height;
m_maxContour.push_back(cv::Point(dst.cols, dst.rows)); }
} else
{
pDib.release(); cv::Rect bounding = rect.boundingRect();
if (/*(m_isCrop && side == 0) || (side == 1 && m_fixedSize.width * m_fixedSize.height == 0)*/ m_isCrop) srcTri[0] = cv::Point(bounding.x, bounding.br().y - 1);
pDib = dst.clone(); srcTri[1] = cv::Point(bounding.x, bounding.y);
else srcTri[2] = cv::Point(bounding.br().x - 1, bounding.y);
{ w = bounding.width;
pDib = cv::Mat(m_fixedSize, dst.type(), m_isFillBlank ? autoBGColor : cv::Scalar(0, 0, 0)); h = bounding.height;
}
cv::Rect roi;
roi.x = dst.cols > pDib.cols ? (dst.cols - pDib.cols) / 2 : 0; dstTri[0] = cv::Point2f((dstROI.cols - w) / 2 + indent, (dstROI.rows - h) / 2 + h - indent);
roi.width = cv::min(pDib.cols, dst.cols); dstTri[1] = cv::Point2f((dstROI.cols - w) / 2 + indent, (dstROI.rows - h) / 2 + indent);
roi.y = dst.rows > pDib.rows ? (dst.rows - pDib.rows) / 2 : 0; dstTri[2] = cv::Point2f((dstROI.cols - w) / 2 - indent + w, (dstROI.rows - h) / 2 + indent);
roi.height = cv::min(pDib.rows, dst.rows); cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
cv::Rect rect((pDib.cols - roi.width) / 2, (pDib.rows - roi.height) / 2, roi.width, roi.height);
double* ptr_m = reinterpret_cast<double*>(warp_mat.data);
for (cv::Point& p : m_maxContour) double a = ptr_m[0];
p += roi.tl(); double b = ptr_m[1];
dst(roi).copyTo(pDib(rect)); double c = ptr_m[2];
} double d = ptr_m[3];
#ifdef LOG double e = ptr_m[4];
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply8"); double f = ptr_m[5];
#endif // LOG
} int x, y;
for (std::vector<cv::Point>& sub : contours)
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide) for (cv::Point& p : sub)
{ {
if (mats.empty()) return; x = p.x;
if (!mats[0].empty()) { y = p.y;
apply(mats[0], 0); p.x = static_cast<int>(a * x + b * y + c);
m_rects.push_back(m_rect); p.y = static_cast<int>(d * x + e * y + f);
//brightSharp(mats[0]); }
}
contours.push_back(std::vector<cv::Point>());
if (isTwoSide && mats.size() > 1) contours[contours.size() - 1].push_back(cv::Point(-1, dstROI.rows - 1));
{ contours[contours.size() - 1].push_back(cv::Point(-1, -1));
cv::Size dSize = m_fixedSize; contours[contours.size() - 1].push_back(cv::Point(dstROI.cols, -1));
if (!mats[0].empty()) contours[contours.size() - 1].push_back(cv::Point(dstROI.cols, dst.rows));
m_fixedSize = mats[0].size(); hg::fillPolys(dstROI, contours, blankColor);
if (!mats[1].empty()) { }
apply(mats[1], 1); }
m_rects.push_back(m_rect);
//brightSharp(mats[1]);
}
if (!mats[0].empty())
m_fixedSize = dSize;
}
}
cv::Scalar CImageApplyAutoCrop::getBackGroudColor(const cv::Mat& image, int total)
{
if (image.channels() == 3)
{
cv::Mat image_bgr[3];
cv::split(image, image_bgr);
uchar bgr[3];
for (size_t i = 0; i < 3; i++)
bgr[i] = getBackGroudChannelMean(image_bgr[i], total);
return cv::Scalar(bgr[0], bgr[1], bgr[2]);
}
else
return cv::Scalar::all(getBackGroudChannelMean(image, total));
}
uchar CImageApplyAutoCrop::getBackGroudChannelMean(const cv::Mat& gray, int total)
{
cv::Mat image_clone;
cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25);
int threnshold = total / 32;
int channels[] = { 0 };
int nHistSize[] = { 256 };
float range[] = { 0, 256 };
const float* fHistRanges[] = { range };
cv::Mat hist;
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false);
int hist_array[256];
for (int i = 0; i < 256; i++)
hist_array[i] = hist.at<float>(i, 0);
int length = 1;
const int length_max = 255 - m_threshold;
while (length < length_max)
{
for (size_t i = m_threshold + 1; i < 256 - length; i++)
{
int count = 0;
uint pixSum = 0;
for (size_t j = 0; j < length; j++)
{
count += hist_array[j + i];
pixSum += hist_array[j + i] * (i + j);
}
if (count >= threnshold)
return pixSum / count;
}
length++;
}
return 255;
}

View File

@ -1,112 +1,125 @@
/* /*
* ==================================================== * ====================================================
* *
* * 绿
* 2020/4/21 * _020/4/21
* 2020/4/21 v1.0 * 2020/4/21 v1.0
2020/7/22 v1.1 maxContourPC端暂时无需使用 2020/7/22 v1.1 maxContourPC端暂时无需使用_
2020/10/16 v1.2 BUG 2020/10/16 v1.2 BUG
2020/10/28 v1.2.1 BUG 2020/10/28 v1.2.1 BUG
2020/10/28 v1.2.2 BUG 2020/10/28 v1.2.2 BUG
2020/10/29 v1.2.3 0° 2020/10/29 v1.2.3 0°_
2020/11/30 v1.3.0 稿 2020/11/30 v1.3.0 稿
* v1.3.0 2021/06/18 v1.3.1 noise
2021/07/01 v1.3.2 BUG
* ==================================================== 2021/07/08 v1.3.3
*/ 2021/07/08 v1.3.4
2021/07/09 v1.3.5 normalCrop机制m_isCrop m_isDesaskew m_isFillBlank均为false时可选用
#ifndef IMAGE_APPLY_AUTO_CROP_H 2021/07/13 v1.3.6 normalCrop逻辑normalCrop为true时m_isCrop m_isDesaskew m_isFillBlank失效
#define IMAGE_APPLY_AUTO_CROP_H 2021/07/19 v1.3.7 仿INTER_LINEAR
2021/07/22 v1.3.8 BUG
#include "ImageApply.h" 2021/08/02 v1.3.9
2021/10/08 v1.3.10
class CImageApplyAutoCrop : public CImageApply 2021/10/19 v1.3.11 0
{ 2021/10/19 v1.3.12
public: 2022/04/24 v1.4
CImageApplyAutoCrop(); 2022/05/03 v1.4.1
2022/06/09 v1.4.2 稿threshold值0.5
* v1.4.2
/*
* isCrop [in]:使true自动裁剪false为固定裁剪 * ====================================================
* isDesaskew [in]:使true自动纠偏false为不纠偏 */
* isFillBlank [in]:使true为填充false为不填充
* fixedSize [in]:isCrop为false时生效fixedSize大小输出 #ifndef IMAGE_APPLY_AUTO_CROP_H
* isConvex [in]:,true为凸多边形填充false为凹多边形填充true #define IMAGE_APPLY_AUTO_CROP_H
* isFillColor [in]:false为白色填充true为自适应文稿底色填充false
* threshold [in]:(0, 255)40 #include "ImageApply.h"
* noise [in]:noise宽度的背景竖条纹干扰2
* indent [in]:indent像素5 class GIMGPROC_LIBRARY_API CImageApplyAutoCrop : public CImageApply
* normalCrop [in]:true且m_isCrop m_isDesaskew m_isFillBlank均为false时生效false {
*/ public:
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, CImageApplyAutoCrop();
bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5, bool normalCrop = false);
/*
virtual ~CImageApplyAutoCrop(); * isCrop [in]:使true自动裁剪false为固定裁剿
* isDesaskew [in]:使true自动纠偏false为不纠偏
virtual void apply(cv::Mat& pDib, int side); * isFillBlank [in]:使true为填充false为不填充
* fixedSize [in]:isCrop为false时生效fixedSize大小输出紿
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); * isConvex [in]:,true为凸多边形填充false为凹多边形填充true
* isFillColor [in]:false为白色填充true为自适应文稿底色填充false
bool isAutoCrop() { return m_isCrop; } * threshold [in]:0, 255)访0
* noise [in]:noise宽度的背景竖条纹干扰访
bool isFillBlank() { return m_isFillBlank; } * indent [in]:indent像素访
* normalCrop [in]:true时m_isCrop m_isDesaskew m_isFillBlank失效false
bool isDesaskew() { return m_isDesaskew; } * dispersion [in]:true时false时不除色散true
*/
bool isConvexHull() { return m_isConvexHull; } CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true,
bool isFillColor = false, double threshold = 40, int noise = 8, int indent = 5, bool normalCrop = false, bool dispersion = true);
double threshold() { return m_threshold; }
virtual ~CImageApplyAutoCrop();
const cv::RotatedRect& rotatedROI() { return m_rect; }
virtual void apply(cv::Mat& pDib, int side);
const std::vector<cv::RotatedRect>& rotatedROIs() { return m_rects; }
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
int noise() { return m_noise; }
bool isAutoCrop() { return m_isCrop; }
int indent() { return m_indent; }
bool isFillBlank() { return m_isFillBlank; }
cv::Size fixedSize() { return m_fixedSize; }
bool isDesaskew() { return m_isDesaskew; }
const std::vector<cv::Point>& maxContour() { return m_maxContour; }
bool isConvexHull() { return m_isConvexHull; }
void setAutoCrop(bool enabled) { m_isCrop = enabled; }
cv::RotatedRect getROI() { return m_rect; }
void setFillBlank(bool enabled) { m_isFillBlank = enabled; }
double threshold() { return m_threshold; }
void setDesaskew(bool enabled) { m_isDesaskew = enabled; }
int noise() { return m_noise; }
void setConvexHull(bool convex) { m_isConvexHull = convex; }
int indent() { return m_indent; }
void setThreshold(double value) { m_threshold = value; }
cv::Size fixedSize() { return m_fixedSize; }
void setNoise(int value) { m_noise = value; }
const std::vector<cv::Point>& maxContour() { return m_maxContour; }
void setIndent(int value) { m_indent = value; }
void setAutoCrop(bool enabled) { m_isCrop = enabled; }
void setFixedSize(cv::Size size) { m_fixedSize = size; }
void setFillBlank(bool enabled) { m_isFillBlank = enabled; }
private:
cv::Scalar getBackGroudColor(const cv::Mat& image, int total); void setDesaskew(bool enabled) { m_isDesaskew = enabled; }
uchar getBackGroudChannelMean(const cv::Mat& gray, int total); void setConvexHull(bool convex) { m_isConvexHull = convex; }
private: void setThreshold(double value) { m_threshold = value; }
bool m_isCrop;
bool m_isDesaskew; void setNoise(int value) { m_noise = value; }
bool m_isFillBlank;
bool m_isConvexHull; void setIndent(int value) { m_indent = value; }
bool m_isFillColor;
void setFixedSize(cv::Size size) { m_fixedSize = size; }
double m_threshold;
int m_noise; void setDispersion(bool enable) { m_isDispersion = enable; }
int m_indent;
bool m_normalCrop; //为true且m_isCrop m_isDesaskew m_isFillBlank均为false时生效固定裁切采用最传统的裁切方式 private:
cv::Size m_fixedSize; bool m_isCrop;
cv::RotatedRect m_rect; bool m_isDesaskew;
std::vector<cv::Point> m_maxContour; bool m_isFillBlank;
std::vector<cv::RotatedRect> m_rects; bool m_isConvexHull;
}; bool m_isFillColor;
bool m_isDispersion;
#endif // !IMAGE_APPLY_AUTO_CROP_H
double m_threshold;
int m_noise;
int m_indent;
bool m_normalCrop; //为true且m_isCrop m_isDesaskew m_isFillBlank均为false时生效固定裁切采用最传统的裁切方弿
cv::Size m_fixedSize;
cv::RotatedRect m_rect;
std::vector<cv::RotatedRect> m_rects;
std::vector<cv::Point> m_maxContour;
};
void autoCrop_desaskew_fillBlank(const cv::Mat& src, cv::Mat& dst, bool isAutoCrop, bool isDesaskew, bool isFillBlank, int dWidth, int dHeight,
bool isConvex = true, bool isColorBlank = false, double threshold = 40, int noise = 8, int indent = 5, bool isNormalCrop = false, bool dispersion = true);
#endif // !IMAGE_APPLY_AUTO_CROP_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,52 +1,52 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2020/6/19 * 2020/6/19
* v1.0 2020/6/19 * v1.0 2020/6/19
v1.1 2020/6/20 BGR转HSV,BGR_MAXBGR_MIN v1.1 2020/6/20 BGR转HSV,BGR_MAXBGR_MIN
* v1.1 * v1.1
* ==================================================== * ====================================================
*/ */
#ifndef IMAGE_APPLY_CONVERT_COLOR_H #ifndef IMAGE_APPLY_CONVERT_COLOR_H
#define IMAGE_APPLY_CONVERT_COLOR_H #define IMAGE_APPLY_CONVERT_COLOR_H
#include "ImageApply.h" #include "ImageApply.h"
class CImageApplyCvtColor : public CImageApply class GIMGPROC_LIBRARY_API CImageApplyCvtColor : public CImageApply
{ {
public: public:
//转换模式 //转换模式
enum ConversionCodes enum ConversionCodes
{ {
BGR_MAX = 1, //BGR取大值转GRAY BGR_MAX = 1, //BGR取大值转GRAY
BGR_MIN = 2, //BGR取小值转GRAY BGR_MIN = 2, //BGR取小值转GRAY
BGR2GRAY = 6, //BGR转GRAY BGR2GRAY = 6, //BGR转GRAY
BGR2HSV = 40 //BGR转HSV BGR2HSV = 40 //BGR转HSV
}; };
/* /*
* type [in]:BGR转Gray * type [in]:BGR转Gray
* */ * */
CImageApplyCvtColor(ConversionCodes type = BGR2GRAY); CImageApplyCvtColor(ConversionCodes type = BGR2GRAY);
virtual ~CImageApplyCvtColor(); virtual ~CImageApplyCvtColor();
virtual void apply(cv::Mat& pDib, int side); virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
inline ConversionCodes getConversionCode() { return m_code; } inline ConversionCodes getConversionCode() { return m_code; }
inline void setConversionCode(ConversionCodes code) { m_code = code; } inline void setConversionCode(ConversionCodes code) { m_code = code; }
private: private:
ConversionCodes m_code; ConversionCodes m_code;
}; };
#endif // !IMAGE_APPLY_CUSTOM_CAMMA_H #endif // !IMAGE_APPLY_CUSTOM_CAMMA_H

View File

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

View File

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

View File

@ -1,114 +1,114 @@
#include "ImageApplyDiscardBlank.h" #include "ImageApplyDiscardBlank.h"
#include "ImageProcess_Public.h" #include "ImageProcess_Public.h"
CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh) CImageApplyDiscardBlank::CImageApplyDiscardBlank(double threshold, int edge, double devTh, double meanTh)
: m_threshold(threshold) : m_threshold(threshold)
, m_edge(edge) , m_edge(edge)
, m_devTh(devTh) , m_devTh(devTh)
, m_meanTh(meanTh) , m_meanTh(meanTh)
{ {
} }
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void) CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
{ {
} }
void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side) void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
{ {
if (apply(pDib, m_threshold, m_edge, m_devTh)) if (apply(pDib, m_threshold, m_edge, m_devTh))
pDib.release(); pDib.release();
} }
void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide) void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{ {
(void)isTwoSide; (void)isTwoSide;
int i = 0; int i = 0;
for (cv::Mat& var : mats) { for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false) if (i != 0 && isTwoSide == false)
break; break;
if (!var.empty()) if (!var.empty())
apply(var, 0); apply(var, 0);
i++; i++;
} }
} }
bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2) bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2)
{ {
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
if (val1[i] > val2[i]) if (val1[i] > val2[i])
return false; return false;
return true; return true;
} }
bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh) bool maxMinCompare(const cv::Mat& img, const cv::Mat& mask, double devTh, double meanTh)
{ {
double min, max; double min, max;
cv::minMaxLoc(img, &min, &max, 0, 0, mask); cv::minMaxLoc(img, &min, &max, 0, 0, mask);
if (cv::mean(img, mask)[0] < meanTh) if (cv::mean(img, mask)[0] < meanTh)
return false; return false;
return (max - min) < devTh; return (max - min) < devTh;
} }
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, int blockSize, double devTh, double meanTh) bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, double threshold, int edge, int blockSize, double devTh, double meanTh)
{ {
if (pDib.empty()) if (pDib.empty())
return true; return true;
cv::Mat img_resize; cv::Mat img_resize;
cv::resize(pDib, img_resize, cv::Size(), 0.2, 0.2); cv::resize(pDib, img_resize, cv::Size(), 0.2, 0.2);
cv::Mat threshold_img; cv::Mat threshold_img;
if (img_resize.channels() == 3) if (img_resize.channels() == 3)
cv::cvtColor(img_resize, threshold_img, cv::COLOR_BGR2GRAY); cv::cvtColor(img_resize, threshold_img, cv::COLOR_BGR2GRAY);
cv::threshold(img_resize.channels() == 3 ? threshold_img : img_resize, threshold_img, threshold, 255, CV_THRESH_BINARY); cv::threshold(img_resize.channels() == 3 ? threshold_img : img_resize, threshold_img, threshold, 255, CV_THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours; std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> h1; std::vector<cv::Vec4i> h1;
hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); hg::findContours(threshold_img, contours, h1, cv::RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> contour; std::vector<cv::Point> contour;
for (const std::vector<cv::Point>& sub : contours) for (const std::vector<cv::Point>& sub : contours)
for (const cv::Point& p : sub) for (const cv::Point& p : sub)
contour.push_back(p); contour.push_back(p);
cv::RotatedRect rect = hg::getBoundingRect(contour); cv::RotatedRect rect = hg::getBoundingRect(contour);
rect.size = cv::Size2f(rect.size.width - edge / 2.5, rect.size.height - edge / 2.5); rect.size = cv::Size2f(rect.size.width - edge / 2.5, rect.size.height - edge / 2.5);
cv::Point2f box[4]; cv::Point2f box[4];
rect.points(box); rect.points(box);
contour.clear(); contour.clear();
contours.clear(); contours.clear();
for (size_t i = 0; i < 4; i++) for (size_t i = 0; i < 4; i++)
contour.push_back(box[i]); contour.push_back(box[i]);
contours.push_back(contour); contours.push_back(contour);
cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1); cv::Mat mask = cv::Mat::zeros(img_resize.size(), CV_8UC1);
hg::fillPolys(mask, contours, cv::Scalar::all(255)); hg::fillPolys(mask, contours, cv::Scalar::all(255));
cv::blur(img_resize, img_resize, cv::Size(3, 3)); cv::blur(img_resize, img_resize, cv::Size(3, 3));
bool b = true; bool b = true;
if (img_resize.channels() == 3) if (img_resize.channels() == 3)
{ {
cv::Mat bgr[3]; cv::Mat bgr[3];
cv::split(img_resize, bgr); cv::split(img_resize, bgr);
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
{ {
b &= maxMinCompare(bgr[i], mask, devTh, meanTh); b &= maxMinCompare(bgr[i], mask, devTh, meanTh);
if (!b) break; if (!b) break;
} }
} }
else else
b &= maxMinCompare(img_resize, mask, devTh, meanTh); b &= maxMinCompare(img_resize, mask, devTh, meanTh);
/* /*
if (b) if (b)
{ {
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/img1/" + std::to_string(index) + ".bmp", img_resize); cv::imwrite("¿Õ°×Ò³/img1/" + std::to_string(index) + ".bmp", img_resize);
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/mask1/" + std::to_string(index) + ".bmp", mask); cv::imwrite("¿Õ°×Ò³/mask1/" + std::to_string(index) + ".bmp", mask);
} }
else else
{ {
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/img2/" + std::to_string(index) + ".bmp", img_resize); cv::imwrite("¿Õ°×Ò³/img2/" + std::to_string(index) + ".bmp", img_resize);
cv::imwrite("<EFBFBD>հ<EFBFBD>ҳ/mask2/" + std::to_string(index) + ".bmp", mask); cv::imwrite("¿Õ°×Ò³/mask2/" + std::to_string(index) + ".bmp", mask);
}*/ }*/
return b; return b;
} }

View File

@ -1,48 +1,48 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2020/4/21 * 2020/4/21
* 2020/4/21 v1.0 * 2020/4/21 v1.0
2020/8/12 v1.1 setIntensity和setMinAreaisNormal标识位setIntensity的设置范围[2, 20][1, 100] 2020/8/12 v1.1 setIntensity和setMinAreaisNormal标识位setIntensity的设置范围[2, 20][1, 100]
2020/8/25 v1.1.1 10020 2020/8/25 v1.1.1 10020
2020/10/16 v1.2 便 2020/10/16 v1.2 便
2020/10/19 v1.2.1 BUG 2020/10/19 v1.2.1 BUG
2021/04/13 v1.3.0 / 2021/04/13 v1.3.0 /
2021/08/12 v1.3.1 opencv版本导致计算结果存在差异的代码 2021/08/12 v1.3.1 opencv版本导致计算结果存在差异的代码
2021/12/14 v1.3.2 2021/12/14 v1.3.2
2021/12/15 v1.3.3 2021/12/15 v1.3.3
2021/12/17 v1.3.4 2021/12/17 v1.3.4
* v1.3.4 * v1.3.4
* ==================================================== * ====================================================
*/ */
#ifndef IMAGE_APPLY_DISCARD_BLANK_H #ifndef IMAGE_APPLY_DISCARD_BLANK_H
#define IMAGE_APPLY_DISCARD_BLANK_H #define IMAGE_APPLY_DISCARD_BLANK_H
#include "ImageApply.h" #include "ImageApply.h"
class CImageApplyDiscardBlank : public CImageApply class GIMGPROC_LIBRARY_API CImageApplyDiscardBlank : public CImageApply
{ {
public: public:
CImageApplyDiscardBlank(double threshold = 40, int edge = 150, double devTh = 50, double meanTh = 200); CImageApplyDiscardBlank(double threshold = 40, int edge = 150, double devTh = 50, double meanTh = 200);
virtual ~CImageApplyDiscardBlank(void); virtual ~CImageApplyDiscardBlank(void);
virtual void apply(cv::Mat& pDib, int side); virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 150, int blockSize = 10, double devTh = 50, double meanTh = 200); static bool apply(const cv::Mat& pDib, double threshold = 40, int edge = 150, int blockSize = 10, double devTh = 50, double meanTh = 200);
private: private:
double m_threshold; double m_threshold;
int m_edge; int m_edge;
double m_devTh; double m_devTh;
double m_meanTh; double m_meanTh;
}; };
#endif // !IMAGE_APPLY_DISCARD_BLANK_H #endif // !IMAGE_APPLY_DISCARD_BLANK_H

View File

@ -0,0 +1,44 @@
#include "ImageApplyDispersion.h"
CImageApplyDispersion::CImageApplyDispersion(float a, float b, float c, float sharpen)
: CImageApply()
, m_kernal_b(3, 1, CV_32FC1)
, m_kernal_g(3, 1, CV_32FC1)
, m_kernal_r(3, 1, CV_32FC1)
{
m_kernal_b.at<float>(0, 0) = a;
m_kernal_b.at<float>(1, 0) = 1.0f + sharpen - a;
m_kernal_b.at<float>(2, 0) = -sharpen;
m_kernal_g.at<float>(0, 0) = b;
m_kernal_g.at<float>(1, 0) = 1.0f + sharpen - b;
m_kernal_g.at<float>(2, 0) = -sharpen;
m_kernal_r.at<float>(0, 0) = c;
m_kernal_r.at<float>(1, 0) = 1.0f + sharpen - c;
m_kernal_r.at<float>(2, 0) = -sharpen;
}
CImageApplyDispersion::~CImageApplyDispersion()
{
}
void CImageApplyDispersion::apply(cv::Mat& pDib, int side)
{
(void)side;
if (pDib.channels() != 3) return;
cv::Mat bgr[3];
cv::split(pDib, bgr);
cv::filter2D(bgr[0], bgr[0], bgr[0].depth(), m_kernal_b);
cv::filter2D(bgr[1], bgr[1], bgr[1].depth(), m_kernal_g);
cv::filter2D(bgr[2], bgr[2], bgr[2].depth(), m_kernal_r);
cv::merge(bgr, 3, pDib);
}
void CImageApplyDispersion::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
}

View File

@ -0,0 +1,36 @@
/*
* ====================================================
*
*
* 2021/09/24
* 2021/11/12 v1.1.0
* 2022/04/21 v1.2.0
* 2022/07/20 v1.3.0
* v1.3.0
* ====================================================
*/
#ifndef IMAGE_APPLY_DISPERSION_COLOR_H
#define IMAGE_APPLY_DISPERSION_COLOR_H
#include "ImageApply.h"
class GIMGPROC_LIBRARY_API CImageApplyDispersion : public CImageApply
{
public:
CImageApplyDispersion(float a = 0.15f, float b = 0.806f, float c = 0.484f, float sharpen = 0.3f);
virtual ~CImageApplyDispersion();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
cv::Mat m_kernal_b;
cv::Mat m_kernal_g;
cv::Mat m_kernal_r;
};
#endif

View File

@ -1,67 +1,106 @@
#include "ImageApplyDogEarDetection.h" #include "ImageApplyDogEarDetection.h"
#include "ImageProcess_Public.h" #include "ImageProcess_Public.h"
CImageApplyDogEarDetection::CImageApplyDogEarDetection() CImageApplyDogEarDetection::CImageApplyDogEarDetection()
: m_threshold(40) : m_threshold(40)
, m_zoom(1.0) , m_zoom_x(1.0)
, m_distance(50) , m_zoom_y(1.0)
, m_result(false) , m_distance1(50)
{ , m_distance2(50)
, m_result(0)
} {
CImageApplyDogEarDetection::CImageApplyDogEarDetection(double threshlod, double zoom, double distance) }
: m_threshold(threshlod)
, m_zoom(zoom) CImageApplyDogEarDetection::CImageApplyDogEarDetection(double threshlod, double zoom_x, double zoom_y, double distance1, double distance2)
, m_distance(distance) : m_threshold(threshlod)
, m_result(false) , m_zoom_x(zoom_x)
{ , m_zoom_y(zoom_y)
, m_distance1(distance1)
} , m_distance2(distance2)
, m_result(0)
CImageApplyDogEarDetection::~CImageApplyDogEarDetection() {
{
}
}
CImageApplyDogEarDetection::~CImageApplyDogEarDetection()
void CImageApplyDogEarDetection::apply(cv::Mat &pDib, int side) {
{
m_result = false; }
(void)side;
if (pDib.empty()) return; #define EDGE_ABS 4
cv::Mat src; void CImageApplyDogEarDetection::apply(cv::Mat& pDib, int side)
if (m_zoom != 1.0) {
cv::resize(pDib, src, cv::Size(), m_zoom, m_zoom, cv::INTER_NEAREST); m_result = 0;
else (void)side;
src = pDib; if (pDib.empty()) return;
cv::Mat src;
cv::Mat thre; if (m_zoom_x != 1.0 && m_zoom_y != 1.0)
hg::threshold_Mat(src, thre, m_threshold); cv::resize(pDib, src, cv::Size(), m_zoom_x, m_zoom_y, cv::INTER_NEAREST);
std::vector<cv::Vec4i> hierarchy; else
std::vector<std::vector<cv::Point>> contours; src = pDib;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
cv::Mat thre;
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy); hg::threshold_Mat(src, thre, m_threshold);
if (maxContour.size() == 0)
{ cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(5, 1));
m_result = true; cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
return;
} std::vector<cv::Vec4i> hierarchy;
hg::convexHull(maxContour, maxContour); std::vector<std::vector<cv::Point>> contours;
cv::RotatedRect rect = hg::getBoundingRect(maxContour); hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
cv::Point2f vertexes[4];
rect.points(vertexes); std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
if (maxContour.size() == 0)
for (int i = 0; i < 4; i++) {
if ((-cv::pointPolygonTest(maxContour, vertexes[i], true)) > (m_distance * m_zoom)) m_result = true;
{ return;
m_result = true; }
return; hg::convexHull(maxContour, maxContour);
} cv::RotatedRect rect = hg::getBoundingRect(maxContour);
} cv::Point2f vertexes[4];
rect.points(vertexes);
void CImageApplyDogEarDetection::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{ double distance;
(void)mats; for (int i = 0; i < 4; i++)
(void)isTwoSide; {
} distance = -cv::pointPolygonTest(maxContour, vertexes[i], true);
//判断是否为普通折角
if (distance > (m_distance1 / m_zoom_x))
{
if (cv::Rect(0, 0, src.cols, src.rows).contains(vertexes[i]))
m_result = 1;
else if (vertexes[i].x < 0 && cv::abs(distance + vertexes[i].x) > EDGE_ABS) //如果是越界折角修改m_result值但是需要继续判断防止漏掉普通折角
m_result = 1;
else if (vertexes[i].y < 0 && cv::abs(distance + vertexes[i].y) > EDGE_ABS)
m_result = 1;
else if (vertexes[i].x > src.cols && cv::abs(distance + src.cols - vertexes[i].x) > EDGE_ABS)
m_result = 1;
else if (vertexes[i].y > src.rows && cv::abs(distance + src.rows - vertexes[i].y) > EDGE_ABS)
m_result = 1;
}
if (m_result == 1)
return;
//判断是否为扫描越界导致的折角
if (distance > (m_distance2 / m_zoom_x))
{
if (vertexes[i].x < 0 && cv::abs(distance + vertexes[i].x) < EDGE_ABS) //如果是越界折角修改m_result值但是需要继续判断防止漏掉普通折角
m_result = 2;
else if (vertexes[i].y < 0 && cv::abs(distance + vertexes[i].y) < EDGE_ABS)
m_result = 2;
else if (vertexes[i].x > src.cols && cv::abs(distance + src.cols - vertexes[i].x) < EDGE_ABS)
m_result = 2;
else if (vertexes[i].y > src.rows && cv::abs(distance + src.rows - vertexes[i].y) < EDGE_ABS)
m_result = 2;
}
}
}
void CImageApplyDogEarDetection::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)mats;
(void)isTwoSide;
}

View File

@ -1,56 +1,64 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2020/10/30 * 2020/10/30
* 2020/10/30 * 2020/10/30 v1.0
* v1.0 * 2021/11/04 v1.1 5
* 2022/07/15 v1.2
* ==================================================== * 2022/07/21 v1.3 21
*/ * 2022/07/21 v1.3.1 12
* 2022/07/22 v1.4 zoom_x,zoom_yXY轴DPI不一致的问题
#ifndef IMAGE_APPLY_DOGEAR_DETECTION_H * v1.4
#define IMAGE_APPLY_DOGEAR_DETECTION_H
* ====================================================
#include "ImageApply.h" */
class CImageApplyDogEarDetection :public CImageApply #ifndef IMAGE_APPLY_DOGEAR_DETECTION_H
{ #define IMAGE_APPLY_DOGEAR_DETECTION_H
public:
#include "ImageApply.h"
/// <summary>
/// 折角检测默认构造函数threshold = 40 zoom = 1.0 distance = 50 class GIMGPROC_LIBRARY_API CImageApplyDogEarDetection : public CImageApply
/// </summary> {
CImageApplyDogEarDetection(); public:
/// <summary> /// <summary>
/// 折角检测构造函数 /// 折角检测默认构造函数threshold = 40 zoom = 1.0 distance = 50
/// </summary> /// </summary>
/// <param name="threshlod">二值化阈值</param> CImageApplyDogEarDetection();
/// <param name="zoom">原图缩放比例对于大尺寸图像而言通过zoom缩小图像可减少计算量。默认值1.0(不缩放)</param>
/// <param name="distance">理论顶点到实际轮廓最小距离的阈值大于该阈值则判定为折角默认值50像素</param> /// <summary>
CImageApplyDogEarDetection(double threshlod, double zoom = 1.0, double distance = 50); /// 折角检测构造函数
/// </summary>
virtual ~CImageApplyDogEarDetection(void); /// <param name="threshlod">二值化阈值</param>
/// <param name="zoom_x">原图X轴缩放比例对于大尺寸图像而言通过zoom缩小图像可减少计算量。默认值1.0(不缩放)</param>
/// <summary> /// <param name="zoom_y">原图Y轴缩放比例对于大尺寸图像而言通过zoom缩小图像可减少计算量。默认值1.0(不缩放)</param>
/// 获取检测结果。该函数须在调用apply之后使用。 /// <param name="distance">理论顶点到实际轮廓最小距离的阈值大于该阈值则判定为折角默认值50像素</param>
/// </summary> CImageApplyDogEarDetection(double threshlod, double zoom_x = 1.0, double zoom_y = 1.0, double distance1 = 50, double distance2 = 50);
/// <returns>true为折角false为不折角</returns>
inline bool getResult() { return m_result; } virtual ~CImageApplyDogEarDetection(void);
virtual void apply(cv::Mat& pDib, int side); /// <summary>
/// 获取检测结果。该函数须在调用apply之后使用。
private: /// </summary>
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); /// <returns>0为非折角1为普通折角2为可能是扫描不完整造成的折角</returns>
inline int getResult() { return m_result; }
private:
double m_threshold; virtual void apply(cv::Mat& pDib, int side);
double m_zoom;
double m_distance; private:
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
bool m_result;
}; private:
double m_threshold;
#endif // IMAGE_APPLY_DOGEAR_DETECTION_H double m_zoom_x;
double m_zoom_y;
double m_distance1;
double m_distance2;
int m_result;
};
#endif // IMAGE_APPLY_DOGEAR_DETECTION_H

View File

@ -1,150 +1,150 @@
#include "ImageApplyFadeBackGroundColor.h" #include "ImageApplyFadeBackGroundColor.h"
CImageApplyFadeBackGroudColor::CImageApplyFadeBackGroudColor(int threshold, int offset, int range) CImageApplyFadeBackGroudColor::CImageApplyFadeBackGroudColor(int threshold, int offset, int range)
: m_threshold(threshold) : m_threshold(threshold)
, m_offset(offset) , m_offset(offset)
, m_range(range) , m_range(range)
{ {
memset(m_table1, 255, 768); memset(m_table1, 255, 768);
memset(m_table1, 0, m_threshold * 3); memset(m_table1, 0, m_threshold * 3);
memset(m_table2, 255, 256 * 3); memset(m_table2, 255, 256 * 3);
for (size_t i = 0; i < 256; i++) for (size_t i = 0; i < 256; i++)
m_table2[i] = i; m_table2[i] = i;
} }
CImageApplyFadeBackGroudColor::~CImageApplyFadeBackGroudColor() CImageApplyFadeBackGroudColor::~CImageApplyFadeBackGroudColor()
{ {
} }
void CImageApplyFadeBackGroudColor::apply(cv::Mat& pDib, int side) void CImageApplyFadeBackGroudColor::apply(cv::Mat& pDib, int side)
{ {
if (pDib.channels() != 3) if (pDib.channels() != 3)
return; return;
#if 0 #if 0
cv::Mat mask; cv::Mat mask;
cv::cvtColor(pDib, mask, cv::COLOR_BGR2GRAY); cv::cvtColor(pDib, mask, cv::COLOR_BGR2GRAY);
cv::threshold(mask, mask, m_threshold, 255, cv::THRESH_BINARY); cv::threshold(mask, mask, m_threshold, 255, cv::THRESH_BINARY);
//cv::imwrite("mask.jpg", mask); //cv::imwrite("mask.jpg", mask);
cv::Mat bgr[3]; cv::Mat bgr[3];
cv::split(pDib, bgr); cv::split(pDib, bgr);
int histSize = 255; int histSize = 255;
float range[] = { 0, 255 }; float range[] = { 0, 255 };
const float* histRange = { range }; const float* histRange = { range };
cv::Mat hist_bgr[3]; cv::Mat hist_bgr[3];
cv::Scalar mean_bgr; cv::Scalar mean_bgr;
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
{ {
cv::calcHist(&bgr[i], 1, 0, mask, hist_bgr[i], 1, &histSize, &histRange); cv::calcHist(&bgr[i], 1, 0, mask, hist_bgr[i], 1, &histSize, &histRange);
double maxVal = 0; double maxVal = 0;
cv::Point maxLoc; cv::Point maxLoc;
cv::minMaxLoc(hist_bgr[i], NULL, &maxVal, NULL, &maxLoc); cv::minMaxLoc(hist_bgr[i], NULL, &maxVal, NULL, &maxLoc);
mean_bgr[i] = maxLoc.y; mean_bgr[i] = maxLoc.y;
} }
cv::add(pDib, cv::Scalar::all(255 + m_offset) - mean_bgr, pDib, mask); cv::add(pDib, cv::Scalar::all(255 + m_offset) - mean_bgr, pDib, mask);
#else #else
fadeBackground(pDib.data, pDib.step, pDib.rows, m_threshold, m_offset, m_range); fadeBackground(pDib.data, pDib.step, pDib.rows, m_threshold, m_offset, m_range);
#endif #endif
} }
void CImageApplyFadeBackGroudColor::fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range) void CImageApplyFadeBackGroudColor::fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range)
{ {
int hist_bgr[3][256] = { 0 }; int hist_bgr[3][256] = { 0 };
int width = bytesPerLine / 3; int width = bytesPerLine / 3;
unsigned char* mask = new unsigned char[width * height]; unsigned char* mask = new unsigned char[width * height];
unsigned char* ptr_data = data; unsigned char* ptr_data = data;
unsigned char* ptr_mask = mask; unsigned char* ptr_mask = mask;
//创建掩模mask并且统计三通道的直方图 //创建掩模mask并且统计三通道的直方图
for (size_t i = 0; i < height; i++) for (size_t i = 0; i < height; i++)
{ {
int x = 0; int x = 0;
unsigned char b = 0; unsigned char b = 0;
for (size_t j = 0; j < width; j++) for (size_t j = 0; j < width; j++)
{ {
b = m_table1[ptr_data[x] + ptr_data[x + 1] + ptr_data[x + 2]]; b = m_table1[ptr_data[x] + ptr_data[x + 1] + ptr_data[x + 2]];
ptr_mask[j] = b; ptr_mask[j] = b;
for (size_t k = 0; k < 3; k++) for (size_t k = 0; k < 3; k++)
hist_bgr[k][ptr_data[x + k] & b]++; hist_bgr[k][ptr_data[x + k] & b]++;
x += 3; x += 3;
} }
ptr_data += bytesPerLine; ptr_data += bytesPerLine;
ptr_mask += width; ptr_mask += width;
} }
//统计背景色 //统计背景色
int max_vals[3] = { 0 }; int max_vals[3] = { 0 };
int max_indexes[3]; int max_indexes[3] = { 0 };
for (size_t i = 1; i < 256; i++) for (size_t i = 1; i < 256; i++)
for (size_t j = 0; j < 3; j++) for (size_t j = 0; j < 3; j++)
if (hist_bgr[j][i] > max_vals[j]) if (hist_bgr[j][i] > max_vals[j])
{ {
max_vals[j] = hist_bgr[j][i]; max_vals[j] = hist_bgr[j][i];
max_indexes[j] = i; max_indexes[j] = i;
} }
//创建背景色误查值表在误差±range范围内的颜色被同样视为背景色 //创建背景色误查值表在误差±range范围内的颜色被同样视为背景色
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
{ {
memset(m_table_rgb[i], 0, 256); memset(m_table_rgb[i], 0, 256);
int start = cv::max(max_indexes[i] - range, 0); int start = cv::max(max_indexes[i] - range, 0);
int end = cv::min(max_indexes[i] + range, 255); int end = cv::min(max_indexes[i] + range, 255);
memset(m_table_rgb[i] + start, 255, end - start + 1); memset(m_table_rgb[i] + start, 255, end - start + 1);
} }
//根据背景色误差查值表,更新掩模,排除背景色以外的内容 //根据背景色误差查值表,更新掩模,排除背景色以外的内容
ptr_data = data; ptr_data = data;
ptr_mask = mask; ptr_mask = mask;
for (size_t i = 0; i < height; i++) for (size_t i = 0; i < height; i++)
{ {
int x = 0; int x = 0;
for (size_t j = 0; j < width; j++) for (size_t j = 0; j < width; j++)
{ {
ptr_mask[j] &= m_table_rgb[0][ptr_data[x]] & m_table_rgb[1][ptr_data[x + 1]] & m_table_rgb[2][ptr_data[x + 2]]; ptr_mask[j] &= m_table_rgb[0][ptr_data[x]] & m_table_rgb[1][ptr_data[x + 1]] & m_table_rgb[2][ptr_data[x + 2]];
x += 3; x += 3;
} }
ptr_data += bytesPerLine; ptr_data += bytesPerLine;
ptr_mask += width; ptr_mask += width;
} }
//根据掩模,除背景色 //根据掩模,除背景色
unsigned char offset_rgb[3]; unsigned char offset_rgb[3];
for (size_t i = 0; i < 3; i++) for (size_t i = 0; i < 3; i++)
offset_rgb[i] = 255 + offset - max_indexes[i]; offset_rgb[i] = 255 + offset - max_indexes[i];
ptr_data = data; ptr_data = data;
ptr_mask = mask; ptr_mask = mask;
for (size_t i = 0; i < height; i++) for (size_t i = 0; i < height; i++)
{ {
int x = 0; int x = 0;
for (size_t j = 0; j < width; j++) for (size_t j = 0; j < width; j++)
{ {
for (size_t k = 0; k < 3; k++) for (size_t k = 0; k < 3; k++)
ptr_data[x + k] = m_table2[(int)ptr_data[x + k] + (offset_rgb[k] & ptr_mask[j])]; ptr_data[x + k] = m_table2[(int)ptr_data[x + k] + (offset_rgb[k] & ptr_mask[j])];
x += 3; x += 3;
} }
ptr_data += bytesPerLine; ptr_data += bytesPerLine;
ptr_mask += width; ptr_mask += width;
} }
delete[] mask; delete[] mask;
} }
void CImageApplyFadeBackGroudColor::apply(std::vector<cv::Mat>& mats, bool isTwoSide) void CImageApplyFadeBackGroudColor::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{ {
(void)isTwoSide; (void)isTwoSide;
int i = 0; int i = 0;
for (cv::Mat& var : mats) for (cv::Mat& var : mats)
if (!var.empty()) if (!var.empty())
{ {
apply(var, i); apply(var, i);
i++; i++;
} }
} }

View File

@ -1,64 +1,65 @@
/* /*
* ==================================================== * ====================================================
* 稿 * 稿
* *
* 2020/11/30 * 2020/11/30
* 2021/04/14 v2.0 * 2021/04/14 v2.0
* 2021/04/14 v2.1 LINUX方案保持一致 * 2021/04/14 v2.1 LINUX方案保持一致
* 2021/08/03 v2.2 opencv版本结果存在偏差 * 2021/08/03 v2.2 opencv版本结果存在偏差
* 2021/10/12 v2.3 * 2021/10/12 v2.3
* 2021/10/23 v3.0 稿 * 2021/10/23 v3.0 稿
* 2021/10/26 v3.1 * 2021/10/26 v3.1
* 2021/10/28 v3.2 C++ * 2021/10/28 v3.2 C++
* 2021/10/29 v3.3 range参数 * 2021/10/29 v3.3 range参数
* v3.2 * 2022/03/08 v3.4 BUG
* v3.4
* ====================================================
*/ * ====================================================
*/
#ifndef IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
#define IMAGE_APPLY_FADE_BACKGROUND_COLOR_H #ifndef IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
#define IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
#include "ImageApply.h"
#include "ImageApply.h"
class CImageApplyAdjustColors;
class CImageApplyFadeBackGroudColor : public CImageApply class CImageApplyAdjustColors;
{ class GIMGPROC_LIBRARY_API CImageApplyFadeBackGroudColor : public CImageApply
public: {
/// <summary> public:
/// 构造函数 /// <summary>
/// </summary> /// 构造函数
/// <param name="offset">在自动识别增白参数的基础上,增加的偏移量。取值范围[-255, 255]</param> /// </summary>
CImageApplyFadeBackGroudColor(int threshold = 100, int offset = 0, int range = 40); /// <param name="offset">在自动识别增白参数的基础上,增加的偏移量。取值范围[-255, 255]</param>
CImageApplyFadeBackGroudColor(int threshold = 100, int offset = 0, int range = 40);
virtual ~CImageApplyFadeBackGroudColor();
virtual ~CImageApplyFadeBackGroudColor();
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private:
private:
/// <summary>
/// 除文稿底色算法仅支持24位图像 /// <summary>
/// </summary> /// 除文稿底色算法仅支持24位图像
/// <param name="data">图像数据头指针</param> /// </summary>
/// <param name="bytesPerLine">每行数据大小</param> /// <param name="data">图像数据头指针</param>
/// <param name="height">图像高度</param> /// <param name="bytesPerLine">每行数据大小</param>
/// <param name="threshold">阈值参考值为100</param> /// <param name="height">图像高度</param>
/// <param name="offset">文稿底色增亮偏移量默认为0。值越大背景越白反之越暗</param> /// <param name="threshold">阈值参考值为100</param>
/// <param name="range">底色误差范围,色彩与识别到的底色误差在[-range, range]范围内,视为底色,否则不会被消除</param> /// <param name="offset">文稿底色增亮偏移量默认为0。值越大背景越白反之越暗</param>
void fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range); /// <param name="range">底色误差范围,色彩与识别到的底色误差在[-range, range]范围内,视为底色,否则不会被消除</param>
void fadeBackground(unsigned char* data, int bytesPerLine, int height, int threshold, int offset, int range);
private:
int m_threshold; private:
int m_offset; int m_threshold;
int m_range; int m_offset;
uchar m_table1[768]; int m_range;
uchar m_table2[512]; uchar m_table1[768];
uchar m_table_rgb[3][256]; uchar m_table2[512];
}; uchar m_table_rgb[3][256];
};
#endif // !IMAGE_APPLY_FADE_BACKGROUND_COLOR_H
#endif // !IMAGE_APPLY_FADE_BACKGROUND_COLOR_H

View File

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

View File

@ -1,64 +1,64 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2020/4/21 * 2020/4/21
* 2020/4/21 v1.0 * 2020/4/21 v1.0
2020/7/17 v1.1 BilateralFilter; 2020/7/17 v1.1 BilateralFilter;
2020/11/30 v1.2 GaussianBlur 2020/11/30 v1.2 GaussianBlur
2021/07/21 v1.2.1 BrightSharp 2021/07/21 v1.2.1 BrightSharp
2021/10/19 v1.2.2 2021/10/19 v1.2.2
* v1.2.2 * v1.2.2
* ==================================================== * ====================================================
*/ */
#ifndef IMAGE_APPLY_FILTER_H #ifndef IMAGE_APPLY_FILTER_H
#define IMAGE_APPLY_FILTER_H #define IMAGE_APPLY_FILTER_H
#include "ImageApply.h" #include "ImageApply.h"
class CImageApplyFilter : public CImageApply class GIMGPROC_LIBRARY_API CImageApplyFilter : public CImageApply
{ {
public: public:
enum FilterMode enum FilterMode
{ {
None, None,
Sharpen, //锐化 Sharpen, //锐化
Sharpen_More, //进一步锐化 Sharpen_More, //进一步锐化
AverBlur, //模糊 AverBlur, //模糊
AverBlur_More, //进一步模糊 AverBlur_More, //进一步模糊
BilateralFilter, //双边滤波--背景平滑减少复杂背景的色彩数量利于jpg等压缩比例 BilateralFilter, //双边滤波--背景平滑减少复杂背景的色彩数量利于jpg等压缩比例
GaussianBlur, GaussianBlur,
BrightSharp //5 * 5提亮锐化 BrightSharp //5 * 5提亮锐化
}; };
/* /*
* sharpentype [in]: * sharpentype [in]:
*/ */
CImageApplyFilter(FilterMode type, int kSize = 30); CImageApplyFilter(FilterMode type, int kSize = 30);
virtual ~CImageApplyFilter(); virtual ~CImageApplyFilter();
virtual void apply(cv::Mat& pDib, int side); virtual void apply(cv::Mat& pDib, int side);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
private: private:
void averblur(cv::Mat& src, int kSize); void averblur(cv::Mat& src, int kSize);
void sharpen(cv::Mat& src, float kSize); void sharpen(cv::Mat& src, float kSize);
void brightSharp(cv::Mat& src); void brightSharp(cv::Mat& src);
void bilateralFilter(cv::Mat& src, double kernel); void bilateralFilter(cv::Mat& src, double kernel);
void gaussianBlur(cv::Mat src, int kSize); void gaussianBlur(cv::Mat src, int kSize);
private: private:
int m_type; int m_type;
float m_kSize; float m_kSize;
double m_kernel; double m_kernel;
}; };
#endif // !IMAGE_APPLY_SHARPEN_H #endif // !IMAGE_APPLY_SHARPEN_H

View File

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

View File

@ -1,87 +1,95 @@
/* /*
* ==================================================== * ====================================================
*
* LUT实现BGR查值表HVSBGR原图进行查值校正 * LUT实现BGR查值表HVSBGR原图进行查值校正
* *
* 2020/3/21 * 2020/3/21
* v1.0 2020/3/21 * v1.0 2020/03/21
v1.1 2020/6/15 HSV取值范围 v1.1 2020/06/15 HSV取值范围
* v1.1 v1.2 2021/08/02 ROI图像的内存偏移
v1.3 2021/08/26 Red_Removal实现方案
* ==================================================== v1.4 2022/04/22 Deafault和LowSaturation_Removal
*/ v1.4.1 2022/04/25 访
v1.4.2 2022/06/09
#ifndef IMAGE_APPLY_COLOR_CORRECT_H * v1.4.2
#define IMAGE_APPLY_COLOR_CORRECT_H *
* ====================================================
#include "ImageApply.h" */
class CImageApplyHSVCorrect : public CImageApply #ifndef IMAGE_APPLY_COLOR_CORRECT_H
{ #define IMAGE_APPLY_COLOR_CORRECT_H
public:
enum CorrectOption #include "ImageApply.h"
{
Red_Removal //除掉红色。红色定义H:[0, 85][170, 255],S:[10, 255],V:[120,255] class GIMGPROC_LIBRARY_API CImageApplyHSVCorrect : public CImageApply
}; {
public: public:
enum CorrectOption
CImageApplyHSVCorrect(); {
Deafault, //默认,无任何除色效果
/* LowSaturation_Removal, //除掉低饱和度像素
* mode [in]: Red_Removal //除掉红色。红色定义H:[0, 85][170, 255],S:[10, 255],V:[120,255]
*/ };
CImageApplyHSVCorrect(CorrectOption mode); public:
/*
virtual ~CImageApplyHSVCorrect(); * mode [in]:
* cvtColor [in]:使使true为灰度值false为默认值
virtual void apply(cv::Mat& pDib,int side); * bgr:[in] uint表示BGR值B在低位R在高位cvtGray false时生效)
*/
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); CImageApplyHSVCorrect(CorrectOption mode = CorrectOption::Deafault, bool cvtColor = false, uint bgr = 0x00FFFFFF);
/* virtual ~CImageApplyHSVCorrect();
* RGBR在高位B在低位32
[00x00FFFFFF] virtual void apply(cv::Mat& pDib, int side);
*/
void initLUT(); virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
/* /*
* RGB索引值设置为目标值 * RGBR在高位B在低位32
= src_b | (src_g << 8) | (src_r << 16) [00x00FFFFFF]
= dst_b | (dst_g << 8) | (dst_r << 16) */
* src_b:[in] B通道索引 void initLUT();
* src_g:[in] G通道索引
* src_r:[in] R通道索引 /*
* dst_b:[in] B通道值 * RGB索引值设置为目标值
* dst_g:[in] G通道值 = src_b | (src_g << 8) | (src_r << 16)
* dst_r:[in] R通道值 = dst_b | (dst_g << 8) | (dst_r << 16)
*/ * src_b:[in] B通道索引
void set_single(const uint src_b, const uint src_g, const uint src_r, * src_g:[in] G通道索引
const uint dst_b, const uint dst_g, const uint dst_r); * src_r:[in] R通道索引
/* * dst_b:[in] B通道值
* HSV色彩空间描述色彩范围BGR索引设置为0x00FFFFFF( * dst_g:[in] G通道值
* range_h:[in] H分量范围[0, 255] * dst_r:[in] R通道值
* range_s:[in] S分量范围[0, 255] */
* range_v:[in] V分量范围[0, 255] void set_single(const uint src_b, const uint src_g, const uint src_r,
* bgr:[in] uint表示BGR值B在低位R在高位 const uint dst_b, const uint dst_g, const uint dst_r);
*/
void set_HSV_value(const std::pair<uchar, uchar>& range_h, /*
const std::pair<uchar, uchar>& range_s, * HSV色彩空间描述色彩范围BGR索引设置为0x00FFFFFF(
const std::pair<uchar, uchar>& range_v, * range_h:[in] H分量范围[0, 255]
uint bgr = 0x00FFFFFF); * range_s:[in] S分量范围[0, 255]
* range_v:[in] V分量范围[0, 255]
/* * bgr:[in] uint表示BGR值B在低位R在高位cvtGray false时生效)
* 256 * 256 * 256 * sizeof(uint * cvtGray:[in] true时RGB值转换为灰度值
* table:[in] */
*/ void set_HSV_value(const std::pair<uchar, uchar>& range_h,
void set_table(const uint* table); const std::pair<uchar, uchar>& range_s,
const std::pair<uchar, uchar>& range_v,
private: uint bgr = 0x00FFFFFF, bool cvtGray = false);
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); * 256 * 256 * 256 * sizeof(uint
* table:[in]
private: */
uint* m_table; void set_table(const uint* table);
};
private:
#endif static bool contained(uchar value, const std::pair<uchar, uchar>& range);
static void RGB_2_HSV_full(int r, int g, int b, uchar& h, uchar& s, uchar& v);
private:
uint* m_table;
};
#endif

View File

@ -1,34 +1,33 @@
#ifndef IMAGE_APPLY_HEADER_H #ifndef IMAGE_APPLY_HEADER_H
#define IMAGE_APPLY_HEADER_H #define IMAGE_APPLY_HEADER_H
#include "ImageApply.h" #include "ImageApply.h"
#include "ImageApplyAdjustColors.h" #include "ImageApplyAdjustColors.h"
#include "ImageApplyAutoCrop.h" #include "ImageApplyAutoContrast.h"
#include "ImageApplyBWBinaray.h" #include "ImageApplyAutoCrop.h"
#include "ImageApplyChannel.h" //#include "ImageApplyBarCodeRecognition.h"
#include "ImageApplyCrop.h" #include "ImageApplyBWBinaray.h"
#include "ImageApplyDiscardBlank.h" #include "ImageApplyChannel.h"
#include "ImageApplyOutHole.h" #include "ImageApplyColorRecognition.h"
#include "ImageApplyDogEarDetection.h" #include "ImageApplyConcatenation.h"
#include "ImageApplyResize.h" #include "ImageApplyCustomCrop.h"
#include "ImageApplyRotation.h" #include "ImageApplyCustomGamma.h"
#include "ImageApplySharpen.h" #include "ImageApplyCvtColor.h"
#include "ImageApplyConcatenation.h" #include "ImageApplyDetachNoise.h"
#include "ImageApplyHSVCorrect.h" #include "ImageApplyDiscardBlank.h"
#include "ImageApplyDetachNoise.h" #include "ImageApplyDispersion.h"
#include "ImageApplyColorRecognition.h" #include "ImageApplyDogEarDetection.h"
#include "ImageApplyUV.h" #include "ImageApplyFadeBackGroundColor.h"
#include "ImageApplyAutoContrast.h" #include "ImageApplyFilter.h"
#include "ImageApplyCustomCrop.h" #include "ImageApplyHSVCorrect.h"
#include "ImageApplyCustomGamma.h" #include "ImageApplyOutHole.h"
#include "ImageApplyCvtColor.h" #include "ImageApplyRefuseInflow.h"
#include "ImageApplyFadeBackGroundColor.h" #include "ImageApplyResize.h"
#include "ImageApplyFilter.h" #include "ImageApplyRotation.h"
#include "ImageApplyRefuseInflow.h" #include "ImageApplySplit.h"
#include "ImageApplySplit.h" #include "ImageApplySizeDetection.h"
#include "ImageApplyTextureRemoval.h" #include "ImageApplyTextureRemoval.h"
#include "ImageMulti.h" #include "ImageMulti.h"
#include "ImageMultiOutputRed.h" #include "ImageMultiOutputRed.h"
#include "ImageApplySplit.h" #include "ImageApplySplit.h"
#include "ImageApplySizeDetection.h" #endif
#endif

View File

@ -0,0 +1,310 @@
#include "ImageApplyMarkCrop.h"
#include "ImageProcess_Public.h"
#define RE 2
//#define DRAW
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;
}

View File

@ -0,0 +1,116 @@
/*
* ====================================================
* Mark点定位裁剪mark点使
*
* 2020/5/22
* 2020/5/22 v1.0
2020/7/29 v1.1 Mark点识别稿
2020/7/30 v1.1.1 Mark点识别稿
2020/8/3 v1.2 Mark点识别文稿方向稿
2020/8/12 v1.3
apply接口增加barCode参数
2020/8/12 v1.4
* v1.4
* ====================================================
*/
#ifndef IMAGEMARKCROPAPPLY_H
#define IMAGEMARKCROPAPPLY_H
#include "ImageApply.h"
class GIMGPROC_LIBRARY_API CImageApplyMarkCrop
{
public:
//识别文稿方向方式
enum DirectionMethod
{
Trilateral_7Net, //三边定位文稿方向(针对七天需求)
Multilateral //多边定位文稿方向
};
enum DPI : ushort
{
DPI_200 = 200,
DPI_300 = 300
};
enum DeviceModel
{
G400 = 2,
G300 = 3
};
enum Orientation
{
Default = 0,
Left_RT, //多边文稿方向识别时靠左为正7天3mark识别时缺角在右上为正
Top_RB, //多边文稿方向识别时靠上为正7天3mark识别时缺角在右下为正
Right_LB, //多边文稿方向识别时靠右为正7天3mark识别时缺角在左下为正
Bottom_LT //多边文稿方向识别时靠下为正7天3mark识别时缺角在左上为正
};
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]:
* markOri [in]: 稿
* barCode [in]: Trilateral_7Net模式
* angle [out]:稿090180270
* 0
-1
-2mark小于3个
-3Multilateral模式时mark点小于4个
-4
-5
*/
int apply(const cv::Mat& src, cv::Mat& dst, Orientation markOri, bool barCode, int& angle);
inline DeviceModel getDeviceModel() { return m_device; }
inline void setDeviceModel(DeviceModel device) { m_device = device; }
inline bool isCropped() { return m_b_isCropped; }
inline void setCropped(bool cropped) { m_b_isCropped = cropped; }
inline double getThreshold() { return m_threshold; }
inline void setThreshold(double threshold) { m_threshold = threshold; }
inline int getNoise() { return m_noise; }
inline void setNoise(int noise) { m_noise = noise; }
inline DPI getDPI() { return m_dpi; }
inline void setDPI(DPI dpi) { m_dpi = dpi; }
inline const cv::Range getSizeRange() { return m_range; }
inline void setSizeRange(const cv::Range& range) { m_range = range; }
inline void setSizeRange(int low, int up) { m_range = cv::Range(low, up); }
private:
void findMarks(const std::vector<std::vector<cv::Point>>& contours, const cv::RotatedRect& region, const cv::Range& range,
std::vector<std::vector<cv::Point>>& marks, std::vector<cv::RotatedRect>& rrect);
bool isContainBarCode(const cv::Mat& image);
private:
DeviceModel m_device;
bool m_b_isCropped;
double m_threshold;
int m_noise;
DPI m_dpi;
cv::Range m_range;
DirectionMethod m_direction;
};
#endif // IMAGEMARKCROPAPPLY_H

View File

@ -1,323 +1,342 @@
#include "ImageApplyOutHole.h" #include "ImageApplyOutHole.h"
#include "ImageProcess_Public.h" #include "ImageProcess_Public.h"
#ifdef LOG #ifdef LOG
#include "Device/filetools.h" #include "Device/filetools.h"
#endif // LOG #endif // LOG
CImageApplyOutHole::CImageApplyOutHole(void) CImageApplyOutHole::CImageApplyOutHole(void)
: CImageApply() : CImageApply()
, m_borderSize(600) , m_borderSize(600)
, m_edgeScale(0.1f) , m_edgeScale(0.1f)
, m_threshold(100) , m_threshold(100)
{ {
} }
CImageApplyOutHole::CImageApplyOutHole(float borderSize, float edgeScale, double threshold) CImageApplyOutHole::CImageApplyOutHole(float borderSize, float edgeScale, double threshold)
: CImageApply() : CImageApply()
, m_borderSize(borderSize) , m_borderSize(borderSize)
, m_edgeScale(edgeScale) , m_edgeScale(edgeScale)
, m_threshold(threshold) , m_threshold(threshold)
{ {
} }
CImageApplyOutHole::~CImageApplyOutHole(void) CImageApplyOutHole::~CImageApplyOutHole(void)
{ {
} }
void CImageApplyOutHole::apply(cv::Mat& pDib, int side) void CImageApplyOutHole::apply(cv::Mat& pDib, int side)
{ {
(void)pDib; (void)pDib;
(void)side; (void)side;
} }
void CImageApplyOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide) void CImageApplyOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{ {
#ifdef LOG #ifdef LOG
FileTools::write_log("imgprc.txt", "enter ImageOutHole apply"); FileTools::write_log("imgprc.txt", "enter ImageOutHole apply");
#endif // LOG #endif // LOG
if (mats.size() < 2) if (mats.size() < 2)
{ {
#ifdef LOG #ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply"); FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG #endif // LOG
return; return;
} }
if (mats[0].empty() || mats[1].empty()) if (mats[0].empty() || mats[1].empty())
{ {
#ifdef LOG #ifdef LOG
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply"); FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
#endif // LOG #endif // LOG
return; return;
} }
//二值化正反面图像 //二值化正反面图像
cv::Mat front = mats[0]; cv::Mat front = mats[0];
cv::Mat back = mats[1]; cv::Mat back = mats[1];
cv::Mat front_thre, back_thre; cv::Mat front_thre, back_thre;
hg::threshold_Mat(front, front_thre, m_threshold); hg::threshold_Mat(front, front_thre, m_threshold);
hg::threshold_Mat(back, back_thre, m_threshold); hg::threshold_Mat(back, back_thre, m_threshold);
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(10, 1)); cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(10, 1));
cv::morphologyEx(front_thre, front_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); cv::morphologyEx(front_thre, front_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
cv::morphologyEx(back_thre, back_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); cv::morphologyEx(back_thre, back_thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
//反面二值化图像水平翻转 //反面二值化图像水平翻转
cv::flip(back_thre, back_thre, 1); //1:Horizontal cv::flip(back_thre, back_thre, 1); //1:Horizontal
//正反面图像寻边 //正反面图像寻边
std::vector<std::vector<cv::Point>> contours_front, contours_back; std::vector<std::vector<cv::Point>> contours_front, contours_back;
std::vector<cv::Vec4i> b1_front, b1_back; std::vector<cv::Vec4i> b1_front, b1_back;
hg::findContours(front_thre.clone(), contours_front, b1_front, cv::RETR_EXTERNAL); hg::findContours(front_thre.clone(), contours_front, b1_front, cv::RETR_EXTERNAL);
hg::findContours(back_thre.clone(), contours_back, b1_back, 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_front = hg::getMaxContour(contours_front, b1_front);
std::vector<cv::Point> maxContour_back = hg::getMaxContour(contours_back, b1_back); std::vector<cv::Point> maxContour_back = hg::getMaxContour(contours_back, b1_back);
cv::RotatedRect rrect_front = hg::getBoundingRect(maxContour_front); //提取正面最大轮廓的最小外接矩形 if (maxContour_front.empty() || maxContour_back.empty())
cv::RotatedRect rrect_back = hg::getBoundingRect(maxContour_back); //提取反面最大轮廓的最小外接矩形 return;
//如果正反面图像尺寸差异超过20个像素直接放弃处理 cv::RotatedRect rrect_front = hg::getBoundingRect(maxContour_front); //提取正面最大轮廓的最小外接矩形
if (cv::abs(rrect_front.size.width - rrect_back.size.width) > 20 || cv::RotatedRect rrect_back = hg::getBoundingRect(maxContour_back); //提取反面最大轮廓的最小外接矩形
cv::abs(rrect_front.size.height - rrect_back.size.height) > 20)
return; //如果正反面图像尺寸差异超过20个像素直接放弃处理
if (cv::abs(rrect_front.size.width - rrect_back.size.width) > 20 ||
//提取正反面图像重叠部分区域 cv::abs(rrect_front.size.height - rrect_back.size.height) > 20)
cv::Rect roi_front, roi_back; return;
cv::RotatedRect mask_rotatedRect;
getRoi(rrect_front, rrect_back, cv::Size(front.cols, front.rows), roi_front, roi_back, mask_rotatedRect); //提取正反面图像重叠部分区域
cv::Rect roi_front, roi_back;
cv::Mat roiMat_front(front_thre, roi_front); //在正面二值图像中截取重叠部分 cv::RotatedRect mask_rotatedRect;
cv::Mat roiMat_back(back_thre, roi_back); //在反面二值图像中截取重叠部分 getRoi(rrect_front, rrect_back, front.size(), back.size(), roi_front, roi_back, mask_rotatedRect);
//正反面二值图像做或运算真正镂空区域保留0其他地方填充为255 cv::Mat roiMat_front(front_thre, roi_front); //在正面二值图像中截取重叠部分
cv::Mat mask; cv::Mat roiMat_back(back_thre, roi_back); //在反面二值图像中截取重叠部分
cv::bitwise_or(roiMat_front, roiMat_back, mask); //或运算,正反面二值图像重叠 //cv::imwrite("roiMat_front.jpg", roiMat_front);
//cv::imwrite("roiMat_back.jpg", roiMat_back);
//cv::imwrite("roiMat_front.jpg", roiMat_front);
//cv::imwrite("roiMat_back.jpg", roiMat_back); //正反面二值图像做或运算真正镂空区域保留0其他地方填充为255
cv::Mat mask;
//二值图像重叠图像颜色取反,膨胀,提取轮廓 cv::bitwise_or(roiMat_front, roiMat_back, mask); //或运算,正反面二值图像重叠
cv::bitwise_not(mask, mask); //反色 //cv::imwrite("mask1.jpg", mask);
element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(10, 10)); //二值图像重叠图像颜色取反,膨胀,提取轮廓
cv::dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //膨胀算法,增大孔洞连通区域面积 cv::bitwise_not(mask, mask);
//cv::imwrite("mask2.jpg", mask); //反色
//为了避免孔洞彻底贯穿纸边,人为绘制纸张轮廓,确保所有孔洞为封闭图形,不会与背景粘连
cv::polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(0), 15); //绘制纸张矩形边缘 element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(10, 10));
cv::dilate(mask, mask, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar(255)); //膨胀算法,增大孔洞连通区域面积
std::vector<std::vector<cv::Point>> contours_mask; //cv::imwrite("mask3.jpg", mask);
std::vector<cv::Vec4i> b1_mask;
hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE); //提取重叠图像轮廓 //为了避免孔洞彻底贯穿纸边,人为绘制纸张轮廓,确保所有孔洞为封闭图形,不会与背景粘连
cv::polylines(mask, hg::getVertices(mask_rotatedRect), true, cv::Scalar(255), 15); //绘制纸张矩形边缘
//过滤非孔洞的联通区域 //cv::imwrite("mask4.jpg", mask);
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++) std::vector<std::vector<cv::Point>> contours_mask;
// cv::drawContours(mask, hole_contours, static_cast<int>(i), cv::Scalar(127), 2); std::vector<cv::Vec4i> b1_mask;
//cv::imwrite("mask.jpg", mask); hg::findContours(mask, contours_mask, b1_mask, cv::RETR_TREE); //提取重叠图像轮廓
cv::Scalar color = getBackGroudColor(front(roi_front), rrect_front.size.area());
for (size_t i = 0; i < hole_contours.size(); i++) //过滤非孔洞的联通区域
{ std::vector<std::vector<cv::Point>> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize);
std::vector<std::vector<cv::Point>> contourss_temp;
contourss_temp.push_back(hole_contours[i]); cv::Scalar color = getBackGroudColor(front(roi_front), rrect_front.size.area());
cv::Mat front_temp = front(roi_front); for (size_t i = 0; i < hole_contours.size(); i++)
hg::fillPolys(front_temp, contourss_temp, color); {
} std::vector<std::vector<cv::Point>> contourss_temp;
contourss_temp.push_back(hole_contours[i]);
if (isTwoSide) cv::Mat front_temp = front(roi_front);
{ hg::fillPolys(front_temp, contourss_temp, color);
int width_ = roi_back.width; }
roi_back.x = back.cols - roi_back.width - roi_back.x; //因为之前反面图像翻转所以现在ROI也要进行相应翻转
color = getBackGroudColor(back(roi_back), rrect_front.size.area()); if (isTwoSide)
for (size_t i = 0; i < hole_contours.size(); i++) {
{ int width_ = roi_back.width;
std::vector<cv::Point> hole_contour; roi_back.x = back.cols - roi_back.width - roi_back.x; //因为之前反面图像翻转所以现在ROI也要进行相应翻转
for (size_t j = 0; j < hole_contours[i].size(); j++) color = getBackGroudColor(back(roi_back), rrect_front.size.area());
hole_contour.push_back(cv::Point(width_ - hole_contours[i][j].x - 1, hole_contours[i][j].y)); for (size_t i = 0; i < hole_contours.size(); i++)
{
std::vector<std::vector<cv::Point>> contours_temp; std::vector<cv::Point> hole_contour;
contours_temp.push_back(hole_contour); for (size_t j = 0; j < hole_contours[i].size(); j++)
cv::Mat back_temp = back(roi_back); hole_contour.push_back(cv::Point(width_ - hole_contours[i][j].x - 1, hole_contours[i][j].y));
hg::fillPolys(back_temp, contours_temp, color);
} std::vector<std::vector<cv::Point>> contours_temp;
} contours_temp.push_back(hole_contour);
#ifdef LOG cv::Mat back_temp = back(roi_back);
FileTools::write_log("imgprc.txt", "exit ImageOutHole apply"); hg::fillPolys(back_temp, contours_temp, color);
#endif // LOG }
} }
#ifdef LOG
void CImageApplyOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, FileTools::write_log("imgprc.txt", "exit ImageOutHole apply");
cv::Rect& roi_front, cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect) #endif // LOG
{ }
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; void CImageApplyOutHole::getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, const cv::Size& srcSize_front, const cv::Size& srcSize_back, cv::Rect& roi_front,
cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect)
rrect_front.size = rrect_back.size = size; {
rrect_front.angle = rrect_back.angle = angle; cv::Rect roi_front_ = rrect_front.boundingRect();
cv::Rect roi_back_ = rrect_back.boundingRect();
roi_front = rrect_front.boundingRect();
roi_back = rrect_back.boundingRect(); cv::Size meanSize = (roi_front_.size() + roi_back_.size()) / 2;
roi_front_.x += (roi_front_.width - meanSize.width) / 2;
if (roi_front.width != roi_back.width || roi_front.height != roi_back.height) roi_front_.width = meanSize.width;
{ roi_front_.y += (roi_front_.height - meanSize.height) / 2;
roi_front.height = roi_back.height; roi_front_.height = meanSize.height;
roi_front.width = roi_back.width; roi_back_.x += (roi_back_.width - meanSize.width) / 2;
} roi_back_.width = meanSize.width;
roi_back_.y += (roi_back_.height - meanSize.height) / 2;
cv::Point offset(0, 0); roi_back_.height = meanSize.height;
int top = std::min(roi_front.y, roi_back.y);
if (top < 0) mask_rotatedRect.angle = (rrect_front.angle + rrect_back.angle) / 2;
{ mask_rotatedRect.size = (rrect_front.size + rrect_back.size) / 2.0f;
roi_front.y -= top; mask_rotatedRect.center = cv::Point2f(roi_front_.size().width + roi_back_.size().width, roi_front_.size().height + roi_back_.size().height) / 4.0f;
roi_back.y -= top;
roi_front.height += top; roi_front = roi_front_ & cv::Rect(cv::Point(0, 0), srcSize_front);
roi_back.height += top; roi_back = roi_back_ & cv::Rect(cv::Point(0, 0), srcSize_back);
offset.y += top;
} int offset_left_f = roi_front.x - roi_front_.x;
int offset_left_b = roi_back.x - roi_back_.x;
int left = std::min(roi_front.x, roi_back.x); int offset_top_f = roi_front.y - roi_front_.y;
if (left < 0) int offset_top_b = roi_back.y - roi_back_.y;
{ int offset_right_f = roi_front_.br().x - roi_front.br().x;
roi_front.x -= left; int offset_right_b = roi_back_.br().x - roi_back.br().x;
roi_back.x -= left; int offset_bottom_f = roi_front_.br().y - roi_front.br().y;
roi_front.width += left; int offset_bottom_b = roi_back_.br().y - roi_back.br().y;
roi_back.width += left;
offset.x += left; if (offset_left_f > offset_left_b)
} {
roi_back.x += offset_left_f - offset_left_b;
int right = std::max(roi_front.x + roi_front.width, roi_back.x + roi_back.width); roi_back.width -= offset_left_f - offset_left_b;
if (right >= srcSize.width) mask_rotatedRect.center.x -= offset_left_f - offset_left_b;
{ }
roi_front.width -= (right - srcSize.width + 1); else
roi_back.width -= (right - srcSize.width + 1); {
} roi_front.x += offset_left_b - offset_left_f;
roi_front.width -= offset_left_b - offset_left_f;
int bottom = std::max(roi_front.y + roi_front.height, roi_back.y + roi_back.height); mask_rotatedRect.center.x -= offset_left_b - offset_left_f;
if (bottom >= srcSize.height) }
{
roi_front.height -= (bottom - srcSize.height + 1); if (offset_top_f > offset_top_b)
roi_back.height -= (bottom - srcSize.height + 1); {
} roi_back.y += offset_top_f - offset_top_b;
roi_back.height -= offset_top_f - offset_top_b;
mask_rotatedRect.center = cv::Point((roi_front.width + offset.x) / 2, (roi_front.height + offset.y) / 2); mask_rotatedRect.center.y -= offset_top_f - offset_top_b;
mask_rotatedRect.size = size; }
mask_rotatedRect.angle = angle; else
} {
roi_front.y += offset_top_b - offset_top_f;
std::vector<std::vector<cv::Point>> CImageApplyOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m, roi_front.height -= offset_top_b - offset_top_f;
cv::RotatedRect roi, float edgeScale, float areaThreshold) mask_rotatedRect.center.y -= offset_top_b - offset_top_f;
{ }
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)), if (offset_right_f > offset_right_b)
static_cast<int>(roi.size.height * (1 - edgeScale * 2))), roi.angle); roi_back.width -= offset_right_f - offset_right_b;
else
std::vector<cv::Point> vertices_roi1 = hg::getVertices(roi); roi_front.width -= offset_right_b - offset_right_f;
std::vector<cv::Point> vertices_roi2 = hg::getVertices(roi2);
if (offset_bottom_f > offset_bottom_b)
std::vector<std::vector<cv::Point>> hole_contours; roi_back.height -= offset_bottom_f - offset_bottom_b;
for (size_t i = 0, length = contours.size(); i < length; i++) else
{ roi_front.height -= offset_bottom_b - offset_bottom_f;
if (m[i][2] != -1) continue; }
cv::RotatedRect rrect = hg::getBoundingRect(contours[i]); std::vector<std::vector<cv::Point>> CImageApplyOutHole::filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m,
if (rrect.size.area() < areaThreshold) continue; cv::RotatedRect roi, float edgeScale, float areaThreshold)
{
bool enabled = true; edgeScale = std::min(0.49f, std::max(edgeScale, 0.0f));
for (size_t j = 0, count = contours[i].size(); j < count; j++) 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);
cv::Point p(contours[i][j]);
double temp1 = pointPolygonTest(vertices_roi1, p, false); //判断是否在纸张内 10-1 std::vector<cv::Point> vertices_roi1 = hg::getVertices(roi);
double temp2 = pointPolygonTest(vertices_roi2, p, false); //判断是否在边缘区域内 10-1 std::vector<cv::Point> vertices_roi2 = hg::getVertices(roi2);
//如果在纸张外,或者边缘内,视为非孔洞
if (temp1 < 0 || temp2 > 0) std::vector<std::vector<cv::Point>> hole_contours;
{ for (size_t i = 0, length = contours.size(); i < length; i++)
enabled = false; {
break; if (m[i][2] != -1) continue;
}
} cv::RotatedRect rrect = hg::getBoundingRect(contours[i]);
if (rrect.size.width < areaThreshold ||
if (enabled) rrect.size.height < areaThreshold ||
hole_contours.push_back(contours[i]); rrect.size.width > areaThreshold * 6 ||
} rrect.size.height > areaThreshold * 6)
return hole_contours; continue;
}
bool enabled = true;
cv::Scalar CImageApplyOutHole::getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints) for (size_t j = 0, count = contours[i].size(); j < count; j++)
{ {
if (pixelPoints.empty()) return cv::Scalar(255, 255, 255); cv::Point p(contours[i][j]);
double temp1 = pointPolygonTest(vertices_roi1, p, false); //判断是否在纸张内 10-1
int channels = image.channels(); double temp2 = pointPolygonTest(vertices_roi2, p, false); //判断是否在边缘区域内 10-1
//如果在纸张外,或者边缘内,视为非孔洞
int temp[3] = { 0 }; if (temp1 < 0 || temp2 > 0)
for (size_t i = 0, length = pixelPoints.size(); i < length; ++i) {
{ enabled = false;
int x = cv::min(cv::max(0, pixelPoints[i].x), image.cols - 1); break;
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) if (enabled)
temp[j] += ptr[j]; hole_contours.push_back(contours[i]);
} }
return hole_contours;
return cv::Scalar(temp[0] / static_cast<int>(pixelPoints.size()), }
temp[1] / static_cast<int>(pixelPoints.size()),
temp[2] / static_cast<int>(pixelPoints.size())); cv::Scalar CImageApplyOutHole::getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints)
} {
if (pixelPoints.empty()) return cv::Scalar(255, 255, 255);
cv::Scalar CImageApplyOutHole::getBackGroudColor(const cv::Mat& image, int total)
{ int channels = image.channels();
if (image.channels() == 3)
{ int temp[3] = { 0 };
cv::Mat image_bgr[3]; for (size_t i = 0, length = pixelPoints.size(); i < length; ++i)
cv::split(image, image_bgr); {
int x = cv::min(cv::max(0, pixelPoints[i].x), image.cols - 1);
uchar bgr[3]; int y = cv::min(cv::max(0, pixelPoints[i].y), image.rows - 1);
for (size_t i = 0; i < 3; i++)
bgr[i] = getBackGroudChannelMean(image_bgr[i], total); const unsigned char* ptr = image.ptr(y, x);
return cv::Scalar(bgr[0], bgr[1], bgr[2]); for (int j = 0; j < channels; ++j)
} temp[j] += ptr[j];
else }
return cv::Scalar::all(getBackGroudChannelMean(image, total));
} return cv::Scalar(temp[0] / static_cast<int>(pixelPoints.size()),
temp[1] / static_cast<int>(pixelPoints.size()),
uchar CImageApplyOutHole::getBackGroudChannelMean(const cv::Mat& gray, int total) temp[2] / static_cast<int>(pixelPoints.size()));
{ }
cv::Mat image_clone;
cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25); cv::Scalar CImageApplyOutHole::getBackGroudColor(const cv::Mat& image, int total)
{
int threnshold = total / 32; if (image.channels() == 3)
int channels[] = { 0 }; {
int nHistSize[] = { 256 }; cv::Mat image_bgr[3];
float range[] = { 0, 256 }; cv::split(image, image_bgr);
const float* fHistRanges[] = { range };
cv::Mat hist; uchar bgr[3];
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false); for (size_t i = 0; i < 3; i++)
bgr[i] = getBackGroudChannelMean(image_bgr[i], total);
int hist_array[256]; return cv::Scalar(bgr[0], bgr[1], bgr[2]);
for (int i = 0; i < 256; i++) }
hist_array[i] = hist.at<float>(i, 0); else
return cv::Scalar::all(getBackGroudChannelMean(image, total));
int length = 1; }
const int length_max = 255 - m_threshold;
while (length < length_max) uchar CImageApplyOutHole::getBackGroudChannelMean(const cv::Mat& gray, int total)
{ {
for (size_t i = m_threshold + 1; i < 256 - length; i++) cv::Mat image_clone;
{ cv::resize(gray, image_clone, cv::Size(), 0.25, 0.25);
int count = 0;
uint pixSum = 0; int threnshold = total / 32;
for (size_t j = 0; j < length; j++) int channels[] = { 0 };
{ int nHistSize[] = { 256 };
count += hist_array[j + i]; float range[] = { 0, 256 };
pixSum += hist_array[j + i] * (i + j); const float* fHistRanges[] = { range };
} cv::Mat hist;
cv::calcHist(&image_clone, 1, channels, cv::Mat(), hist, 1, nHistSize, fHistRanges, true, false);
if (count >= threnshold)
return pixSum / count; int hist_array[256];
} for (int i = 0; i < 256; i++)
length++; hist_array[i] = hist.at<float>(i, 0);
}
return 255; int length = 1;
const int length_max = 255;
while (length < length_max)
{
for (size_t i = 1; i < 256 - length; i++)
{
int count = 0;
uint pixSum = 0;
for (size_t j = 0; j < length; j++)
{
count += hist_array[j + i];
pixSum += hist_array[j + i] * (i + j);
}
if (count >= threnshold)
return pixSum / count;
}
length++;
}
return 255;
} }

View File

@ -1,74 +1,80 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2020/11/21 * 2020/11/21
* 2020/05/12 v1.0 * 2020/05/12 v1.0
* 2020/11/17 v1.1 * 2020/11/17 v1.1
* 2021/09/06 v1.2 50100 * 2021/09/06 v1.2 50100
* 2021/11/03 v1.3 10穿 * 2021/11/03 v1.3 10穿
* 2021/11/04 v1.4 5 * 2021/11/04 v1.4 5
* 2021/11/17 v1.5 opencv版本导致的BUG * 2021/11/17 v1.5 opencv版本导致的BUG
* v1.5 * 2022/04/18 v1.6 BUG
* 2022/05/04 v1.6.1
* ==================================================== * 2022/07/16 v1.6.2 BUG
*/ * 2022/07/18 v1.6.3 mask的一些逻辑错误
* 2022/07/18 v1.7 BUGborderSize逻辑,穿[borderSize, borderSize * 6]
#ifndef IMAGE_APPLY_OUT_HOLE_H * 2022/07/22 v1.7.1 BUG
#define IMAGE_APPLY_OUT_HOLE_H * v1.7.1
#include "ImageApply.h" * ====================================================
*/
class CImageApplyOutHole : public CImageApply
{ #ifndef IMAGE_APPLY_OUT_HOLE_H
public: #define IMAGE_APPLY_OUT_HOLE_H
CImageApplyOutHole(); #include "ImageApply.h"
/* class GIMGPROC_LIBRARY_API CImageApplyOutHole : public CImageApply
* borderSize [in]: {
* edgeScale [in]:(0,0.5),0.1 public:
* threshold [in]:
*/ CImageApplyOutHole();
CImageApplyOutHole(float borderSize, float edgeScale, double threshold);
/*
~CImageApplyOutHole(void); * borderSize [in]:
* edgeScale [in]:(0,0.5),0.1
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); * threshold [in]:
*/
float getBorderSize() { return m_borderSize; } CImageApplyOutHole(float borderSize, float edgeScale, double threshold);
float getEdgeScale() { return m_edgeScale; } ~CImageApplyOutHole(void);
double getThreshold() { return m_threshold; } virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
void setBorderSize(float size) { m_borderSize = size; } float getBorderSize() { return m_borderSize; }
void setEdgeScale(float scale) { m_edgeScale = scale; } float getEdgeScale() { return m_edgeScale; }
void setThreshold(double threshold) { m_threshold = (std::min)((std::max)(threshold, 1.0), 254.0); } double getThreshold() { return m_threshold; }
private: void setBorderSize(float size) { m_borderSize = size; }
virtual void apply(cv::Mat& pDib, int side); void setEdgeScale(float scale) { m_edgeScale = scale; }
void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, cv::Rect& roi_front, void setThreshold(double threshold) { m_threshold = (std::min)((std::max)(threshold, 1.0), 254.0); }
cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect);
private:
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); virtual void apply(cv::Mat& pDib, int side);
cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints); void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, const cv::Size& srcSize_front, const cv::Size& srcSize_back, cv::Rect& roi_front,
cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect);
cv::Scalar getBackGroudColor(const cv::Mat& image, int total);
std::vector<std::vector<cv::Point> > filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& m, cv::RotatedRect roi,
uchar getBackGroudChannelMean(const cv::Mat& gray, int total); float edgeScale, float areaThreshold);
private: cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints);
float m_borderSize;
float m_edgeScale; cv::Scalar getBackGroudColor(const cv::Mat& image, int total);
double m_threshold;
}; uchar getBackGroudChannelMean(const cv::Mat& gray, int total);
#endif // !IMAGE_APPLY_OUT_HOLE_H private:
float m_borderSize;
float m_edgeScale;
double m_threshold;
};
#endif // !IMAGE_APPLY_OUT_HOLE_H

View File

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

View File

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

View File

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

View File

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

View File

@ -1,172 +1,139 @@
#include "ImageApplyRotation.h" #include "ImageApplyRotation.h"
//#define USE_TESSERCAT
#ifdef _WIN32
//#define USE_HANWANG #ifdef USE_HANWANG
#include<sstream>
//#define HG_GPDF_API_BUILD #endif
#include "hg_ocr.h" #endif
CImageApplyRotation::CImageApplyRotation(RotationType rotation, bool isBackTransposed, int dpi, const char* tessdataPath) CImageApplyRotation::CImageApplyRotation(RotationType rotation, bool isBackTransposed, int dpi, const char* tessdataPath)
: m_rotation(rotation) : m_rotation(rotation)
, m_backTranspose(isBackTransposed) , m_backTranspose(isBackTransposed)
, m_dpi(dpi) , m_dpi(dpi)
, osd(nullptr) #ifdef _WIN32
{ #ifdef USE_HANWANG
if (rotation == RotationType::AutoTextOrientation) , m_ocr(nullptr)
{ #endif
#ifdef USE_TESSERCAT #endif
osd = new HG_OCR(); {
std::string strpath(tessdataPath); #ifdef _WIN32
reinterpret_cast<HG_OCR*>(osd)->init(strpath.c_str(), HG_OCR::PSM_TYPE::Orientation); #ifdef USE_HANWANG
#endif if (tessdataPath != nullptr)
} {
} std::wstringstream wss;
wss << tessdataPath;
CImageApplyRotation::~CImageApplyRotation() m_ocr = new HG_OCR(wss.str().c_str());
{ }
#ifdef USE_TESSERCAT #endif
if (osd) delete reinterpret_cast<HG_OCR*>(osd); #endif
#endif }
}
CImageApplyRotation::~CImageApplyRotation()
void CImageApplyRotation::apply(cv::Mat& pDib, int side) {
{ #ifdef _WIN32
m_angleResult = 0; #ifdef USE_HANWANG
if (pDib.empty()) if (m_ocr)
{ delete m_ocr;
return; #endif
} #endif
}
if (m_rotation == RotationType::AutoTextOrientation) //<2F>Զ<EFBFBD><D4B6>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><CAB6>
{ void CImageApplyRotation::apply(cv::Mat& pDib, int side)
#ifdef USE_HANWANG {
cv::Mat temp; #ifdef LOG
if (m_dpi != 200) FileTools::write_log("imgprc.txt", "enter CImageApplyRotation apply");
{ #endif // LOG
double scale = 200 / static_cast<double>(m_dpi); if (pDib.empty())
int new_w = static_cast<int>(pDib.cols * scale) / 4 * 4; {
int new_h = pDib.rows * scale; #ifdef LOG
cv::resize(pDib, temp, cv::Size(new_w, new_h)); FileTools::write_log("imgprc.txt", "exit CImageApplyRotation apply");
} #endif // LOG
else return;
temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone(); }
if (temp.channels() == 3) if (m_rotation == RotationType::AutoTextOrientation) //<2F>Զ<EFBFBD><D4B6>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>ʶ<EFBFBD><CAB6>
cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY); {
cv::threshold(temp, temp, 180, 255, cv::THRESH_OTSU); #ifdef USE_HANWANG
cv::Mat temp;
int orientation = HG_OCR::orientation(temp.data, temp.cols, temp.rows, temp.channels()); if (m_dpi != 200)
{
switch (orientation) double scale = 200 / static_cast<double>(m_dpi);
{ int new_w = static_cast<int>(pDib.cols * scale) / 4 * 4;
case 90: int new_h = pDib.rows * scale;
cv::transpose(pDib, pDib); cv::resize(pDib, temp, cv::Size(new_w, new_h));
cv::flip(pDib, pDib, 0); }
break; else
case 180: temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone();
cv::flip(pDib, pDib, 0);
cv::flip(pDib, pDib, 1); if (temp.channels() == 3)
break; cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY);
case 270: cv::threshold(temp, temp, 180, 255, cv::THRESH_OTSU);
cv::transpose(pDib, pDib);
cv::flip(pDib, pDib, 1); int orientation = 0;
break; if (m_ocr)
default: orientation = m_ocr->orientation(temp.data, temp.cols, temp.rows, temp.channels());
break;
} switch (orientation)
#endif {
#ifdef USE_TESSERCAT case 90:
if (osd) cv::transpose(pDib, pDib);
{ cv::flip(pDib, pDib, 0);
cv::Mat temp; break;
if (m_dpi != 200) case 180:
{ cv::flip(pDib, pDib, 0);
double scale = 200 / static_cast<double>(m_dpi); cv::flip(pDib, pDib, 1);
int new_w = (static_cast<int>(pDib.cols * scale) + 3) / 4 * 4; break;
int new_h = pDib.rows * scale; case 270:
cv::resize(pDib, temp, cv::Size(new_w, new_h)); cv::transpose(pDib, pDib);
} cv::flip(pDib, pDib, 1);
else break;
temp = pDib(cv::Rect(0, 0, pDib.cols / 4 * 4, pDib.rows)).clone(); default:
break;
}
HG_OCR* ptr_osd = reinterpret_cast<HG_OCR*>(osd); #endif
int ori = -1; }
int direction = -1; else if (m_backTranspose && side == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת180
int order = -1; {
float angle = -1; if (m_rotation != RotationType::Rotate_180) //<2F><>ת180<38><30>
ptr_osd->getOrientation(temp.data, temp.cols, temp.rows, temp.channels(), temp.step1(), {
ori, direction, order, angle); if (m_rotation == RotationType::Rotate_90_clockwise || m_rotation == RotationType::Rotate_90_anti_clockwise) //90<39><30> -90<39><30>
{
switch (ori) transpose(pDib, pDib);
{ flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 0 : 1);
case 1: }
cv::transpose(pDib, pDib); else
cv::flip(pDib, pDib, 0); {
m_angleResult = 90; flip(pDib, pDib, 0);
break; flip(pDib, pDib, 1);
case 2: }
cv::flip(pDib, pDib, 0); }
cv::flip(pDib, pDib, 1); }
m_angleResult = 180; else //zh
break; {
case 3: if (m_rotation == RotationType::Rotate_90_clockwise || m_rotation == RotationType::Rotate_90_anti_clockwise) //90<39><30> -90<39><30>
cv::transpose(pDib, pDib); {
cv::flip(pDib, pDib, 1); transpose(pDib, pDib);
m_angleResult = 270; flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 1 : 0);
break; }
default: else if (m_rotation == RotationType::Rotate_180)
m_angleResult = 0; {
break; flip(pDib, pDib, 0);
} flip(pDib, pDib, 1);
} }
#endif }
} #ifdef LOG
else if (m_backTranspose && side == 1) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת180 FileTools::write_log("imgprc.txt", "exit CImageApplyRotation apply");
{ #endif // LOG
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> void CImageApplyRotation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{ {
transpose(pDib, pDib); (void)isTwoSide;
flip(pDib, pDib, m_rotation == RotationType::Rotate_90_clockwise ? 0 : 1); int i = 0;
m_angleResult = m_rotation == RotationType::Rotate_90_clockwise ? 270 : 90; for (cv::Mat& var : mats) {
} if (!var.empty()) {
else apply(var, i);
{ i++;
flip(pDib, pDib, 0); }
flip(pDib, pDib, 1); }
m_angleResult = 180; }
}
}
}
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 ? 1 : 0);
m_angleResult = m_rotation == RotationType::Rotate_90_clockwise ? 90 : 270;
}
else if (m_rotation == RotationType::Rotate_180)
{
flip(pDib, pDib, 0);
flip(pDib, pDib, 1);
m_angleResult = 180;
}
}
}
void CImageApplyRotation::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
(void)isTwoSide;
m_angleResults.clear();
int i = 0;
for (cv::Mat& var : mats) {
if (!var.empty()) {
apply(var, i);
m_angleResults.push_back(m_angleResult);
i++;
}
}
}

View File

@ -1,56 +1,82 @@
#ifndef IMAGE_APPLY_ROTATION_H /*
#define IMAGE_APPLY_ROTATION_H * ====================================================
#include "ImageApply.h" *
*
class CImageApplyRotation : public CImageApply * 2020/4/21
{ * v1.0 2020/04/21
public: v1.1 2020/08/12 稿BUG
enum class RotationType v1.2 2021/10/15 稿
{ v1.2.1 2022/04/25
Invalid, * v1.2.1
Rotate_90_clockwise,
Rotate_180, * ====================================================
Rotate_90_anti_clockwise, */
AutoTextOrientation #ifndef IMAGE_APPLY_ROTATION_H
}; #define IMAGE_APPLY_ROTATION_H
public: #include "ImageApply.h"
CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr); #ifdef _WIN32
//#define USE_HANWANG
virtual ~CImageApplyRotation(); #ifdef USE_HANWANG
#define HG_GPDF_API_BUILD
virtual void apply(cv::Mat& pDib, int side) override; #include <hg_gpdf.h>
#endif
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide); #endif
bool isBackTransposed() { return m_backTranspose; } class GIMGPROC_LIBRARY_API CImageApplyRotation : public CImageApply
{
int getDPI() { return m_dpi; } public:
enum class RotationType
int angleResult() { return m_angleResult; } {
Invalid, //无效
const std::vector<int>& angleResults() { return m_angleResults; } Rotate_90_clockwise, //顺时针90°
Rotate_180, //180°
RotationType getRotationType() { return m_rotation; } Rotate_90_anti_clockwise, //逆时针90°即270°
void setBackTransposed(bool enabled) { m_backTranspose = enabled; } AutoTextOrientation //自动文稿方向识别旋转
};
void setDPI(int dpi) { m_dpi = dpi; }
public:
void setRotationType(RotationType type) { m_rotation = type; }
/*
private: * rotation [in]:
RotationType m_rotation; * isBackTransposed [in]:true为背面180°
bool m_backTranspose; * dpi [in]:DPIrotation为AutoTextOrientation时生效稿200DPI进行识别
int m_dpi; * tessadataPath [in]:rotation为AutoTextOrientation时生效
*/
void* osd; CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr);
int m_angleResult; virtual ~CImageApplyRotation();
std::vector<int> m_angleResults;
}; virtual void apply(cv::Mat& pDib, int side) override;
#endif // !IMAGE_APPLY_ROTATION_H 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;
#ifdef _WIN32
#ifdef USE_HANWANG
HG_OCR* m_ocr;
#endif
#endif
};
#endif // !IMAGE_APPLY_ROTATION_H

View File

@ -1,47 +1,46 @@
#include "ImageApplySizeDetection.h" #include "ImageApplySizeDetection.h"
#include "ImageProcess_Public.h" #include "ImageProcess_Public.h"
CImageApplySizeDetection::CImageApplySizeDetection(int paperType, int thre_x, int thre_y) CImageApplySizeDetection::CImageApplySizeDetection(int paperType, int thre_x, int thre_y)
: m_paperType(paperType) : m_paperType(paperType)
, m_thre_x(thre_x) , m_thre_x(thre_x)
, m_thre_y(thre_y) , m_thre_y(thre_y)
{ {
printf("\n paperType =%d \r\n", paperType); }
}
CImageApplySizeDetection::~CImageApplySizeDetection()
CImageApplySizeDetection::~CImageApplySizeDetection() {
{ }
}
#define THRESHOLD 40
#define THRESHOLD 40 #define ELEMNT_K 8
#define ELEMNT_K 8 int CImageApplySizeDetection::apply(const cv::Mat& pDib)
int CImageApplySizeDetection::apply(const cv::Mat& pDib) {
{ if (pDib.empty()) return 0;
if (pDib.empty()) return 0;
float width, height;
float width, height; cv::Mat thre;
cv::Mat thre; hg::threshold_Mat(pDib, thre, THRESHOLD);
hg::threshold_Mat(pDib, thre, THRESHOLD); cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(ELEMNT_K, 1));
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(ELEMNT_K, 1)); cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0)); std::vector<std::vector<cv::Point>> contours;
std::vector<std::vector<cv::Point>> contours; std::vector<cv::Vec4i> hierarchy;
std::vector<cv::Vec4i> hierarchy; hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy); cv::RotatedRect rect = hg::getBoundingRect(maxContour);
cv::RotatedRect rect = hg::getBoundingRect(maxContour); width = rect.size.width;
width = rect.size.width; height = rect.size.height;
height = rect.size.height; printf("\n width =%f ,height = %f ", width, height);
printf("\n width =%f ,height = %f ", width, height);
HGSize dstSize;
HGSize dstSize; if (m_supportPaper.count((PaperSize)m_paperType) > 0)//°üº¬ÉèÖõķùÃæ
if (m_supportPaper.count((PaperSize)m_paperType) > 0)//包含设置的幅面 {
{ dstSize = m_supportPaper[(PaperSize)m_paperType];
dstSize = m_supportPaper[(PaperSize)m_paperType]; if ((width > (dstSize.width + m_thre_x)) ||
if ((width > (dstSize.width + m_thre_x)) || (width < (dstSize.width - m_thre_x)) ||
(width < (dstSize.width - m_thre_x)) || (height > (dstSize.height + m_thre_y)) ||
(height > (dstSize.height + m_thre_y)) || (height < (dstSize.height - m_thre_y)))
(height < (dstSize.height - m_thre_y))) return 1;
return 1; }
} return 0;
return 0; }
}

View File

@ -1,84 +1,83 @@
/* /*
* ==================================================== * ====================================================
* *
* *
* 2022/05/11 * 2022/05/11
* 2022/05/11 * 2022/05/11
* v1.0 * v1.0
* ==================================================== * ====================================================
*/ */
#ifndef IMAGE_APPLY_SIZE_DETECTION_H #ifndef IMAGE_APPLY_SIZE_DETECTION_H
#define IMAGE_APPLY_SIZE_DETECTION_H #define IMAGE_APPLY_SIZE_DETECTION_H
#include "ImageApply.h" #include "ImageApply.h"
#include <map> #include<map>
class GIMGPROC_LIBRARY_API CImageApplySizeDetection
class CImageApplySizeDetection {
{ public:
public: enum PaperSize
enum PaperSize {
{ G400_A3,
G400_A3, G400_A4,
G400_A4, G400_A4R,
G400_A4R, G400_A5,
G400_A5, G400_A5R,
G400_A5R, G400_A6,
G400_A6, G400_A6R,
G400_A6R, G400_B4,
G400_B4, G400_B5,
G400_B5, G400_B5R,
G400_B5R, G400_B6R,
G400_B6R, G400_B6,
G400_B6, G400_DOUBLELETTER,
G400_DOUBLELETTER, G400_LEGAL,
G400_LEGAL, G400_LETTER,
G400_LETTER, G400_LONGLETTER,
G400_LONGLETTER, G400_MAXSIZE
G400_MAXSIZE };
};
struct HGSize
struct HGSize {
{ int width;
int width; int height;
int height; };
};
public:
public:
CImageApplySizeDetection(int paperType, int thre_x = 70, int thre_y = 80);
CImageApplySizeDetection(int paperType, int thre_x = 70, int thre_y = 80);
~CImageApplySizeDetection();
~CImageApplySizeDetection();
virtual int apply(const cv::Mat& pDib);
virtual int apply(const cv::Mat& pDib);
inline void setPaperType(int paperType) { m_paperType = paperType; }
inline void setPaperType(int paperType) { m_paperType = paperType; }
private:
private: int m_paperType;
int m_paperType; int m_thre_x;
int m_thre_x; int m_thre_y;
int m_thre_y; std::map<PaperSize, HGSize> m_supportPaper = {
std::map<PaperSize, HGSize> m_supportPaper = { {PaperSize::G400_A3,HGSize{2338,3307}},
{PaperSize::G400_A3,HGSize{2338,3307}}, {PaperSize::G400_A4,HGSize{1653,2338}},
{PaperSize::G400_A4,HGSize{1653,2338}}, {PaperSize::G400_A4R,HGSize{2338,1653}},
{PaperSize::G400_A4R,HGSize{2338,1653}}, {PaperSize::G400_A5,HGSize{1165,1653}},
{PaperSize::G400_A5,HGSize{1165,1653}}, {PaperSize::G400_A5R,HGSize{1653,1165}},
{PaperSize::G400_A5R,HGSize{1653,1165}}, {PaperSize::G400_A6,HGSize{826,1165}},
{PaperSize::G400_A6,HGSize{826,1165}}, {PaperSize::G400_A6R,HGSize{1165,826}},
{PaperSize::G400_A6R,HGSize{1165,826}}, {PaperSize::G400_B4,HGSize{1969,2780}},
{PaperSize::G400_B4,HGSize{1969,2780}}, {PaperSize::G400_B5,HGSize{1385,1968}},
{PaperSize::G400_B5,HGSize{1385,1968}}, {PaperSize::G400_B5R,HGSize{1968,1385}},
{PaperSize::G400_B5R,HGSize{1968,1385}}, {PaperSize::G400_B6R,HGSize{1433,1007}},
{PaperSize::G400_B6R,HGSize{1433,1007}}, {PaperSize::G400_B6,HGSize{1007,1433}},
{PaperSize::G400_B6,HGSize{1007,1433}}, {PaperSize::G400_DOUBLELETTER,HGSize{2200,3400}},
{PaperSize::G400_DOUBLELETTER,HGSize{2200,3400}}, {PaperSize::G400_LEGAL,HGSize{1700,2800}},
{PaperSize::G400_LEGAL,HGSize{1700,2800}}, {PaperSize::G400_LETTER,HGSize{1700,2198}},
{PaperSize::G400_LETTER,HGSize{1700,2198}}, {PaperSize::G400_LONGLETTER,HGSize{2040,2640}},
{PaperSize::G400_LONGLETTER,HGSize{2040,2640}}, {PaperSize::G400_MAXSIZE,HGSize{2338,6614}}
{PaperSize::G400_MAXSIZE,HGSize{2338,6614}} };
}; };
};
#endif // !IMAGE_APPLY_SIZE_DETECTION_H
#endif // !IMAGE_APPLY_SIZE_DETECTION_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,34 @@
/*
* ====================================================
* <EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD>UVͼ<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>UV<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>UVһ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>
* <EFBFBD><EFBFBD><EFBFBD>ߣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ά
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD>2020/7/20
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>ʱ<EFBFBD>2020/7/20
* <EFBFBD><EFBFBD>ţ<EFBFBD>v1.0 2020/7/20
* ====================================================
*/
#ifndef IMAGE_APPLY_UV_MERGE_H
#define IMAGE_APPLY_UV_MERGE_H
#include "ImageApply.h"
#include <map>
class GIMGPROC_LIBRARY_API CImageApplyUVMerge
{
public:
CImageApplyUVMerge();
~CImageApplyUVMerge();
void Apply(cv::Mat& image, const cv::Mat& uv, int dpi = 200, int thresh = 100);
static cv::Mat Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle);
private:
void purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map<int, cv::Scalar> map_color, int dpi, int threshold);
cv::Scalar getColor(const cv::Mat& image, int col, int threshold);
void update_lutData(int contrast);
cv::Mat lut;
};
#endif // !IMAGE_APPLY_UV_MERGE_H

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,165 @@
#-------------------------------------------------
#
# Project created by QtCreator 2019-12-29T09:49:19
#
#-------------------------------------------------
QT -= core gui
TARGET = hgimgproc
TEMPLATE = lib
DEFINES += GIMGPROC_LIBRARY GIMGPROC_LIBRARY_BUILD
# 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
win32 {
DEFINES += _WIN32
INCLUDEPATH += $$PWD/../gpdf
DEPENDPATH += $$PWD/../gpdf
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/lib/x86/Release -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/lib/x86/Debug -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/lib/x64/Release -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/lib/x64/Debug -lopencv_world346d
LIBS += -L$$PWD/../bin/x64/debug -lhg_gpdf
}
}
}
else:unix:!macx: {
#LIBS += -lopencv_world
#linux系统上面需安装opencv3.4.6
INCLUDEPATH += $$PWD/../Tirdparty/3rdparty/opencv/include
CONFIG(debug, debug|release) {
DESTDIR += ../bin/x86/debug
LIBS += -L$$PWD/../Tirdparty/3rdparty/opencv/lib/Debug -lopencv_world -llibtiff -llibjpeg-turbo -lIlmImf -littnotify -llibjasper \
-llibprotobuf -llibwebp -llibpng -lquirc -lzlib
#LIBS += -L$$PWD/../bin/x86/debug -lhg_gpdf
}
CONFIG(release, debug|release) {
DESTDIR += ../bin/x86/release
LIBS += -L$$PWD/../Tirdparty/3rdparty/opencv/lib/Debug -lopencv_world -llibtiff -llibjpeg-turbo -lIlmImf -littnotify -llibjasper \
-llibprotobuf -llibwebp -llibpng -lquirc -lzlib
#LIBS += -L$$PWD/../bin/x86/release -lhg_gpdf
}
}
SOURCES += \
ImageApply.cpp \
ImageApplyAdjustColors.cpp \
ImageApplyAutoContrast.cpp \
ImageApplyAutoCrop.cpp \
ImageApplyBWBinaray.cpp \
#ImageApplyBarCodeRecognition.cpp \
ImageApplyChannel.cpp \
ImageApplyColorRecognition.cpp \
ImageApplyConcatenation.cpp \
ImageApplyCustomCrop.cpp \
ImageApplyCustomGamma.cpp \
ImageApplyCvtColor.cpp \
ImageApplyDetachNoise.cpp \
ImageApplyDiscardBlank.cpp \
ImageApplyDispersion.cpp \
ImageApplyDogEarDetection.cpp \
ImageApplyFadeBackGroundColor.cpp \
ImageApplyFilter.cpp \
ImageApplyHSVCorrect.cpp \
ImageApplyMarkCrop.cpp \
ImageApplyOutHole.cpp \
ImageApplyRefuseInflow.cpp \
ImageApplyResize.cpp \
ImageApplyRotation.cpp \
ImageApplySizeDetection.cpp \
ImageApplySplit.cpp \
ImageApplyTextureRemoval.cpp \
#ImageApplyUVMerge.cpp \
ImageMulti.cpp \
ImageMultiOutputRed.cpp \
ImageProcess_Public.cpp \
IMulti.cpp
HEADERS += \
ImageApply.h \
ImageApplyAdjustColors.h \
ImageApplyAutoContrast.h \
ImageApplyAutoCrop.h \
ImageApplyBWBinaray.h \
#ImageApplyBarCodeRecognition.h \
ImageApplyChannel.h \
ImageApplyColorRecognition.h \
ImageApplyConcatenation.h \
ImageApplyCustomCrop.h \
ImageApplyCustomGamma.h \
ImageApplyCvtColor.h \
ImageApplyDetachNoise.h \
ImageApplyDiscardBlank.h \
ImageApplyDispersion.h \
ImageApplyDogEarDetection.h \
ImageApplyFadeBackGroundColor.h \
ImageApplyFilter.h \
ImageApplyHSVCorrect.h \
ImageApplyHeaders.h \
ImageApplyMarkCrop.h \
ImageApplyOutHole.h \
ImageApplyRefuseInflow.h \
ImageApplyResize.h \
ImageApplyRotation.h \
ImageApplySizeDetection.h \
ImageApplySplit.h \
ImageApplyTextureRemoval.h \
#ImageApplyUVMerge.h \
ImageMulti.h \
ImageMultiOutputRed.h \
ImageProcess_Public.h \
IMulti.h\
imgprocdefs.h
#VERSION = 1.0.0.0
QMAKE_TARGET_PRODUCT = "gimgproc"
QMAKE_TARGET_COMPANY = "huagaoscan"
QMAKE_TARGET_DESCRIPTION = "文件描述"
QMAKE_TARGET_COPYRIGHT = "版权"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,48 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __INVERTEDLUMINANCESOURCE_H__
#define __INVERTEDLUMINANCESOURCE_H__
/*
* Copyright 2013 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/ZXing.h>
#include <zxing/LuminanceSource.h>
namespace zxing {
class InvertedLuminanceSource : public LuminanceSource {
private:
typedef LuminanceSource Super;
const Ref<LuminanceSource> delegate;
public:
InvertedLuminanceSource(Ref<LuminanceSource> const&);
ArrayRef<char> getRow(int y, ArrayRef<char> row) const;
ArrayRef<char> getMatrix() const;
boolean isCropSupported() const;
Ref<LuminanceSource> crop(int left, int top, int width, int height) const;
boolean isRotateSupported() const;
virtual Ref<LuminanceSource> invert() const;
Ref<LuminanceSource> rotateCounterClockwise() const;
};
}
#endif /* INVERTEDLUMINANCESOURCE_H_ */

View File

@ -0,0 +1,59 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __LUMINANCESOURCE_H__
#define __LUMINANCESOURCE_H__
/*
* LuminanceSource.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/Array.h>
#include <string.h>
namespace zxing {
class LuminanceSource : public Counted {
private:
const int width;
const int height;
public:
LuminanceSource(int width, int height);
virtual ~LuminanceSource();
int getWidth() const { return width; }
int getHeight() const { return height; }
// Callers take ownership of the returned memory and must call delete [] on it themselves.
virtual ArrayRef<char> getRow(int y, ArrayRef<char> row) const = 0;
virtual ArrayRef<char> getMatrix() const = 0;
virtual bool isCropSupported() const;
virtual Ref<LuminanceSource> crop(int left, int top, int width, int height) const;
virtual bool isRotateSupported() const;
virtual Ref<LuminanceSource> invert() const;
virtual Ref<LuminanceSource> rotateCounterClockwise() const;
operator std::string() const;
};
}
#endif /* LUMINANCESOURCE_H_ */

View File

@ -0,0 +1,48 @@
#ifndef __MULTI_FORMAT_READER_H__
#define __MULTI_FORMAT_READER_H__
/*
* MultiFormatBarcodeReader.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/Reader.h>
#include <zxing/common/BitArray.h>
#include <zxing/Result.h>
#include <zxing/DecodeHints.h>
namespace zxing {
class MultiFormatReader : public Reader {
private:
Ref<Result> decodeInternal(Ref<BinaryBitmap> image);
std::vector<Ref<Reader> > readers_;
DecodeHints hints_;
public:
MultiFormatReader();
Ref<Result> decode(Ref<BinaryBitmap> image);
Ref<Result> decode(Ref<BinaryBitmap> image, DecodeHints hints);
Ref<Result> decodeWithState(Ref<BinaryBitmap> image);
void setHints(DecodeHints hints);
~MultiFormatReader();
};
}
#endif

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