twain2/hugaotwainds/AutoCrop.cpp

382 lines
8.9 KiB
C++

#include "StdAfx.h"
#include "AutoCrop.h"
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES
#endif // !_USE_MATH_DEFINES
#include <math.h>
#include "PublicFunc.h"
CAutoCrop::CAutoCrop( bool bFill,bool bautoDeScrew, bool bCrop,SIZE dstsize,SIZE originSize)
:m_bAutoDescrew(bautoDeScrew), m_bCrop(bCrop), m_bFill(bFill),m_dstSize(dstsize),m_originSize(originSize)
{
}
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;
ProcessRect(dib, rect, contour, scale, thresh, blobSize);
//XdPrint("Begin m_bFill \n");
if (m_bFill)
{
fillBlack(dib, contour,edgeWidth);
//XdPrint("m_bFill \n");
}
if (m_bAutoDescrew)//自动纠偏
{
//XdPrint("m_bAutoDescrew strart\n");
RotateImage(dib,rect,m_bCrop,m_bFill);//自动纠偏和自动裁切或自动纠偏 不自动裁切
//XdPrint("m_bAutoDescrew end\n");
}
if (m_bCrop&&!m_bAutoDescrew)//自动裁切 但不纠偏
{
vector<Point> vec(contour);
Rect rectOut=boundingRect(vec);
Mat temp=dib(rectOut);
dib=temp.clone();
temp.release();
}
if (!m_bCrop)
{
dib=FixedCut(dib,side);
//XdPrint("m_bCrop \n");
}
}
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;
}
Point2f CAutoCrop::RotateP2P(Point2f p, Point2f center, double Angle)
{
double h = Angle * M_PI / 180;
float x = (p.x - center.x) * (float)cos(h) - (p.y - center.y) * (float)sin(h) + center.x;
float y = (p.y - center.y) * (float)cos(h) + (p.x - center.x) * (float)sin(h) + center.y;
return Point2f(x, y);
}
void CAutoCrop::RotateImage(Mat & image, RotatedRect rotatedRect, bool bCrop,bool fillBlack)
{
Point2f center(image.cols / 2, image.rows / 2);
Mat rot = getRotationMatrix2D(center, rotatedRect.angle, 1);
RotatedRect rotated = RotatedRect(center, image.size(), -rotatedRect.angle);
Rect bbox = rotated.boundingRect();
Scalar sc;
if (fillBlack)
{
warpAffine(image, image, rot, bbox.size(), CV_INTER_LINEAR,0,image.channels()==3?Scalar(255,255,255):Scalar(255));//CV_INTER_NN
}
else
{
warpAffine(image, image, rot, bbox.size(), CV_INTER_LINEAR,0,Scalar(0));//CV_INTER_NN
}
if(!bCrop)
return;
Point2f box[4];
vector<Point2f > vec;
rotatedRect.points(box);
for (int i = 0; i < 4; i++)
{
box[i] = RotateP2P(box[i], center, -rotatedRect.angle);
vec.push_back(box[i]);
}
RotatedRect rec = minAreaRect(vec);
Rect roi = rec.boundingRect();
Rect rectIm(0, 0, image.cols, image.rows);
roi = roi & rectIm;
image = image(roi);
}
int CAutoCrop::ProcessRect(Mat & image, RotatedRect & rotatedRect, vector<Point>& maxContour, double scale, double thresh, int blobAreaSize)
{
Mat gray;
int blockCount = 0;
if (image.channels() == 3)
{
if (scale != 1.0f)
{
Size ResImgSiz = Size(image.cols*scale, image.rows*scale);
resize(image, gray, cv::Size(), scale, scale, 0);
cvtColor(gray, gray, CV_BGR2GRAY);
}
}
else
{
if (scale != 1.0f)
{
resize(image, gray, cv::Size(), scale, scale, 0);
}
}
Mat threshold_img;
threshold(gray, threshold_img, thresh, 255.0, CV_THRESH_BINARY);
vector<vector<Point>> contours;
vector<Vec4i> h1;
GetContours(threshold_img, contours,h1,CV_RETR_EXTERNAL);
threshold_img.release();
if (contours.size() == 0)
{
return blockCount;
}
vector<Point> list_com;
for (int i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area > blobAreaSize)
{
blockCount++;
for (int j = 0; j < contours[i].size(); j++)
{
list_com.push_back(contours[i][j]);
}
}
}
if (list_com.size() == 0)
{
return blockCount;
}
rotatedRect = minAreaRect(list_com);
rotatedRect.center.x /= (float)scale;
rotatedRect.center.y /= (float)scale;
rotatedRect.size.width /= (float)scale;
rotatedRect.size.height /= (float)scale;
if (rotatedRect.angle < -45.0f)
{
rotatedRect.angle += 90.0f;
float l_temp = rotatedRect.size.width;
rotatedRect.size.width = rotatedRect.size.height;
rotatedRect.size.height = l_temp;
}
vector<int> hull(list_com.size());
convexHull(list_com, hull);
for (int i = 0; i < hull.size(); i++)
{
Point temp = list_com[hull[i]];
int x = (int)(temp.x / scale);
int y = (int)(temp.y / scale);
maxContour.push_back(Point(x, y));
}
return blockCount;
}
void CAutoCrop::fillBlack(cv::Mat & dib, std::vector<cv::Point>& contour, int edge)
{
Mat mask(dib.rows, dib.cols, CV_8UC1);
if (contour.size() < 3)
{
return;
}
mask.setTo(255);
fillConvexPoly(mask, contour, Scalar(0));//填充轮廓构成的凸多边形
Mat dilateKer = getStructuringElement(MORPH_RECT, Size(3, 3));
dilate(mask, mask, dilateKer, Point(-1, -1), edge, BORDER_CONSTANT);//向内腐蚀灰边的宽度
//imwrite("mask1.bmp",mask);
dilateKer.release();
cv::vector<cv::vector<Point>> contours;
cv::vector<Vec4i> h1;
GetContours(mask, contours, h1,CV_RETR_LIST);//向内腐蚀后的轮廓
//XdPrint("GetContours after");
mask.release();
//vector<Point> temp=contours.at(0);
//const Point* pnt[1]={&temp[0]};
//int numofPoints=(int)temp.size();
//for (int i=0;i<contours.size();i++)
//{
// for (int j=0;j<contours[i].size();j++)
// {
// XdPrint(" X: %d Y: %d \n",contours[i][j].x,contours[i][j].y);
// }
//}
MyFillPoly(dib,contours,cv::Scalar::all(255));
}
Mat CAutoCrop::AutomaticDeskew(Mat image,int thres,float scale)
{
RotatedRect rotatedRect;
vector<Point> contour;
RotateImage(image, rotatedRect);
//XdPrint("AutomaticDeskew");
return image;
}
Mat CAutoCrop::FixedCut(Mat image,int side)
{
Size szActual;
szActual.width=m_dstSize.cx;
szActual.height=m_dstSize.cy;
Size szOrg;
szOrg.width=m_originSize.cx;
szOrg.height=m_originSize.cy;
Rect rectCrop;
rectCrop.x = (image.cols- szOrg.width) / 2 ;
rectCrop.y = 0;
rectCrop.width = szOrg.width;
rectCrop.height = szOrg.height;
Rect rectImage(0, 0, image.cols, image.rows);
if (side != 0)
{
rectCrop.y = 143; //调整反面
}else
{
rectCrop.y = 73; //调整正面
}
Size CropOrg = (rectCrop & rectImage).size ();
Mat roi = image(rectCrop);
//XdPrint("FixedCut");
return roi;
}
//void CAutoCrop::fillrect(InputOutputArray img, InputArrayOfArrays pts, const Scalar& color, int lineType, int shift, Point offset)
//{
// int i, ncontours = (int)pts.total();
// if( ncontours == 0 )
// return;
// AutoBuffer<Point*> _ptsptr(ncontours);
// AutoBuffer<int> _npts(ncontours);
// Point** ptsptr = _ptsptr.data();
// int* npts = _npts.data();
//
// for( i = 0; i < ncontours; i++ )
// {
// Mat p = pts.getMat(i);
// CV_Assert(p.checkVector(2, CV_32S) >= 0);
// ptsptr[i] = p.ptr<Point>();
// npts[i] = p.rows*p.cols*p.channels()/2;
// }
// fillPoly(img, (const Point**)ptsptr, npts, (int)ncontours, color, lineType, shift, offset);
//}
int CAutoCrop::range(int low, int up, int value)
{
if (low > up)
{
return value;
}
if (value < low)
{
return low;
}
if (value > up)
{
return up;
}
return value;
}
void CAutoCrop::GetContours(const Mat& src, vector<vector<Point>>& contours, vector<Vec4i>& hierarchy, int retr /*= RETR_CCOMP*/)
{
CvMat c_image = src;
MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = 0;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, CHAIN_APPROX_SIMPLE);
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);
}
}
void CAutoCrop::MyFillPoly(Mat& img, vector<vector<Point>> contours, const Scalar& color, int lineType, int shift, Point offset)
{
Point** ptsptr = new Point*[contours.size()];
int length1 = contours.size();
int* npts = new int[length1];
for (size_t i = 0; i < length1; i++)
{
int length2 = contours[i].size();
npts[i] = length2;
ptsptr[i] = new Point[length2];
for (size_t j = 0; j < length2; j++)
{
ptsptr[i][j] = contours[i][j];
}
}
fillPoly(img, (const Point**)ptsptr, npts, length1, color, lineType, shift, offset);
for (size_t i = 0; i < length1; i++)
{
delete[] ptsptr[i];
}
delete[] ptsptr;
delete[] npts;
}