#include "StdAfx.h" #include "AutoCrop.h" #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif // !_USE_MATH_DEFINES #include #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 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 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 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& 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> contours; vector h1; GetContours(threshold_img, contours,h1,CV_RETR_EXTERNAL); threshold_img.release(); if (contours.size() == 0) { return blockCount; } vector 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 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& 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> contours; cv::vector h1; GetContours(mask, contours, h1,CV_RETR_LIST);//向内腐蚀后的轮廓 //XdPrint("GetContours after"); mask.release(); //vector temp=contours.at(0); //const Point* pnt[1]={&temp[0]}; //int numofPoints=(int)temp.size(); //for (int i=0;i 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 _ptsptr(ncontours); // AutoBuffer _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(); // 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>& contours, vector& 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 all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); int total = (int)all_contours.size(); contours.resize(total); SeqIterator 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> 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; }