1,修改自动裁剪参数列表

2,更新所有算法到最新版
This commit is contained in:
masayume 2020-12-21 17:34:20 +08:00
parent 40e5903aca
commit a72e300eb1
24 changed files with 456 additions and 190 deletions

View File

@ -87,7 +87,7 @@ static std::vector<CString> reslutions{
_T("240"),
_T("300"),
#ifndef LANXUM
//_T("600")
_T("600")
#endif // LANXUM
};

View File

@ -162,7 +162,7 @@ void ImageMatQueue::setparam(const GScanCap& param)
#else // REAL300DPI
fixedSize = papersize.GetPaperSize(param.papertype, 200.0f, param.paperAlign);
#endif
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : param.is_autocrop, param.autodescrew, param.fillbackground, cv::Size(fixedSize.cx, fixedSize.cy), param.is_convex,param.AutoCrop_threshold,param.noise,param.indent)));
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(islongcustomcrop ? islongcustomcrop : param.is_autocrop, param.autodescrew, param.fillbackground, cv::Size(fixedSize.cx, fixedSize.cy), param.is_convex,false,param.AutoCrop_threshold,param.noise,param.indent)));
}
if (param.is_autodiscradblank_normal || param.is_autodiscradblank_vince) {
//m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank()));

View File

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

View File

@ -9,6 +9,11 @@ public:
CImageApplyAdjustColors(void);
/*
* brightness [in]: [-255, 255]
* constrast [in]: [-128 127]
* gamma [in]: [0.1, 5.0]
*/
CImageApplyAdjustColors(int brightness, int contrast, float gamma);
virtual ~CImageApplyAdjustColors(void);

View File

@ -6,17 +6,19 @@ CImageApplyAutoCrop::CImageApplyAutoCrop()
, m_isDesaskew(false)
, m_isFillBlank(false)
, m_isConvexHull(true)
, m_isFillColor(false)
, m_threshold(40)
, m_noise(2)
, m_indent(5)
{
}
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, double threshold, int noise, int indent)
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, bool isFillColor, double threshold, int noise, int indent)
: m_isCrop(isCrop)
, m_isDesaskew(isDesaskew)
, m_isFillBlank(isFillBlank)
, m_isConvexHull(isConvex)
, m_isFillColor(isFillColor)
, m_threshold(threshold)
, m_noise(noise)
, m_indent(indent)
@ -101,7 +103,7 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
cv::Point(thre_dst.cols - 1, thre_dst.rows - 1), cv::Point(0, thre_dst.rows - 1) };
std::vector<std::vector<cv::Point>> rectEdges{ rectEdge };
cv::drawContours(thre_dst, rectEdges, 0, cv::Scalar::all(0));
cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(m_indent * 2, m_indent * 2));
cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(m_indent, m_indent));
cv::erode(thre_dst, thre_dst, element, cv::Point(-1, -1), 1);
}
hierarchy.clear();
@ -123,7 +125,7 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
contours[contours.size() - 1].push_back(cv::Point(dst.cols, -1));
contours[contours.size() - 1].push_back(cv::Point(dst.cols, dst.rows));
hg::fillPolys(dst, contours, cv::Scalar(255, 255, 255));
hg::fillPolys(dst, contours, m_isFillColor ? getBackGroudColor(pDib, rect.size.area()) : cv::Scalar(255, 255, 255));
}
pDib.release();
@ -131,17 +133,6 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
pDib = dst.clone();
else
{
#if 0
if (m_isCrop && side == 1 && !m_fixedSize.empty())
if (std::abs(m_fixedSize.width - dst.cols) > 50 || std::abs(m_fixedSize.height - dst.rows) > 50)
{
pDib = dst.clone();
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
#endif // LOG
return;
}
#endif
pDib = cv::Mat(m_fixedSize, dst.type(), m_isFillBlank ? cv::Scalar(255, 255, 255) : cv::Scalar(0, 0, 0));
cv::Rect roi;
@ -153,18 +144,7 @@ void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
for (cv::Point& p : m_maxContour)
p += roi.tl();
#if 0
std::string outrectinfo = "copy to rect x: " + std::to_string(rect.x) + "y: " + std::to_string(rect.y) + "width: " + std::to_string(rect.width) + "height: " + std::to_string(rect.height);
std::string outroiinfo = "roi x: " + std::to_string(roi.x) + "y: " + std::to_string(roi.y) + "width: " + std::to_string(roi.width) + "height: " + std::to_string(roi.height);
std::string dstsize = "dst size: width:" + std::to_string(dst.cols) + "height: " + std::to_string(dst.rows);
std::string pDibszie = "pDib size: width: " + std::to_string(pDib.cols) + "height: " + std::to_string(pDib.rows);
FileTools::write_log("imgprc.txt", dstsize);
FileTools::write_log("imgprc.txt", pDibszie);
FileTools::write_log("imgprc.txt", outrectinfo);
FileTools::write_log("imgprc.txt", outroiinfo);
#endif // LOG
dst(roi).copyTo(pDib(rect));
}
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply8");
@ -191,3 +171,58 @@ void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
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

@ -5,13 +5,13 @@
*
* 2020/4/21
* 2020/4/21 v1.0
2020/7/22 v1.1 maxContourPC端暂时无需使用
2020/10/16 v1.2 BUG
2020/10/28 v1.2.1 BUG
2020/10/28 v1.2.2 BUG
2020/10/29 v1.2.3 0°
2020/11/09 v1.2.4 false
* v1.2.4
2020/7/22 v1.1 maxContourPC端暂时无需使用
2020/10/16 v1.2 BUG
2020/10/28 v1.2.1 BUG
2020/10/28 v1.2.2 BUG
2020/10/29 v1.2.3 0°
2020/11/30 v1.3.0 稿
* v1.3.0
* ====================================================
*/
@ -32,11 +32,12 @@ public:
* isFillBlank [in]:使true为填充false为不填充
* fixedSize [in]:isCrop为false时生效fixedSize大小输出
* isConvex [in]:,true为凸多边形填充false为凹多边形填充true
* isFillColor [in]:false为白色填充true为自适应文稿底色填充false
* threshold [in]:(0, 255)40
* noise [in]:noise宽度的背景竖条纹干扰40
* indent [in]:indent像素5
*/
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, double threshold = 40, int noise = 40, int indent = 5);
CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex = true, bool isFillColor = false, double threshold = 40, int noise = 40, int indent = 5);
virtual ~CImageApplyAutoCrop();
@ -78,11 +79,17 @@ public:
void setFixedSize(cv::Size size) { m_fixedSize = size; }
private:
cv::Scalar getBackGroudColor(const cv::Mat& image, int total);
uchar getBackGroudChannelMean(const cv::Mat& gray, int total);
private:
bool m_isCrop;
bool m_isDesaskew;
bool m_isFillBlank;
bool m_isConvexHull;
bool m_isFillColor;
double m_threshold;
int m_noise;

View File

@ -36,10 +36,10 @@ void CImageApplyBWBinaray::apply(cv::Mat& pDib, int side)
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
cv::Mat integ;
int blockSize = 13;//ÁÚÓò³ß´ç
int blockSize = 25;//ÁÚÓò³ß´ç
int threshold = 1;
int low = 110;
int up = 230;
int low = 30;
int up = 235;
int halfSize = blockSize / 2;
int square_blockSize = blockSize * blockSize;
switch (m_type)

View File

@ -4,10 +4,12 @@
*
*
* 2020/4/21
* 2020/5/28 v1.1
2020/5/29 v1.2
2020/6/19 v1.3
* v1.3
* 2020/5/28 v1.1
2020/5/29 v1.2
2020/6/19 v1.3
2020/12/21 v1.3.1
2020/12/21 v1.3.2 blockSize,5125
* v1.3.2
* ====================================================
*/

View File

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

View File

@ -1,21 +1,23 @@
#ifndef IMAGE_APPLY_CHANNEL_H
#define IMAGE_APPLY_CHANNEL_H
#include "imageapply.h"
//class CImageApplyAdjustColors;
class CImageApplyChannel : public CImageApply
#include "ImageApply.h"
class CImageApplyAdjustColors;
class CImageApplyChannel : public CImageApply
{
public:
typedef enum channel
{
Red,
Green,
Blue,
Invalid,
Except_Red,
Except_Green,
Except_Blue
Red, //红色通道
Green, //绿色通道
Blue, //蓝色通道
All, //去除所有HSV色彩结构中S大于80的色彩
Invalid, //无效
Except_Red, //绿蓝色通道混合
Except_Green, //红蓝色通道混合
Except_Blue //红绿色通道混合
}Channel;
public:
@ -34,10 +36,12 @@ private:
void except_channel(const cv::Mat& src, cv::Mat& dst, int channel);
void colourless(const cv::Mat& src, cv::Mat& dst, uchar threshold = 80);
private:
Channel m_channel;
//CImageApplyAdjustColors* colors;
CImageApplyAdjustColors* colors;
};
#endif // !IMAGE_APPLY_CHANNEL_H

View File

@ -28,7 +28,7 @@ bool isColor(const cv::Mat& image)
cv::inRange(hsv_channels[2], 100, 255, range_v);
cv::Mat thre = (range_h1 | range_h2) & range_s & range_v;
return cv::sum(thre)[0] > 4;
return (cv::sum(thre)[0] / 255)> 4;
}
bool isGray(const cv::Mat& image)

View File

@ -2,11 +2,13 @@
CImageApplyConcatenation::CImageApplyConcatenation()
: m_direction(autoDirection)
, m_BG_color(0, 0, 0)
{
}
CImageApplyConcatenation::CImageApplyConcatenation(ConcatMode dir)
CImageApplyConcatenation::CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& background)
: m_direction(dir)
, m_BG_color(background)
{
}
@ -44,6 +46,7 @@ cv::Mat CImageApplyConcatenation::concat(cv::Mat &front, cv::Mat &back, ConcatMo
cv::Mat dst;
if (direction == horizontal)
{
#if 0
int top, bottom;
if (front.rows > back.rows)
{
@ -58,9 +61,21 @@ cv::Mat CImageApplyConcatenation::concat(cv::Mat &front, cv::Mat &back, ConcatMo
cv::copyMakeBorder(front, front, top, bottom, 0, 0, cv::BORDER_CONSTANT);
}
cv::hconcat(front, back, dst);
#else
int width = cv::max(front.cols, back.cols) * 2;
int height = cv::max(front.rows, back.rows);
dst = cv::Mat(height, width, front.type(), m_BG_color);
front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows)));
int offset = front.cols;
front.release();
back.copyTo(dst(cv::Rect(offset, 0, back.cols, back.rows)));
back.release();
#endif
}
else if (direction == vertical)
{
#if 0
int left, right;
if (front.cols > back.cols)
{
@ -75,6 +90,17 @@ cv::Mat CImageApplyConcatenation::concat(cv::Mat &front, cv::Mat &back, ConcatMo
cv::copyMakeBorder(front, front, 0, 0, left, right, cv::BORDER_CONSTANT);
}
cv::vconcat(front, back, dst);
#else
int width = cv::max(front.cols, back.cols);
int height = cv::max(front.rows, back.rows) * 2;
dst = cv::Mat(height, width, front.type(), m_BG_color);
front.copyTo(dst(cv::Rect(0, 0, front.cols, front.rows)));
int offset = front.rows;
front.release();
back.copyTo(dst(cv::Rect(0, offset, back.cols, back.rows)));
back.release();
#endif
}
return dst;
}

View File

@ -1,3 +1,15 @@
/*
* ====================================================
*
*
* 2020/4/21
* 2020/4/29
* v1.0 2020/4/21
* v1.1 2020/4/29 : 1m_BG_color接口2
* ====================================================
*/
#ifndef IMAGE_APPLY_CONCATENATION_H
#define IMAGE_APPLY_CONCATENATION_H
@ -17,15 +29,23 @@ public:
public:
CImageApplyConcatenation(); //ĬÈÏm_direction = autoDirection;
CImageApplyConcatenation(ConcatMode dir);
/*
* dir [in]:
* backgroud [in]:
* */
CImageApplyConcatenation(ConcatMode dir, const cv::Scalar& backgroud = cv::Scalar(0, 0, 0));
virtual ~CImageApplyConcatenation(void);
virtual void apply(std::vector<cv::Mat>& mats, bool isTwoSide);
inline ConcatMode getConcatDirection() { return m_direction; }
inline 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 void setBackGroundColor(const cv::Scalar& color) { m_BG_color = color; }
private:
@ -35,6 +55,7 @@ private:
private:
ConcatMode m_direction;
cv::Scalar m_BG_color;
};
#endif // !IMAGE_APPLY_CONCATENATION_H

View File

@ -1,10 +1,16 @@
#include "ImageApplyDiscardBlank.h"
#include "ImageProcess_Public.h"
#include "filetools.h"
CImageApplyDiscardBlank::CImageApplyDiscardBlank(int blockSize, int devTh)
: m_res(false)
, m_dSize(blockSize)
, m_devTh(devTh)
{
}
CImageApplyDiscardBlank::CImageApplyDiscardBlank()
: m_res(false)
, dSize(200)
, devTh(15, 15, 15, 15)
, m_dSize(200)
, m_devTh(15, 15, 15, 15)
{
}
@ -95,8 +101,8 @@ int CImageApplyDiscardBlank::processRectR(const cv::Mat& image, cv::RotatedRect&
void CImageApplyDiscardBlank::setIntensity(int val)
{
val = cv::max(cv::min(100, val), 1);
devTh = cv::Scalar(val, val, val, val);
val = cv::max(cv::min(100, val), 2);
m_devTh = cv::Scalar::all(val);
}
cv::Mat CImageApplyDiscardBlank::getRoiMat(const cv::Mat& image)
@ -107,12 +113,14 @@ cv::Mat CImageApplyDiscardBlank::getRoiMat(const cv::Mat& image)
double scale = 0.25;
double thresh = 50;
int blobSize = 200;
int edgeWidth = 10;
processRectR(image, rect, contour, scale, thresh, blobSize);
cv::Rect rect2 = rect.boundingRect();
cv::Rect inRect = rect2 & cv::Rect(0, 0, image.cols, image.rows);
gap = cv::max(inRect.width - rect.size.width, inRect.height - rect.size.height) + 20;
gap = cv::max(inRect.width - rect.size.width, inRect.height - rect.size.height) + 100;
inRect = cv::Rect(inRect.x + gap, inRect.y + gap, inRect.width - gap * 2, inRect.height - gap * 2);
if (inRect.width <= 0 || inRect.height <= 0)
return cv::Mat();
return image(inRect);
}
@ -135,18 +143,18 @@ void CImageApplyDiscardBlank::apply(cv::Mat& pDib, int side)
cv::Mat image = getRoiMat(pDib);
cv::Rect rect;
cv::Rect imRect(0, 0, image.cols, image.rows);
for(int i = 0; i < image.cols; i+= dSize)
for(int j = 0; j < image.rows; j+= dSize)
for(int i = 0; i < image.cols; i+= m_dSize)
for(int j = 0; j < image.rows; j+= m_dSize)
{
rect = cv::Rect(i, j,dSize, dSize) & imRect;
rect = cv::Rect(i, j, m_dSize, m_dSize) & imRect;
if(rect != cv::Rect())
{
cv::meanStdDev (image(rect) , mean, dev);
if(!scalar_LE(dev, devTh))
if(!scalar_LE(dev, m_devTh))
{
m_res = false;
#ifdef LOG
FileTools::write_log("D:\\imgprc.txt", "CImageApplyDiscardBlank blank");
FileTools::write_log("imgprc.txt", "exit CImageApplyDiscardBlank apply");
#endif // LOG
return;
}
@ -172,3 +180,30 @@ void CImageApplyDiscardBlank::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
i++;
}
}
bool CImageApplyDiscardBlank::apply(const cv::Mat& pDib, int blockSize, int devTh)
{
if (pDib.empty())
return true;
cv::Scalar mean;
cv::Scalar dev;
cv::Scalar s_devTh = cv::Scalar::all(devTh);
cv::Mat image = getRoiMat(pDib);
if (image.empty())
return false;
cv::Rect rect;
cv::Rect imRect(0, 0, image.cols, image.rows);
for (int i = 0; i < image.cols; i += blockSize)
for (int j = 0; j < image.rows; j += blockSize)
{
rect = cv::Rect(i, j, blockSize, blockSize) & imRect;
if (rect != cv::Rect())
{
cv::meanStdDev(image(rect), mean, dev);
if (!scalar_LE(dev, s_devTh))
return false;
}
}
return true;
}

View File

@ -19,6 +19,8 @@
class CImageApplyDiscardBlank : public CImageApply
{
public:
CImageApplyDiscardBlank(int blockSize, int devTh);
/*
* isnormal [in]:true标准模式false为票据复写纸模式
* */
@ -32,21 +34,23 @@ public:
void setIntensity(int val);
void setMinArea(int val) { dSize = val; }
void setMinArea(int val) { m_dSize = val; }
static bool apply(const cv::Mat& pDib, int blockSize = 200, int devTh = 15);
private:
int processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector<cv::Point>& maxContour,
static int processRectR(const cv::Mat& image, cv::RotatedRect& rotatedRect, std::vector<cv::Point>& maxContour,
double scale, double thresh, int blobAreaSize);
bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2);
static bool scalar_LE(const cv::Scalar& val1, const cv::Scalar& val2);
cv::Mat getRoiMat(const cv::Mat& pDib);
static cv::Mat getRoiMat(const cv::Mat& pDib);
private:
bool m_res;
bool isNormalDiscard;
int dSize;
cv::Scalar devTh;
bool m_isNormalDiscard;
int m_dSize;
cv::Scalar m_devTh;
};
#endif // !IMAGE_APPLY_DISCARD_BLANK_H

View File

@ -25,7 +25,11 @@ CImageOutHole::~CImageOutHole(void)
{
}
void CImageOutHole::apply(cv::Mat& pDib, int side) {}
void CImageOutHole::apply(cv::Mat& pDib, int side)
{
(void)pDib;
(void)side;
}
void CImageOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
@ -99,8 +103,8 @@ void CImageOutHole::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
//过滤非孔洞的联通区域
std::vector<std::vector<cv::Point>> hole_contours = filterPoly(contours_mask, b1_mask, mask_rotatedRect, m_edgeScale, m_borderSize);
for (int i = 0; i < hole_contours.size(); i++)
cv::drawContours(mask, hole_contours, i, cv::Scalar(127), 2);
for (size_t i = 0; i < hole_contours.size(); i++)
cv::drawContours(mask, hole_contours, static_cast<int>(i), cv::Scalar(127), 2);
for (size_t i = 0; i < hole_contours.size(); i++)
{
@ -247,5 +251,7 @@ cv::Scalar CImageOutHole::getBackGroudColor(const cv::Mat &image, const std::vec
temp[j] += ptr[j];
}
return cv::Scalar(temp[0] / pixelPoints.size(), temp[1] / pixelPoints.size(), temp[2] / pixelPoints.size());
return cv::Scalar(temp[0] / static_cast<int>(pixelPoints.size()),
temp[1] / static_cast<int>(pixelPoints.size()),
temp[2] / static_cast<int>(pixelPoints.size()));
}

View File

@ -26,7 +26,7 @@ public:
void setEdgeScale(float scale) { m_edgeScale = scale; }
void setThreshold(double threshold) { m_threshold = std::min(std::max(threshold, 1.0), 254.0); }
void setThreshold(double threshold) { m_threshold = (std::min)((std::max)(threshold, 1.0), 254.0); }
private:

View File

@ -23,37 +23,25 @@ CImageApplyResize::~CImageApplyResize(void)
void CImageApplyResize::apply(cv::Mat& pDib,int side)
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "enter CImageApplyResize apply");
#endif // LOG
if (pDib.empty())
{
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyResize apply");
#endif // LOG
return;
}
(void)side;
if (pDib.empty()) return;
if (m_type == ResizeType::RATIO)
cv::resize(pDib, pDib, cv::Size(0, 0), m_fx, m_fy);
else
cv::resize(pDib, pDib, m_dSize);
#ifdef LOG
FileTools::write_log("imgprc.txt", "exit CImageApplyResize apply");
#endif // LOG
cv::resize(pDib, pDib, m_dSize);
}
void CImageApplyResize::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
{
if (mats.empty()) return;
(void)isTwoSide;
if (!mats[0].empty()) {
apply(mats[0], 0);
}
if (isTwoSide && mats.size() > 1) {
if (!mats[1].empty())
apply(mats[1], 1);
int i = 0;
for (cv::Mat& var : mats) {
if (i != 0 && isTwoSide == false)
break;
if (!var.empty())
apply(var, 0);
i++;
}
}

View File

@ -16,6 +16,12 @@ public:
public:
CImageApplyResize();
/*
* type [in]:
* size [in]:type为DSIZE时生效
* fx [in]:type为RATIO时生效
* fy [in]:type为RATIO时生效
*/
CImageApplyResize(ResizeType type, const cv::Size& size, double fx, double fy);
virtual ~CImageApplyResize(void);

View File

@ -1,3 +1,16 @@
/*
* ====================================================
*
*
* 2020/4/21
* v1.0 2020/4/21
v1.1 2020/8/12 稿BUG
* v1.1
* ====================================================
*/
#ifndef IMAGE_APPLY_ROTATION_H
#define IMAGE_APPLY_ROTATION_H
@ -8,16 +21,22 @@ class CImageApplyRotation : public CImageApply
public:
enum class RotationType
{
Invalid,
Rotate_90_clockwise,
Rotate_180,
Rotate_90_anti_clockwise,
Invalid, //无效
Rotate_90_clockwise, //顺时针90°
Rotate_180, //180°
Rotate_90_anti_clockwise, //逆时针90°即270°
AutoTextOrientation
AutoTextOrientation //自动文稿方向识别旋转
};
public:
/*
* rotation [in]:
* isBackTransposed [in]:true为背面180°
* dpi [in]:DPIrotation为AutoTextOrientation时生效稿200DPI进行识别
* tessadataPath [in]:rotation为AutoTextOrientation时生效
*/
CImageApplyRotation(RotationType rotation, bool isBackTransposed = false, int dpi = 200, const char* tessdataPath = nullptr);
virtual ~CImageApplyRotation();

View File

@ -21,8 +21,7 @@ namespace hg
//dst
dst.clear();
int hullCount = hull->total;
for (int i = 0; i < hullCount; i++)
for (int i = 0, hullCount = hull->total; i < hullCount; i++)
dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i));
//storage
@ -297,7 +296,7 @@ namespace hg
cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY);
}
cv::Point warpPoint(cv::Point p, const cv::Mat& warp_mat)
cv::Point warpPoint(const cv::Point& p, const cv::Mat& warp_mat)
{
double src_data[3] = { static_cast<double>(p.x), static_cast<double>(p.y), 1 };
cv::Mat src(3, 1, warp_mat.type(), src_data); //warp_mat.type() == CV_64FC1
@ -306,4 +305,20 @@ namespace hg
double* ptr = reinterpret_cast<double*>(dst.data);
return cv::Point(static_cast<int>(ptr[0]), static_cast<int>(ptr[1]));
}
int distanceP2P(const cv::Point& p1, const cv::Point& p2)
{
return cv::sqrt(cv::pow(p1.x - p2.x, 2) + cv::pow(p1.y - p2.y, 2));
}
float distanceP2L(const cv::Point& p, const cv::Point& l1, const cv::Point& l2)
{
//求直线方程
int A = 0, B = 0, C = 0;
A = l1.y - l2.y;
B = l2.x - l1.x;
C = l1.x * l2.y - l1.y * l2.x;
//代入点到直线距离公式
return ((float)abs(A * p.x + B * p.y + C)) / ((float)sqrtf(A * A + B * B));
}
}

View File

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

View File

@ -70,7 +70,7 @@ using namespace std::placeholders;
TWPP_ENTRY_MFC(HuagaoDs)
static constexpr const Identity srcIdent(
Version(3, 3, Language::English, Country::China, "v3.3.2.4"),
Version(3, 3, Language::English, Country::China, "v3.3.4.1"),
DataGroup::Image,
#ifdef MAKEHUAGAO
"HUAGO",
@ -2919,6 +2919,8 @@ Twpp::Result HuagaoDs::startScan()
scanner->ResetScanner();
std::string info = "\n m_scanparam->is_autocrop :" + to_string(m_scanparam->is_autocrop);
info += "\n m_scanparam->colorenable :" + to_string(m_scanparam->automaticcolor);
info += "\n m_scanparam->colorenabletype :" + to_string(m_scanparam->automaticcolortype);
info += "\n m_scanparam->papertype :" + to_string(m_scanparam->papertype);
info += "\n m_scanparam->fillbackground :" + to_string(m_scanparam->fillbackground);
info += "\n m_scanparam->autodescrew :" + to_string(m_scanparam->autodescrew);

Binary file not shown.