更新丁维优化重构图像处理算法代码

This commit is contained in:
pm 2019-12-12 11:12:48 +08:00
parent 1c0d0c33b2
commit 72cba36185
53 changed files with 1456 additions and 1611 deletions

View File

@ -1,510 +0,0 @@
#include "StdAfx.h"
#include "AutoCrop.h"
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif // !_USE_MATH_DEFINES
#include <math.h>
#include "PublicFunc.h"
#include "filetools.h"
using namespace std;
using namespace cv;
CAutoCrop::CAutoCrop( bool bFill,bool bautoDeScrew, bool bCrop,SIZE dstsize,SIZE originSize,int tw_pixType)
:m_bAutoDescrew(bautoDeScrew), m_bCrop(bCrop), m_bFill(bFill),m_dstSize(dstsize),m_originSize(originSize),tw_pixType(tw_pixType)
{
}
CAutoCrop::~CAutoCrop()
{
}
void CAutoCrop::apply(cv::Mat & dib,int side)
{
//XdPrint("CAutoCrop");
//RotatedRect rect;
//vector<Point> contour;
//double scale = 0.25;
//double thresh = 70;
//int blobSize = 200;
//int edgeWidth =5;
//FileTools::write_log("D:\\1.txt", "Enter autocrop apply");
int flags=RC_INVALID;
if (m_bCrop)
{
flags|=RC_CUT;
}
if (m_bAutoDescrew)
{
flags|=RC_ROTATED;
}
if (m_bFill)
{
flags|=RC_BLACK_BACKGROUD;
}
if (m_bCrop||m_bAutoDescrew)
{
if (tw_pixType!=0)//TWPT_BW)
{
flags|=RC_SHARPING;
}
}
Mat mat;
rotated_and_cut(dib,mat,flags,32.0,7,5);
dib=mat;
if (!m_bCrop)
{
Size szActual,szOrg;
Rect rectCrop;
if (!m_bAutoDescrew)
{
int offsetF=72;
int offsetB=143;
rectCrop.x=(dib.cols-m_originSize.cx)/2;
rectCrop.y=side==0?offsetF:offsetB;
rectCrop.width=m_originSize.cx;
rectCrop.height=m_originSize.cy;
}
else
{
rectCrop.x=(dib.cols-m_originSize.cx)/2;
rectCrop.y=(dib.rows-m_originSize.cy)/2;
rectCrop.width=m_originSize.cx;
rectCrop.height=m_originSize.cy;
}
Rect rectImage(0, 0, dib.cols, dib.rows);
dib = dib(rectCrop);
}
//FileTools::write_log("D:\\1.txt", "Exit autocrop apply");
}
static int i=0;
void CAutoCrop::setFill(bool val)
{
m_bFill = val;
}
bool CAutoCrop::getFill()
{
return m_bFill;
}
void CAutoCrop::setCrop(bool val)
{
m_bCrop = val;
}
bool CAutoCrop::getCrop()
{
return m_bCrop;
}
void CAutoCrop::sharpen(Mat& mat)
{
float kernel_data[] = { -0.1f, 0, 0, 0, -0.1f, 0, 0, 0, 0, 0, 0, 0, 1.5f, 0, 0, 0, 0, 0, 0, 0, -0.1f, 0, 0, 0, -0.1f };
Mat kernel(5, 5, CV_32FC1, kernel_data);
filter2D(mat, mat, mat.depth(), kernel);
}
cv::Point2f CAutoCrop::warpPoint(Point p, const Mat& warp_mat)
{
double src_data[3] = {p.x, p.y, 1};
Mat src(3, 1, warp_mat.type(), src_data); //warp_mat.type() == CV_64FC1
int type = warp_mat.type();
Mat dst = warp_mat * src;
double* ptr = (double*)dst.data;
return Point(ptr[0], ptr[1]);
}
void CAutoCrop::rotated_and_cut(Mat &src,Mat& dst,int flags,double threshold,int noise,int indent)
{
if (flags == RC_INVALID)
{
dst = src.clone();
return;
}
Mat scale_mat;
Mat thre;
threshold_Mat(src, thre, threshold, noise);
vector<Vec4i> hierarchy;
vector<vector<Point>> contours;
findContours(thre, contours, hierarchy, RETR_EXTERNAL);
if (contours.size()<=0)
{
dst = src.clone();
flags=0;
return;
}
vector<Point> maxContour = getMaxContour(contours, hierarchy);
MyConvexHull(maxContour,maxContour);
//convexHull(maxContour, maxContour); //用于排序,确保轮廓随逆时针排序
thre.release();
dst.release();
RotatedRect rect = getBoundingRect(maxContour);
Rect bounding_rect = boundingRect(maxContour);
if (flags & RC_CUT)
{
if (flags & RC_ROTATED)
{
dst = Mat::zeros(rect.size, src.type());
}
else
{
dst = src(bounding_rect).clone();
}
}
else
{
if (flags & RC_BLACK_BACKGROUD)
{
dst = src.clone();
}
else
{
dst = Mat::zeros(src.size(), src.type());
}
}
Mat warp_mat;
if (flags & RC_ROTATED)
{
Point2f dstTri[3];
Point2f srcTri[4];
rect.points(srcTri);
if (flags & RC_CUT)
{
dstTri[0] = Point2f(0, rect.size.height);
dstTri[1] = Point2f(0, 0);
dstTri[2] = Point2f(rect.size.width, 0);
}
else
{
float left = (src.cols - rect.size.width) / 2;
float right = left + rect.size.width - 1;
float top = (src.rows - rect.size.height) / 2;
float bottom = top + rect.size.height - 1;
dstTri[0] = Point2f(left, bottom);
dstTri[1] = Point2f(left, top);
dstTri[2] = Point2f(right, top);
}
warp_mat = getAffineTransform(srcTri, dstTri);
Size dSize = (flags & RC_CUT) ? Size(rect.size) : dst.size();
warpAffine(src, dst, warp_mat, dSize, INTER_AREA);
}
if (flags & RC_BLACK_BACKGROUD)
{
if (flags & RC_ROTATED)
{
for (int i=0;i<maxContour.size();i++)//for (Point& item : maxContour)
{
maxContour[i] = warpPoint(maxContour[i], warp_mat);
}
}
else
{
if (flags & RC_CUT)
{
Point offset = bounding_rect.tl();
for (int i=0;i<maxContour.size();i++)//for (Point& item : maxContour)
{
maxContour[i] -= offset;
}
}
}
fillBlackBackGround(dst, maxContour, indent);
}
if (flags&RC_SHARPING)
{
sharpen(dst);
}
warp_mat.release();
}
void CAutoCrop::fillBlackBackGround(Mat& src, vector<Point> points, float indent)
{
polyIndent(points, indent);
Mat mask = Mat::zeros(src.size(), CV_8UC(src.channels()));
fillConvexPoly(mask, points, Scalar(255, 255, 255, 255));
bitwise_not(mask, mask);
//imwrite("mask1.bmp", mask);
//imwrite("mask2.bmp", src);
bitwise_or(src, mask, src);
}
void CAutoCrop::polyIndent(vector<Point>& points, float indent)
{
static Point zero(0, 0);
Point center = getBoundingRect(points).center;
for (int i=0;i<points.size();i++)// for (Point& item : points)
{
Point vec = points[i] - center;
if (vec != zero)
{
float length = vec.x * vec.x + vec.y * vec.y;
float x = sqrt((float)(vec.x * vec.x) / length) * indent;
float y = sqrt((float)(vec.y * vec.y) / length) * indent;
if (vec.x < 0)
{
x *= -1.0f;
}
if (vec.y < 0)
{
y *= -1.0f;
}
points[i].x -= x;
points[i].y -= y;
}
}
//convexHull(points, points); //用于排序,确保轮廓随逆时针排序
MyConvexHull(points,points);
}
void CAutoCrop::fill_poly(Mat& src, const vector<vector<Point>>& contours, const Scalar& color, int lineType /*= 8*/, int shift /*= 0*/, Point offset /*= Point()*/)
{
int ncontours = contours.size();
Point** ptsptr = new Point*[ncontours];
int* npts = new int[ncontours];
for (size_t i = 0; i < ncontours; i++)
{
ptsptr[i] = new Point[contours[i].size()];
npts[i] = contours[i].size();
for (size_t j = 0; j < npts[i]; j++)
{
ptsptr[i][j] = contours[i][j];
}
}
fillPoly(src, (const Point**)ptsptr, (const int*)npts, ncontours, color, lineType, shift, offset);
for (size_t i = 0; i < ncontours; i++)
{
delete[] ptsptr[i];
}
delete[] ptsptr;
delete[] npts;
}
cv::RotatedRect CAutoCrop::getBoundingRect(const vector<Point>& contour)
{
if (contour.empty())
{
return RotatedRect();//return {};
}
RotatedRect rect = minAreaRect(contour);
if (rect.angle < -45)
{
rect.angle += 90;
double temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
}
return rect;
}
vector<Point> CAutoCrop::getMaxContour(const vector<vector<Point>>& contours, const vector<Vec4i>& hierarchy)
{
vector<Point> maxContour;
if (contours.empty())
{
return maxContour;
}
if (contours.size() == 1)
{
maxContour = contours[0];
return maxContour;
}
for (int i = 0, length = hierarchy.size(); i < length; i++)
{
if (hierarchy[i][3] == -1)
{
for(int j=0;j<contours[i].size();j++)//for (const auto &item : contours[i])
{
maxContour.push_back(contours[i][j]);
}
}
}
return maxContour;
}
void CAutoCrop::findContours(const Mat& src, vector<vector<Point>>& contours, vector<Vec4i>& hierarchy, int retr /*= RETR_LIST*/, int method /*= CHAIN_APPROX_SIMPLE*/, Point offset /*= Point(0, 0)*/)
{
CvMat c_image = src;
MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
if (!_ccontours)
{
contours.clear();
return;
}
Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
int total = (int)all_contours.size();
contours.resize(total);
SeqIterator<CvSeq*> it = all_contours.begin();
for (int i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
((CvContour*)c)->color = (int)i;
int count = (int)c->total;
int* data = new int[count * 2];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
{
contours[i].push_back(Point(data[j * 2], data[j * 2 + 1]));
}
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (int i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? ((CvContour*)c->h_next)->color : -1;
int h_prev = c->h_prev ? ((CvContour*)c->h_prev)->color : -1;
int v_next = c->v_next ? ((CvContour*)c->v_next)->color : -1;
int v_prev = c->v_prev ? ((CvContour*)c->v_prev)->color : -1;
hierarchy[i] = Vec4i(h_next, h_prev, v_next, v_prev);
}
cvClearMemStorage(storage);
}
void CAutoCrop::threshold_Mat(const Mat& src, Mat& dst, double thre, int noise)
{
if (src.channels() == 3)
{
Mat gray = transforColor(src);
threshold(gray, dst, thre, 255, THRESH_BINARY);
Mat element = getStructuringElement(MORPH_RECT, Size(noise, noise));
morphologyEx(dst, dst, MORPH_ERODE, element);
#if 0
imwrite("gray.bmp", gray);
imwrite("thre.bmp", dst);
#endif
gray.release();
}
else
{
threshold(src, dst, thre, 255, THRESH_BINARY);
Mat element=getStructuringElement(MORPH_RECT,Size(noise,noise));
morphologyEx(dst,dst,MORPH_ERODE,element);
}
}
cv::Mat CAutoCrop::transforColor(const Mat& src)
{
if (src.channels() == 1)
{
return src.clone();
}
Mat channels[3];
split(src, channels);
Mat temp, dst;
bitwise_or(channels[0], channels[1], temp);
bitwise_or(channels[2], temp, dst);
temp.release();
//for(Mat& index : channels)
//{
// index.release();
//}
for (int i=0;i < 3;i++)
{
channels[i].release();
}
return dst;
}
void CAutoCrop::MyConvexHull(const vector<Point>& src, vector<Point>& dst, bool clockwise /*= false*/)
{
CvMemStorage* storage = cvCreateMemStorage(0); //申请内存空间,用于存放源数据和结果数据
CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseq作为storage的迭代器
//填充源数据
for (size_t i=0;i<src.size();i++)
{
CvPoint p;
p.x = src[i].x;
p.y = src[i].y;
cvSeqPush(ptseq, &p);
}
//for (const Point& item : src)
//{
// CvPoint p;
// p.x = item.x;
// p.y = item.y;
// cvSeqPush(ptseq, &p);
//}
//凸多边形计算得到结果数据的迭代器hull结果数据依然保存在storage分配的内存空间中
CvSeq* hull = cvConvexHull2(ptseq, 0, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0);
//填充结果数据到dst中
dst.clear();
int hullCount = hull->total;
for (size_t i = 0; i < hullCount; i++)
{
dst.push_back(Point(**CV_GET_SEQ_ELEM(CvPoint*, hull, i)));
}
//释放storage
//cvClearMemStorage(storage);
cvReleaseMemStorage(&storage);
}
vector<Point> getMaxContour(const vector<vector<Point>>& contours, const vector<Vec4i>& hierarchy)
{
vector<Point> maxContour;
if (contours.empty())
{
return maxContour;
}
if (contours.size() == 1)
{
maxContour = contours[0];
return maxContour;
}
for (int i = 0, length = hierarchy.size(); i < length; i++)
{
if (hierarchy[i][3] == -1)
{
for(int j=0;j<contours[i].size();j++)//for (const auto &item : contours[i])
{
maxContour.push_back(contours[i][j]);
}
}
}
return maxContour;
}

View File

@ -1,48 +0,0 @@
#pragma once
#include "ImageApply.h"
class CAutoCrop : public CImageApply
{
public:
CAutoCrop( bool bFill = true,bool bautoDeScrew = true,bool bCrop = true,SIZE dstsize = CSize(0, 0),SIZE originsize=CSize(0,0),int tw_pixType=2);
virtual ~CAutoCrop();
void apply(cv::Mat& dib,int side);
void setFill(bool val);
bool getFill();
void setCrop(bool val);
bool getCrop();
private:
enum RC_TYPE {
RC_INVALID = 0x0,
RC_ROTATED = 0x1,
RC_CUT = 0x2,
RC_BLACK_BACKGROUD = 0x4,
RC_SHARPING = 0x8
};
void sharpen(cv::Mat& Mat);
cv::Point2f warpPoint(cv::Point p, const cv::Mat& warp_Mat);
void rotated_and_cut(cv::Mat &src, cv::Mat& dst,int flags,double threshold,int noise,int indent);
void fillBlackBackGround(cv::Mat& src, std::vector<cv::Point> points, float indent);
void polyIndent(std::vector<cv::Point>& points, float indent);
void fill_poly(cv::Mat& src, const std::vector<std::vector<cv::Point>>& contours, const cv::Scalar& color, int lineType = 8, int shift = 0, cv::Point offset = cv::Point());
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);
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));
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre, int noise);
cv::Mat transforColor(const cv::Mat& src);
void MyConvexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise = false);
bool m_bCrop;
bool m_bFill;
bool m_bAutoDescrew;
SIZE m_dstSize;
SIZE m_originSize;
int tw_pixType;
};

View File

@ -48,12 +48,7 @@
#include <fcntl.h>
#include "scn_config.h"
#include "PublicFunc.h"
#include "AutoCrop.h"
#include "ImageAdjustColors.h"
#include "ImageChannel.h"
#include "ImageApplyResize.h"
#include "ImageRotation.h"
#include "ImageProcDiscardBlank.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "filetools.h"
#include "hugaotwainds.h"
#include "GScanO200.h"

View File

@ -1,213 +0,0 @@
#include "StdAfx.h"
#include "ImageAdjustColors.h"
CImageAdjustColors::CImageAdjustColors(void)
{
lut.create(1, 256, CV_8UC1);
setAdjustColors(0, 0, 1.0);
}
CImageAdjustColors::CImageAdjustColors(float fBrightness, float fContrast, float fGamma)
{
lut.create(1, 256, CV_8UC1);
setAdjustColors(fBrightness, fContrast, fGamma);
}
CImageAdjustColors::~CImageAdjustColors(void)
{
}
void CImageAdjustColors::apply(cv::Mat& pDib,int side)
{
if (m_fBrightness != 0|| m_fContrast != 0|| m_fGamma != 1.0)
{
//FileTools::write_log("D:\\1.txt", "Enter CImageAdjustColors apply");
cv::LUT(pDib, lut, pDib);
//FileTools::write_log("D:\\1.txt", "Exit CImageAdjustColors apply");
}
}
void CImageAdjustColors::setAdjustColors(float fBrightness, float fContrast, float fGamma)
{
m_fBrightness = fBrightness;
m_fContrast = getRealContrast(fContrast);
m_fGamma = fGamma;
updata();
}
int CImageAdjustColors::getContrast()
{
return m_fContrast;
}
int CImageAdjustColors::getBrightness()
{
return m_fBrightness;
}
double CImageAdjustColors::getGamma()
{
return m_fGamma;
}
void CImageAdjustColors::setContrast(int contrast)
{
m_fContrast = cv::max(-127, cv::min(contrast, 127));
updata();
}
void CImageAdjustColors::setBrightness(int brightness)
{
m_fBrightness = cv::max(-255, cv::min(brightness, 255));
updata();
}
void CImageAdjustColors::setGamma(double gamma)
{
m_fGamma = cv::max(0.1, cv::min(gamma, 5.0));
updata();
}
void CImageAdjustColors::MapToMap(byte* mapsIn, byte* mapsOut)
{
for (int i = 0; i < 256; i++)
{
mapsOut[i] = mapsIn[mapsOut[i]];
}
}
float CImageAdjustColors::getRealContrast(float twContrast)
{
float ret=0.0;
if (twContrast<=-1000.0)
{
ret=-36.0;
}
else if(twContrast>-1000.0&&twContrast<=-666.0)
{
ret=-24.0;
}
else if(twContrast>-666.0&&twContrast<=-333.0)
{
ret=-12.0;
}
else if (twContrast>= 333 && twContrast < 666)
{
ret=12.0;
}
else if (twContrast >= 666 && twContrast < 1000)
{
ret=24.0;
}
else if (twContrast >= 1000)
{
ret=36.0;
}
return ret;
}
void CImageAdjustColors::CalculateMap(Range in, Range out, unsigned char* map)
{
double k = 0, b = 0;
if (in.getMax() != in.getMin())
{
k = (double)(out.getMax() - out.getMin()) / (double)(in.getMax() - in.getMin());
b = (double)(out.getMin()) - k * in.getMin();
}
for (int i = 0; i < 256; i++)
{
byte v = (byte)i;
if (v >= in.getMax())
v = (byte)out.getMax();
else if (v <= in.getMin())
v = (byte)out.getMin();
else
v = (byte)(k * v + b);
map[i] = v;
}
}
void CImageAdjustColors::updata()
{
Range inIR;
Range OutIR;
byte maps[256];
byte _maps[256];
for (int i = 0; i < 256; i++)
{
_maps[i] = maps[i] = (byte)i;
}
//if (m_fBrightness > 0)
//{
// inIR = Range(0, (int)(255 - m_fBrightness));
// OutIR = Range((int)m_fBrightness, 255);
//}
//else
//{
// inIR = Range((int)-m_fBrightness, 255);
// OutIR = Range(0, (int)(255 + m_fBrightness));
//}
//CalculateMap(inIR, OutIR, maps);
//MapToMap(maps, _maps);
//if (m_fContrast > 0)
//{
// inIR = Range(0, (int)(255 - m_fContrast));
// OutIR = Range((int)m_fContrast, 255);
//}
//else
//{
// inIR = Range((int)-m_fContrast, 255);
// OutIR = Range(0, (int)(255 + m_fContrast));
//}
//CalculateMap(inIR, OutIR, maps);
//MapToMap(maps, _maps);
double g = 1 / m_fGamma;
if (g != 1.0)
{
for (int i = 0; i < 256; i++)
{
maps[i] = (byte)MIN(255, (int)(pow(i / 255.0, g) * 255 + 0.5));
}
}
else
{
for (int i = 0; i < 128; i++)
{
int color = GetRangeValue(0, 127, i - (int)m_fContrast);
color = GetRangeValue(0, 255, color + (int)m_fBrightness);
maps[i] = (byte)color;
}
for (int i = 128; i < 256; i++)
{
int color = GetRangeValue(128, 255, i + (int)m_fContrast);
color = GetRangeValue(0, 255, color + (int)m_fBrightness);
maps[i] = (byte)color;
}
}
MapToMap(maps, _maps);
memcpy(lut.data, _maps, sizeof(_maps));
}
int CImageAdjustColors::GetRangeValue(int low, int up, int value)
{
if (low > up)
{
return value;
}
if (value<low)
{
return low;
}
if (value>up)
{
return up;
}
return value;
}

View File

@ -1,64 +0,0 @@
#pragma once
#include "ImageApply.h"
class CImageAdjustColors : public CImageApply
{
public:
CImageAdjustColors(void);
CImageAdjustColors(float fBrightness, float fContrast, float fGamma);
virtual ~CImageAdjustColors(void);
virtual void apply(cv::Mat& pDib,int side);
void setAdjustColors(float fBrightness, float fContrast, float fGamma);
int getContrast();
int getBrightness();
double getGamma();
void setContrast(int contrast);
void setBrightness(int brightness);
void setGamma(double gamma);
private:
class Range
{
public:
Range()
{
}
Range(int nMin, int nMax)
{
m_min = MIN(nMin, nMax);
m_max = MAX(nMin, nMax);
}
int getMin()
{
return m_min;
}
int getMax()
{
return m_max;
}
private:
int m_min;
int m_max;
};
void updata();
int GetRangeValue(int low, int up, int value);
void CalculateMap(Range in, Range out, unsigned char* map);
void MapToMap(byte* mapsIn, byte* mapsOut);
float m_fBrightness;
float m_fContrast;
float m_fGamma;
float getRealContrast(float twContrast);
cv::Mat lut;
};

View File

@ -1,37 +0,0 @@
#include "StdAfx.h"
#include "ImageApplyCrop.h"
CImageApplyCrop::CImageApplyCrop(void)
{
}
CImageApplyCrop::~CImageApplyCrop(void)
{
}
void CImageApplyCrop::apply(cv::Mat& pDib,int side)
{
pDib = pDib(cv::Rect(m_org, m_size));
}
cv::Size CImageApplyCrop::getSize()
{
return m_size;
}
cv::Point CImageApplyCrop::getOrg()
{
return m_org;
}
void CImageApplyCrop::setSize(cv::Size size)
{
m_size=size;
}
void CImageApplyCrop::setOrg(cv::Point point)
{
m_org=point;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include "imageapply.h"
class CImageApplyCrop :
public CImageApply
{
public:
CImageApplyCrop(void);
virtual ~CImageApplyCrop(void);
void apply(cv::Mat& pDib,int side);
cv::Size getSize();
cv::Point getOrg();
void setSize(cv::Size size);
void setOrg(cv::Point point);
private:
cv::Size m_size;
cv::Point m_org;
};

8
ImageApplyHeaders.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef IMAGE_APPLY_HEADER_H
#define IMAGE_APPLY_HEADER_H
#include "ImageApply.h"
#include "ImageApplyAdjustColors.h"
#endif

View File

@ -1,54 +0,0 @@
#include "StdAfx.h"
#include "ImageApplyResize.h"
#include "PublicFunc.h"
CImageApplyResize::CImageApplyResize(float orgResulution,float setResulution,bool autocut,SIZE dstsize)
:m_orgDpi(orgResulution),m_dpi(setResulution),autoCut(autocut),dstSize(dstsize)
{
}
CImageApplyResize::~CImageApplyResize(void)
{
}
void CImageApplyResize::apply(cv::Mat& pDib,int side)
{
//FileTools::write_log("D:\\1.txt", "Enter CImageApplyResize apply");
if(autoCut)
{
if (m_dpi != m_orgDpi)
{
//FileTools::write_log("D:\\1.txt", "Exit CImageApplyResize autoCut m_dpi != m_orgDpi apply");
float ratio = m_dpi / m_orgDpi;
cv::resize(pDib, pDib, cv::Size(0, 0), ratio, ratio);
//XdPrint("1");
}
}
else
{
cv::Size dst(dstSize.cx,dstSize.cy);
cv::resize(pDib,pDib,dst,0,0);
}
//FileTools::write_log("D:\\1.txt", "Exit CImageApplyResize apply");
}
float CImageApplyResize::getDpi()
{
return m_dpi;
}
void CImageApplyResize::setDpi(float dpi)
{
m_dpi = dpi;
}
float CImageApplyResize::getOrgDpi()
{
return m_orgDpi;
}
void CImageApplyResize::setOrgDpi(float dpi)
{
m_orgDpi = dpi;
}

View File

@ -1,24 +0,0 @@
#pragma once
#include "imageapply.h"
class CImageApplyResize :
public CImageApply
{
public:
CImageApplyResize(float orgResulution=0.0,float setResulution=0.0,bool autocut=false,SIZE dstsize=CSize(0,0));
virtual ~CImageApplyResize(void);
virtual void apply(cv::Mat& pDib,int side);
float getDpi();
void setDpi(float dpi);
float getOrgDpi();
void setOrgDpi(float dpi);
private:
float m_dpi;
float m_orgDpi;
SIZE dstSize;
bool autoCut;
};

View File

@ -1,48 +0,0 @@
#include "StdAfx.h"
#include "ImageBWBinaray.h"
CImageBWBinaray::CImageBWBinaray(bool needtoBW):needToBW(needtoBW)
{
}
CImageBWBinaray::~CImageBWBinaray(void)
{
}
void CImageBWBinaray::apply(cv::Mat& dib,int side)
{
if (needToBW)
{
if (dib.channels()!=1)
{
return;
}
threshold(dib,dib,128.0,255.0,CV_THRESH_BINARY);
}
}
void CImageBWBinaray::gray2binary(cv::Mat gray, unsigned char* binary){
if(gray.channels() != 1)
return;
int width = gray.cols;
int height = gray.rows;
int n_lineByte = (width + 7)/8;
int lineByte = (n_lineByte * 8 + 31)/32*4;
unsigned char * imageData = gray.data;
unsigned char temp;
for(int row = height -1 ; row >= 0 ; row--){
for(int col =0; col < width; col++ ){
int pos = col % 8;
int pix = *(imageData+ row * width + col);
temp = 1 << (7 - pos );
if( pix == 255 ){
*(binary + col /8) |= temp;
}else{
*(binary + col / 8 ) &= (~temp);
}
}
binary = binary + lineByte;
}
}

View File

@ -1,15 +0,0 @@
#pragma once
#include "ImageApply.h"
class CImageBWBinaray:public CImageApply
{
public:
CImageBWBinaray(bool needtoBW=false);
~CImageBWBinaray(void);
void apply(cv::Mat& dib,int side);
private:
void gray2binary(cv::Mat gray, unsigned char* binary);
bool needToBW;
};

View File

@ -2,7 +2,7 @@
#include "ImageMatQueue.h"
#include "PublicFunc.h"
#include "filetools.h"
#include "ImageOutHole.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "ImageMultiOutput.h"
using namespace cv;
@ -73,25 +73,33 @@ void ImageMatQueue::setparam(SFreeImage param)
scanParam = param;
m_iaList.clear();
if (param.m_bAutoDiscardBlank || param.m_bAutoDiscardBlankInvoice)
m_iaList.push_back(shared_ptr<CImageApply>(new CImageProcDiscardBlank(param.m_bAutoDiscardBlank ? true : false)));
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyDiscardBlank(param.m_bAutoDiscardBlank ? true : false)));
bool m_bAutoCrop = false;
if (param.m_HardWareParams.PaperType == 90)
m_bAutoCrop = true;
{
CSize fixedSize = papersize.GetPaperSize(param.m_HardWareParams.PaperType, 200.0f);
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAutoCrop(param.m_bAutoCrop, param.m_bFillBlackRect, param.m_bAutoDeskew, cv::Size(fixedSize.cx, fixedSize.cy))));
}
m_iaList.push_back(shared_ptr<CImageApply>(new CAutoCrop(param.m_bFillBlackRect, param.m_bAutoDeskew, param.m_bAutoCrop, papersize.GetPaperSize(param.m_HardWareParams.PaperType, param.m_fXResolution), papersize.GetPaperSize(param.m_HardWareParams.PaperType, 200.0), param.m_nPixelType)));
if (param.m_nPixelType != 0) //sharpen
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplySharpen()));
if (param.m_nFilter)
m_iaList.push_back(shared_ptr<CImageApply>(new CImageChannel(param.m_nFilter)));
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyChannel(param.m_nFilter)));
if (param.m_fBrightness != 0 || param.m_fContrast != 0 || param.m_fGamma != 1.0)
m_iaList.push_back(shared_ptr<CImageApply>(new CImageAdjustColors(param.m_fBrightness, param.m_fContrast, param.m_fGamma)));
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyAdjustColors(param.m_fBrightness, param.m_fContrast, param.m_fGamma)));
if (param.m_fXResolution != 200.0)
m_iaList.push_back(shared_ptr< CImageApply>(new CImageApplyResize(200.0, param.m_fXResolution, param.m_bAutoCrop, papersize.GetPaperSize(param.m_HardWareParams.PaperType, param.m_fXResolution))));
{
CSize dSize = papersize.GetPaperSize(param.m_HardWareParams.PaperType, param.m_fXResolution);
CImageApplyResize* apply = new CImageApplyResize();
apply->setType(CImageApplyResize::DSIZE);
apply->setDSize(cv::Size(dSize.cx, dSize.cy));
m_iaList.push_back(shared_ptr< CImageApply>(apply));
}
if (param.m_wRotation != 0 || param.m_bBackRotate180)
m_iaList.push_back(shared_ptr<CImageApply>(new CImageRotation(param.m_wRotation, param.m_bBackRotate180)));
m_iaList.push_back(shared_ptr<CImageApply>(new CImageApplyRotation(param.m_wRotation, param.m_bBackRotate180)));
}
cv::Mat ImageMatQueue::_popMat()
@ -154,16 +162,16 @@ void ImageMatQueue::proc()
// ImageOutHole().puncture(mats[0], mats[1], 50.0, scanParam.m_OutHole.OutHoleRatio / 100.0, 50);
//}
//for (int i = 0; i < mats.size(); i++) {
// if (!mats[i].empty()) {
// for (int j = 0; j < m_iaList.size(); j++) {
// if (mats[i].empty())//ÌÞ³ý¿Õ°×Ò³
// break;
for (int i = 0; i < mats.size(); i++) {
if (!mats[i].empty()) {
for (int j = 0; j < m_iaList.size(); j++) {
if (mats[i].empty())//ÌÞ³ý¿Õ°×Ò³
break;
// m_iaList[j]->apply(mats[i], i);
// }
// }
//}
m_iaList[j]->apply(mats[i], i);
}
}
}
for (int i = 0; i < mats.size(); i++) {
//if (!scanParam.m_bDuplex && i == 1) {

View File

@ -5,18 +5,12 @@
#include <opencv2\opencv.hpp>
#include "JpegBuffer.h"
#include <queue>
#include "ImageApply.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "PublicFunc.h"
#include "BlockingQueue.h"
#include <memory>
#include <atomic>
#include "PaperSize.h"
#include "AutoCrop.h"
#include "ImageAdjustColors.h"
#include "ImageApplyResize.h"
#include "ImageChannel.h"
#include "ImageProcDiscardBlank.h"
#include "ImageRotation.h"
#include <memory>
class ImageMatQueue

View File

@ -1,5 +1,5 @@
#pragma once
#include "ImageApply.h"
#include "ImageProcess/ImageApply.h"
class ImageMultiOutput
{

View File

@ -1,315 +0,0 @@
#include "StdAfx.h"
#include "ImageOutHole.h"
#include <memory>
#include <math.h>
#include "opencv2/opencv.hpp"
#include "opencv/cv.h"
#include "opencv2/core/core.hpp"
using namespace cv;
using namespace std;
ImageOutHole::ImageOutHole(void)
{
}
ImageOutHole::~ImageOutHole(void)
{
}
void ImageOutHole::puncture(Mat& front, Mat& back, double threshold, float edgeScale, double areaThreshold)
{
//二值化正反面图像
//FileTools::write_log("D:\\1.txt", "enter ImageOutHole apply");
threshold = min(max(threshold, 1.0), 254.0);
Mat front_thre = threshold_mat(front, threshold);
Mat back_thre = threshold_mat(back, threshold);
//反面二值化图像水平翻转
flip(back_thre, back_thre, 1); //1:Horizontal
//正反面图像寻边
vector<vector<Point>> contours_front, contours_back;
vector<Vec4i> b1_front, b1_back;
findContours22(front_thre.clone(), contours_front, b1_front);
findContours22(back_thre.clone(), contours_back, b1_back);
#if 0
imwrite("front_thre.bmp", front_thre);
imwrite("back_thre.bmp", back_thre);
#endif
//提取正反面图像最大轮廓
vector<Point> maxContour_front = getMaxContour(contours_front, b1_front);
vector<Point> maxContour_back = getMaxContour(contours_back, b1_back);
RotatedRect rrect_front = minAreaRect(maxContour_front); //提取正面最大轮廓的最小外接矩形
RotatedRect rrect_back = minAreaRect(maxContour_back); //提取反面最大轮廓的最小外接矩形
//提取正反面图像重叠部分区域
Rect roi_front, roi_back;
RotatedRect mask_rotatedRect;
getRoi(rrect_front, rrect_back, Size(front.cols, front.rows), roi_front, roi_back, mask_rotatedRect);
Mat roiMat_front(front_thre, roi_front); //在正面二值图像中截取重叠部分
Mat roiMat_back(back_thre, roi_back); //在反面二值图像中截取重叠部分
//正反面二值图像做或运算真正镂空区域保留0其他地方填充为255
//为了避免孔洞彻底贯穿纸边,认为绘制纸张轮廓,确保所有孔洞为封闭图形,不会与背景粘连。
#if 0
imwrite("front_thre.bmp", roiMat_front);
imwrite("back_thre.bmp", roiMat_back);
#endif
Mat mask;
bitwise_or(roiMat_front, roiMat_back, mask); //或运算,正反面二值图像重叠
vector<Point> vertices_point = getVertices(mask_rotatedRect);
polylines(mask, vertices_point, true, Scalar(255), 3); //绘制纸张矩形边缘
//二值图像重叠图像颜色取反,并提取轮廓
vector<vector<Point>> contours_mask;
vector<Vec4i> b1_mask;
bitwise_not(mask, mask); //取反
findContours22(mask.clone(), contours_mask, b1_mask); //提取重叠图像轮廓
//过滤非孔洞的联通区域
filterPoly(mask, contours_mask, mask_rotatedRect, edgeScale, areaThreshold);
//膨胀算法,增大孔洞连通区域面积
dilate(mask, mask, Mat(), Point(-1, -1), 3, BORDER_DEFAULT, Scalar(255));
vector<Point> rect_poly;
rect_poly.push_back(Point(2, 2));
rect_poly.push_back(Point(2, mask.rows - 2));
rect_poly.push_back(Point(mask.cols - 2, mask.rows - 2));
rect_poly.push_back(Point(mask.cols - 2, 2));
polylines(mask, rect_poly, true, Scalar(0), 5); //把mask边缘涂黑
#if 0
imwrite("mask.bmp", mask);
#endif
//填充正面图像孔洞
Mat mask_flip;
flip(mask, mask_flip, 1); //因为之前反面图像翻转,所以现在要再翻转回去
roi_back.x = back.cols - roi_back.width - roi_back.x; //因为之前反面图像翻转所以现在ROI也要进行相应翻转
fillPuncture(front, mask, roi_front); //正面孔洞填充
fillPuncture(back, mask_flip, roi_back); //反面孔洞填充
#if 0
imwrite("111.jpg", front);
imwrite("222.jpg", back);
#endif
//FileTools::write_log("D:\\1.txt", "Exit ImageOutHole apply");
}
cv::Mat ImageOutHole::threshold_mat(const Mat& src, double threshold)
{
Mat dst(src.rows, src.cols, CV_8UC1, 1);
if (src.channels() == 3)
{
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
cv::threshold(gray, dst, threshold, 255, THRESH_BINARY);
}
else
{
cv::threshold(src, dst, threshold, 255, THRESH_BINARY);
}
return dst;
}
void ImageOutHole::findContours22(const Mat& src, vector<vector<Point>>& contours, vector<Vec4i>& hierarchy,
int retr/* = RETR_CCOMP*/, int method/* = CHAIN_APPROX_SIMPLE*/, Point offset /*= Point(0, 0)*/)
{
CvMat c_image = src;
MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
if (!_ccontours)
{
contours.clear();
return;
}
Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
int total = (int)all_contours.size();
contours.resize(total);
SeqIterator<CvSeq*> it = all_contours.begin();
for (int i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
((CvContour*)c)->color = (int)i;
int count = (int)c->total;
int* data = new int[count * 2];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
{
contours[i].push_back(Point(data[j * 2], data[j * 2 + 1]));
}
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (int i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? ((CvContour*)c->h_next)->color : -1;
int h_prev = c->h_prev ? ((CvContour*)c->h_prev)->color : -1;
int v_next = c->v_next ? ((CvContour*)c->v_next)->color : -1;
int v_prev = c->v_prev ? ((CvContour*)c->v_prev)->color : -1;
hierarchy[i] = Vec4i(h_next, h_prev, v_next, v_prev);
}
}
vector<Point> ImageOutHole::getMaxContour(const vector<vector<Point>>& contours, const vector<Vec4i>& hierarchy, int areaThreshold /*= 20000*/)
{
vector<Point> maxContour;
for (size_t i = 0, length = hierarchy.size(); i < length; i++)
{
Vec4i h = hierarchy[i];
if (h[3] == -1)
{
if (contourArea(contours[i]) > areaThreshold)
{
maxContour = contours[i];
break;
}
}
}
return maxContour;
}
void ImageOutHole::getRoi(RotatedRect rrect_front, RotatedRect rrect_back, Size srcSize, Rect& roi_front, Rect& roi_back, RotatedRect& mask_rotatedRect)
{
Size size((rrect_front.size.width + rrect_back.size.width) / 2, (rrect_front.size.height + rrect_back.size.height) / 2);
float angle = (rrect_front.angle + rrect_back.angle) / 2;
rrect_front.size = rrect_back.size = size;
rrect_front.angle = rrect_back.angle = angle;
roi_front = rrect_front.boundingRect();
roi_back = rrect_back.boundingRect();
if (roi_front.width!=roi_back.width||roi_front.height!=roi_back.height)
{
roi_front.height=roi_back.height;
roi_front.width=roi_back.width;
}
Point offset(0, 0);
int top = min(roi_front.y, roi_back.y);
if (top < 0)
{
roi_front.y -= top;
roi_back.y -= top;
roi_front.height += top;
roi_back.height += top;
offset.y += top;
}
int left = min(roi_front.x, roi_back.x);
if (left < 0)
{
roi_front.x -= left;
roi_back.x -= left;
roi_front.width += left;
roi_back.width += left;
offset.x += left;
}
int right = max(roi_front.x + roi_front.width, roi_back.x + roi_back.width);
if (right >= srcSize.width)
{
roi_front.width -= (right - srcSize.width + 1);
roi_back.width -= (right - srcSize.width + 1);
}
int bottom = max(roi_front.y + roi_front.height, roi_back.y + roi_back.height);
if (bottom >= srcSize.height)
{
roi_front.height -= (bottom - srcSize.height + 1);
roi_back.height -= (bottom - srcSize.height + 1);
}
mask_rotatedRect.center = Point((roi_front.width + offset.x) / 2, (roi_front.height + offset.y) / 2);
mask_rotatedRect.size = size;
mask_rotatedRect.angle = angle;
}
Point ImageOutHole::rotatedPoint(Point p, Point center, double angle)
{
double cos_ = cos(angle / 180 * CV_PI);
double sin_ = sin(angle / 180 * CV_PI);
double x = (p.x - center.x) * cos_ - (p.y - center.y) * sin_ + center.x;
double y = (p.y - center.y) * cos_ + (p.x - center.x) * sin_ + center.y;
return Point(x, y);
}
vector<Point> ImageOutHole::getVertices(RotatedRect rect)
{
vector<Point> points;
Point leftTop(rect.center.x - rect.size.width / 2, rect.center.y - rect.size.height / 2);
Point leftBottom(rect.center.x - rect.size.width / 2, rect.center.y + rect.size.height / 2);
Point rightTop(rect.center.x + rect.size.width / 2, rect.center.y - rect.size.height / 2);
Point rigthBottom(rect.center.x + rect.size.width / 2, rect.center.y + rect.size.height / 2);
points.push_back(rotatedPoint(leftTop, rect.center, rect.angle));
points.push_back(rotatedPoint(leftBottom, rect.center, rect.angle));
points.push_back(rotatedPoint(rigthBottom, rect.center, rect.angle));
points.push_back(rotatedPoint(rightTop, rect.center, rect.angle));
return points;
}
void ImageOutHole::filterPoly(const Mat& mask, vector<vector<Point>>& contours, RotatedRect roi, float edgeScale, double areaThreshold)
{
edgeScale = min(0.49f, max(edgeScale, 0.0f));
RotatedRect roi2(roi.center, Size(roi.size.width * (1 - edgeScale * 2), roi.size.height * (1 - edgeScale * 2)), roi.angle);
vector<Point> vertices_roi1 = getVertices(roi);
vector<Point> vertices_roi2 = getVertices(roi2);
vector<Point> contour;
for (size_t i = 0, length = contours.size(); i < length; i++)
{
//contour = /*Mat_<Point>*/(contours[i]);
if (contourArea(contours[i]) < areaThreshold)
{
fillConvexPoly(mask, contours[i], Scalar(0));
continue;
}
for (int j = 0, count = contours[i].size(); j < count; j++)
{
Point p(contours[i][j]);
double temp1 = pointPolygonTest(vertices_roi1, p, false); //判断是否在纸张内 10-1
double temp2 = pointPolygonTest(vertices_roi2, p, false); //判断是否在边缘区域内 10-1
//如果在纸张外或者边缘内视为非孔洞填充为0
if (temp1 < 0 || temp2 > 0)
{
fillConvexPoly(mask, contours[i], Scalar(0));
break;
}
}
}
}
void ImageOutHole::fillPuncture(Mat& src, const Mat& mask, Rect roi)
{
Mat mask_temp;
if (src.channels() == 3)
{
cvtColor(mask, mask_temp, COLOR_GRAY2RGB);
}
else
{
mask_temp = mask;
}
Mat src_roi(src, roi);
bitwise_or(src_roi, mask_temp, src_roi);
}

View File

@ -1,22 +0,0 @@
#pragma once
#include "ImageApply.h"
#include <vector>
class ImageOutHole
{
public:
ImageOutHole(void);
~ImageOutHole(void);
public:
void puncture(cv::Mat& front, cv::Mat& back, double threshold, float edgeScale, double areaThreshold);
private:
cv::Mat threshold_mat(const cv::Mat& src, double threshold);
void findContours22(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr = cv::RETR_CCOMP, int method = cv::CHAIN_APPROX_SIMPLE, cv::Point offset = cv::Point(0, 0));
std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy, int areaThreshold = 20000);
void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, cv::Rect& roi_front, cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect);
cv::Point rotatedPoint(cv::Point p, cv::Point center, double angle);
std::vector<cv::Point> getVertices(cv::RotatedRect rect);
void filterPoly(const cv::Mat& mask, std::vector<std::vector<cv::Point>>& contours, cv::RotatedRect roi, float edgeScale, double areaThreshold);
void fillPuncture(cv::Mat& src, const cv::Mat& mask, cv::Rect roi);
};

View File

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

View File

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

View File

@ -0,0 +1,79 @@
#include "ImageApplyAdjustColors.h"
CImageApplyAdjustColors::CImageApplyAdjustColors(void)
: m_brightness(0)
, m_contrast(0)
, m_gamma(1.0f)
, lut(1, 256, CV_8UC1)
{
update_lutData();
}
CImageApplyAdjustColors::CImageApplyAdjustColors(int brightness, int contrast, float gamma)
: lut(1, 256, CV_8UC1)
{
setAdjustColors(brightness, contrast, gamma);
}
CImageApplyAdjustColors::~CImageApplyAdjustColors(void)
{
}
void CImageApplyAdjustColors::apply(cv::Mat& pDib,int side)
{
if (m_brightness != 0 || m_contrast != 0 || m_gamma != 1.0)
cv::LUT(pDib, lut, pDib);
}
void CImageApplyAdjustColors::setAdjustColors(int brightness, int contrast, float gamma)
{
setBrightness(brightness);
setContrast(contrast);
setGamma(gamma);
update_lutData();
}
void CImageApplyAdjustColors::setBrightness(int brightness)
{
m_brightness = cv::max(-255, cv::min(brightness, 255));
update_lutData();
}
void CImageApplyAdjustColors::setContrast(int contrast)
{
m_contrast = cv::max(-127, cv::min(contrast, 127));
update_lutData();
}
void CImageApplyAdjustColors::setGamma(float gamma)
{
m_gamma = cv::max(0.1f, cv::min(gamma, 5.0f));
update_lutData();
}
void CImageApplyAdjustColors::update_lutData()
{
unsigned char* ptr = lut.data;
if (m_gamma != 1.0f)
{
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(ptr[i] + m_brightness, 255)));
}
}
}

View File

@ -0,0 +1,46 @@
#ifndef IMAGE_APPLY_ADJUST_COLOR_H
#define IMAGE_APPLY_ADJUST_COLOR_H
#include "ImageApply.h"
class CImageApplyAdjustColors : public CImageApply
{
public:
CImageApplyAdjustColors(void);
CImageApplyAdjustColors(int brightness, int contrast, float gamma);
virtual ~CImageApplyAdjustColors(void);
virtual void apply(cv::Mat& pDib, int side);
void setAdjustColors(int brightness, int contrast, float gamma);
int getContrast() { return m_contrast; }
int getBrightness() { return m_brightness; }
double getGamma() { return m_gamma; }
void setBrightness(int brightness);
void setContrast(int contrast);
void setGamma(float gamma);
private:
void update_lutData();
private:
int m_brightness;
int m_contrast;
float m_gamma;
cv::Mat lut;
};
#endif // !IMAGE_APPLY_ADJUST_COLOR_H

View File

@ -0,0 +1,165 @@
#include "ImageApplyAutoCrop.h"
#include "ImageProcess_Public.h"
#define RE 8
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isFillBlank, bool isDesaskew, cv::Size size)
: m_isCrop(isCrop)
, m_isFillBlank(isFillBlank)
, m_isDesaskew(isDesaskew)
, m_fixedSize(size)
, m_threshold(35)
, m_noise(7)
, m_indent(5)
{
}
CImageApplyAutoCrop::~CImageApplyAutoCrop()
{
}
void CImageApplyAutoCrop::apply(cv::Mat & pDib, int side)
{
if (!m_isCrop && !m_isFillBlank && !m_isDesaskew) return;
cv::Mat src = pDib;
cv::Mat dst;
cv::Mat src_resize;
cv::resize(src, src_resize, cv::Size(src.cols / RE, src.rows / RE));
cv::Mat scale_mat;
cv::Mat thre(src_resize.size(), CV_8UC1);
hg::threshold_Mat(src_resize, thre, m_threshold);
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_noise, m_noise));
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element);
std::vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point>> contours;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
for (cv::Point& item : maxContour)
{
item.x = item.x * RE + RE / 2;
item.y = item.y * RE + RE / 2;
}
if (maxContour.size() == 0)
{
thre.release();
return;
}
thre.release();
dst.release();
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
hg::convexHull(maxContour, maxContour);
cv::Rect bounding_rect = rect.boundingRect();
if (m_isCrop)
if (m_isDesaskew)
dst = cv::Mat::zeros(cv::Size(rect.size), src.type());
else
{
cv::Rect bounding_rect_clone = bounding_rect;
bounding_rect.x = cv::max(0, bounding_rect_clone.x);
bounding_rect.y = cv::max(0, bounding_rect_clone.y);
bounding_rect.width = cv::min(src.cols, bounding_rect_clone.x + bounding_rect_clone.width) - bounding_rect.x;
bounding_rect.height = cv::min(src.rows, bounding_rect_clone.y + bounding_rect_clone.height) - bounding_rect.y;
dst = src(bounding_rect).clone();
}
else
if (m_isFillBlank)
dst = src.clone();
else
dst = cv::Mat(src.rows, src.cols, src.type());
cv::Mat warp_mat;
if (m_isDesaskew)
{
cv::Point2f dstTri[3];
cv::Point2f srcTri[4];
rect.points(srcTri);
for (cv::Point2f& p : srcTri)
p.y /= 1.5f;
if (m_isCrop)
{
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
dstTri[1] = cv::Point2f(0, 0);
dstTri[2] = cv::Point2f(rect.size.width - 1, 0);
}
else
{
float left = (src.cols - rect.size.width) / 2;
float right = left + rect.size.width - 1;
float top = (src.rows - rect.size.height) / 2;
float bottom = top + rect.size.height - 1;
dstTri[0] = cv::Point2f(left, bottom);
dstTri[1] = cv::Point2f(left, top);
dstTri[2] = cv::Point2f(right, top);
}
cv::Size dSize = m_isCrop ? cv::Size(static_cast<int>(rect.size.width),
static_cast<int>(rect.size.height)) : dst.size();
bounding_rect.width = dSize.width;
bounding_rect.height = dSize.height;
warp_mat = cv::getAffineTransform(srcTri, dstTri);
cv::warpAffine(src, dst, warp_mat, dSize);
}
if (m_isFillBlank)
{
if (m_isDesaskew)
for (cv::Point& item : maxContour)
item = hg::warpPoint(item, warp_mat);
else
{
if (m_isCrop)
{
cv::Point offset = bounding_rect.tl();
for (cv::Point& item : maxContour)
item -= offset;
}
}
hg::polyIndent(maxContour, m_indent);
hg::fillBlackBackGround(dst, maxContour);
}
if (!m_isCrop)
{
cv::Rect fixed_roi;
if (m_fixedSize.width > dst.cols)
{
fixed_roi.x = 0;
fixed_roi.width = dst.cols;
}
else
{
fixed_roi.x = (dst.cols - m_fixedSize.width) / 2;
fixed_roi.width = m_fixedSize.width;
}
if (m_fixedSize.height > dst.rows)
{
fixed_roi.y = 0;
fixed_roi.height = dst.rows;
}
else
{
fixed_roi.y = (dst.rows - m_fixedSize.height) / 2;
fixed_roi.height = m_fixedSize.height;
}
dst = dst(fixed_roi);
}
pDib.release();
pDib = dst;
}

View File

@ -0,0 +1,57 @@
#ifndef IMAGE_APPLY_AUTO_CROP_H
#define IMAGE_APPLY_AUTO_CROP_H
#include "ImageApply.h"
class CImageApplyAutoCrop : public CImageApply
{
public:
CImageApplyAutoCrop(bool isCrop,bool isFillBlank,bool isDesaskew,cv::Size size);
virtual ~CImageApplyAutoCrop();
virtual void apply(cv::Mat& pDib, int side);
bool isAutoCrop() { return m_isCrop; }
bool isFillBlank() { return m_isFillBlank; }
bool isDesaskew() { return m_isDesaskew; }
double threshold() { return m_threshold; }
int noise() { return m_noise; }
int indent() { return m_indent; }
cv::Size fixedSize() { return m_fixedSize; }
void setAutoCrop(bool enabled) { m_isCrop = enabled; }
void setFillBlank(bool enabled) { m_isFillBlank = enabled; }
void setDesaskew(bool enabled) { m_isDesaskew = enabled; }
void setThreshold(double value) { m_threshold = value; }
void setNoise(int value) { m_noise = value; }
void setIndent(int value) { m_indent = value; }
void setFixedSize(cv::Size size) { m_fixedSize = size; }
private:
bool m_isCrop;
bool m_isFillBlank;
bool m_isDesaskew;
double m_threshold;
int m_noise;
int m_indent;
cv::Size m_fixedSize;
};
#endif // !IMAGE_APPLY_AUTO_CROP_H

View File

@ -0,0 +1,40 @@
#include "ImageApplyBWBinaray.h"
CImageApplyBWBinaray::CImageApplyBWBinaray()
: m_threshold(127)
, m_type(THRESH_BINARY)
, m_blockSize(25)
, m_constant(5)
{
}
CImageApplyBWBinaray::~CImageApplyBWBinaray(void)
{
}
void CImageApplyBWBinaray::apply(cv::Mat& pDib,int side)
{
if (pDib.channels() == 3)
cv::cvtColor(pDib, pDib, cv::COLOR_BGR2GRAY);
switch (m_type)
{
case THRESH_BINARY:
cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_BINARY);
break;
case THRESH_OTSU:
cv::threshold(pDib, pDib, m_threshold, 255, CV_THRESH_OTSU);
break;
case ADAPTIVE_GAUSSIAN:
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
break;
case ADAPTIVE_MEAN:
cv::adaptiveThreshold(pDib, pDib, 255, cv::ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, m_blockSize, m_constant);
break;
case ERROR_DIFFUSION:
break;
default:
break;
}
}

View File

@ -0,0 +1,55 @@
#ifndef IMAGE_APPLY_BW_BINARAY_H
#define IMAGE_APPLY_BW_BINARAY_H
#include "ImageApply.h"
class CImageApplyBWBinaray:public CImageApply
{
public:
enum ThresholdType
{
THRESH_BINARY,
THRESH_OTSU,
ADAPTIVE_GAUSSIAN,
ADAPTIVE_MEAN,
ERROR_DIFFUSION
};
CImageApplyBWBinaray();
virtual ~CImageApplyBWBinaray(void);
virtual void apply(cv::Mat& pDib,int side);
double getThreshold() { return m_threshold; }
ThresholdType getThresholdType() { return m_type; }
int getBlockSize() { return m_blockSize; }
double getConstant() { return m_constant; }
void setThreshold(double value) { m_threshold = value; }
void setThresholdType(ThresholdType type) { m_type = type; }
void setBlockSize(int value) { m_blockSize = value; }
void setConstant(double value) { m_constant = value; }
private:
double m_threshold;
ThresholdType m_type;
int m_blockSize;
double m_constant;
};
#endif //!IMAGE_APPLY_BW_BINARAY_H

View File

@ -1,8 +1,6 @@
#include "StdAfx.h"
#include "ImageChannel.h"
using namespace cv;
#include "ImageApplyChannel.h"
CImageChannel::CImageChannel(int index)
CImageApplyChannel::CImageApplyChannel(int index)
: m_cmIndex(index)
{
colorTable=NULL;
@ -14,8 +12,7 @@ CImageChannel::CImageChannel(int index)
}
CImageChannel::~CImageChannel(void)
CImageApplyChannel::~CImageApplyChannel(void)
{
if (colorTable!=NULL)
{
@ -23,7 +20,7 @@ CImageChannel::~CImageChannel(void)
}
}
void CImageChannel::apply(cv::Mat& pDib,int side)
void CImageApplyChannel::apply(cv::Mat& pDib,int side)
{
//FileTools::write_log("D:\\1.txt", "Exit CImageChannel apply");
if (m_cmIndex>0&&m_cmIndex<4)
@ -50,18 +47,18 @@ void CImageChannel::apply(cv::Mat& pDib,int side)
//FileTools::write_log("D:\\1.txt", "Exit CImageChannel apply");
}
void CImageChannel::setCH(int channel)
void CImageApplyChannel::setCH(int channel)
{
m_cmIndex = channel;
}
int CImageChannel::getCH()
int CImageApplyChannel::getCH()
{
return m_cmIndex;
}
void CImageChannel::RGBtoHSV(double r, double g, double b, double &h, double &s, double &v)
void CImageApplyChannel::RGBtoHSV(double r, double g, double b, double &h, double &s, double &v)
{
double min, max, delta;
min = ( (r<g ? r:g) < b ) ?(r<g ? r:g):b;
@ -100,7 +97,7 @@ void CImageChannel::RGBtoHSV(double r, double g, double b, double &h, double &s
}
}
void CImageChannel::InitColorTable(short channel)
void CImageApplyChannel::InitColorTable(short channel)
{
//colorTable=new unsigned char();
colorTable=(unsigned char *)malloc(sizeof(unsigned char)*256*256*256);
@ -127,9 +124,9 @@ void CImageChannel::InitColorTable(short channel)
}
}
cv::Mat CImageChannel::colorEnhancement(cv::Mat image,short channel)
cv::Mat CImageApplyChannel::colorEnhancement(cv::Mat image,short channel)
{
Mat grayImage(image.rows,image.cols,CV_8UC1);
cv::Mat grayImage(image.rows,image.cols,CV_8UC1);
if (channel>3)
{
return grayImage;
@ -148,9 +145,9 @@ cv::Mat CImageChannel::colorEnhancement(cv::Mat image,short channel)
}
cv::Mat CImageChannel::FilterColor(cv::Mat image,short channel)
cv::Mat CImageApplyChannel::FilterColor(cv::Mat image,short channel)
{
Mat dstImage(image.rows,image.cols,CV_8UC1);
cv::Mat dstImage(image.rows,image.cols,CV_8UC1);
//int pixelSize = image.depth();
int channels = image.channels();

View File

@ -1,11 +1,13 @@
#pragma once
#ifndef IMAGE_APPLY_CHANNEL_H
#define IMAGE_APPLY_CHANNEL_H
#include "imageapply.h"
class CImageChannel :
public CImageApply
class CImageApplyChannel : public CImageApply
{
public:
CImageChannel(int index);
virtual ~CImageChannel(void);
CImageApplyChannel(int index);
virtual ~CImageApplyChannel(void);
virtual void apply(cv::Mat& pDib,int side);
void setCH(int channel);
@ -20,3 +22,4 @@ private:
unsigned char * colorTable;
};
#endif // !IMAGE_APPLY_CHANNEL_H

View File

@ -0,0 +1,18 @@
#include "ImageApplyCrop.h"
CImageApplyCrop::CImageApplyCrop(void)
{
}
CImageApplyCrop::~CImageApplyCrop(void)
{
}
void CImageApplyCrop::apply(cv::Mat& pDib,int side)
{
if (m_roi.x < 0 || m_roi.y < 0 || m_roi.br().x >= pDib.cols || m_roi.br().y >= pDib.rows || m_roi.width == 0 || m_roi.height == 0)
return;
pDib = pDib(m_roi).clone();
}

View File

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

View File

@ -1,10 +1,9 @@
#include "StdAfx.h"
#include "ImageProcDiscardBlank.h"
#include "ImageApplyDiscardBlank.h"
using namespace cv;
using namespace std;
int CImageProcDiscardBlank::ProcessRectR(Mat & image, RotatedRect & rotatedRect, vector<Point>& maxContour, double scale, double thresh, int blobAreaSize)
int CImageApplyDiscardBlank::ProcessRectR(Mat & image, RotatedRect & rotatedRect, vector<Point>& maxContour, double scale, double thresh, int blobAreaSize)
{
Mat gray;
int blockCount = 0;
@ -91,7 +90,7 @@ int CImageProcDiscardBlank::ProcessRectR(Mat & image, RotatedRect & rotatedRect,
return blockCount;
}
bool CImageProcDiscardBlank:: Scalar_LE(cv::Scalar& val1, cv::Scalar& val2)
bool CImageApplyDiscardBlank:: Scalar_LE(cv::Scalar& val1, cv::Scalar& val2)
{
for(int i = 0; i < 3; i++)
{
@ -101,28 +100,28 @@ int CImageProcDiscardBlank::ProcessRectR(Mat & image, RotatedRect & rotatedRect,
return true;
}
CImageProcDiscardBlank::CImageProcDiscardBlank(bool isnormal)
CImageApplyDiscardBlank::CImageApplyDiscardBlank(bool isnormal)
: devTh (10, 10, 10, 10), dSize(200),isNormalDiscard(isnormal)
{
}
CImageProcDiscardBlank::~CImageProcDiscardBlank(void)
CImageApplyDiscardBlank::~CImageApplyDiscardBlank(void)
{
}
void CImageProcDiscardBlank::setIntensity(int val)
void CImageApplyDiscardBlank::setIntensity(int val)
{
val = max(min(20, val), 2);
devTh = cv::Scalar(val, val, val, val);
}
void CImageProcDiscardBlank::setMinArea(int val)
void CImageApplyDiscardBlank::setMinArea(int val)
{
dSize = max(min(500, val), 100);
}
void CImageProcDiscardBlank::GetContours(const Mat& src, vector<vector<Point>>& contours, vector<Vec4i>& hierarchy, int retr /*= RETR_CCOMP*/)
void CImageApplyDiscardBlank::GetContours(const Mat& src, vector<vector<Point>>& contours, vector<Vec4i>& hierarchy, int retr /*= RETR_CCOMP*/)
{
CvMat c_image = src;
MemStorage storage(cvCreateMemStorage());
@ -166,7 +165,7 @@ void CImageProcDiscardBlank::GetContours(const Mat& src, vector<vector<Point>>&
}
}
cv::Mat CImageProcDiscardBlank::getRoiMat(cv::Mat& image)
cv::Mat CImageApplyDiscardBlank::getRoiMat(cv::Mat& image)
{
int gap = 100;
RotatedRect rect;
@ -183,7 +182,7 @@ cv::Mat CImageProcDiscardBlank::getRoiMat(cv::Mat& image)
return image(inRect);
}
void CImageProcDiscardBlank::apply(cv::Mat& pDib,int side)
void CImageApplyDiscardBlank::apply(cv::Mat& pDib,int side)
{
//FileTools::write_log("D:\\1.txt", "enter CImageProcDiscardBlank apply");
setIntensity(isNormalDiscard?8:20);

View File

@ -1,13 +1,13 @@
#pragma once
#include "ImageApply.h"
#include <math.h>
#ifndef IMAGE_APPLY_DISCARD_BLANK_H
#define IMAGE_APPLY_DISCARD_BLANK_H
class CImageProcDiscardBlank :
public CImageApply
#include "ImageApply.h"
class CImageApplyDiscardBlank : public CImageApply
{
public:
CImageProcDiscardBlank(bool isnormal=true);
virtual ~CImageProcDiscardBlank(void);
CImageApplyDiscardBlank(bool isnormal=true);
virtual ~CImageApplyDiscardBlank(void);
virtual void apply(cv::Mat& pDib,int side);
@ -27,3 +27,4 @@ private:
cv::Mat getRoiMat(cv::Mat& pDib);
};
#endif // !IMAGE_APPLY_DISCARD_BLANK_H

View File

@ -0,0 +1,18 @@
#ifndef IMAGE_APPLY_HEADER_H
#define IMAGE_APPLY_HEADER_H
#include "../stdafx.h"
#include "ImageApply.h"
#include "ImageApplyAdjustColors.h"
#include "ImageApplyAutoCrop.h"
#include "ImageApplyBWBinaray.h"
#include "ImageApplyChannel.h"
#include "ImageApplyCrop.h"
#include "ImageApplyDiscardBlank.h"
#include "ImageApplyOutHole.h"
#include "ImageApplyResize.h"
#include "ImageApplyRotation.h"
#include "ImageApplySharpen.h"
#include "ImageApplyTextOrientation.h"
#endif

View File

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

View File

@ -0,0 +1,31 @@
#ifndef IMAGE_APPLY_OUT_HOLE_H
#define IMAGE_APPLY_OUT_HOLE_H
#include "opencv2/opencv.hpp"
#include <vector>
class ImageOutHole
{
public:
ImageOutHole(void);
~ImageOutHole(void);
public:
void puncture(cv::Mat& front, cv::Mat& back, double threshold, float edgeScale, float borderSize, bool isDoubleFaces = true);
private:
void getRoi(cv::RotatedRect rrect_front, cv::RotatedRect rrect_back, cv::Size srcSize, cv::Rect& roi_front,
cv::Rect& roi_back, cv::RotatedRect& mask_rotatedRect);
std::vector<std::vector<cv::Point> > filterPoly(std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i> &m, cv::RotatedRect roi,
float edgeScale, float areaThreshold);
cv::Scalar getBackGroudColor(const cv::Mat& image, const std::vector<cv::Point> pixelPoints);
};
#endif // !IMAGE_APPLY_OUT_HOLE_H

View File

@ -0,0 +1,22 @@
#include "ImageApplyResize.h"
CImageApplyResize::CImageApplyResize()
: m_fx(1.0)
, m_fy(1.0)
, m_type(RATIO)
{
}
CImageApplyResize::~CImageApplyResize(void)
{
}
void CImageApplyResize::apply(cv::Mat& pDib,int side)
{
if (m_type == RATIO)
cv::resize(pDib, pDib, cv::Size(0, 0), m_fx, m_fy);
else
cv::resize(pDib, pDib, m_dSize);
}

View File

@ -0,0 +1,46 @@
#ifndef IMAGE_APPLY_RESIZE_H
#define IMAGE_APPLY_RESIZE_H
#include "imageapply.h"
class CImageApplyResize : public CImageApply
{
public:
enum ResizeType
{
RATIO,
DSIZE
};
public:
CImageApplyResize();
virtual ~CImageApplyResize(void);
virtual void apply(cv::Mat& pDib,int side);
double getFX() { return m_fx; }
double getFY() { return m_fy; }
cv::Size getDSize() { return m_dSize; }
ResizeType getType() { return m_type; }
void setFX(double value) { m_fx = value; }
void setFY(double value) { m_fy = value; }
void setDSize(const cv::Size& size) { m_dSize = size; }
void setType(ResizeType type) { m_type = type; }
private:
double m_fx;
double m_fy;
cv::Size m_dSize;
ResizeType m_type;
};
#endif // !IMAGE_APPLY_RESIZE_H

View File

@ -1,28 +1,26 @@
#include "StdAfx.h"
#include "ImageRotation.h"
using namespace cv;
using namespace std;
#include "ImageApplyRotation.h"
CImageRotation::CImageRotation(int index_of_orentation, bool m_bBackRotate) :m_nRotation(index_of_orentation), m_BackRotate(m_bBackRotate)
CImageApplyRotation::CImageApplyRotation(int index_of_orentation, bool m_bBackRotate)
: m_nRotation(index_of_orentation), m_BackRotate(m_bBackRotate)
{
}
CImageRotation::~CImageRotation()
CImageApplyRotation::~CImageApplyRotation()
{
}
void CImageRotation::setRotationFlip(int flip)
void CImageApplyRotation::setRotationFlip(int flip)
{
m_nRotation = flip;
}
int CImageRotation::getRotetion()
int CImageApplyRotation::getRotetion()
{
return m_nRotation;
}
void CImageRotation::apply(cv::Mat & pDib, int side)
void CImageApplyRotation::apply(cv::Mat & pDib, int side)
{
//FileTools::write_log("D:\\1.txt", "enter CImageRotation apply");
if (m_nRotation == 4)//自动文本方向识别

View File

@ -0,0 +1,34 @@
#ifndef IMAGE_APPLY_ROTATION_H
#define IMAGE_APPLY_ROTATION_H
#include "ImageApply.h"
class CImageApplyRotation : public CImageApply
{
enum RotationType
{
ROTATE_90_CLOCKWISE,
ROTATE_180,
ROTATE_90_COUNTERCLOCKWISE
};
public:
CImageApplyRotation(int index_of_orentation,bool m_bBackRotate=false);
virtual ~CImageApplyRotation();
void setRotationFlip(int flip);
int getRotetion();
// ͨ¹ý CImageApply ¼Ì³Ð
virtual void apply(cv::Mat & pDib,int side) override;
private:
int m_nRotation;
bool m_BackRotate;
int side;
};
#endif // !IMAGE_APPLY_ROTATION_H

View File

@ -0,0 +1,17 @@
#include "ImageApplySharpen.h"
CImageApplySharpen::CImageApplySharpen()
: kernel(5, 5, CV_32FC1)
{
float kernel_data[] = { -0.1f, 0, 0, 0, -0.1f, 0, 0, 0, 0, 0, 0, 0, 1.5f, 0, 0, 0, 0, 0, 0, 0, -0.1f, 0, 0, 0, -0.1f };
memcpy(kernel.data, kernel_data, sizeof(float) * 25);
}
CImageApplySharpen::~CImageApplySharpen()
{
}
void CImageApplySharpen::apply(cv::Mat & pDib, int side)
{
cv::filter2D(pDib, pDib, pDib.depth(), kernel);
}

View File

@ -0,0 +1,18 @@
#ifndef IMAGE_APPLY_SHARPEN_H
#define IMAGE_APPLY_SHARPEN_H
#include "ImageApply.h"
class CImageApplySharpen : public CImageApply
{
public:
CImageApplySharpen();
virtual ~CImageApplySharpen();
virtual void apply(cv::Mat& pDib, int side);
private:
cv::Mat kernel;
};
#endif // !IMAGE_APPLY_SHARPEN_H

View File

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

View File

@ -0,0 +1,14 @@
#ifndef IMAGE_APPLY_TEXT_ORIENTATION_H
#define IMAGE_APPLY_TEXT_ORIENTATION_H
#include "ImageApply.h"
class ImageApplyTextOrientation
{
public:
ImageApplyTextOrientation();
~ImageApplyTextOrientation();
};
#endif // !IMAGE_APPLY_TEXT_ORIENTATION_H

View File

@ -0,0 +1,289 @@
#include "ImageProcess_Public.h"
namespace hg
{
void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise)
{
CvMemStorage* storage = cvCreateMemStorage(); //
CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage
//
for (const cv::Point& item : src)
{
CvPoint p;
p.x = item.x;
p.y = item.y;
cvSeqPush(ptseq, &p);
}
//¦Ìhullstorage
CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0);
//dst
dst.clear();
int hullCount = hull->total;
for (int i = 0; i < hullCount; i++)
dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i));
//storage
cvReleaseMemStorage(&storage);
}
#define R_COLOR 255
void fillBlackBackGround(cv::Mat& src, std::vector<cv::Point> points)
{
uint index_top = 0;
uint index_bottom = 0;
for (size_t i = 0, length = points.size(); i < length; i++)
{
if (points[i].y < points[index_top].y)
index_top = i;
if (points[i].y > points[index_bottom].y)
index_bottom = i;
}
std::vector<cv::Point> edge_left;
uint temp = index_top;
while (temp != index_bottom)
{
edge_left.push_back(points[temp]);
temp = (temp + points.size() - 1) % points.size();
}
edge_left.push_back(points[index_bottom]);
std::vector<cv::Point> edge_right;
temp = index_top;
while (temp != index_bottom)
{
edge_right.push_back(points[temp]);
temp = (temp + points.size() + 1) % points.size();
}
edge_right.push_back(points[index_bottom]);
std::vector<int> left_edge;
std::vector<int> left_ede_y;
for (size_t i = 0, length = edge_left.size() - 1; i < length; i++)
{
int y_top = edge_left[i].y;
int x_top = edge_left[i].x;
int y_bottom = edge_left[i + 1].y;
int x_bottom = edge_left[i + 1].x;
for (int y = y_top; y < y_bottom; y++)
if (y_top != y_bottom && y < src.rows)
{
left_edge.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top));
left_ede_y.push_back(y);
}
}
size_t step = src.step;
unsigned char* ptr = src.data + static_cast<uint>(edge_left[0].y) * step;
for (size_t i = 0, length = cv::min(left_edge.size(), static_cast<size_t>(src.rows)); i < length; i++)
{
int offset = left_edge[i];
if (offset < src.cols - 1 && offset > 0)
memset(ptr + i * step, R_COLOR, static_cast<size_t>((offset + 1) * src.channels()));
}
std::vector<int> right_edge;
std::vector<int> right_edge_y;
for (size_t i = 0, length = edge_right.size() - 1; i < length; i++)
{
int y_top = edge_right[i].y;
int x_top = edge_right[i].x;
int y_bottom = edge_right[i + 1].y;
int x_bottom = edge_right[i + 1].x;
for (int y = y_top; y < y_bottom; y++)
if (y_top != y_bottom && y < src.rows)
{
right_edge.push_back(((x_bottom - x_top) * y + x_top * y_bottom - x_bottom * y_top) / (y_bottom - y_top));
right_edge_y.push_back(y);
}
}
ptr = src.data + static_cast<uint>(edge_right[0].y) * step;
for (size_t i = 0, length = cv::min(right_edge.size(), static_cast<size_t>(src.rows)); i < length; i++)
{
int offset = right_edge[i];
if (offset < src.cols - 1 && offset > 0)
memset(ptr + i * step + offset * src.channels(), R_COLOR, step - static_cast<size_t>(offset * src.channels()));
}
if (edge_left[0].y > 0)
memset(src.data, R_COLOR, static_cast<size_t>(edge_left[0].y) * step);
if (edge_left.back().y < src.rows - 1)
memset(src.data + static_cast<size_t>(edge_left.back().y) * step, R_COLOR,
static_cast<size_t>(src.rows - edge_left.back().y) * step);
}
void fillPoly(cv::Mat & image, const std::vector<cv::Point>& contours, const cv::Scalar & color)
{
size_t count = contours.size();
cv::Point * points = new cv::Point[count];
for (size_t i = 0; i < count; i++)
points[i] = contours[i];
const cv::Point* pointss[1] = { points };
int npts[1];
npts[0] = static_cast<int>(count);
cv::fillPoly(image, pointss, npts, 1, color);
delete[] points;
}
void findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
{
CvMat c_image = src;
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
if (!_ccontours)
{
contours.clear();
return;
}
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
size_t total = all_contours.size();
contours.resize(total);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
int count = c->total;
int* data = new int[static_cast<size_t>(count * 2)];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
{
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
}
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
}
storage.release();
}
cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour)
{
if (contour.empty()) return {};
cv::RotatedRect rect = minAreaRect(contour);
if (rect.angle < -45)
{
rect.angle += 90;
float temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
}
return rect;
}
std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy)
{
std::vector<cv::Point> maxContour;
if (contours.size() < 1) return {};
for (size_t i = 0, length = hierarchy.size(); i < length; i++)
if (hierarchy[i][3] == -1)
for (const auto &item : contours[i])
maxContour.push_back(item);
return maxContour;
}
std::vector<cv::Point> getVertices(const cv::RotatedRect& rect)
{
cv::Point2f box[4];
rect.points(box);
std::vector<cv::Point> points;
for (int i = 0; i < 4; i++)
points.push_back(cv::Point(box[i]));
return points;
}
void polyIndent(std::vector<cv::Point>& points, float indent)
{
static cv::Point zero(0, 0);
cv::Point center = getBoundingRect(points).center;
for (cv::Point& item : points)
{
cv::Point vec = item - center;
if (vec != zero)
{
int length = vec.x * vec.x + vec.y * vec.y;
float x = cv::sqrt(static_cast<float>(vec.x * vec.x / length)) * indent;
float y = cv::sqrt(static_cast<float>(vec.y * vec.y / length)) * indent;
if (vec.x < 0) x *= -1.0f;
if (vec.y < 0) y *= -1.0f;
item.x -= static_cast<int>(x);
item.y -= static_cast<int>(y);
}
}
hg::convexHull(points, points);
}
cv::Mat transforColor(const cv::Mat& src)
{
if (src.channels() == 1) return src.clone();
std::vector<cv::Mat> channels(3);
cv::split(src, channels);
cv::Mat temp, dst;
bitwise_or(channels[0], channels[1], temp);
bitwise_or(channels[2], temp, dst);
temp.release();
for (cv::Mat& index : channels)
index.release();
return dst;
}
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
{
if (src.channels() == 3)
{
#if 0
if (cl_res.context)
transforColor_threshold_opencl(src, dst, static_cast<uchar>(thre));
else
#endif
{
cv::Mat gray = transforColor(src);
cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY);
gray.release();
}
}
else
cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY);
}
cv::Point warpPoint(cv::Point p, const cv::Mat& warp_mat)
{
double src_data[3] = { static_cast<double>(p.x), static_cast<double>(p.y), 1 };
cv::Mat src(3, 1, warp_mat.type(), src_data); //warp_mat.type() == CV_64FC1
cv::Mat dst = warp_mat * src;
double* ptr = reinterpret_cast<double*>(dst.data);
return cv::Point(static_cast<int>(ptr[0]), static_cast<int>(ptr[1]));
}
}

View File

@ -0,0 +1,33 @@
#ifndef IMAGE_PROCESS_PUBLIC_H
#define IMAGE_PROCESS_PUBLIC_H
#include "opencv2/opencv.hpp"
#include <vector>
namespace hg
{
void convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise = false);
void fillBlackBackGround(cv::Mat& src, std::vector<cv::Point> points);
void fillPoly(cv::Mat& image, const std::vector<cv::Point>& contours, const cv::Scalar& color);
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);
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);
void polyIndent(std::vector<cv::Point>& points, float indent);
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre);
cv::Mat transforColor(const cv::Mat& src);
cv::Point warpPoint(cv::Point p, const cv::Mat& warp_mat);
}
#endif // !IMAGE_PROCESS_C_H

View File

@ -1,20 +0,0 @@
#pragma once
#include "ImageApply.h"
class CImageRotation :
public CImageApply
{
public:
CImageRotation(int index_of_orentation,bool m_bBackRotate=false);
virtual ~CImageRotation();
void setRotationFlip(int flip);
int getRotetion();
// ͨ¹ý CImageApply ¼Ì³Ð
virtual void apply(cv::Mat & pDib,int side) override;
private:
int m_nRotation;
bool m_BackRotate;
int side;
};

View File

@ -1,24 +0,0 @@
#include "StdAfx.h"
#include "TextDirection.h"
CTextDirection::CTextDirection(void)
{
}
CTextDirection::~CTextDirection(void)
{
}
void CTextDirection::applyInPlace(cv::Mat& pDib)
{
}
bool CTextDirection::getResult()
{
return m_res;
}

View File

@ -1,17 +0,0 @@
#pragma once
#include "ImageApply.h"
class CTextDirection :
public CImageApply
{
public:
CTextDirection(void);
virtual ~CTextDirection(void);
virtual void applyInPlace(cv::Mat& pDib);
bool getResult();
private:
bool m_res;
};

View File

@ -74,4 +74,5 @@ void config_new::set_unused_default_value(void)
ms.v_setting = 0;
ms.speed_set_enable = 0;
ms.key_staple_enable = 0;
ms.scan_busy_motor_stop = 1;
}

View File

@ -97,9 +97,10 @@ typedef union Motor_Setting {
unsigned int iic_config : 1;
unsigned int v_setting : 2;
unsigned int speed_set_enable : 1;
unsigned int scan_busy_motor_stop : 1;
unsigned int papar_type : 4;
unsigned int color_model : 1;
unsigned int reserve : 3;
unsigned int reserve : 2;
};
} MotorSetting;

View File

@ -5,7 +5,7 @@
#include <map>
#include "twainEx.h"
#include "jpeglib.h"
#include "ImageApply.h"
#include "ImageProcess/ImageApplyHeaders.h"
#include "hugaotwainds.h"
#include "filetools.h"
#include "UsbScanEx.h"

View File

@ -23,7 +23,7 @@
<ProjectGuid>{F928F998-CD13-478E-8D23-5943C2B108F5}</ProjectGuid>
<Keyword>MFCDLLProj</Keyword>
<RootNamespace>hugaotwainds</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@ -213,7 +213,6 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AboutHuaGoDlg.cpp" />
<ClCompile Include="AutoCrop.cpp" />
<ClCompile Include="BasicSetting.cpp" />
<ClCompile Include="BrightSetting.cpp" />
<ClCompile Include="cJSON.cpp" />
@ -234,18 +233,48 @@
<ClCompile Include="GScanO200.cpp" />
<ClCompile Include="gscn_drv.cpp" />
<ClCompile Include="hugaotwainds.cpp" />
<ClCompile Include="ImageAdjustColors.cpp" />
<ClCompile Include="ImageApply.cpp" />
<ClCompile Include="ImageApplyCrop.cpp" />
<ClCompile Include="ImageApplyResize.cpp" />
<ClCompile Include="ImageBWBinaray.cpp" />
<ClCompile Include="ImageChannel.cpp" />
<ClCompile Include="ImageMatQueue.cpp" />
<ClCompile Include="ImageMultiOutput.cpp" />
<ClCompile Include="ImageOutHole.cpp" />
<ClCompile Include="ImageProcDiscardBlank.cpp" />
<ClCompile Include="ImageProcess.cpp" />
<ClCompile Include="ImageRotation.cpp" />
<ClCompile Include="ImageProcess\ImageApply.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyAdjustColors.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyAutoCrop.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyBWBinaray.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyChannel.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyCrop.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyDiscardBlank.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyOutHole.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyResize.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyRotation.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplySharpen.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyTextOrientation.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageProcess\ImageProcess_Public.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ImageTranferBW.cpp" />
<ClCompile Include="ImageTranferMat.cpp" />
<ClCompile Include="IndicatorDlg.cpp" />
@ -264,7 +293,6 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="SupperScanImageMTF.cpp" />
<ClCompile Include="TextDirection.cpp" />
<ClCompile Include="TWAINContainer.cpp" />
<ClCompile Include="TWAINContainerBool.cpp" />
<ClCompile Include="TWAINContainerFix32.cpp" />
@ -284,7 +312,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="AboutHuaGoDlg.h" />
<ClInclude Include="AutoCrop.h" />
<ClInclude Include="BasicSetting.h" />
<ClInclude Include="BrightSetting.h" />
<ClInclude Include="cJSON.h" />
@ -309,18 +336,23 @@
<ClInclude Include="hugaotwainds.h" />
<ClInclude Include="IConfig.h" />
<ClInclude Include="IGDevice.h" />
<ClInclude Include="ImageAdjustColors.h" />
<ClInclude Include="ImageApply.h" />
<ClInclude Include="ImageApplyCrop.h" />
<ClInclude Include="ImageApplyResize.h" />
<ClInclude Include="ImageBWBinaray.h" />
<ClInclude Include="ImageChannel.h" />
<ClInclude Include="ImageMatQueue.h" />
<ClInclude Include="ImageMultiOutput.h" />
<ClInclude Include="ImageOutHole.h" />
<ClInclude Include="ImageProcDiscardBlank.h" />
<ClInclude Include="ImageProcess.h" />
<ClInclude Include="ImageRotation.h" />
<ClInclude Include="ImageProcess\ImageApply.h" />
<ClInclude Include="ImageProcess\ImageApplyAdjustColors.h" />
<ClInclude Include="ImageProcess\ImageApplyAutoCrop.h" />
<ClInclude Include="ImageProcess\ImageApplyBWBinaray.h" />
<ClInclude Include="ImageProcess\ImageApplyChannel.h" />
<ClInclude Include="ImageProcess\ImageApplyCrop.h" />
<ClInclude Include="ImageProcess\ImageApplyDiscardBlank.h" />
<ClInclude Include="ImageProcess\ImageApplyHeaders.h" />
<ClInclude Include="ImageProcess\ImageApplyOutHole.h" />
<ClInclude Include="ImageProcess\ImageApplyResize.h" />
<ClInclude Include="ImageProcess\ImageApplyRotation.h" />
<ClInclude Include="ImageProcess\ImageApplySharpen.h" />
<ClInclude Include="ImageProcess\ImageApplyTextOrientation.h" />
<ClInclude Include="ImageProcess\ImageProcess_Public.h" />
<ClInclude Include="ImageTranferBW.h" />
<ClInclude Include="ImageTranferMat.h" />
<ClInclude Include="ImageTransfer.h" />
@ -341,7 +373,6 @@
<ClInclude Include="StopWatch.h" />
<ClInclude Include="SupperScanImageMTF.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TextDirection.h" />
<ClInclude Include="TWAINContainer.h" />
<ClInclude Include="TWAINContainerBool.h" />
<ClInclude Include="TWAINContainerFix32.h" />

View File

@ -117,42 +117,12 @@
<ClCompile Include="JsonConfig.cpp">
<Filter>公共库</Filter>
</ClCompile>
<ClCompile Include="ImageProcDiscardBlank.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageAdjustColors.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageApply.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageApplyCrop.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageApplyResize.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageChannel.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="SupperScanImageMTF.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="TextDirection.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="AboutHuaGoDlg.cpp">
<Filter>UI</Filter>
</ClCompile>
<ClCompile Include="AutoCrop.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageRotation.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageBWBinaray.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="CTwainMutex.cpp">
<Filter>代码文件</Filter>
</ClCompile>
@ -165,9 +135,6 @@
<ClCompile Include="jpeglib.cpp">
<Filter>USB通信</Filter>
</ClCompile>
<ClCompile Include="ImageOutHole.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="cJSON.cpp">
<Filter>代码文件</Filter>
</ClCompile>
@ -198,12 +165,51 @@
<ClCompile Include="UsbScanEx.cpp">
<Filter>USB通信</Filter>
</ClCompile>
<ClCompile Include="ImageMultiOutput.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="config_new.cpp">
<Filter>代码文件</Filter>
</ClCompile>
<ClCompile Include="ImageMultiOutput.cpp">
<Filter>代码文件</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApply.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyAdjustColors.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyAutoCrop.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyBWBinaray.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyChannel.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyCrop.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyDiscardBlank.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyOutHole.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyResize.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyRotation.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplyTextOrientation.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageProcess_Public.cpp">
<Filter>图像处理</Filter>
</ClCompile>
<ClCompile Include="ImageProcess\ImageApplySharpen.cpp">
<Filter>图像处理</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="hugaotwainds.def">
@ -322,45 +328,15 @@
<ClInclude Include="JsonConfig.h">
<Filter>公共库</Filter>
</ClInclude>
<ClInclude Include="ImageAdjustColors.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcDiscardBlank.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageApply.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageApplyCrop.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageApplyResize.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageChannel.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="SupperScanImageMTF.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="TextDirection.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="twainEx.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="AboutHuaGoDlg.h">
<Filter>UI</Filter>
</ClInclude>
<ClInclude Include="AutoCrop.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageRotation.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageBWBinaray.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="CTwainMutex.h">
<Filter>头文件</Filter>
</ClInclude>
@ -376,9 +352,6 @@
<ClInclude Include="filetools.h">
<Filter>公共库</Filter>
</ClInclude>
<ClInclude Include="ImageOutHole.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageMultiOutput.h">
<Filter>头文件</Filter>
</ClInclude>
@ -430,6 +403,48 @@
<ClInclude Include="config_new.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApply.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyAdjustColors.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyAutoCrop.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyBWBinaray.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyChannel.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyCrop.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyDiscardBlank.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyOutHole.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyResize.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyRotation.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyTextOrientation.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageProcess_Public.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplyHeaders.h">
<Filter>图像处理</Filter>
</ClInclude>
<ClInclude Include="ImageProcess\ImageApplySharpen.h">
<Filter>图像处理</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="hugaotwainds.rc">

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommand>C:\Program Files\XnView\xnview.exe</LocalDebuggerCommand>
<LocalDebuggerCommand>E:\软件安装包\xnviewer\xnviewer\xnview.exe</LocalDebuggerCommand>
<LocalDebuggerWorkingDirectory>C:\Windows\twain_32\huagoscan</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>