123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606 |
- #include "stdafx.h"
- #include "OnLineCardPageIdentifier.h"
- #include "OnLineCardSchemaStruct.h"
- #include "schema_struct.h"
- #include "schema_struct_auto.h"
- #include <iostream>
- #include <vector>
- #include <string>
- #include <sstream>
- #include <zxing\LuminanceSource.h>
- #include "GrayImageSource.h"
- #include <zxing\Exception.h>
- #include <zxing\qrcode\QRCodeReader.h>
- #include <zxing\qrcode\QRCodeReader.h>
- #include <zxing\BinaryBitmap.h>
- #include <zxing\common\GlobalHistogramBinarizer.h>
- #include <zxing\Binarizer.h>
- #include <zxing\qrcode\QRCodeReader.h>
- #include "schema_struct.h"
- #include <map>
- #include <..\zxinglib\zxing\ReaderException.h>
- #include "Util.h"
- #include "../lib/myqr/include/GetQRCode.h"
- #include "opencv2/opencv.hpp"
- #include <chrono>
- #include <ctime>
- #include "ParseQRInfo.h"
- /********************************************************
- * @function :
- * @brief : 红色分析判断的客户端交互接口(阶段1:实现红色像素的数量统计 阶段2:实现红色的形状判断 目前只实现阶段1
- * @input : Mat img_input; // 切割好的打分框区域 精准区域
- int cols; // 该打分框的个数
- int type; // 打分框所属(非在线模板解答0 非在线模板填空1 在线模板解答2 在线模板填空3 )
- int mutil: // 是否是组合型包含(个位+十位) 打分框
- int * a_res; // 存放结果的数组
- int len; // a_res的长度 len应该等于cols
- * @output : int ret; // 0: succ 1: faild 2: img.empty||img.error
- * @return : int ret;
- * @author : Duste 2020/03/27 10:07
- * @History :
- *********************************************************/
- __declspec(dllimport) int api_red_check_analysis(cv::Mat&img, int cols, int type, int mutil, int * arr_result, int arr_len);
- /********************************************************
- * @function :
- * @brief : DTK的定位点查找
- * @input : @见函数说明 给定图像+模板定位点位置信息,
- * @output :
- * @return : int,(0:succ) (-1:input error) (-2:img.empty||img type.error) (-3:not found)
- * @author : Duste 2020/07/02 15:33
- * @History :
- *********************************************************/
- int api_location_anchor_points(const cv::Mat&img_gray, // 输入的灰度图像
- const std::vector<cv::Rect>&vec_lcpts, // json内的定位点信息
- const cv::Size&mb_size, // json内模板图像的宽高
- std::vector<cv::Rect>&vec_tops, // 接受找到的上面三个定位点 下标访问
- std::vector<cv::Rect>&vec_bottoms, // 接受找到的下面的两个定位点 下标访问
- std::vector<int>&vec_len, // 解决不同版本内存权限问题
- int&dir, // 接受识别到的本图像的方向(0123-上下左右)
- int top_number, // 知心慧学 top_number=3或4 在线模板 top_number=3
- int need_bottom // 是否需要查找bottom定位点
- );// Vec_lcpts: json内的两页内所有的定位点的矩形信息合集
- #if _DEBUG
- #pragma comment(lib,"../lib/myqr/debug/GetQR.lib")
- #pragma comment(lib,"../Win32/Debug/client_interactive_api_d.lib")
- #else
- #pragma comment(lib,"../lib/myqr/Release/GetQR.lib")
- #pragma comment(lib,"../Win32/Release/client_interactive_api.lib")
- #endif
- using namespace cv;
- using namespace std;
- using namespace zxing;
- namespace OnLineCard{
- enum SelectType{
- //未选中
- UNSELECT,
- //不确定
- UNCERTAIN,
- //选中
- SELECTED
- };
- #define MAX_ITEM 64
- enum
- {
- JIEDATITYPE = 0,
- TIANKONGTITYPE = 1,
- };
- void SetTBLR(SchemaQuestionScore& score)
- {
- score.lt.x = score.lb.x = (int)(0.5 + score.centerx - score.width / 2.0);
- score.rt.x = score.rb.x = (int)(0.5 + score.centerx + score.width / 2.0);
- score.lt.y = score.rt.y = (int)(0.5 + score.centery - score.height / 2.0);
- score.lb.y = score.rb.y = (int)(0.5 + score.centery + score.height / 2.0);
- }
- COnLineCardPageIdentifier::COnLineCardPageIdentifier()
- {
- m_pTemplate = nullptr;
- src = NULL;
- feedDirection = ROTATE_0;
- m_strQrClass = "";
- m_bUseQr = false;
- }
- COnLineCardPageIdentifier::~COnLineCardPageIdentifier()
- {
- }
- // 识别
- int COnLineCardPageIdentifier::Identify()
- {
- try{
- int r = Identify_impl();
- if (r == identify::result::IDF_SUCCESS){
- omr_result->identified = TRUE;
- omr_result->identify_msg = "识别成功";
- return r;
- }
- }catch (std::exception &e){
- return identify::result::IDF_FAILURE;
- }
- return identify::result::IDF_CANNOT_MATCH_TEMPLATE;
- }
- void COnLineCardPageIdentifier::SetScanMode(int type)
- {
- m_scantype = type;
- }
- void COnLineCardPageIdentifier::SetUseQr(std::string strQr, bool bUse)
- {
- m_bUseQr = bUse;
- m_strQrClass = strQr;
- }
- void COnLineCardPageIdentifier::SetPaperMode(int mode)
- {
- m_paper_mode = mode;
- }
- void COnLineCardPageIdentifier::SetIdentiforMode(int subject, int mode)
- {
- m_subjectMode = subject;
- m_identiforMode = mode;
- }
- #define ROUND_SCALE(x) ((int)(x*scale+0.5))
- #define ROUND_SCALE_ARRAY(_dst,_src,count) \
- for (int i=0;i<count;i++)\
- {\
- _dst[i]=((int)(_src[i]*scale+0.5));\
- }
- void COnLineCardPageIdentifier::myscale_shema_param0(const schema_const_param& default_schema_const_param, schema_const_param& schema_param, double scale){
- schema_param.main_locate_point = default_schema_const_param.main_locate_point;
- ROUND_SCALE_ARRAY(schema_param.minw, default_schema_const_param.minw, 4);
- ROUND_SCALE_ARRAY(schema_param.maxw, default_schema_const_param.maxw, 4);
- ROUND_SCALE_ARRAY(schema_param.minh, default_schema_const_param.minh, 4);
- ROUND_SCALE_ARRAY(schema_param.maxh, default_schema_const_param.maxh, 4);
- }
- //旋转指定区域
- int COnLineCardPageIdentifier::xuanzhuan(IplImage * src0, IplImage * &dst_img, CvRect myRect)
- {
- cvSetImageROI(src0, myRect);
- IplImage* result = cvCreateImage(cvSize(myRect.width, myRect.height), src0->depth, src0->nChannels);
- cvCopy(src0, result, NULL);
- cvResetImageROI(src0);
- dst_img = cvCreateImage(cvSize(myRect.height, myRect.width), src0->depth, src0->nChannels);
- cvTranspose(result, dst_img);
- cvFlip(dst_img, NULL, 1);
- cvReleaseImage(&result);
- return identify::result::IDF_SUCCESS;
- }
- inline int get_distance(CvPoint2D32f p1, CvPoint2D32f p2){
- double dy = p2.y - p1.y;
- double dx = p2.x - p1.x;
- return static_cast<int>(sqrt(dx*dx + dy*dy));
- }
- // 纠偏后的新坐标点
- CvPoint2D32f get_new_point(CvPoint2D32f ptOld, int iWidth, int iHight, float thir)
- {
- // 转图像中心坐标系
- CvPoint2D32f ptNew, ptNew_, ptOld_;
- CvPoint2D32f ptMid = cvPoint2D32f(iWidth / 2.0, iHight / 2.0);
- ptOld_.x = ptOld.x - ptMid.x;
- ptOld_.y = -(ptOld.y - ptMid.y);
- float thetia = atan2(float(ptOld_.y), float(ptOld_.x));
- float angleOld = static_cast<int>( thetia * 180.0 / CV_PI);
- float angleNew = angleOld - thir;
- double dx = cos(angleNew*CV_PI / 180.0)*ptOld_.y / sin(angleOld*CV_PI / 180.0);
- double dy = sin(angleNew*CV_PI / 180.0)*ptOld_.y / sin(angleOld*CV_PI / 180.0);
- ptNew_.x = dx > 0 ? (dx + 0.5) : (dx - 0.5);
- ptNew_.y = dy > 0 ? (dy + 0.5) : (dy - 0.5);
- // 转回原坐标系坐标
- // 这里需要重新计算 中心点坐标(计算四个顶点后计算外接矩形再确定中心点)
- // 这里简化处理 因为只需要处理 90,180,270,等固定角度旋转
- if (90 == abs(thir) || 270 == abs(thir))
- ptMid = cvPoint2D32f(iHight / 2.0, iWidth / 2.0);
- ptNew.x = ptNew_.x + ptMid.x;
- ptNew.y = ptMid.y - ptNew_.y;
- return ptNew;
- }
- bool sort_locate_point_by_x_pt2f(const CvPoint2D32f c1, const CvPoint2D32f c2)
- {
- return c1.x < c2.x;
- }
- inline void sort_point_list(CvPoint2D32f * points_src){
- int max_y = std::max(std::max(points_src[0].y, points_src[1].y), points_src[2].y);
- vector<CvPoint2D32f> vec_one, vec_two;
- for (int i = 0; i < 3; i++)
- {
- CvPoint2D32f tmp = points_src[i];
- if (tmp.y > max_y / 2)
- vec_two.push_back(tmp);
- else
- vec_one.push_back(tmp);
- }
- std::sort(vec_one.begin(), vec_one.end(), sort_locate_point_by_x_pt2f);
- for (std::size_t i = 0; i < vec_one.size(); i++)
- points_src[i] = vec_one[i];
- points_src[vec_one.size()] = vec_two[0];
- return;
- }
- inline cv::Mat IplImageToMat(const IplImage* image, bool copyData = false)
- {
- if (!image)
- return cv::Mat();
- int imageDepth = IPL2CV_DEPTH(image->depth);
- int type = CV_MAKETYPE(imageDepth, image->nChannels);
- cv::Mat ret(image->height, image->width, type, image->imageData, image->widthStep);
- return copyData ? ret.clone() : ret;
- }
- int COnLineCardPageIdentifier::JiaoZheng_20200418_first(IplImage * src0_, IplImage * &dst_img,
- const vector<CvRect> & top_locate_point_list, const vector<CvRect> & bottom_locate_point_list, const vector<CvRect> & word_location_point_list,
- int dir)
- {
- // printf("线程:%s JiaoZheng_20200418_first1 \n", std::to_string(GetCurrentThreadId()).c_str());
- int bottom_id = 0;
- if (3 == dir)
- bottom_id = 1;
- CvPoint2D32f points_src[3] = {
- cvPoint2D32f(top_locate_point_list[0].x + top_locate_point_list[0].width / 2.0, top_locate_point_list[0].y + top_locate_point_list[0].height / 2.0),
- cvPoint2D32f(top_locate_point_list[top_locate_point_list.size() - 1].x + top_locate_point_list[top_locate_point_list.size() - 1].width / 2.0, top_locate_point_list[top_locate_point_list.size() - 1].y + top_locate_point_list[top_locate_point_list.size() - 1].height / 2.0),
- cvPoint2D32f(bottom_locate_point_list[bottom_id].x + bottom_locate_point_list[bottom_id].width / 2.0, bottom_locate_point_list[bottom_id].y + bottom_locate_point_list[bottom_id].height / 2.0)
- };
- IplImage * src0 = nullptr;
- // printf("线程:%s JiaoZheng_20200418_first2 \n", std::to_string(GetCurrentThreadId()).c_str());
- try{
- src0 = cvCloneImage(src0_);
- }
- catch (cv::Exception&e){
- // printf("线程:%s cvCloneImage %s\n", std::to_string(GetCurrentThreadId()).c_str(), e.what());
- }
- // printf("线程:%s JiaoZheng_20200418_first3 \n", std::to_string(GetCurrentThreadId()).c_str());
- // 0:上 旋转0度 1:下 旋转180度 2:左 旋转90度 3:右 旋转270度 如果不对请自行调整
- CvPoint2D32f points_src_rotate[3] = { points_src[0], points_src[1], points_src[2] };
- // printf("线程:%s JiaoZheng_20200418_first cvCreateImage dir=%d %d %d %d %d \n", std::to_string(GetCurrentThreadId()).c_str(), dir, src0->width, src0->height, src0->depth, src0->nChannels);
- float angle = 0.0;
- if (0 == dir) {
- angle = 0.0;
- dst_img = cvCreateImage(cvSize(src0->width, src0->height), src0->depth, src0->nChannels);
- }
- else if (1 == dir){
- angle = 180;
- //cvFlip(src0,src0,1);
- dst_img = cvCreateImage(cvSize(src0->width, src0->height), src0->depth, src0->nChannels);
- }
- else if (2 == dir) {
- angle = 90;
- dst_img = cvCreateImage(cvSize(src0->height, src0->width), src0->depth, src0->nChannels);
- }
- else if (3 == dir) {
- angle = 270;
- dst_img = cvCreateImage(cvSize(src0->height, src0->width), src0->depth, src0->nChannels);
- }
- else
- return identify::result::IDF_FAILURE;
- // printf("线程:%s JiaoZheng_20200418_first cvCreateImage end \n", std::to_string(GetCurrentThreadId()).c_str());
- if (angle > 1.0){
- for (int i = 0; i < 3; i++){
- points_src_rotate[i] = get_new_point(points_src_rotate[i], src0->width, src0->height, angle);
- }
- }
- // printf("线程:%s JiaoZheng_20200418_first4 \n", std::to_string(GetCurrentThreadId()).c_str());
- CvPoint2D32f points_dst[3];
- for (int i = 0; i < 3; i++){
- CvPoint2D32f pt_src_tmp = points_src_rotate[i];
- int nearst_id = -1;
- int nearst_distance = 100000000;
- for (std::size_t j = 0; j < word_location_point_list.size(); j++){
- CvPoint2D32f pt_dst_tmp = cvPoint2D32f(word_location_point_list[j].x + word_location_point_list[j].width / 2.0, word_location_point_list[j].y + word_location_point_list[j].height / 2.0);
- int distance = get_distance(pt_src_tmp, pt_dst_tmp);
- if (distance < nearst_distance){
- nearst_distance = distance;
- nearst_id = j;
- }
- }
- if (-1 == nearst_id)
- return identify::result::IDF_FAILURE;
- points_dst[i] = cvPoint2D32f(word_location_point_list[nearst_id].x + word_location_point_list[nearst_id].width / 2.0, word_location_point_list[nearst_id].y + word_location_point_list[nearst_id].height / 2.0);;
- }
- // printf("线程:%s JiaoZheng_20200418_first5 \n", std::to_string(GetCurrentThreadId()).c_str());
- CvMat * warp_mat = cvCreateMat(2, 3, CV_32FC1);
- cvGetAffineTransform(points_src, points_dst, warp_mat);
- cvWarpAffine(src0, dst_img, warp_mat, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(255));
- cvReleaseMat(&warp_mat);
- #if _DEBUG
- cvSaveImage("D:\\show\\1.png", src0);
- cvSaveImage("D:\\show\\2.png", dst_img);
- #endif
- cvReleaseImage(&src0);
- // printf("线程:%s JiaoZheng_20200418_first6 \n", std::to_string(GetCurrentThreadId()).c_str());
- return identify::result::IDF_SUCCESS;
- }
- int COnLineCardPageIdentifier::JiaoZheng_20200418_second_four(IplImage * src0_, IplImage * &dst_img,
- const vector<CvRect> & top_locate_point_list, const vector<CvRect> & bottom_locate_point_list, const vector<CvRect> & word_location_point_list,
- int dir)
- {
- //CV_Assert(top_locate_point_list.size()>2);
- //CV_Assert(bottom_locate_point_list.size());
- CvPoint2D32f points_src[4] = {
- cvPoint2D32f(top_locate_point_list[0].x + top_locate_point_list[0].width / 2.0, top_locate_point_list[0].y + top_locate_point_list[0].height / 2.0),
- cvPoint2D32f(top_locate_point_list[top_locate_point_list.size() - 1].x + top_locate_point_list[top_locate_point_list.size() - 1].width / 2.0, top_locate_point_list[top_locate_point_list.size() - 1].y + top_locate_point_list[top_locate_point_list.size() - 1].height / 2.0),
- cvPoint2D32f(bottom_locate_point_list[0].x + bottom_locate_point_list[0].width / 2.0, bottom_locate_point_list[0].y + bottom_locate_point_list[0].height / 2.0),
- cvPoint2D32f(bottom_locate_point_list[1].x + bottom_locate_point_list[1].width / 2.0, bottom_locate_point_list[1].y + bottom_locate_point_list[1].height / 2.0)
- };
- IplImage * src0 = cvCloneImage(src0_);
- // 0:上 旋转0度 1:下 旋转180度 2:左 旋转90度 3:右 旋转270度 如果不对请自行调整
- CvPoint2D32f points_src_rotate[4] = { points_src[0], points_src[1], points_src[2], points_src[3] };
- float angle = 0.0;
- if (0 == dir) {
- angle = 0.0;
- dst_img = cvCreateImage(cvSize(src0->width, src0->height), src0->depth, src0->nChannels);
- }
- else if (1 == dir){
- angle = 180;
- //cvFlip(src0,src0,1);
- dst_img = cvCreateImage(cvSize(src0->width, src0->height), src0->depth, src0->nChannels);
- }
- else if (2 == dir) {
- angle = 90;
- dst_img = cvCreateImage(cvSize(src0->height, src0->width), src0->depth, src0->nChannels);
- }
- else if (3 == dir) {
- angle = 270;
- dst_img = cvCreateImage(cvSize(src0->height, src0->width), src0->depth, src0->nChannels);
- }
- else
- return identify::result::IDF_FAILURE;
- if (angle > 1.0){
- for (int i = 0; i < 4; i++){
- points_src_rotate[i] = get_new_point(points_src_rotate[i], src0->width, src0->height, angle);
- }
- }
- CvPoint2D32f points_dst[4];
- for (std::size_t i = 0; i < 4; i++){
- CvPoint2D32f pt_src_tmp = points_src_rotate[i];
- int nearst_id = -1;
- int nearst_distance = 100000000;
- for (std::size_t j = 0; j < word_location_point_list.size(); j++){
- CvPoint2D32f pt_dst_tmp = cvPoint2D32f(word_location_point_list[j].x + word_location_point_list[j].width / 2.0, word_location_point_list[j].y + word_location_point_list[j].height / 2.0);
- int distance = get_distance(pt_src_tmp, pt_dst_tmp);
- if (distance < nearst_distance){
- nearst_distance = distance;
- nearst_id = j;
- }
- }
- if (-1 == nearst_id)
- return identify::result::IDF_FAILURE;
- points_dst[i] = cvPoint2D32f(word_location_point_list[nearst_id].x + word_location_point_list[nearst_id].width / 2.0, word_location_point_list[nearst_id].y + word_location_point_list[nearst_id].height / 2.0);;
- }
- Point2f pts[4];
- for (int i = 0; i < 4; i++)
- pts[i] = Point2f(points_src[i].x, points_src[i].y);
- Point2f ptd[4];
- for (int i = 0; i < 4; i++)
- ptd[i] = Point2f(points_dst[i].x, points_dst[i].y);
- cv::Mat warp_mat(cv::Size(3, 3), CV_32FC1);
- warp_mat = getPerspectiveTransform(pts, ptd);
- CvMat b = warp_mat;
- cvWarpPerspective(src0_, dst_img, &b, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(255));
- #if _DEBUG
- cvSaveImage("D:\\show\\1.png", src0);
- cvSaveImage("D:\\show\\2.png", dst_img);
- #endif
- cvReleaseImage(&src0);
- return identify::result::IDF_SUCCESS;
- }
- int COnLineCardPageIdentifier::JiaoZheng_20200418_second_five(IplImage * src0_, IplImage * &dst_img,
- const vector<CvRect> & top_locate_point_list, const vector<CvRect> & bottom_locate_point_list, const vector<CvRect> & word_location_point_list,
- int dir)
- {
- //CV_Assert(top_locate_point_list.size()>2);
- //CV_Assert(bottom_locate_point_list.size());
- CvPoint2D32f points_src[5] = {
- cvPoint2D32f(top_locate_point_list[0].x + top_locate_point_list[0].width / 2.0, top_locate_point_list[0].y + top_locate_point_list[0].height / 2.0),
- cvPoint2D32f(top_locate_point_list[1].x + top_locate_point_list[1].width / 2.0, top_locate_point_list[1].y + top_locate_point_list[1].height / 2.0),
- cvPoint2D32f(top_locate_point_list[top_locate_point_list.size() - 1].x + top_locate_point_list[top_locate_point_list.size() - 1].width / 2.0, top_locate_point_list[top_locate_point_list.size() - 1].y + top_locate_point_list[top_locate_point_list.size() - 1].height / 2.0),
- cvPoint2D32f(bottom_locate_point_list[0].x + bottom_locate_point_list[0].width / 2.0, bottom_locate_point_list[0].y + bottom_locate_point_list[0].height / 2.0),
- cvPoint2D32f(bottom_locate_point_list[1].x + bottom_locate_point_list[1].width / 2.0, bottom_locate_point_list[1].y + bottom_locate_point_list[1].height / 2.0)
- };
- IplImage * src0 = cvCloneImage(src0_);
- // 0:上 旋转0度 1:下 旋转180度 2:左 旋转90度 3:右 旋转270度 如果不对请自行调整
- CvPoint2D32f points_src_rotate[5] = { points_src[0], points_src[1], points_src[2], points_src[3], points_src[4] };
- float angle = 0.0;
- if (0 == dir) {
- angle = 0.0;
- dst_img = cvCreateImage(cvSize(src0->width, src0->height), src0->depth, src0->nChannels);
- }
- else if (1 == dir){
- angle = 180;
- //cvFlip(src0,src0,1);
- dst_img = cvCreateImage(cvSize(src0->width, src0->height), src0->depth, src0->nChannels);
- }
- else if (2 == dir) {
- angle = 90;
- dst_img = cvCreateImage(cvSize(src0->height, src0->width), src0->depth, src0->nChannels);
- }
- else if (3 == dir) {
- angle = 270;
- dst_img = cvCreateImage(cvSize(src0->height, src0->width), src0->depth, src0->nChannels);
- }
- else
- return identify::result::IDF_FAILURE;
- if (angle > 1.0){
- for (int i = 0; i < 5; i++){
- points_src_rotate[i] = get_new_point(points_src_rotate[i], src0->width, src0->height, angle);
- }
- }
- CvPoint2D32f points_dst[5];
- for (std::size_t i = 0; i < 5; i++){
- CvPoint2D32f pt_src_tmp = points_src_rotate[i];
- int nearst_id = -1;
- int nearst_distance = 100000000;
- for (std::size_t j = 0; j < word_location_point_list.size(); j++){
- CvPoint2D32f pt_dst_tmp = cvPoint2D32f(word_location_point_list[j].x + word_location_point_list[j].width / 2.0, word_location_point_list[j].y + word_location_point_list[j].height / 2.0);
- int distance = get_distance(pt_src_tmp, pt_dst_tmp);
- if (distance < nearst_distance){
- nearst_distance = distance;
- nearst_id = j;
- }
- }
- if (-1 == nearst_id)
- return identify::result::IDF_FAILURE;
- points_dst[i] = cvPoint2D32f(word_location_point_list[nearst_id].x + word_location_point_list[nearst_id].width / 2.0, word_location_point_list[nearst_id].y + word_location_point_list[nearst_id].height / 2.0);;
- }
- Point2f pts[5];
- for (int i = 0; i < 5; i++)
- pts[i] = Point2f(points_src[i].x, points_src[i].y);
- Point2f ptd[5];
- for (int i = 0; i < 5; i++)
- ptd[i] = Point2f(points_dst[i].x, points_dst[i].y);
- cv::Mat warp_mat(cv::Size(3, 3), CV_32FC1);
- warp_mat = getPerspectiveTransform(pts, ptd);
- CvMat b = warp_mat;
- cvWarpPerspective(src0_, dst_img, &b, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(255));
- #if _DEBUG
- cvSaveImage("D:\\show\\1.png", src0);
- cvSaveImage("D:\\show\\2.png", dst_img);
- #endif
- cvReleaseImage(&src0);
- return identify::result::IDF_SUCCESS;
- }
- int COnLineCardPageIdentifier::JiaoZheng_20200418(IplImage * src0, IplImage * &dst_img,
- const vector<CvRect> & top_locate_point_list, const vector<CvRect> & bottom_locate_point_list, const vector<CvRect> & word_location_point_list,
- int dir, double scale_x, double scale_y, int word_w, int word_h)
- {
- int len_l = top_locate_point_list.size();
- if (len_l != 3 || bottom_locate_point_list.size() != 2)
- return identify::result::IDF_FAILURE;
- // 中心点
- CvPoint2D32f points_src_[3] = {
- cvPoint2D32f(top_locate_point_list[0].x + top_locate_point_list[0].width / 2.0, top_locate_point_list[0].y + top_locate_point_list[0].height / 2.0),
- cvPoint2D32f(top_locate_point_list[len_l - 1].x + top_locate_point_list[len_l - 1].width / 2.0, top_locate_point_list[len_l - 1].y + top_locate_point_list[len_l - 1].height / 2.0),
- cvPoint2D32f(bottom_locate_point_list[0].x + bottom_locate_point_list[0].width / 2.0, bottom_locate_point_list[0].y + bottom_locate_point_list[0].height / 2.0)
- };
- cv::Size location_size[3] = {
- cvSize(top_locate_point_list[0].width, top_locate_point_list[0].height),
- cvSize(top_locate_point_list[len_l - 1].width, top_locate_point_list[len_l - 1].height),
- cvSize(bottom_locate_point_list[0].width, bottom_locate_point_list[0].height)
- };
- // 0:上 旋转0度 1:下 旋转180度 2:左 旋转90度 3:右 旋转270度 如果不对请自行调整
- CvPoint2D32f points_src_rotate[3] = { points_src_[0], points_src_[1], points_src_[2] };
- float angle = 0.0;
- int use_w = src0->width;
- int use_h = src0->height;
- if (0 == dir) {
- angle = 0.0;
- }
- else if (1 == dir){
- angle = 180;
- }
- else if (2 == dir) {
- angle = 90;
- swap(use_w, use_h);
- for (int i = 0; i < 3; i++)
- swap(location_size[i].width, location_size[i].height);
- }
- else if (3 == dir) {
- angle = 270;
- swap(use_w, use_h);
- for (int i = 0; i < 3; i++)
- swap(location_size[i].width, location_size[i].height);
- }
- else
- return identify::result::IDF_FAILURE;
- if (angle > 1.0){
- for (int i = 0; i < 3; i++){
- points_src_rotate[i] = get_new_point(points_src_rotate[i], src0->width, src0->height, angle);
- }
- }
- // 按照从左到右 从上到下 排序
- sort_point_list(points_src_rotate);
- // 推算边缘点
- CvPoint2D32f points_src[3] = {
- cvPoint2D32f(points_src_rotate[0].x - (location_size[0].width / 2.0 + 0.55), top_locate_point_list[0].y - (location_size[0].height / 2.0 + 0.55)),
- cvPoint2D32f(points_src_rotate[1].x + (location_size[1].width / 2.0 + 0.55), top_locate_point_list[1].y - (location_size[1].height / 2.0 + 0.55)),
- cvPoint2D32f(points_src_rotate[2].x - (location_size[2].width / 2.0 + 0.55), top_locate_point_list[2].y + (location_size[2].height / 2.0 + 0.55))
- };
- // 寻找json数据的对应定位点坐标
- CvPoint2D32f points_dst_[3]; // 中心点
- CvPoint2D32f points_dst[3]; // 边缘点
- for (std::size_t i = 0; i < 3; i++){
- CvPoint2D32f pt_src_tmp = points_src_rotate[i];
- int nearst_id = -1;
- int nearst_distance = 100000000;
- for (std::size_t j = 0; j < word_location_point_list.size(); j++){
- CvRect rc_tmp;
- rc_tmp.x = word_location_point_list[j].x*scale_x + 0.55;
- rc_tmp.y = word_location_point_list[j].y*scale_y + 0.55;
- rc_tmp.width = word_location_point_list[j].width*scale_x + 0.55;
- rc_tmp.height = word_location_point_list[j].height*scale_y + 0.55;
- CvPoint2D32f pt_dst_tmp = cvPoint2D32f(rc_tmp.x + rc_tmp.width / 2.0, rc_tmp.y + rc_tmp.height / 2.0);
- int distance = get_distance(pt_src_tmp, pt_dst_tmp);
- if (distance < nearst_distance){
- nearst_distance = distance;
- nearst_id = j;
- }
- }
- if (-1 == nearst_id)
- return identify::result::IDF_FAILURE;
- points_dst_[i] = cvPoint2D32f(word_location_point_list[nearst_id].x + word_location_point_list[nearst_id].width / 2.0, word_location_point_list[nearst_id].y + word_location_point_list[nearst_id].height / 2.0);;
- if (0 == i)
- points_dst[i] = cvPoint2D32f(word_location_point_list[nearst_id].x, word_location_point_list[nearst_id].y);
- else if (1 == i)
- points_dst[i] = cvPoint2D32f(word_location_point_list[nearst_id].x + word_location_point_list[nearst_id].width, word_location_point_list[nearst_id].y);
- else
- points_dst[i] = cvPoint2D32f(word_location_point_list[nearst_id].x, word_location_point_list[nearst_id].y + word_location_point_list[nearst_id].height);
- }
- #define GET_SCALE 1
- #if GET_SCALE
- int len = 3;
- int dis_w = get_distance(points_src_rotate[1], points_src_rotate[0]);
- int dis_h = get_distance(points_src_rotate[0], points_src_rotate[2]);
- int dis_ww = get_distance(points_dst[1], points_dst[0]);
- int dis_hw = get_distance(points_dst[0], points_dst[2]);
- double s_x = dis_w*1.0 / dis_ww*1.0;
- double s_y = dis_h*1.0 / dis_hw*1.0;
- int add_left = points_src_rotate[0].x - points_dst[0].x*s_x;
- int dis_w_right = (word_w - points_dst[1].x)*s_x;
- int dis_s_right = use_w - points_src_rotate[1].x;
- int add_right = dis_s_right - dis_w_right;
- int add_top = points_src_rotate[0].y - points_dst[0].y*s_y;
- int dis_w_bottom = (word_h - points_dst[1].y)*s_y;
- int dis_s_bottom = use_h - points_src_rotate[1].y;
- int add_bottom = dis_s_bottom - dis_w_bottom;
- IplImage* lp_after_warp = NULL;
- int xn_w = use_w - add_left - add_right;
- int xn_h = use_h - add_bottom - add_top;
- CvRect rc_box;//= cvRect(add_left,add_top,src0->width-add_left-add_right,src0->height-add_top-add_bottom);
- // 旋转矩形
- // 新的水平坐标点更新回 切割后的原图
- points_src_[0] = cvPoint2D32f(points_src_rotate[0].x - add_left, points_src_rotate[0].y - add_top);
- points_src_[1] = cvPoint2D32f(points_src_rotate[1].x - add_left, points_src_rotate[1].y - add_top);
- points_src_[2] = cvPoint2D32f(points_src_rotate[2].x - add_left, points_src_rotate[2].y - add_top);
- angle = 0.0;
- if (0 == dir) {
- rc_box = cvRect(add_left, add_top, src0->width - add_left - add_right, src0->height - add_top - add_bottom);
- lp_after_warp = cvCreateImage(cvSize(rc_box.width, rc_box.height), src0->depth, src0->nChannels);
- dst_img = cvCreateImage(cvSize(lp_after_warp->width, lp_after_warp->height), lp_after_warp->depth, lp_after_warp->nChannels);
- }
- else if (1 == dir){
- angle = -180;
- rc_box = cvRect(add_right, add_bottom, src0->width - add_left - add_right, src0->height - add_top - add_bottom);
- lp_after_warp = cvCreateImage(cvSize(rc_box.width, rc_box.height), src0->depth, src0->nChannels);
- dst_img = cvCreateImage(cvSize(lp_after_warp->width, lp_after_warp->height), lp_after_warp->depth, lp_after_warp->nChannels);
- }
- else if (2 == dir) {
- angle = -90;
- rc_box = cvRect(add_top, add_right, src0->width - add_top - add_bottom, src0->height - add_right - add_left);
- lp_after_warp = cvCreateImage(cvSize(rc_box.width, rc_box.height), src0->depth, src0->nChannels);
- dst_img = cvCreateImage(cvSize(lp_after_warp->height, lp_after_warp->width), lp_after_warp->depth, lp_after_warp->nChannels);
- }
- else if (3 == dir) {
- angle = -270;
- rc_box = cvRect(add_bottom, add_left, src0->width - add_bottom - add_top, src0->height - add_left - add_right);
- lp_after_warp = cvCreateImage(cvSize(rc_box.width, rc_box.height), src0->depth, src0->nChannels);
- dst_img = cvCreateImage(cvSize(lp_after_warp->height, lp_after_warp->width), lp_after_warp->depth, lp_after_warp->nChannels);
- }
- else
- return identify::result::IDF_FAILURE;
- if (angle < -1.0){
- for (int i = 0; i < 3; i++){
- points_src_[i] = get_new_point(points_src_[i], xn_w, xn_h, angle);
- }
- }
- cvSetImageROI(src0, rc_box);
- cvCopy(src0, lp_after_warp, NULL);
- #if _DEBUG
- cvSaveImage("D:\\show\\0.png", lp_after_warp);
- #endif
- cvResetImageROI(src0);
- //}
- use_w = lp_after_warp->width;
- use_h = lp_after_warp->height;
- if (dir > 1)
- swap(use_h, use_w);
- double d_x = use_w*1.0 / word_w;
- double d_y = use_h*1.0 / word_h;
- points_dst_[0] = cvPoint2D32f(points_dst_[0].x*d_x + 0.55, points_dst_[0].y*d_y + 0.55);
- points_dst_[1] = cvPoint2D32f(points_dst_[1].x*d_x + 0.55, points_dst_[1].y*d_y + 0.55);
- points_dst_[2] = cvPoint2D32f(points_dst_[2].x*d_x + 0.55, points_dst_[2].y*d_y + 0.55);
- #endif
- CvMat * warp_mat = cvCreateMat(2, 3, CV_32FC1);
- cvGetAffineTransform(points_src_, points_dst_, warp_mat);
- cvWarpAffine(lp_after_warp, dst_img, warp_mat, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(255));
- cvReleaseMat(&warp_mat);
- cvReleaseImage(&lp_after_warp);
- #if _DEBUG
- cvSaveImage("D:\\show\\1.png", src0);
- cvSaveImage("D:\\show\\2.png", dst_img);
- #endif
- return identify::result::IDF_SUCCESS;
- }
- int COnLineCardPageIdentifier::MyFindDingWeiDian(IplImage * src_gray_img, CvMemStorage* storage, schema_const_param &schema_param, vector<CvRect>& locate_point_list, int & _dir)
- {
- CvRect roi[4] = {//上下左右 roi
- cvRect(0, 0, src_gray_img->width, min(300, src_gray_img->height)),
- cvRect(0, src_gray_img->height - min(300, src_gray_img->height) - 1, src_gray_img->width, min(300, src_gray_img->height)),
- cvRect(0, 0, min(200, src_gray_img->width), src_gray_img->height),
- cvRect(src_gray_img->width - min(300, src_gray_img->width) - 1, 0, min(300, src_gray_img->width), src_gray_img->height)
- };
- CvSeq * contour = NULL;
- for (int dir = 0; dir < 4; dir++)
- {
- if (dir < 2)myscale_shema_param0(m_default_schema_param, schema_param, src_gray_img->width / (double)m_default_schema_param.shijuanwidth);
- else myscale_shema_param0(m_default_schema_param, schema_param, src_gray_img->height / (double)m_default_schema_param.shijuanwidth);
- IplImage * binary_img = cvCreateImage(cvSize(roi[dir].width + 10, roi[dir].height + 10), IPL_DEPTH_8U, 1);
- IplImage * binary_img2 = cvCreateImage(cvSize(roi[dir].width + 10, roi[dir].height + 10), IPL_DEPTH_8U, 1);
- cvSet(binary_img, cvScalarAll(0));
- cvSetImageROI(src_gray_img, roi[dir]);
- cvSetImageROI(binary_img, cvRect(5, 5, roi[dir].width, roi[dir].height));
- cvThreshold(src_gray_img, binary_img, 180, 255, CV_THRESH_BINARY_INV);
- cvResetImageROI(binary_img);
- int an = 2;
- IplConvKernel * element = cvCreateStructuringElementEx(an * 2 + 1, an * 2 + 1, an, an, CV_SHAPE_RECT, 0);//创建结构元素
- cvErode(binary_img, binary_img2, element, 1);//腐蚀图像
- cvDilate(binary_img2, binary_img2, element, 1);//膨胀图像
- cvSub(binary_img, binary_img2, binary_img2);
- cvDilate(binary_img, binary_img, element, 1);//膨胀图像
- cvErode(binary_img, binary_img, element, 1);//腐蚀图像
- cvSub(binary_img, binary_img2, binary_img);
- if (element)
- cvReleaseStructuringElement(&element);
- #ifdef _DEBUG
- cvSaveImage("D:\\Debug.jpg",binary_img);
- #endif
- int contours = cvFindContours(binary_img, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(roi[dir].x - 5, roi[dir].y - 5));
- cvReleaseImage(&binary_img);
- cvReleaseImage(&binary_img2);
- int validCount = 0;
- vector<CvContour *> contourList;
- for (CvContour * c = (CvContour *)contour; c != 0; c = (CvContour *)c->h_next)
- {
- locate_point_list.clear();
- if (c->rect.width > schema_param.maxw[dir])continue;
- if (c->rect.height > schema_param.maxh[dir])continue;
- if (c->rect.width < schema_param.minw[dir] * 0.7)continue;
- if (c->rect.height < schema_param.minh[dir] * 0.7)continue;
- cvSetImageROI(src_gray_img, c->rect);
- int area = GetBlackArea(src_gray_img);
- if (area < c->rect.width*c->rect.height*0.75)continue;
- validCount++;
- contourList.push_back(c);
- }
- cvResetImageROI(src_gray_img);
- std::vector<CvRect> list;
- for (int i = 0; i < contourList.size(); i++)
- {
- CvRect rect = contourList[i]->rect;
- list.push_back(rect);
- }
- CvRect rect;
- float k = 0, b = 0;
- if (dir == 0 || dir == 1){
- std::sort(list.begin(), list.end(), sort_locate_point_by_x);
- }
- else {
- std::sort(list.begin(), list.end(), sort_locate_point_by_y);
- }
- if (list.size() > 1)
- {
- bool bV = false;
- locate_point_list.push_back(list[0]);
- if (list[list.size() - 1].x - list[0].x>-0.00001 && list[list.size() - 1].x - list[0].x<0.00001)
- {
- bV = true;
- }
- else{
- k = (list[list.size() - 1].y - list[0].y + 0.0) / (list[list.size() - 1].x - list[0].x);
- }
- b = list[0].y - k*list[0].x;
- for (int i = 1; i < list.size() - 1; i++)
- {
- if (dir == 0 || dir == 1){
- int y = k*list[i].x + b;
- if (fabs(y - list[i].y + 0.0) < list[i].height / 2)
- locate_point_list.push_back(list[i]);
- }
- else
- {
- int x = 0;
- if (bV){
- x = list[0].x;
- }
- else{
- x =(list[i].y - b) / k;
- }
- if (fabs(x - list[i].x + 0.0) < list[i].width / 2)
- locate_point_list.push_back(list[i]);
- }
- }
- locate_point_list.push_back(list[list.size() - 1]);
- }
- if (locate_point_list.size() == 3)
- {
- _dir = dir;
- if (MyFindBottomDingWeiDian(src_gray_img, storage, schema_param, locate_point_list, dir) == identify::result::IDF_FAILURE)
- return identify::result::IDF_FAILURE;
- return identify::result::IDF_SUCCESS;
- break;
- }
- }
- return identify::result::IDF_FAILURE;
- }
- //查找定位点
- int COnLineCardPageIdentifier::MyFindBottomDingWeiDian(IplImage * src_gray_img, CvMemStorage* storage, schema_const_param &schema_param, vector<CvRect>& locate_point_list, int & _dir)
- {
- CvRect roi[4] = {//上下左右 roi
- cvRect(0, 0, src_gray_img->width, min(300, src_gray_img->height)),
- cvRect(0, src_gray_img->height - min(300, src_gray_img->height) - 1, src_gray_img->width, min(300, src_gray_img->height)),
- cvRect(0, 0, min(300, src_gray_img->width), src_gray_img->height),
- cvRect(src_gray_img->width - min(300, src_gray_img->width) - 1, 0, min(300, src_gray_img->width), src_gray_img->height)
- };
- CvSeq * contour = NULL;
- int dir;
- _dir > 1 ? dir = 3 - _dir + 2 : dir = 1 - _dir;
- m_vecBottom.clear();
- //for (int dir=0;dir<4;dir++)
- {
- IplImage * binary_img = cvCreateImage(cvSize(roi[dir].width + 10, roi[dir].height + 10), IPL_DEPTH_8U, 1);
- IplImage * binary_img2 = cvCreateImage(cvSize(roi[dir].width + 10, roi[dir].height + 10), IPL_DEPTH_8U, 1);
- cvSet(binary_img, cvScalarAll(0));
- cvSetImageROI(src_gray_img, roi[dir]);
- cvSetImageROI(binary_img, cvRect(5, 5, roi[dir].width, roi[dir].height));
- cvThreshold(src_gray_img, binary_img, 180, 255, CV_THRESH_BINARY_INV);
- cvResetImageROI(binary_img);
- int an = 2;
- IplConvKernel * element = cvCreateStructuringElementEx(an * 2 + 1, an * 2 + 1, an, an, CV_SHAPE_RECT, 0);//创建结构元素
- cvErode(binary_img, binary_img2, element, 1);//腐蚀图像
- cvDilate(binary_img2, binary_img2, element, 1);//膨胀图像
- cvSub(binary_img, binary_img2, binary_img2);
- cvDilate(binary_img, binary_img, element, 1);//膨胀图像
- cvErode(binary_img, binary_img, element, 1);//腐蚀图像
- cvSub(binary_img, binary_img2, binary_img);
- int contours = cvFindContours(binary_img, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(roi[dir].x - 5, roi[dir].y - 5));
- if (element)
- cvReleaseStructuringElement(&element);
- cvReleaseImage(&binary_img);
- cvReleaseImage(&binary_img2);
- int validCount = 0;
- vector<CvContour *> contourList;
- for (CvContour * c = (CvContour *)contour; c != 0; c = (CvContour *)c->h_next)
- {
- if (c->rect.width > schema_param.maxw[dir])continue;
- if (c->rect.height > schema_param.maxh[dir])continue;
- if (c->rect.width < schema_param.minw[dir] * 0.7)continue;
- if (c->rect.height < schema_param.minh[dir] * 0.7)continue;
- cvSetImageROI(src_gray_img, c->rect);
- //cvSaveImage( "d://debug1.jpg", binary_img );
- int area = GetBlackArea(src_gray_img);
- if (area < c->rect.width*c->rect.height*0.75)continue;
- validCount++;
- contourList.push_back(c);
- }
- cvResetImageROI(src_gray_img);
- if (contourList.size() == 2){
- for (std::size_t i = 0; i < contourList.size(); i++){
- CvRect rect = contourList[i]->rect;
- m_vecBottom.push_back(rect);
- }
- if (m_vecBottom.size() > 1){
- std::sort(m_vecBottom.begin(), m_vecBottom.end(), sort_locate_point_by_x);
- if (_dir == 1)
- std::sort(m_vecBottom.begin(), m_vecBottom.end(), sort_locate_point_by_x);
- }
- return identify::result::IDF_SUCCESS;
- }
- else
- {
- return identify::result::IDF_FAILURE;
- }
- }
- }
- int COnLineCardPageIdentifier::OnLineCardJZ(IplImage* src, IplImage* &dst_img, int nPageIndex, int dir, std::vector<CvRect>&main_locate_point, int &wordloctlt)
- {
- int ret = identify::result::IDF_FAILURE;
- std::vector<CvRect> vec_locations_word; vec_locations_word.clear();
- double tt[4] = { 0.0, 0.0, 0.0, 0.0 };
- if (!m_pTemplate->pages.empty()){
- PageTemplate&page = m_pTemplate->pages[nPageIndex];
- std::vector<Location>& lcs = page.location;
- for (std::size_t j = 0; j < lcs.size(); j++){
- CvRect rc_tmp;
- rc_tmp.x = lcs[j].pos.x;
- rc_tmp.y = lcs[j].pos.y;
- rc_tmp.width = lcs[j].pos.w;
- rc_tmp.height = lcs[j].pos.h;
- vec_locations_word.push_back(rc_tmp);
- }
- wordloctlt = vec_locations_word[3].y - vec_locations_word[0].y;
- double word_w = page.w;
- double word_h = page.h;
- tt[2] = word_w;
- tt[3] = word_h;
- // resize point
- int mb_w = src->width;
- int mb_h = src->height;
- if (2 == dir || 3 == dir) //
- swap(mb_h, mb_w);
- float rio_w = mb_w*1.0 / word_w*1.0;
- float rio_h = mb_h*1.0 / word_h*1.0;
- tt[0] = rio_w;
- tt[1] = rio_h;
- for (std::size_t i = 0; i < vec_locations_word.size(); i++){
- vec_locations_word[i].x = vec_locations_word[i].x*rio_w + 0.55;
- vec_locations_word[i].y = vec_locations_word[i].y*rio_h + 0.55;
- vec_locations_word[i].width = vec_locations_word[i].width*rio_w + 0.55;
- vec_locations_word[i].height = vec_locations_word[i].height*rio_h + 0.55;
- }
- }
- if (2 == m_vecBottom.size() && vec_locations_word.size()>3){
- try{
- // 三点校正
- ret = JiaoZheng_20200418_first(src, dst_img, main_locate_point, m_vecBottom, vec_locations_word, dir);
- }
- catch (cv::Exception &e)
- {
- return identify::result::IDF_FAILURE;
- }
- }
- return ret;
- }
- void COnLineCardPageIdentifier::InitScoreArea(SchemaQuestionScore&sqs, const ScoreBox&box, CvPoint offset, double w_scale, double h_scale)
- {
- // 打分框类型
- sqs.scoreBox.type = box.type;
- // 填空题打分类型
- sqs.scoreBox.vctScore = box.vctScore;
- // 上限
- sqs.scoreBox.limit = box.limit;
- // 最后一个格子是否为小数(0.5分)
- sqs.scoreBox.bPoint = box.bPoint;
- // 位置
- sqs.scoreBox.pos.x = offset.x + box.pos.x * w_scale;
- sqs.scoreBox.pos.y = offset.y + box.pos.y * h_scale;
- sqs.scoreBox.pos.w = box.pos.w *w_scale;
- sqs.scoreBox.pos.h = box.pos.h *h_scale;
- }
- int COnLineCardPageIdentifier::GetQrCode(IplImage* dst_gray_img, schema_const_param &schema_param, vector<CvRect> &main_locate_point, vector<SchemaCode> &codev, string& paper_id, string& student_code)
- {
- std::string result;
- CvRect myRect = cvRect(max(0, min(dst_gray_img->width - schema_param.paper_bar_width1, main_locate_point[0].x + schema_param.paper_bar_offsetx1)),
- max(0, min(dst_gray_img->height - schema_param.paper_bar_height1, main_locate_point[0].y + schema_param.paper_bar_offsety1)),
- schema_param.paper_bar_width1,
- schema_param.paper_bar_height1);
- IplImage* mydst_gray_img = NULL;
- xuanzhuan(dst_gray_img, mydst_gray_img, myRect);
- #ifdef _DEBUG
- cv::imwrite("D:\\TTTTT.JPG", cvarrToMat(mydst_gray_img));
- #endif
- cv::Mat matDstGray = cvarrToMat(mydst_gray_img);
- int ret = 0;
- try{
- ret = GetQR(matDstGray, result);
- }
- catch (cv::Exception&e){
- const char* what = e.what();
- int n = 0;
- ++n;
- }
- //CParseQRInfo test;
- //char result[512] = { 0 };
- //bool bRet = test.parseQRInfo(matDstGray, result, sizeof(result)/sizeof(char));
- //if (/*ret == identify::result::IDF_SUCCESS*/bRet){
- if (ret == identify::result::IDF_SUCCESS){
- SchemaCode qrcode1;
- qrcode1.centerx = (main_locate_point[0].x + schema_param.paper_bar_offsetx1) + schema_param.paper_bar_width1 / 2.0;
- qrcode1.centery = (main_locate_point[0].y + schema_param.paper_bar_offsety1) + schema_param.paper_bar_height1 / 2.0;
- qrcode1.width = schema_param.paper_bar_width1;
- qrcode1.height = schema_param.paper_bar_height1;
- qrcode1.index = obj_index++;
- qrcode1.nQrOrBar = 1;
- qrcode1.isXuanZhuan = false;
- student_code = result;
- qrcode1.strContent = result;
- codev.push_back(qrcode1);
- }
- if (mydst_gray_img != NULL)cvReleaseImage(&mydst_gray_img);
- return identify::result::IDF_SUCCESS;
- }
- void COnLineCardPageIdentifier::CalcPos(const Pos&pos, const CvPoint& offset, double w_scale, double h_scale, int ¢er_x, int ¢er_y, int &w, int &h)
- {
- w = static_cast<int>(pos.w*w_scale);
- h = static_cast<int>(pos.h*h_scale);
- center_x = static_cast<int>(offset.x + pos.x*w_scale + pos.w*w_scale / 2);
- center_y = static_cast<int>(offset.y + pos.y*h_scale + pos.h*h_scale / 2);
- }
- void COnLineCardPageIdentifier::SetPageDefault(SchemaPage& page)
- {
- page.codeCount = 0;
- page.cutAreaCount = 0;
- page.group_spacer = ';';
- page.groupCount = 0;
- page.stuItemCount = 0;
- page.stuGroupsCount = 0;
- page.hei_du_ling_min_du = 4;
- page.height = 0;
- page.index = 0;
- page.itemCount = 0;
- page.locateAreaCount = 0;
- page.locateCrossCount = 0;
- page.locatePointCount = 0;
- page.option_spacer = ',';
- page.question_score_count = 0;
- page.unselect_char = '*';
- page.user_float_heidu = 4;
- page.width = 0;
- page.worthwhileBlk = 4;
- }
- void COnLineCardPageIdentifier::SetTemplate(OnLineCard::PaperTemplate*pT)
- {
- m_pTemplate = pT;
- int dingweidianH;
- int dingweidianW;
- if (m_pTemplate->pages[1].location.size() >= 5){
- int m = 0;
- dingweidianH = m_pTemplate->pages[1].location[m].pos.h;
- dingweidianW = m_pTemplate->pages[1].location[m].pos.w;
- m_default_schema_param.main_locate_point_distance = m_pTemplate->pages[1].location[m + 2].pos.x - m_pTemplate->pages[1].location[m].pos.x;
- m_default_schema_param.shijuanwidth = m_pTemplate->pages[1].w;
- for (int i = 0; i < 4; i++)
- {
- if (i < 2)
- {
- m_default_schema_param.minw[i] = dingweidianW*0.75;
- m_default_schema_param.maxw[i] = dingweidianW*1.25;
- m_default_schema_param.minh[i] = dingweidianH*0.75;
- m_default_schema_param.maxh[i] = dingweidianH*1.25;
- }
- else
- {
- m_default_schema_param.minw[i] = dingweidianH*0.75;
- m_default_schema_param.maxw[i] = dingweidianH*1.25;
- m_default_schema_param.minh[i] = dingweidianW*0.75;
- m_default_schema_param.maxh[i] = dingweidianW*1.25;
- }
- }
- }
- }
- int COnLineCardPageIdentifier::createSchema(const IplImage* src, IplImage* *dst, SchemaPage* *pageSchema, const char * result_path, bool flag, std::string qr, bool bUseQr)
- {
- if (!m_pTemplate || m_pTemplate->pages.size() < 2 || m_pTemplate->pages[1].location.size() < 5){
- return identify::result::IDF_FAILURE;
- }
- int wordloctlt = 0;
- int schoolCardStatus = m_pTemplate->schoolCardStatus;
- obj_index = 0;
- CvRect roi_old = cvGetImageROI(src);
- IplImage * src0 = (IplImage *)src;
- int ret;
- int mode_type = 1115;
- vector<SchemaGroup> groupv;
- vector<SchemaItem> itemv;
- vector<SchemaQuestionScore> scorev;
- vector<SchemaCode> codev;
- vector<SchemaCutArea> cutareav;
- vector<SchemaLocatePoint> questionLocatePoints;
- vector<KEGUANTI_QUESTION_LOCATEPOINT_INDEX> keguanti_question_locatepoint_indexs;
- vector<SchemaGroup> stuGroupv;
- vector<SchemaItem> stuItemv;
- vector<KEGUANTI_QUESTION_LOCATEPOINT_INDEX> stuIndex;
- vector<KEGUANTI_QUESTION_LOCATEPOINT_INDEX> quekaoIndex;
- CvMemStorage* storage = cvCreateMemStorage(0);
- IplImage * src_gray_img;
- int question_count = 0;
- int itemcount = 0;
- cvResetImageROI((IplImage*)src0);
- src_gray_img = cvCreateImage(cvGetSize(src0), IPL_DEPTH_8U, 1);
- cvCvtColor(src0, src_gray_img, CV_BGR2GRAY);
- schema_const_param schema_param;
- std::vector<CvRect> main_locate_point;
- CvPoint offset_pt;
- int dir;//上下左右
- // printf("线程:%s 第一次查找定位点\n", std::to_string(GetCurrentThreadId()).c_str());
- ret = MyFindDingWeiDian(src_gray_img, storage, schema_param, main_locate_point, dir);
- if (ret != identify::result::IDF_SUCCESS){
- cv::Size sz;
- std::vector<cv::Rect> vec_locations_word; vec_locations_word.clear();
- if (!m_pTemplate->pages.empty()){
- PageTemplate&page = m_pTemplate->pages[1];
- sz = cv::Size(page.w, page.h);
- std::vector<Location>& lcs = page.location;
- for (std::size_t j = 0; j < lcs.size(); j++){
- cv::Rect rc_tmp;
- rc_tmp.x = lcs[j].pos.x;
- rc_tmp.y = lcs[j].pos.y;
- rc_tmp.width = lcs[j].pos.w;
- rc_tmp.height = lcs[j].pos.h;
- vec_locations_word.push_back(rc_tmp);
- }
- }
- std::vector<cv::Rect> vec_tops; // 接受找到的上面三个定位点 下标访问
- std::vector<cv::Rect> vec_bottoms; // 接受找到的下面的两个定位点 下标访问
- std::vector<int> vec_len;
- vec_tops.resize(100);
- vec_bottoms.resize(100);
- vec_len.push_back(-1);
- vec_len.push_back(-1);
- #ifdef _DEBUG
- cv::imwrite("D:\\src_gray_img.png", cv::cvarrToMat(src_gray_img));
- #endif
- int nRet = api_location_anchor_points(cv::cvarrToMat(src_gray_img), vec_locations_word, sz, vec_tops, vec_bottoms, vec_len, dir, 3, 1);
- if (nRet == 0 && vec_len.size()==2 && vec_len[0] == 3 && vec_len[1] == 2){
- main_locate_point.clear();
- m_vecBottom.clear();
- for (std::size_t i = 0; i < vec_tops.size() && i < vec_len[0]; ++i){
- main_locate_point.push_back(vec_tops[i]);
- }
- for (std::size_t i = 0; i < vec_bottoms.size() && i < vec_len[1]; ++i){
- m_vecBottom.push_back(vec_bottoms[i]);
- }
- }
- else{
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- cvSetImageROI(src0, roi_old);
- return identify::result::IDF_TEMPLATE_NOTFOUND_ENOUGH_LOCATEPOINT;
- }
- }
- IplImage * dst_img = NULL;
- // printf("线程:%s 开始矫正\n", std::to_string(GetCurrentThreadId()).c_str());
- ret = OnLineCardJZ(src0, dst_img, 1, dir, main_locate_point, wordloctlt);
- if (ret != identify::result::IDF_SUCCESS){
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- cvSetImageROI(src0, roi_old);
- if (dst_img)cvReleaseImage(&dst_img);
- return identify::result::IDF_TEMPLATE_NOTFOUND_ENOUGH_LOCATEPOINT;
- }
- //printf("线程:%s 矫正结束\n", std::to_string(GetCurrentThreadId()).c_str());
- IplImage* dst_gray_img = cvCreateImage(cvGetSize(dst_img), IPL_DEPTH_8U, 1);
- cvCvtColor(dst_img, dst_gray_img, CV_BGR2GRAY);
- int locate_point_count = main_locate_point.size();
- main_locate_point.clear();
- //printf("线程:%s 第二次查找定位点\n", std::to_string(GetCurrentThreadId()).c_str());
- ret = MyFindDingWeiDian(dst_gray_img, storage, schema_param, main_locate_point, dir);
- std::sort(main_locate_point.begin(), main_locate_point.end(), sort_locate_point_by_x);
- if (ret != identify::result::IDF_SUCCESS || main_locate_point.size() != locate_point_count){
- cv::Size sz;
- std::vector<cv::Rect> vec_locations_word; vec_locations_word.clear();
- if (!m_pTemplate->pages.empty()){
- PageTemplate&page = m_pTemplate->pages[1];
- sz = cv::Size(page.w, page.h);
- std::vector<Location>& lcs = page.location;
- for (std::size_t j = 0; j < lcs.size(); j++){
- cv::Rect rc_tmp;
- rc_tmp.x = lcs[j].pos.x;
- rc_tmp.y = lcs[j].pos.y;
- rc_tmp.width = lcs[j].pos.w;
- rc_tmp.height = lcs[j].pos.h;
- vec_locations_word.push_back(rc_tmp);
- }
- }
- std::vector<cv::Rect> vec_tops; // 接受找到的上面三个定位点 下标访问
- std::vector<cv::Rect> vec_bottoms; // 接受找到的下面的两个定位点 下标访问
- std::vector<int> vec_len;
- vec_tops.resize(100);
- vec_bottoms.resize(100);
- vec_len.push_back(-1);
- vec_len.push_back(-1);
- int nRet = api_location_anchor_points(cv::cvarrToMat(src_gray_img), vec_locations_word, sz, vec_tops, vec_bottoms, vec_len, dir, 3, 1);
- if (nRet == 0 && vec_len.size() == 2 && vec_len[0] == 3 && vec_len[1] == 2){
- main_locate_point.clear();
- m_vecBottom.clear();
- for (std::size_t i = 0; i < vec_tops.size() && i < vec_len[0]; ++i){
- main_locate_point.push_back(vec_tops[i]);
- }
- for (std::size_t i = 0; i < vec_bottoms.size() && i < vec_len[1]; ++i){
- m_vecBottom.push_back(vec_bottoms[i]);
- }
- }
- else{
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- cvReleaseImage(&dst_gray_img);
- cvSetImageROI(src0, roi_old);
- if (dst_img)cvReleaseImage(&dst_img);
- return identify::result::IDF_TEMPLATE_NOTFOUND_ENOUGH_LOCATEPOINT;
- }
- }
- double fffx = (main_locate_point[main_locate_point.size() - 1].x - main_locate_point[0].x)*(main_locate_point[main_locate_point.size() - 1].x - main_locate_point[0].x);
- double fffy = (main_locate_point[main_locate_point.size() - 1].y - main_locate_point[0].y)*(main_locate_point[main_locate_point.size() - 1].y - main_locate_point[0].y);
- double w_scale = (sqrt(fffx + fffy)) / m_default_schema_param.main_locate_point_distance;
- double Hfffx = (m_vecBottom[0].x - main_locate_point[0].x)*(m_vecBottom[0].x - main_locate_point[0].x);
- double Hfffy = (m_vecBottom[0].y - main_locate_point[0].y)*(m_vecBottom[0].y - main_locate_point[0].y);
- double h_scale = (sqrt(Hfffx + Hfffy)) / wordloctlt;
- {
- //保存
- SchemaLocatePoint leftp;
- leftp.centerx = main_locate_point[0].x + main_locate_point[0].width / 2.0;
- leftp.centery = main_locate_point[0].y + main_locate_point[0].height / 2.0;
- leftp.width = main_locate_point[0].width;
- leftp.height = main_locate_point[0].height;
- questionLocatePoints.push_back(leftp);
- SchemaLocatePoint rightp;
- rightp.centerx = main_locate_point[2].x + main_locate_point[2].width / 2.0;
- rightp.centery = main_locate_point[2].y + main_locate_point[2].height / 2.0;
- rightp.width = main_locate_point[2].width;
- rightp.height = main_locate_point[2].height;
- questionLocatePoints.push_back(rightp);
- leftp.centerx = m_vecBottom[0].x + m_vecBottom[0].width / 2.0;
- leftp.centery = m_vecBottom[0].y + m_vecBottom[0].height / 2.0;
- leftp.width = m_vecBottom[0].width;
- leftp.height = m_vecBottom[0].height;
- questionLocatePoints.push_back(leftp);
- rightp.centerx = m_vecBottom[1].x + m_vecBottom[1].width / 2.0;
- rightp.centery = m_vecBottom[1].y + m_vecBottom[1].height / 2.0;
- rightp.width = m_vecBottom[1].width;
- rightp.height = m_vecBottom[1].height;
- questionLocatePoints.push_back(rightp);
- }
- int page_index = 1;
- string paper_id = "";
- string student_code = "";
- bool is_stu_id = false;
- offset_pt.x = main_locate_point[0].x;
- offset_pt.y = main_locate_point[0].y;
- bool front_page = false;
- //判断前后页
- if ((main_locate_point[1].x - main_locate_point[0].x) < (main_locate_point[2].x - main_locate_point[1].x)){//正面
- front_page = true;
- }
- else{
- front_page = false;
- }
- PageTemplate&page = m_pTemplate->pages[front_page ? 1 : 2];
- // 正面
- if (front_page){
- SchemaCode code_tmp;
- std::vector<std::string> split_qr;
- split(qr, (std::string)",", &split_qr);
- if (split_qr.size() > 0){
- if (split_qr.size() > 0)
- paper_id = split_qr[0];
- if (bUseQr){
- if (split_qr.size() > 2){
- std::vector<std::string> _vct;
- split(split_qr[2], std::string("@"), &_vct);
- if (_vct.size() > 1){
- student_code = _vct[2];
- is_stu_id = !student_code.empty();
- }
- }
- }
- }
- if (bUseQr&&!student_code.empty())
- {
- SchemaCode code;
- code.index = obj_index++;
- code.nQrOrBar = 1;
- code.strContent = paper_id + "_" + student_code + "_3_1";
- codev.push_back(code);
- }
- else{
- // 二维码
- schema_param.paper_bar_width1 = page.QrCode.w*w_scale;
- schema_param.paper_bar_height1 = page.QrCode.h*h_scale;
- schema_param.paper_bar_offsetx1 = page.QrCode.x*w_scale;
- schema_param.paper_bar_offsety1 = page.QrCode.y*h_scale;
- if (m_pTemplate->useQrCode){
- std::size_t nOld = codev.size();
- ret = GetQrCode(dst_gray_img, schema_param, main_locate_point, codev, paper_id, student_code);
- if (ret != identify::result::IDF_SUCCESS){
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- cvReleaseImage(&dst_img);
- cvReleaseImage(&dst_gray_img);
- return identify::result::IDF_TEMPLATE_QRCODE_ILLEGAL;
- }
- if (nOld < codev.size()){
- vector<std::string> splits;
- split(student_code, (std::string)"@", &splits);
- if (splits.size() == 1){
- paper_id = splits[0];
- codev[codev.size() - 1].strContent = paper_id + "_6582234412574771625_3_1_12_1_1_1";
- student_code = "";
- }
- else if (splits.size() >= 2){
- student_code = splits[0];
- paper_id = splits[1];
- codev[codev.size() - 1].strContent = paper_id + "_" + student_code + "_3_1";
- }
- if (student_code.empty()){
- if (!codev.empty())
- code_tmp = codev[0];
- codev.clear();
- }
- }
- is_stu_id = !student_code.empty();
- }
- // 二维码中含有学生信息 不需要识别条形码和填涂考号
- if (!m_pTemplate->useQrCode)
- {
- //条形码
- schema_param.paper_bar_width1 = page.studentcode_bar.w*w_scale;
- schema_param.paper_bar_height1 = page.studentcode_bar.h*h_scale;
- schema_param.paper_bar_offsetx1 = page.studentcode_bar.x*w_scale;
- schema_param.paper_bar_offsety1 = page.studentcode_bar.y*h_scale;
- if (schema_param.paper_bar_width1 != 0 && schema_param.paper_bar_height1 != 0){
- auto oldSize = codev.size();
- ret = GetQrCode(dst_gray_img, schema_param, main_locate_point, codev, paper_id, student_code);
- if (ret != identify::result::IDF_SUCCESS){
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- cvReleaseImage(&dst_img);
- cvReleaseImage(&dst_gray_img);
- return identify::result::IDF_TEMPLATE_QRCODE_ILLEGAL;;
- }
- if (oldSize < codev.size()){
- codev[codev.size() - 1].strContent = paper_id + "_" + student_code + "_3_1_12_1_1_1";
- }
- }
- //填涂考号
- if (student_code.empty())
- {
- int q_item_count = 10;
- int itemcount = 0;
- int question_count = 0;
- int x, y, w, h;
- for (std::size_t j = 0; j < page.studentcode_fill.size(); j++)
- {
- SchemaGroup group;
- group.question_code = "";
- group.index = question_count++;
- group.question_index = question_count;
- group.itemCount = q_item_count;
- group.itemIndex.clear();
- group.omr_out_type = OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT;
- for (std::size_t m = 0; m < page.studentcode_fill[j].size(); m++)
- {
- group.itemIndex.push_back(itemcount + m);
- SchemaItem item;
- CalcPos(page.studentcode_fill[j][m].pos, offset_pt, w_scale, h_scale, item.centerx, item.centery, item.width, item.height);
- std::string&optName = page.studentcode_fill[j][m].optName;
- if (!optName.empty())
- item.OutChar = std::stoi(optName) + '0';
- item.keguanti_question_locate_point_index = stuIndex.size();
- stuItemv.push_back(item);
- }
- if (j == 0){
- x = stuItemv[0].centerx - stuItemv[0].width / 2 - 35;
- y = stuItemv[0].centery - stuItemv[0].height - stuItemv[0].height / 2 - 105;
- }
- else if (j == page.studentcode_fill.size() - 1){
- SchemaItem &item = stuItemv[stuItemv.size() - 1];
- int tx = item.centerx + item.width / 2 + 35;
- int ty = item.centery + item.height / 2 + 5;
- w = tx - x;
- h = ty - y;
- }
- itemcount += q_item_count;
- stuGroupv.push_back(group);
- }
- KEGUANTI_QUESTION_LOCATEPOINT_INDEX kqli;
- kqli[0] = 0;
- kqli[1] = 1;
- kqli[2] = 2;
- kqli[3] = 3;
- stuIndex.push_back(kqli);
- code_tmp.centerx = x + w / 2;
- code_tmp.centery = y + h / 2;
- code_tmp.width = w;
- code_tmp.height = h;
- code_tmp.index = obj_index++;
- code_tmp.nQrOrBar = 1;
- code_tmp.strContent = paper_id + "_6582234412574771625_3_1_12_1_1_1";
- codev.clear();
- codev.push_back(code_tmp);
- }
- }
- }
- // 缺考标记
- {
- schema_param.quekao_item_offset_x = main_locate_point[0].x + page.absent.x*w_scale;
- schema_param.quekao_item_offset_y = main_locate_point[0].y + page.absent.y*h_scale;
- schema_param.quekao_item_width = page.absent.w*w_scale;
- schema_param.quekao_item_height = page.absent.h*h_scale;
- KEGUANTI_QUESTION_LOCATEPOINT_INDEX QKIndex;
- QKIndex[0] = 0;
- QKIndex[1] = 1;
- QKIndex[2] = 2;
- QKIndex[3] = 3;
- quekaoIndex.push_back(QKIndex);
- }
- }
- for (std::size_t i = 0; i < page.vctQuestions.size(); ++i){
- question&qt = page.vctQuestions[i];
- if (qt.type == 0 || qt.type == 8){//选
- SchemaGroup group;
- question_count++;
- group.question_code = qt.id;
- static int id = 0; id = std::stoi(qt.id);
- group.index = obj_index++;
- group.question_index = question_count;
- group.itemCount = qt.opt.size();
- group.itemIndex.clear();
- group.omr_out_type = qt.type == 0 ? OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT : OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT;
- for (int q = 0; q < group.itemCount; q++)
- {
- group.itemIndex.push_back(itemcount + q);
- SchemaItem item;
- CalcPos(qt.opt[q].pos, offset_pt, w_scale, h_scale, item.centerx, item.centery, item.width, item.height);
- if (!qt.opt[q].optName.empty())
- item.OutChar = qt.opt[q].optName.at(0);
- item.keguanti_question_locate_point_index = keguanti_question_locatepoint_indexs.size();
- itemv.push_back(item);
- }
- itemcount += group.itemCount;
- groupv.push_back(group);
- KEGUANTI_QUESTION_LOCATEPOINT_INDEX kqli;
- kqli[0] = 0;
- kqli[1] = 1;
- kqli[2] = 2;
- kqli[3] = 3;
- keguanti_question_locatepoint_indexs.push_back(kqli);
- }
- else if (qt.type == 1 || qt.type == 2){
- //通过linkparm判断第一次还是第二次出现(第一次一定小于2)
- if (qt.cut.linkparm < 2){
- SchemaQuestionScore sqs;
- cv::warpAffine;
- sqs.type = QUESTION_SCORE_TYPE::MUTIL_SCORE;
- InitScoreArea(sqs, qt.scoreBox, offset_pt, w_scale, h_scale);
- if (sqs.scoreBox.type == 1){ // 1-16
- sqs.count = sqs.scoreBox.limit;
- if (sqs.scoreBox.bPoint)
- sqs.count++;
- }
- else if (sqs.scoreBox.type == 2){ // 29/49
- sqs.count = ((int)sqs.scoreBox.limit / 10) + 12;// 12 = 各位数字+ 十/个位标记 10+2
- if (sqs.scoreBox.bPoint)
- sqs.count++;
- }
- sqs.scoreBox.bXuanZuoTi = (qt.type == 2);
- sqs.index = obj_index++;
- if (!qt.id.empty())
- sqs.question_index = std::stoi(qt.id);
- sqs.question_code = qt.id;
- if (qt.type ==2){
- sqs.question_code_all = qt.all_id;
- }
- sqs.valid_option_count = 0;
- sqs.questionLocatePointIndex[0] = 0;
- sqs.questionLocatePointIndex[1] = 1;
- CalcPos(qt.cut.pos, offset_pt, w_scale, h_scale, sqs.centerx, sqs.centery, sqs.width, sqs.height);
- if (qt.type == 2){
- sqs.questionLocatePointIndex[2] = 2;
- sqs.questionLocatePointIndex[3] = 3;
- for (int v = 0; v < qt.selTotal && qt.opt.size() == qt.selTotal; v++)
- {
- CalcPos(qt.opt[v].pos, offset_pt, w_scale, h_scale, sqs.item[v].centerx, sqs.item[v].centery, sqs.item[v].width, sqs.item[v].height);
- }
- sqs.countItemSelete = qt.selItem;
- sqs.countNum = qt.selTotal;
- SetTBLR(sqs);
- }
- SchemaCutArea cutarea;
- cutarea.index = obj_index++;
- cutarea.area_name = sqs.question_code;
- cutarea.isfirst = TRUE;
- cutarea.question_index = sqs.question_index;
- cutarea.iscut = TRUE;
- CalcPos(qt.cut.pos, offset_pt, w_scale, h_scale, cutarea.centerx, cutarea.centery, cutarea.width, cutarea.height);
- SetTBLR(sqs);
- scorev.push_back(sqs);
- cutareav.push_back(cutarea);
- }else{
- SchemaCutArea cutarea;
- CalcPos(qt.cut.pos, offset_pt, w_scale, h_scale, cutarea.centerx, cutarea.centery, cutarea.width, cutarea.height);
- cutarea.index = obj_index++;
- cutarea.isfirst = FALSE;
- cutarea.question_index = -1;
- cutarea.area_name = qt.id;
- cutareav.push_back(cutarea);
- }
- }else if (qt.type == 3){
- //填空(不会跨页,所以可以直接处理)
- SchemaQuestionScore sqs;
- sqs.type = QUESTION_SCORE_TYPE::SINGLE_SCORE;
- InitScoreArea(sqs, qt.scoreBox, offset_pt, w_scale, h_scale);
- sqs.count = sqs.scoreBox.vctScore.size();
- if (sqs.count <= 0)
- sqs.count = 1;
- sqs.index = obj_index++;
- if (!qt.id.empty())
- sqs.question_index = std::stoi(qt.id);
- sqs.question_code = qt.id;
- sqs.valid_option_count = 0;
- sqs.questionLocatePointIndex[0] = 0;
- sqs.questionLocatePointIndex[1] = 1;
- CalcPos(qt.cut.pos, offset_pt, w_scale, h_scale, sqs.centerx, sqs.centery, sqs.width, sqs.height);
- SchemaCutArea cutarea;
- cutarea.index = obj_index++;
- cutarea.area_name = sqs.question_code;
- cutarea.isfirst = TRUE;
- cutarea.question_index = question_count;
- cutarea.iscut = FALSE;
- CalcPos(qt.cut.pos, offset_pt, w_scale, h_scale, cutarea.centerx, cutarea.centery, cutarea.width, cutarea.height);
- SetTBLR(sqs);
- scorev.push_back(sqs);
- cutareav.push_back(cutarea);
- }
- }
- SchemaPage* schemapage = (SchemaPage*) new SchemaPage;
- SetPageDefault(*schemapage);
- schemapage->schoolCardStatus = m_pTemplate->schoolCardStatus;
- schemapage->isZaiXianDaTiKa = true;
- schemapage->index = front_page ? page_index : 2;
- strcpy(schemapage->paper_id, paper_id.c_str());
- strcpy(schemapage->student_code, student_code.c_str());
- schemapage->is_stu_id = is_stu_id;
- schemapage->width = dst_img->width;
- schemapage->height = dst_img->height;
- schemapage->locatePointCount = main_locate_point.size();
- schemapage->questionLocatePoints = questionLocatePoints;
- schemapage->keguantiQuestionLocatePointIndexs = keguanti_question_locatepoint_indexs;
- schemapage->stuQuestionLocatePointIndex = stuIndex;
- schemapage->codeCount = codev.size();
- schemapage->groupCount = groupv.size();
- schemapage->itemCount = itemv.size();
- schemapage->stuGroupsCount = stuGroupv.size();
- schemapage->stuItemCount = stuItemv.size();
- schemapage->question_score_count = scorev.size();
- schemapage->cutAreaCount = cutareav.size();
- int offset = sizeof(SchemaPage);
- for (std::size_t i = 0; i < main_locate_point.size(); i++)
- {
- SchemaLocatePoint slp;
- slp.centerx = main_locate_point[i].x + main_locate_point[i].width / 2.;
- slp.centery = main_locate_point[i].y + main_locate_point[i].height / 2.;
- slp.width = main_locate_point[i].width;
- slp.height = main_locate_point[i].height;
- schemapage->locatePoints.push_back(slp);
- }
- schemapage->codes = codev;
- schemapage->groups = groupv;
- schemapage->items = itemv;
- schemapage->question_score = scorev;
- schemapage->cutAreas = cutareav;
- schemapage->mode_type = mode_type;
- schemapage->stuGroups = stuGroupv;
- schemapage->stuItems = stuItemv;
- schemapage->schoolCardStatus = schoolCardStatus;
- //缺考标记相关参数
- schemapage->quekao.centerx = schema_param.quekao_item_offset_x + schema_param.quekao_item_width / 2;
- schemapage->quekao.centery = schema_param.quekao_item_offset_y + schema_param.quekao_item_height / 2;
- schemapage->quekao.width = schema_param.quekao_item_width;
- schemapage->quekao.height = schema_param.quekao_item_height;
- schemapage->quekaoLocatePointIndex = quekaoIndex;
- *pageSchema = schemapage;
- if (flag){
- DrawSchema(dst_img, schemapage);
- cvSaveImage(result_path, dst_img);
- }
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- *dst = dst_img;
- cvReleaseImage(&dst_gray_img);
- {
- cvSetImageROI(src0, roi_old);
- return identify::result::IDF_SUCCESS;
- }
- //printf("线程:%s 单页识别结束\n", std::to_string(GetCurrentThreadId()).c_str());
- }
- std::string getTimeStamp()
- {
- std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
- auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
- std::time_t timestamp = tmp.count();
- return std::move(std::to_string(timestamp));
- }
- //按照指定模板进行识别
- int COnLineCardPageIdentifier::Identify_impl()
- {
- int ret = BaseCheck();
- if (ret != identify::result::IDF_SUCCESS)return ret;
- InitalizeTempVar();
- CvMemStorage* storage = cvCreateMemStorage(0);
- IplImage * dst = NULL;
- SchemaPage* pschemaPage = NULL;
- std::string path = std::string("d:\\image\\") + getTimeStamp() + ".jpg";
- ret = createSchema(src, &dst, &pschemaPage, path.c_str(), true, m_strQrClass, m_bUseQr);
- if (ret != identify::result::IDF_SUCCESS){
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- return ret;
- }
- SchemaPage& schemaPage = *pschemaPage;
- /************************读取学生学号*********************************************/
- ret = ReadStudentID(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- /************************查找题目定位点,准备定位数据*********************************************/
- ret = FindQuestionLocatePoints(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- /************************客观题()*********************************************/
- ret = ReadKeGuanTi(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- /************************阅卷读取*************************************************/
- ret = ReadQuestionScore(schemaPage, dst, storage);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- /************************根据给定区域切割图片*********************************************/
- ret = ClipImg(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- /************************读取缺考标记*********************************************/
- omr_result->quekaoFlag = ReadQuekaoFlag(schemaPage, dst);
- omr_result->card_index = schemaPage.index;
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return identify::result::IDF_SUCCESS;
- }
- //获取全局背景灰度,通过统计所有涂点周围像素(灰度不小于160)的灰度平均值获得
- int COnLineCardPageIdentifier::caculate_global_background(SchemaPage& schemaPage, IplImage * dst, bool flag)
- {
- int global_background_color_count = 0;
- int global_background_color_avg = 0;
- int totalCount = 0;
- if (!flag)
- {
- totalCount = schemaPage.itemCount;
- }
- else
- {
- totalCount = schemaPage.stuItemCount;
- }
- for (int i = 0; i<totalCount; i++)
- {
- SchemaItem & item = m_items[i];
- RESULT_RECT result_rect;
- GetRect(item.centerx, item.centery, item.width, item.height, result_rect);
- int left = int(result_rect.x);
- int top = int(result_rect.y);
- int right = int(result_rect.x + result_rect.width);
- int bottom = int(result_rect.y + result_rect.height);
- int vtop = (int)(result_rect.y - (result_rect.width + 2) / 4);
- int vbottom = (int)(result_rect.y + result_rect.height + (result_rect.height + 2) / 4);
- int background_color_count = 0, background_color_avg = 0;
- int gray;
- int(*GetGray)(const IplImage * dst, int x, int y);
- if (dst->nChannels == 1)GetGray = GetGrayValue;
- else GetGray = GetBGRGray;
- for (int x = left; x <= right; x++)
- {
- gray = GetGray(dst, x, vtop);
- if (gray>160){ background_color_avg += gray; background_color_count++; }
- gray = GetGray(dst, x, vbottom);
- if (gray>160){ background_color_avg += gray; background_color_count++; }
- }
- background_color_avg = background_color_count>0 ? background_color_avg / background_color_count : 0;
- if (background_color_avg>100){
- global_background_color_avg += background_color_avg;
- global_background_color_count++;
- }
- }
- global_background_color_avg = global_background_color_count>0 ? global_background_color_avg / global_background_color_count : 0;
- return global_background_color_avg;
- }
- //计算涂点属性
- inline int COnLineCardPageIdentifier::caculate_cell_property(SchemaPage& schemaPage, SchemaItem &item, IplImage * dst, int &cellSize, double &refArea, double &avg_gray, int &grayNum, double &mo_hu_du, double &gao_heidu,/*字符区域大小*/int &char_area_size,/*字符区域黑色点数(统计选项的字符区域的灰度判定为黑色的点数,用于统计试卷该选项全局的平均字符黑点数)*/int& char_area_black_count,/*字符区域黑色点的平均灰度*/double& char_area_avg_gray, int flag)
- {
- int gray;//临时变量,灰度值
- //int tembackcolor=max((anlyseResult.globalBackGround+200)/2,200);
- int tembackcolor = (flag == 0) ? max(anlyseResult.backGroundGray - 20, 200) : max(anlyseResult.backGroundGray - 20, 0);
- //获取灰度的函数指针
- int(*ggray)(const IplImage * dst, int x, int y);
- if (dst->nChannels == 1)ggray = GetGrayValue;
- else ggray = GetBGRGray;
- int left = int(item.centerx - item.width / 2. + 0.5);
- int top = int(item.centery - item.height / 2. + 0.5);
- int right = int(item.centerx + item.width / 2. + 0.5);
- int bottom = int(item.centery + item.height / 2. + 0.5);
- int vtop = (int)(item.centery - item.height*0.75 + 0.5);
- /*******************统计字符区域属性************************************/
- int cl = left + ((right - left + 1) + 2) / 4;
- int cr = left + ((right - left + 1) * 3 + 2) / 4;
- int ct = top;
- int cb = bottom;
- //初始化字符区域参数
- char_area_avg_gray = 0;
- char_area_black_count = 0;
- char_area_size = 0;
- for (int y = ct; y <= cb; y++)
- {
- for (int x = cl; x <= cr; x++)
- {
- gray = ggray(dst, x, y);
- char_area_size++;
- if (gray<tembackcolor){
- char_area_avg_gray += gray;
- char_area_black_count++;
- }
- }
- }
- if (char_area_black_count>0)char_area_avg_gray /= char_area_black_count;
- //灰度直方图
- int gray256[260];
- cellSize = 0;
- memset(gray256, 0, sizeof(gray256));
- double yRatio, xRatio, maxRatio;
- double dist;
- if (item.width >= item.height){
- xRatio = 1.0;
- yRatio = (item.width / (double)item.height)*(1 - 0.3);
- if (yRatio<1)yRatio = 1;
- }
- else{
- yRatio = 1.0;
- xRatio = (item.height / (double)item.width)*(1 - 0.3);
- if (xRatio<1)xRatio = 1;
- }
- double yd = item.centery;
- double xd = item.centerx;
- //理想点数
- int li_xiang_dian_shu = item.width*item.height;
- double dx;
- double dy;
- maxRatio = sqrt(xRatio*xRatio + yRatio*yRatio);
- xRatio = xRatio / (item.width / 2.0);
- yRatio = yRatio / (item.height / 2.0);
- xRatio = xRatio / maxRatio;
- yRatio = yRatio / maxRatio;
- refArea = 0;
- double distSum = 0;
- avg_gray = 0;
- grayNum = 0;
- for (int y = top; y <= bottom; y++)
- {
- for (int x = left; x <= right; x++)
- {
- gray = ggray(dst, x, y);
- gray256[gray]++;
- cellSize++;
- if (gray<tembackcolor){
- avg_gray += gray;
- grayNum++;
- }
- dx = (x - xd)*xRatio;
- dy = (y - yd)*xRatio;
- dist = sqrt(dx*dx + dy*dy);
- gray = max(0, 255 - gray - 32);
- refArea += gray*(1 - dist);
- distSum += (1 - dist);
- }
- }
- avg_gray = grayNum>0 ? avg_gray / grayNum : 256;
- refArea /= 16;
- refArea /= distSum;
- //灰度上限
- int grayUp = 256 - schemaPage.hei_du_ling_min_du * 16;
- mo_hu_du = 0;
- //合格黑点数
- int he_ge_hei_dian_shu = 0;
- for (int i = 0; i<grayUp; i++)
- {
- if (gray256[i]>0){
- he_ge_hei_dian_shu += gray256[i];
- mo_hu_du += (i*gray256[i]);
- }
- }
- mo_hu_du = he_ge_hei_dian_shu>0 ? mo_hu_du / he_ge_hei_dian_shu : 0;
- double ping_jun_hei_du = he_ge_hei_dian_shu>0 ? mo_hu_du / he_ge_hei_dian_shu : 0;
- int i, endpos, flag = 0;
- int hui_du_he = 0;
- int hei_dian_shu = 0;
- for (i = 0, endpos = grayUp; i<endpos; i++)
- {
- if (gray256[i]>0){
- if (flag == 0){
- flag = 1;
- endpos = min(grayUp, i + 40);
- }
- hui_du_he += (i*gray256[i]);
- hei_dian_shu += gray256[i];
- }
- if (hei_dian_shu>li_xiang_dian_shu*0.1 || hei_dian_shu >= he_ge_hei_dian_shu*0.3 + 1){
- endpos = i;
- i++;
- break;
- }
- }
- for (; i<grayUp&&hei_dian_shu<dianshu_meihaomi*dianshu_meihaomi / 4 + 1 && hei_dian_shu<hei_dian_shu >= he_ge_hei_dian_shu*0.3 + 1; i++)
- {
- hui_du_he += (i*gray256[i]);
- hei_dian_shu += gray256[i];
- }
- endpos = i;
- gao_heidu = hei_dian_shu>0 ? (255 - hui_du_he / hei_dian_shu) / 16 : 0;
- refArea /= max(1.0, gao_heidu - 2);
- /************确定清晰度**************************/
- int pnt_high = 0, pnt_low = 0, pnt_mid = 0;
- int pos1, pos2, pos3;
- double minRatio = 0.3; maxRatio = 0.8;
- pos1 = 255 - (int)(gao_heidu*maxRatio * 16);
- for (i = 0; i <= pos1; i++)
- {
- pnt_high += gray256[i];
- }
- for (i = pos1 + 1; i<grayUp&&pnt_high<dianshu_meihaomi*dianshu_meihaomi / 4 + 1; i++)
- {
- pnt_high += gray256[i];
- }
- pos1 = i;
- pos2 = hei_dian_shu*minRatio >= 3 ? 255 - (int)(gao_heidu*minRatio * 16) : 255 - 48;
- pos3 = min(pos2, pos1 + 16);
- for (i = pos1 + 1; i <= pos3; i++)
- {
- pnt_mid += gray256[i];
- }
- for (i = pos3 + 1; i <= pos2; i++)
- {
- pnt_low += gray256[i];
- }
- if (pnt_high == 0){ return identify::result::IDF_DIVIDE_ZERO; }
- mo_hu_du = ((pnt_low + pnt_mid) / (double)pnt_high + pnt_low / (double)(pnt_high + pnt_mid)) / 2.0;
- mo_hu_du = min(mo_hu_du, gao_heidu - ping_jun_hei_du);
- mo_hu_du = min(min(gao_heidu, mo_hu_du), 5.0);
- return identify::result::IDF_SUCCESS;
- }
- //分析全局属性
- int COnLineCardPageIdentifier::analyseOmrPanoramic(SchemaPage& schemaPage)
- {
- int i;
- int lev;
- int count; // 所有涂点个数
- int numAblePnt; // 参与分析的点的个数
- double maxblk[16];
- int numBlk[16];
- double maxBlur[16];
- int numBlur[16];
- double stdBlur;
- memset(numBlk, 0, sizeof(int) * 16);
- memset(maxblk, 0, sizeof(double) * 16);
- memset(maxBlur, 0, sizeof(double) * 16);
- memset(numBlur, 0, sizeof(int) * 16);
- count = schemaPage.itemCount;
- numAblePnt = 0;
- double& m_avaMaxBlk = anlyseResult.avgMax_heidu;
- double& m_benchmarkBlk = anlyseResult.benchmarkBlk;
- double& m_benchmarkArea = anlyseResult.benchmarkAreaBlk;
- m_avaMaxBlk = 0;
- for (i = 0; i<count; i++)
- {
- OnlineAnalyseResult::itemResult& itemr = anlyseResult.itemAnalyseResult[i];
- if (itemr.heidu < m_benchmarkBlk || itemr.xiangdui_value < m_benchmarkArea)
- continue;
- if (itemr.heidu< 4.0) continue;
- m_avaMaxBlk += itemr.heidu;
- numAblePnt++;
- lev = int(itemr.heidu);
- maxblk[lev] += itemr.heidu;
- numBlk[lev] ++;
- lev = int(itemr.mohudu);
- maxBlur[lev] += itemr.mohudu;
- numBlur[lev] ++;
- //pPnt++;
- }
- if (numAblePnt > 0)
- m_avaMaxBlk /= numAblePnt;
- else
- m_avaMaxBlk = 12;
- int stdId = 2;
- int numStd = numBlk[0] + numBlk[1] + numBlk[2];
- int numCur = numStd;
- for (i = 3; i<16; i++)
- {
- numCur += (numBlk[i] - numBlk[i - 3]);
- if (numCur > numStd)
- {
- numStd = numCur;
- stdId = i;
- }
- }
- double stdBlk = maxblk[stdId - 2] + maxblk[stdId - 1] + maxblk[stdId];
- if (numStd > 0)
- stdBlk /= numStd;
- else
- stdBlk = 12;
- // 计算模糊度代表值
- stdId = 2;
- numStd = numBlur[0] + numBlur[1] + numBlur[2];
- numCur = numStd;
- for (i = 3; i<16; i++)
- {
- numCur += (numBlur[i] - numBlur[i - 3]);
- if (numCur > numStd)
- {
- numStd = numCur;
- stdId = i;
- }
- }
- stdBlur = maxBlur[stdId - 2] + maxBlur[stdId - 1] + maxBlur[stdId];
- if (numStd > 0)
- stdBlur /= numStd;
- else
- stdBlur = 0;
- if (stdBlur < 2.0)
- stdBlk -= stdBlur;
- else
- stdBlk -= 2.0;
- if (stdBlk < m_avaMaxBlk)
- m_avaMaxBlk = stdBlk;
- //统计字符区域的黑色点数的平均值
- if (schemaPage.groupCount>0){
- int max_item = 1;
- for (int gi = 0; gi<schemaPage.groupCount; gi++)
- {
- if (schemaPage.groups[gi].itemCount>max_item) max_item = schemaPage.groups[gi].itemCount;
- }
- int * char_area_black_counts = new int[schemaPage.groupCount];
- int cur_item_count;//当前选项的数量
- for (int ii = 0; ii<max_item; ii++)
- {
- cur_item_count = 0;
- long total_char_area_size = 0;
- for (int gi = 0; gi<schemaPage.groupCount; gi++)
- {
- if (schemaPage.groups[gi].itemCount>ii){
- OnlineAnalyseResult::itemResult& ir = anlyseResult.itemAnalyseResult[schemaPage.groups[gi].itemIndex[ii]];
- char_area_black_counts[cur_item_count] = ir.char_area_black_count;
- total_char_area_size += ir.char_area_size;
- cur_item_count++;
- }
- }
- double char_area_size_avg = total_char_area_size / (double)cur_item_count;
- int temp;
- for (int m = 0; m<cur_item_count; m++)
- {
- for (int n = m + 1; n<cur_item_count; n++)
- {
- if (char_area_black_counts[n]<char_area_black_counts[m]){
- temp = char_area_black_counts[n];
- char_area_black_counts[n] = char_area_black_counts[m];
- char_area_black_counts[m] = temp;
- }
- }
- }
- anlyseResult.char_area_black_avg[ii] = -1;
- if (char_area_black_counts[0] * 1.4<char_area_black_counts[cur_item_count - 1] || char_area_black_counts[cur_item_count - 1] * 1.4<char_area_size_avg){
- double t = char_area_black_counts[0] * 1.15;
- double f = 0;
- int count__ = 0;
- for (int l = 0; l<cur_item_count; l++)
- {
- if (t<char_area_black_counts[l]){
- f += char_area_black_counts[l];
- count__++;
- }
- }
- anlyseResult.char_area_black_avg[ii] = f / count__;
- }
- }
- delete[]char_area_black_counts;
- }
- return(0);
- }
- /************************************************************************/
- /* 生成OMR涂点字符串(客观题填涂判断) 2014年11月28日10:54:19 */
- /************************************************************************/
- int COnLineCardPageIdentifier::GenerateOmrStr(SchemaPage& schemaPage)
- {
- char omr_str[512] = { 0 };
- int omr_str_len = 0;
- omr_result->group_result.resize(schemaPage.groups.size());
- identify::result::KEGUANTI_RESULT* ketuanti_result_value = omr_result->group_result.data();
- //标记是否被选中
- SelectType sel[MAX_ITEM];
- for (int groupIndex = 0; groupIndex<schemaPage.groupCount; groupIndex++)
- {
- omr_str_len = 0;
- memset(sel, UNSELECT, sizeof(sel));
- SchemaGroup& group = schemaPage.groups[groupIndex];
- int pn = min(MAX_ITEM, group.itemCount);
- OnlineAnalyseResult::itemResult* results[MAX_ITEM];
- SchemaItem* items[MAX_ITEM] = { nullptr };
- int maxgraynum = -1;
- int mingraynum = 0xffffff;
- for (int i = 0; i<pn; i++){
- results[i] = &anlyseResult.itemAnalyseResult[group.itemIndex[i]];
- items[i] = &m_items[group.itemIndex[i]];
- if (results[i]->gray_num > maxgraynum)maxgraynum = results[i]->gray_num;
- if (results[i]->gray_num < mingraynum)mingraynum = results[i]->gray_num;
- }
- int selected_num = 0;
- int unselect_num = 0;
- int uncertain_num = 0;
- for (int i = 0; i<pn; i++)
- {
- //被涂面积小于10%
- if (results[i]->gray_num<results[i]->cell_size*0.1){
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- //面积超过65%
- if (results[i]->gray_num>results[i]->cell_size*0.65){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%15,将面积不小于最大点填涂面积的总面积%10的涂点视为填涂
- if (maxgraynum - mingraynum>results[i]->cell_size*0.2&&results[i]->gray_num>maxgraynum - results[i]->cell_size*0.1){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%50,将面积不小于最大点填涂面积的总面积%30的涂点视为填涂
- if (maxgraynum - mingraynum>results[i]->cell_size*0.5&&results[i]->gray_num>maxgraynum - results[i]->cell_size*0.3){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- if (maxgraynum - results[i]->gray_num>results[i]->cell_size*0.2){
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- sel[i] = UNCERTAIN;
- uncertain_num++;
- }
- int out_count;
- identify::result::OMR_QUESTION_STATE question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_NORMAL;
- if (group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT){
-
- if (selected_num>1){
- int maxgrayindex = -1;
- int maxgraynum = -101;
- for (int i = 0; i<pn; i++)
- {
- if (sel[i] == SELECTED)
- {
- if ((results[i]->gray_num - maxgraynum>100) || (abs(results[i]->gray_num - maxgraynum) <= 100 && results[i]->heidu > results[maxgrayindex]->heidu))
- {
- maxgraynum = results[i]->gray_num;
- maxgrayindex = i;
- }
- }
- }
- for (int i = 0; i<pn; i++)
- {
- if (sel[i] == SELECTED&&i != maxgrayindex){
- sel[i] = UNSELECT;
- }
- }
- }
- out_count = 0;
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED){
- if (out_count>0)omr_str[omr_str_len++] = schemaPage.option_spacer;
- omr_str[omr_str_len++] = items[i]->OutChar;
- out_count++;
- }
- }
- if (out_count == 0){
- omr_str[omr_str_len++] = schemaPage.unselect_char;
- question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_LOUTU;
- }
- }
- else if (group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT)
- {
- out_count = 0;
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED){
- if (out_count > 0)omr_str[omr_str_len++] = schemaPage.option_spacer;
- omr_str[omr_str_len++] = items[i]->OutChar;
- out_count++;
- }
- }
- if (out_count == 0){
- omr_str[omr_str_len++] = schemaPage.unselect_char;
- question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_LOUTU;
- }
- }
- omr_str[omr_str_len] = '\0';
- ketuanti_result_value[groupIndex].question_code = group.question_code;
- ketuanti_result_value[groupIndex].obj_id = static_cast<unsigned int>(group.question_index);
- ketuanti_result_value[groupIndex].answer = omr_str;
- ketuanti_result_value[groupIndex].question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_NORMAL;
- ketuanti_result_value[groupIndex].omr_question_type = group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT ?
- identify::DANXUANTI :identify::DUOXUANTI ;
- }
- return 0;
- }
- // //识别指定图像
- int COnLineCardPageIdentifier::Identify(const IplImage* img, void* out_result, int out_size)
- {
- if (out_result){
- this->out_result = out_result;
- this->omr_result = (identify::result::OMR_RESULT*)this->out_result;
- // printf("线程:%s 缓冲区:缺考标记:%d %p\n", std::to_string(GetCurrentThreadId()).c_str(), omr_result->quekaoFlag, this->out_result);
- src = (IplImage*)img;
- if (src == NULL)
- return identify::result::IDF_FAILURE;
- }else{
- return identify::result::IDF_FAILURE;
- }
- return Identify();
- }
- /************************************************************************/
- /* 获取区域黑色点数量 */
- /************************************************************************/
- int COnLineCardPageIdentifier::GetBlackArea(const IplImage * dst)
- {
- int blackArea = 0;
- CvRect rect = cvGetImageROI(dst);
- int(*GetGray)(const IplImage * dst, int x, int y);
- if (dst->nChannels == 1)GetGray = GetGrayValue;
- else GetGray = GetBGRGray;
- for (int y = rect.y, endy = rect.y + rect.height; y<endy; y++)
- {
- for (int x = rect.x, endx = rect.x + rect.width; x<endx; x++)
- {
- if (GetGray(dst, x, y)<180)blackArea++;
- }
- }
- return blackArea;
- }
- /************************************************************************/
- /*
- 图像基本信息检查
- 最小宽高限制
- 长宽比例限制 */
- /************************************************************************/
- int COnLineCardPageIdentifier::BaseCheck()
- {
- if (src->width<200 || src->height<200){
- return identify::result::IDF_SIZE2SMALL;
- }
- if (abs(max(src->width, src->height) / (double)min(src->width, src->height) - max(21.0, 27.9) / (double)min(21.0, 27.9))>0.2){
- //图像长宽比不符
- return identify::result::IDF_SIDERATIO;
- }
- return identify::result::IDF_SUCCESS;
- }
- /*
- 临时变量初始化
- */
- void COnLineCardPageIdentifier::InitalizeTempVar()
- {
- m_relationKey.clear();
- m_relationValue.clear();
- }
- // 读取学生学号
- int COnLineCardPageIdentifier::ReadStudentID(SchemaPage &schemaPage, IplImage * dst)
- {
- omr_result->qr_result.clear();
- identify::result::CODE_RESULT code_rst; code_rst.qr_str = "";
- code_rst.is_stu_id = false;
- if (strlen(schemaPage.student_code)>0){
- code_rst.qr_str = schemaPage.student_code;
- code_rst.is_stu_id = schemaPage.is_stu_id;
- }else{
- m_items = schemaPage.stuItems;
- // 计算每个填图区域图像信息
- int global_background_color_avg = caculate_global_background(schemaPage, dst, true);
- //模糊度,面积,高黑度,平均黑度
- double mo_hu_du, refArea, gao_heidu, avg_gray;
- //黑色像素数,涂点大小
- int grayNum, cellSize;
- //高黑度和
- double topGraySum = 0;
- //高黑度面积
- double topGrayAreaSum = 0;
- anlyseResult.backGroundGray = global_background_color_avg;
- anlyseResult.cellAvgGray = 0;
- anlyseResult.cellNum = 0;
- int numTopGray = 0;
- int ret;
- item_result.resize(schemaPage.stuItemCount);
- for (int i = 0; i < schemaPage.stuItemCount; i++)
- {
- SchemaItem & item = m_items[i];
- item_result[i] = GetCVRect(item);
- ret = caculate_cell_property(schemaPage, item, dst, cellSize, refArea, avg_gray, grayNum, mo_hu_du, gao_heidu, anlyseResult.itemAnalyseResult[i].char_area_size, anlyseResult.itemAnalyseResult[i].char_area_black_count, anlyseResult.itemAnalyseResult[i].char_area_avg_gray);
- if (ret != identify::result::IDF_SUCCESS)return ret;
- topGraySum += gao_heidu;
- topGrayAreaSum += refArea;
- numTopGray++;
- anlyseResult.cellAvgGray += avg_gray;
- anlyseResult.cellNum++;
- anlyseResult.itemAnalyseResult[i].avg_gray = avg_gray;
- anlyseResult.itemAnalyseResult[i].cell_size = cellSize;
- anlyseResult.itemAnalyseResult[i].gray_num = grayNum;
- anlyseResult.itemAnalyseResult[i].heidu = gao_heidu;
- anlyseResult.itemAnalyseResult[i].mohudu = mo_hu_du;
- anlyseResult.itemAnalyseResult[i].xiangdui_mianji = refArea;
- anlyseResult.itemAnalyseResult[i].xiangdui_value = refArea;
- }
- anlyseResult.cellAvgGray = anlyseResult.cellNum > 0 ? anlyseResult.cellAvgGray / anlyseResult.cellNum : 256;
- anlyseResult.avg_heidu = topGrayAreaSum > 0 ? topGraySum / topGrayAreaSum : 6;
- if (numTopGray >= int(schemaPage.itemCount / 5)){
- anlyseResult.float_heidu = anlyseResult.avg_heidu / schemaPage.user_float_heidu;
- anlyseResult.benchmarkBlk = schemaPage.worthwhileBlk + anlyseResult.float_heidu;
- }
- else{
- anlyseResult.benchmarkBlk = numTopGray > 0 ? min(6.0, schemaPage.worthwhileBlk + anlyseResult.avg_heidu / schemaPage.user_float_heidu) : 6;
- anlyseResult.float_heidu = anlyseResult.benchmarkBlk - schemaPage.worthwhileBlk;
- }
- if (numTopGray > 0){
- anlyseResult.avg_heidu = topGrayAreaSum / numTopGray;
- anlyseResult.float_heidu = anlyseResult.avg_heidu / schemaPage.user_float_heidu;
- anlyseResult.benchmarkAreaBlk = anlyseResult.float_heidu;
- }
- else{
- anlyseResult.avg_heidu = 0;
- anlyseResult.float_heidu = 0;
- anlyseResult.benchmarkAreaBlk = 0.1;
- }
- // 获取
- std::string strStudent;
- if (GenerateOmrStr(schemaPage, strStudent) == 0){
- code_rst.qr_str = strStudent;
- }
- }
- if (!code_rst.qr_str.empty())
- omr_result->qr_result.push_back(code_rst);
- omr_result->online_card_paperid = schemaPage.paper_id;
- omr_result->schoolCardStatus = schemaPage.schoolCardStatus;
- if (m_bUseQr)
- {
- std::vector<std::string> split_qr;
- split(m_strQrClass, (std::string)",", &split_qr);
- if (split_qr.size()>1&& !split_qr[1].empty()){
- omr_result->paper_id = std::stoi(split_qr[1]);
- }
- }
- else{
- omr_result->paper_id = -1;
- }
- return identify::result::IDF_SUCCESS;
- }
- //读取客观题分数
- int COnLineCardPageIdentifier::ReadKeGuanTi(SchemaPage &schemaPage, IplImage * dst)
- {
- m_items = schemaPage.items;
- int global_background_color_avg = caculate_global_background(schemaPage, dst);
- //模糊度,面积,高黑度,平均黑度
- double mo_hu_du, refArea, gao_heidu, avg_gray;
- //黑色像素数,涂点大小
- int grayNum, cellSize;
- //高黑度和
- double topGraySum = 0;
- //高黑度面积
- double topGrayAreaSum = 0;
- anlyseResult.backGroundGray = global_background_color_avg;
- anlyseResult.cellAvgGray = 0;
- anlyseResult.cellNum = 0;
- int numTopGray = 0;
- int ret;
- item_result.resize(schemaPage.itemCount);
- for (int i = 0; i<schemaPage.itemCount; i++)
- {
- SchemaItem & item = m_items[i];
- item_result[i] = GetCVRect(item);
- ret = caculate_cell_property(schemaPage, item, dst, cellSize, refArea, avg_gray, grayNum, mo_hu_du, gao_heidu, anlyseResult.itemAnalyseResult[i].char_area_size, anlyseResult.itemAnalyseResult[i].char_area_black_count, anlyseResult.itemAnalyseResult[i].char_area_avg_gray);
- if (ret != identify::result::IDF_SUCCESS)return ret;
- topGraySum += gao_heidu;
- topGrayAreaSum += refArea;
- numTopGray++;
- anlyseResult.cellAvgGray += avg_gray;
- anlyseResult.cellNum++;
- anlyseResult.itemAnalyseResult[i].avg_gray = avg_gray;
- anlyseResult.itemAnalyseResult[i].cell_size = cellSize;
- anlyseResult.itemAnalyseResult[i].gray_num = grayNum;
- anlyseResult.itemAnalyseResult[i].heidu = gao_heidu;
- anlyseResult.itemAnalyseResult[i].mohudu = mo_hu_du;
- anlyseResult.itemAnalyseResult[i].xiangdui_mianji = refArea;
- anlyseResult.itemAnalyseResult[i].xiangdui_value = refArea;
- }
- anlyseResult.cellAvgGray = anlyseResult.cellNum>0 ? anlyseResult.cellAvgGray / anlyseResult.cellNum : 256;
- anlyseResult.avg_heidu = topGrayAreaSum>0 ? topGraySum / topGrayAreaSum : 6;
- if (numTopGray >= int(schemaPage.itemCount / 5)){
- anlyseResult.float_heidu = anlyseResult.avg_heidu / schemaPage.user_float_heidu;
- anlyseResult.benchmarkBlk = schemaPage.worthwhileBlk + anlyseResult.float_heidu;
- }
- else{
- anlyseResult.benchmarkBlk = numTopGray>0 ? min(6.0, schemaPage.worthwhileBlk + anlyseResult.avg_heidu / schemaPage.user_float_heidu) : 6;
- anlyseResult.float_heidu = anlyseResult.benchmarkBlk - schemaPage.worthwhileBlk;
- }
- if (numTopGray>0){
- anlyseResult.avg_heidu = topGrayAreaSum / numTopGray;
- anlyseResult.float_heidu = anlyseResult.avg_heidu / schemaPage.user_float_heidu;
- anlyseResult.benchmarkAreaBlk = anlyseResult.float_heidu;
- }
- else{
- anlyseResult.avg_heidu = 0;
- anlyseResult.float_heidu = 0;
- anlyseResult.benchmarkAreaBlk = 0.1;
- }
- analyseOmrPanoramic(schemaPage);
- GenerateOmrStr(schemaPage);
- return identify::result::IDF_SUCCESS;
- }
- //读取填空题,和主观题分数
- int COnLineCardPageIdentifier::ReadQuestionScore(SchemaPage &schemaPage, IplImage * dst, CvMemStorage* storage)
- {
- int tiankong_total_count = 0;
- int zhuguan_total_count = 0;
- for (int i = 0; i<schemaPage.question_score_count; i++){
- if (schemaPage.question_score[i].type == QUESTION_SCORE_TYPE::MUTIL_SCORE)
- zhuguan_total_count++;
- else if (schemaPage.question_score[i].type == QUESTION_SCORE_TYPE::SINGLE_SCORE)
- tiankong_total_count++;
- }
- omr_result->tiankongti_result.resize(tiankong_total_count);
- omr_result->zhutuanti_result.resize(zhuguan_total_count);
- identify::result::TIANKONGTI_RESULT*tiankongti_result_value = omr_result->tiankongti_result.data();
- identify::result::ZHUGUANTI_RESULT*zhutuanti_result_value = omr_result->zhutuanti_result.data();
- int score_count = 0;
- int tiankong_count = 0;
- for (int i = 0; i<schemaPage.question_score_count; i++){
- SchemaQuestionScore& qs = schemaPage.question_score[i];
- //查找题目定位点,校正题目位置
- SchemaLocatePoint& lp1 = schemaPage.questionLocatePoints[qs.questionLocatePointIndex[0]];
- SchemaLocatePoint& lp2 = schemaPage.questionLocatePoints[qs.questionLocatePointIndex[1]];
- CvPoint2D32f point1, point2;
- BOOL s1 = FindQuestionLocatePoint(dst, lp1, point1);
- BOOL s2 = FindQuestionLocatePoint(dst, lp2, point2);
- if (!s1&&!s2){
- point1.x = lp1.centerx;
- point1.y = lp1.centery;
- point2.x = lp2.centerx;
- point2.y = lp2.centery;
- }
- else if (!s1){
- point1.x = lp1.centerx + (point2.x - lp2.centerx);
- point1.y = lp1.centery + (point2.y - lp2.centery);
- }
- else if (!s2){
- point2.x = lp2.centerx + (point1.x - lp1.centerx);
- point2.y = lp2.centery + (point1.y - lp1.centery);
- }
- float data[6];
- CvMat* m = caculate_scm(point1, point2, cvPoint2D32f(lp1.centerx, lp1.centery), cvPoint2D32f(lp2.centerx, lp2.centery));
- memcpy(data, m->data.fl, sizeof(float) * 6);
- cvReleaseMat(&m);
- SchemaQuestionScore::Point * point[4] = { &qs.lt, &qs.rt, &qs.lb, &qs.rb };
- float lx = -1, ly = -1;
- float rx = -1, ry = -1;
- double pscale = 1.0;
- int redcount[30] = { 0 };
- int red_in_count[30] = { 0 };
- lx = data[0] * qs.lt.x + data[1] * qs.lt.y + data[2];
- rx = data[0] * qs.rt.x + data[1] * qs.rt.y + data[2];
- ly = data[3] * qs.lt.x + data[4] * qs.lt.y + data[5];
- ry = data[3] * qs.rt.x + data[4] * qs.rt.y + data[5];
- if (qs.type == QUESTION_SCORE_TYPE::MUTIL_SCORE){
- if (lx >= 0 && rx >= 0){
- float h = (point[2]->y - point[0]->y)*pscale;
- CvRect detect_rect = cvRect(qs.scoreBox.pos.x, qs.scoreBox.pos.y, qs.scoreBox.pos.w, qs.scoreBox.pos.h);
- GetZhuGuanTiRedCount(dst, detect_rect, detect_rect, redcount, red_in_count, qs.count, qs.scoreBox.type != 1 || qs.scoreBox.bPoint, false);
- float score = 0;
- if (qs.scoreBox.type == 1)
- {
- // 小数位
- if (qs.scoreBox.bPoint){
- if (red_in_count[0] > 25){
- score += 0.5;
- }
- }
- // 整数位
- {
- int red_area = 0;
- int red_area_index = -1;
- for (int i = (qs.scoreBox.bPoint ? 1 : 0);
- i < qs.count; ++i)
- {
- if (red_in_count[i]>red_area){
- red_area = red_in_count[i]; red_area_index = i;
- }
- }
- if (red_area_index >= (qs.scoreBox.bPoint ? 1 : 0)){
- score += (qs.scoreBox.limit - red_area_index + (qs.scoreBox.bPoint ? 1 : 0));
- }
- }
- }
- else if (qs.scoreBox.type == 2)
- {
- // 小数位
- if (qs.scoreBox.bPoint){
- if (red_in_count[0] > 25){
- score += 0.5;
- }
- }
- {
- //个位数
- int red_area = 0;
- int red_area_index = -1;
- for (int i = (qs.scoreBox.bPoint ? 1 : 0);
- i < (qs.scoreBox.bPoint ? 11 : 10); ++i)
- {
- if (red_in_count[i]>red_area){
- red_area = red_in_count[i]; red_area_index = i;
- }
- }
- if (red_area_index >= (qs.scoreBox.bPoint ? 1 : 0)){
- score += (9 - red_area_index + (qs.scoreBox.bPoint ? 1 : 0));
- }
- }
- {
- //十位数
- int red_area = 0;
- int red_area_index = -1;
- int begin_index = (qs.scoreBox.bPoint ? 11 : 10);
- for (int i = begin_index; i < begin_index + (int)(qs.scoreBox.limit / 10) + 1; ++i)
- {
- if (red_in_count[i] > red_area){ red_area = red_in_count[i]; red_area_index = i; }
- }
- if (red_area_index >= begin_index){
- score = score + 10 * ((int)(qs.scoreBox.limit / 10) - (red_area_index - begin_index) + 1);
- }
- }
- }
- zhutuanti_result_value[score_count].question_score = score;
- zhutuanti_result_value[score_count].question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_NORMAL;
- }
- else{
- zhutuanti_result_value[score_count].question_score = 0;
- zhutuanti_result_value[score_count].question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_WUFASHIBIE;
- }
- zhutuanti_result_value[score_count].obj_id = static_cast<unsigned int>(qs.question_index);
- zhutuanti_result_value[score_count].question_code = qs.question_code;
- zhutuanti_result_value[score_count].omr_question_type = identify::OMR_QUESTION_TYPE::ZHUTUANTI;
- zhutuanti_result_value[score_count].total = 0;
- zhutuanti_result_value[score_count].required = 0;
- zhutuanti_result_value[score_count].xuanze = -1;
- if (qs.scoreBox.bXuanZuoTi){
- zhutuanti_result_value[score_count].omr_question_type = identify::OMR_QUESTION_TYPE::XUANZUOTI;
- zhutuanti_result_value[score_count].total = qs.countNum;
- zhutuanti_result_value[score_count].required = qs.countItemSelete;
- zhutuanti_result_value[score_count].xuanze = ReadXuanZuoTi(schemaPage, qs, dst);
- zhutuanti_result_value[score_count].question_code_all = qs.question_code_all;
- }
- score_count++;
- }
- else
- {
- if (lx >= 0 && rx >= 0){
- if (qs.count > 1){
- float score = 0;
- int red_area_index = -1;
- // 在线答题卡-填空题
- if (qs.scoreBox.type == 3){
- float h = (point[2]->y - point[0]->y)*pscale;
- CvRect detect_rect = cvRect(qs.scoreBox.pos.x, qs.scoreBox.pos.y, qs.scoreBox.pos.w, qs.scoreBox.pos.h);
- GetZhuGuanTiRedCount(dst, detect_rect, detect_rect, redcount, red_in_count, qs.count, 0, true);
- int red_area = 0;
- for (int m = 0; m<qs.scoreBox.vctScore.size(); m++){
- if (red_in_count[m]>red_area&&red_in_count[m]>25){ red_area = red_in_count[m]; red_area_index = m; }
- }
- if (red_area_index >= 0 && static_cast<int>(qs.scoreBox.vctScore.size())>red_area_index){
- score = qs.scoreBox.vctScore.at(qs.count - red_area_index - 1);
- }
- }
- tiankongti_result_value[tiankong_count].question_score = score;
- tiankongti_result_value[tiankong_count].omr_question_type = identify::OMR_QUESTION_TYPE::TIANKONGTI2;
- }else{
- float w = (rx - lx) / qs.count;
- float h = (point[2]->y - point[0]->y)*pscale;
- for (int j = 0; j<1; j++){
- CvRect rect_detect = cvRect(qs.scoreBox.pos.x, qs.scoreBox.pos.y, qs.scoreBox.pos.w, qs.scoreBox.pos.h);
- int red_area = GetTianKongTiRedCount(dst, rect_detect, rect_detect, 1, 0);
- if (red_area>25){
- tiankongti_result_value[tiankong_count].isright = TRUE;
- break;
- }
- else{
- tiankongti_result_value[tiankong_count].isright = FALSE;
- }
- }
- tiankongti_result_value[tiankong_count].omr_question_type = identify::OMR_QUESTION_TYPE::TIANKONGTI;
- }
- }else{
- tiankongti_result_value[tiankong_count].isright = FALSE;
- if (qs.count > 1)
- {
- tiankongti_result_value[tiankong_count].omr_question_type = identify::OMR_QUESTION_TYPE::TIANKONGTI2;
- }
- else
- {
- tiankongti_result_value[tiankong_count].omr_question_type = identify::OMR_QUESTION_TYPE::TIANKONGTI;
- }
- }
- tiankongti_result_value[tiankong_count].obj_id = static_cast<unsigned int>(qs.question_index);
- tiankongti_result_value[tiankong_count].question_code = qs.question_code;
- tiankong_count++;
- }
- }
- return identify::result::IDF_SUCCESS;
- }
- //截取图像
- int COnLineCardPageIdentifier::ClipImg(SchemaPage& schemaPage, IplImage * dst)
- {
- cvResetImageROI(dst);
- vector<int> compression_params;
- compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
- compression_params.push_back(60);
- omr_result->cut_area_result.resize(schemaPage.cutAreaCount);
- identify::result::CUT_AREA_RESULT* cut_area_result_value = omr_result->cut_area_result.data();
- for (int i = 0; i<schemaPage.cutAreaCount; i++)
- {
- SchemaCutArea& cutArea = schemaPage.cutAreas[i];
- CvRect rect = cvRect(cutArea.centerx - cutArea.width / 2, cutArea.centery - cutArea.height / 2, cutArea.width, cutArea.height);
- SaveRect(rect, cut_area_result_value[i]);
- IplImage* img = CutImage(dst, rect);
- vector<uchar> dst;
- cv::Mat _img = cvarrToMat(img);
- imencode(".jpg", _img, dst, compression_params);
- cut_area_result_value[i].obj_id = cutArea.index;
- cut_area_result_value[i].area_index = cutArea.index;
- cut_area_result_value[i].area_sub_index = cutArea.isfirst?1:0;
- cut_area_result_value[i].centerx = cutArea.centerx;
- cut_area_result_value[i].centery = cutArea.centery;
- cut_area_result_value[i].width = cutArea.width;
- cut_area_result_value[i].height = cutArea.height;
- cut_area_result_value[i].area_name = cutArea.area_name;
- cut_area_result_value[i].is_cut = cutArea.iscut;
- cut_area_result_value[i].img_data.resize(dst.size());
- memcpy(cut_area_result_value[i].img_data.data(), &dst[0], dst.size());
- cvReleaseImage(&img);
- }
- return identify::result::IDF_SUCCESS;
- }
- //获取图像指定区域红色点数(主观题) 去除长直线和周边像素 减少直线边缘偏色影响
- int COnLineCardPageIdentifier::GetZhuGuanTiRedCount(IplImage * dst, const CvRect& rect, const CvRect& normal_rect, int * red_counts, int * red_in_counts, int count, int mutil, bool bTianKongTi /*= false*/)
- {
- if (count >= 30) return 0;
- if (dst->nChannels != 3){ return 0; }
- if (m_nXianXiaDaFenType == 1)
- {
- memset(red_counts, 0, sizeof(int)*count);
- memset(red_in_counts, 0, sizeof(int)*count);
- cvSetImageROI(dst, rect);
- Mat img= cv::cvarrToMat(dst);
- cvResetImageROI(dst);
- int tempi[50] = { 0 };
- try{
- EnterCriticalSection(m_althom_rcs);
- // printf("线程:%s 新算法判分-开始\n", std::to_string(GetCurrentThreadId()).c_str());
- if (api_red_check_analysis(img, count, bTianKongTi ? 3 : 2, mutil, tempi, count) != 0)
- {
- // printf("线程:%s 新算法判分-错误\n", std::to_string(GetCurrentThreadId()).c_str());
- LeaveCriticalSection(m_althom_rcs);
- return 0;
- }
- // printf("线程:%s 新算法判分-结束\n", std::to_string(GetCurrentThreadId()).c_str());
- LeaveCriticalSection(m_althom_rcs);
- }
- catch (cv::Exception&e){
- // printf("线程:%s 新算法判分-异常\n", std::to_string(GetCurrentThreadId()).c_str());
- LeaveCriticalSection(m_althom_rcs);
- #if 0
- static const char* str;
- str = e.what();
- #endif
- }
- for (int i = 0; i < count; i++)
- {
- red_in_counts[i] = tempi[count - i - 1];
- if (red_in_counts[i] > 0)
- {
- red_counts[i] = 30; //目的大于25
- }
- }
- return identify::result::IDF_SUCCESS;
- }
- IplImage* red = NULL;
- BOOL s = GetRedBinary(dst, rect, &red);
- if (!s)return 0;
- IplImage * temp = cvCloneImage(red);
- CvMemStorage* storage = cvCreateMemStorage();
- CvSeq* contours = NULL;
- cvFindContours(temp, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
- int top = normal_rect.y - rect.y;
- int bottom = normal_rect.y + normal_rect.height - 1 - rect.y;
- for (CvContour * c = (CvContour *)contours; c != NULL; c = (CvContour *)c->h_next) {
- CvRect b_rect = cvBoundingRect(c);
- if (b_rect.y>bottom - 1 || b_rect.y + b_rect.height - 1<top + 1){
- cvDrawContours(red, (CvSeq *)c, cvScalar(0), cvScalar(0), 0, CV_FILLED, 8);
- }
- }
- cvReleaseImage(&temp);
- cvReleaseMemStorage(&storage);
- memset(red_counts, 0, sizeof(int)*count);
- memset(red_in_counts, 0, sizeof(int)*count);
- int w = red->width;
- int h = red->height;
- for (int x = 0; x<w; x++){
- int option_index = (count - 1) - x*count / w;
- for (int y = 0; y<h; y++){
- if (CV_IMAGE_ELEM(red, unsigned char, y, x)){
- red_counts[option_index]++;
- if (y <= bottom - 1 && y >= top + 1){
- red_in_counts[option_index]++;
- }
- }
- }
- }
- cvReleaseImage(&red);
- return identify::result::IDF_SUCCESS;
- }
- //获取图像指定区域红色点数(填空题)
- int COnLineCardPageIdentifier::GetTianKongTiRedCount(IplImage * dst, const CvRect& rect_normal, const CvRect& rect_detect,int count,int multi)
- {
- CvRect rect = cvGetImageROI(dst);
- if (dst->nChannels != 3){ return 0; }
- if (m_nXianXiaDaFenType == 1){
- cvSetImageROI(dst, rect_detect);
- Mat img = cv::cvarrToMat(dst);
- cvResetImageROI(dst);
- int tempi[50] = { 0 };
- try{
- EnterCriticalSection(m_althom_rcs);
- // printf("线程:%s 新算法判分-开始\n", std::to_string(GetCurrentThreadId()).c_str());
- int fff = api_red_check_analysis(img, count, 3, multi, tempi, count);
- if (fff != 0){
- // printf("线程:%s 新算法判分-错误\n", std::to_string(GetCurrentThreadId()).c_str());
- LeaveCriticalSection(m_althom_rcs);
- return 0;
- }
- // printf("线程:%s 新算法判分-结束\n", std::to_string(GetCurrentThreadId()).c_str());
- LeaveCriticalSection(m_althom_rcs);
- }
- catch (cv::Exception&e){
- // printf("线程:%s 新算法判分-异常\n", std::to_string(GetCurrentThreadId()).c_str());
- LeaveCriticalSection(m_althom_rcs);
- #if 0
- static const char* str;
- str = e.what();
- #endif
- }
- if (tempi[0] > 0)
- return 300;
- return 0;
- }
- int w = rect_detect.width;
- int h = rect_detect.height;
- IplImage * red = NULL;
- BOOL r = GetRedBinary(dst, rect_detect, &red);
- if (!r)return 0;
- vector<CvPoint2D32f> redPoints;
- for (int y = 0; y<red->height; y++)
- {
- unsigned char * red_row_first = (unsigned char *)(red->imageData + (y*red->widthStep));
- for (int x = 0; x<red->width; x++)
- {
- if (red_row_first[x]){
- redPoints.push_back(cvPoint2D32f(x, y));
- }
- }
- }
- CvMemStorage * storage = cvCreateMemStorage();
- CvSeq* contour = NULL;
- int contours = cvFindContours(red, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
- int red_count = 0;
- int normal_left = rect_normal.x - rect_detect.x;
- int normal_top = rect_normal.y - rect_detect.y;
- int normal_right = normal_left + rect_normal.width;
- int normal_bottom = normal_top + rect_normal.height;
- for (CvContour * c = (CvContour *)contour; c != NULL; c = (CvContour *)c->h_next){
- float sum_x = 0;
- float sum_y = 0;
- int in_count = 0;
- int area_c = 0;//轮廓在评分框内的点数
- for (std::size_t i = 0; i<redPoints.size(); i++)
- {
- double distance = cvPointPolygonTest(c, redPoints[i], FALSE);
- if (distance >= 0){
- sum_x += redPoints[i].x;
- sum_y += redPoints[i].y;
- in_count++;
- if (normal_left <= redPoints[i].x&&redPoints[i].x <= normal_right&&normal_top <= redPoints[i].y&&redPoints[i].y <= normal_bottom){
- area_c++;
- }
- }
- }
- if (in_count == 0)continue;
- if (area_c>60){
- red_count += in_count;
- continue;
- }
- //重心位置
- float avg_x = sum_x / in_count;
- float avg_y = sum_y / in_count;
- if (normal_left <= avg_x&&avg_x <= normal_right + 30 && normal_top <= avg_y&&avg_y <= normal_bottom){
- red_count += in_count;
- }
- }
- cvReleaseImage(&red);
- cvReleaseMemStorage(&storage);
- return red_count;
- }
-
- int COnLineCardPageIdentifier::SaveLocateInfo(SchemaPage& schemaPage, vector<CvPoint2D32f> &relationKey, vector<CvPoint2D32f> &relationValue)
- {
- if (relationKey.size() >= 2)
- {
- m_relationKey = relationKey;
- m_relationValue = relationValue;
- double distance = 0;
- int index1;
- int index2;
- for (std::size_t i = 0; i<m_relationKey.size(); i++)
- {
- for (std::size_t j = i + 1; j<m_relationKey.size(); j++)
- {
- double d = sqrt((m_relationKey[i].x - m_relationKey[j].x)*(m_relationKey[i].x - m_relationKey[j].x) + (m_relationKey[j].y - m_relationKey[i].y)*(m_relationKey[j].y - m_relationKey[i].y));
- if (d>distance){ distance = d; index1 = i; index2 = j; }
- }
- }
- //模板上的定位点
- CvPoint2D32f *p11 = &m_relationKey[index1];
- CvPoint2D32f *p12 = &m_relationKey[index2];
- //试卷上的定位点
- CvPoint2D32f*p21 = &m_relationValue[index1];
- CvPoint2D32f*p22 = &m_relationValue[index2];
- CvMat* m_m = caculate_scm(*p21, *p22, *p11, *p12);
- memcpy(data, m_m->data.fl, sizeof(float) * 6);
- cvReleaseMat(&m_m);
- return identify::result::IDF_SUCCESS;
- }
- return identify::result::IDF_NOTFOUND_ENOUGH_LOCATEPOINT;
- }
- int COnLineCardPageIdentifier::GetRect(const int centerx, const int centery, const int width, const int height, RESULT_RECT& result_rect)
- {
- result_rect.x = centerx - width / 2;
- result_rect.y = centery - height / 2;
- result_rect.width = width;
- result_rect.height = height;
- return identify::result::IDF_FAILURE;
- }
- int COnLineCardPageIdentifier::GetRect2(const int centerx, const int centery, const int width, const int height, RESULT_RECT& result_rect)
- {
- double x = data[0] * centerx + data[1] * centery + data[2];
- double y = data[3] * centerx + data[4] * centery + data[5];
- result_rect.x = (int)(x - width / 2 + 0.5);
- result_rect.y = (int)(y - height / 2 + 0.5);
- result_rect.width = width;
- result_rect.height = height;
- return identify::result::IDF_SUCCESS;
- }
- template<class T>
- void COnLineCardPageIdentifier::SaveRect(CvRect& rect, T& result)
- {
- result.centerx = static_cast<decltype(result.centerx)>(rect.x + rect.width / 2.0);
- result.centery = static_cast<decltype(result.centery)>(rect.y + rect.height / 2.0);
- result.width = static_cast<decltype(result.width)>(rect.width);
- result.height = static_cast<decltype(result.height)>(rect.height);
- result.angle = 0;
- }
- template<class T >
- void COnLineCardPageIdentifier::DrawObjRect(IplImage * dst, T& obj_result, CvScalar& scalar)
- {
- cvDrawRect(dst,
- cvPoint(obj_result.centerx - obj_result.width / 2, obj_result.centery - obj_result.height / 2),
- cvPoint(obj_result.centerx + obj_result.width / 2, obj_result.centery + obj_result.height / 2),
- scalar);
- }
- //查找题目定位点
- BOOL COnLineCardPageIdentifier::FindQuestionLocatePoint(IplImage * dst, SchemaLocatePoint& lp1, CvPoint2D32f& point1)
- {
- int top = max(0, (int)(lp1.centery - lp1.height*1.5 + 0.5));
- int bottom = min(dst->height - 1, (int)(lp1.centery + lp1.height*1.5 + 0.5));
- int left = max(0, (int)(lp1.centerx - lp1.width*1.5 + 0.5));
- int right = min(dst->width - 1, (int)(lp1.centerx + lp1.width*1.5 + 0.5));
- int x = left;
- int y = top;
- int width = right - left + 1;
- int height = bottom - top + 1;
- if (width<1 || height<1)return FALSE;
- IplImage* dst_gray_img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
- IplImage* dst_binary_img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
- CvMemStorage* storage = cvCreateMemStorage();
- cvSetImageROI(dst, cvRect(x, y, width, height));
- if (dst->nChannels == 3)cvCvtColor(dst, dst_gray_img, CV_BGR2GRAY);
- else cvCopy(dst, dst_gray_img);
- cvThreshold(dst_gray_img, dst_binary_img, 180, 255, CV_THRESH_BINARY);
- int an = 2;
- IplConvKernel * element = cvCreateStructuringElementEx(an * 2 + 1, an * 2 + 1, an, an, CV_SHAPE_RECT, 0);//创建结构元素
- cvDilate(dst_binary_img, dst_binary_img, element, 1);//膨胀图像
- cvErode(dst_binary_img, dst_binary_img, element, 1);//腐蚀图像
- cvReleaseStructuringElement(&element);
- CvSeq * pcontours = NULL;
- int ncontours = cvFindContours(dst_binary_img, storage, &pcontours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
- vector<CvContour*> quesiontLocatePoints;
- for (CvContour * c = (CvContour *)pcontours; c != NULL; c = (CvContour *)c->h_next)
- {
- if (c->rect.width<lp1.width - 3)continue;
- if (c->rect.height<lp1.height - 3)continue;
- if (c->rect.width>lp1.width + 3)continue;
- if (c->rect.height>lp1.height + 3)continue;
- cvSetImageROI(dst_gray_img, c->rect);
- int area = GetBlackArea(dst_gray_img);
- if (area<c->rect.width*c->rect.height*0.75)continue;
- quesiontLocatePoints.push_back(c);
- }
- double distance = 99999;
- int min_index = -1;
- for (std::size_t i = 0; i<quesiontLocatePoints.size(); i++)
- {
- double d = GetDistance(cvPoint2D32f(lp1.centerx - x, lp1.centery - y), cvPoint2D32f(quesiontLocatePoints[i]->rect.x + quesiontLocatePoints[i]->rect.width / 2.0, quesiontLocatePoints[i]->rect.y + quesiontLocatePoints[i]->rect.height / 2.0));
- if (d<distance){ distance = d; min_index = i; }
- }
- if (min_index >= 0){
- point1 = cvPoint2D32f(quesiontLocatePoints[min_index]->rect.x + quesiontLocatePoints[min_index]->rect.width / 2.0 + x, quesiontLocatePoints[min_index]->rect.y + quesiontLocatePoints[min_index]->rect.height / 2.0 + y);
- cvReleaseImage(&dst_gray_img);
- cvReleaseImage(&dst_binary_img);
- cvReleaseMemStorage(&storage);
- return TRUE;
- }
- cvReleaseImage(&dst_gray_img);
- cvReleaseImage(&dst_binary_img);
- cvReleaseMemStorage(&storage);
- return FALSE;
- }
- double COnLineCardPageIdentifier::GetDistance(CvPoint2D32f point1, CvPoint2D32f point2)
- {
- double dx = point1.x - point2.x;
- double dy = point1.y - point2.y;
- return sqrt(dx*dx + dy*dy);
- }
- int COnLineCardPageIdentifier::FindQuestionLocatePoints(SchemaPage& schemaPage, IplImage * dst)
- {
- std::vector<SchemaLocatePoint>& questionLocatePoints = schemaPage.questionLocatePoints;
- m_question_locate_points.resize(questionLocatePoints.size());
- m_question_locate_point_found.resize(questionLocatePoints.size());
- for (std::size_t i = 0; i<questionLocatePoints.size(); i++)
- {
- m_question_locate_point_found[i] = FindQuestionLocatePoint(dst, questionLocatePoints[i], m_question_locate_points[i]);
- }
- return identify::result::IDF_SUCCESS;
- }
- BOOL COnLineCardPageIdentifier::GetRedBinary(IplImage * dst, const CvRect& rect_detect, IplImage ** red_binary)
- {
- #define GETREDBINARY_DEBUG 0
- #define rename_image(img,new_name) IplImage * new_name = img; img = NULL;
- if (dst == NULL || dst->nChannels != 3)return FALSE;
- int w = rect_detect.width;
- int h = rect_detect.height;
- IplImage * hsv = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3);
- //存储灰度图像和二值化图像
- IplImage * gray = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
- IplImage * black = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
- IplImage * black_dilate = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
- //记录较浅一些的红色
- IplImage * red_low = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
- //记录较深一些的红色
- IplImage * red_high = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
- IplImage * red = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
- cvSetImageROI(dst, rect_detect);
- #if GETREDBINARY_DEBUG
- cvSaveImage("D:\\dst.png", dst);
- #endif
- cvCvtColor(dst, hsv, CV_BGR2HSV);
- cvCvtColor(dst, gray, CV_BGR2GRAY);
- cvAdaptiveThreshold(gray, gray, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, 9, 10.0);
- rename_image(gray, binary);
- #define HSV_VALUE_H hsv_row_first[hsv_offset]
- #define HSV_VALUE_S hsv_row_first[hsv_offset+1]
- #define HSV_VALUE_V hsv_row_first[hsv_offset+2]
- const int hsv_v_valve = 255 * 50 / 100;
- const int hsv_h_max_valve = 180 * 20 / 360;
- const int hsv_h_min_valve = 180 * 315 / 360;
- const int hsv_s_valve_1 = 255 * 23 / 100;
- const int hsv_s_valve_2 = 255 * 33 / 100;
- const int hsv_valve_high = 255 * (23 + 70) / 100;
- const int hsv_valve_low = 255 * (13 + 60) / 100;
- for (int y = 0; y<h; y++)
- {
- unsigned char * hsv_row_first = (unsigned char *)(hsv->imageData + y*hsv->widthStep);
- unsigned char * red1_row_first = (unsigned char *)(red_low->imageData + y*red_low->widthStep);
- unsigned char * red2_row_first = (unsigned char *)(red_high->imageData + y*red_high->widthStep);
- unsigned char * binary_row_first = (unsigned char *)(binary->imageData + y*binary->widthStep);
- unsigned char * black_row_first = (unsigned char *)(black->imageData + y*black->widthStep);
- for (int x = 0, hsv_offset = 0; x<w; x++, hsv_offset += 3)
- {
- if (HSV_VALUE_V >= hsv_v_valve && (HSV_VALUE_H >= hsv_h_min_valve || HSV_VALUE_H <= hsv_h_max_valve)){
- red1_row_first[x] = (HSV_VALUE_S >= hsv_s_valve_1 && (HSV_VALUE_S + HSV_VALUE_V) >= hsv_valve_low) ? 255 : 0;
- red2_row_first[x] = (HSV_VALUE_S >= hsv_s_valve_2 && (HSV_VALUE_S + HSV_VALUE_V) >= hsv_valve_high) ? HSV_VALUE_S : 0;
- }
- else{
- red1_row_first[x] = red2_row_first[x] = 0;
- }
- black_row_first[x] = (binary_row_first[x] && !red1_row_first[x]) ? 255 : 0;
- }
- }
- #if GETREDBINARY_DEBUG
- cvSaveImage("D:\\hsv.png", hsv);
- cvSaveImage("D:\\red_low.png", red_low);
- cvSaveImage("D:\\red_high.png", red_high);
- cvSaveImage("D:\\binary.png", binary);
- cvSaveImage("D:\\black.png", black);
- #endif
- cvThreshold(red_high, red_high, 0, 255, CV_THRESH_OTSU);
- int an = 1;
- IplConvKernel * element = cvCreateStructuringElementEx(an * 2 + 1, an * 2 + 1, an, an, CV_SHAPE_RECT, 0);//创建结构元素
- cvDilate(binary, binary, element, 2);//膨胀图像
- cvDilate(red_high, red_high, element, 2);//膨胀图像
- cvDilate(black, black_dilate, element, 2);//膨胀图像
- for (int y = 0; y<h; y++)
- {
- unsigned char * binary_row_first = (unsigned char *)(binary->imageData + y*binary->widthStep);
- unsigned char * red1_row_first = (unsigned char *)(red_low->imageData + y*red_low->widthStep);
- unsigned char * red2_row_first = (unsigned char *)(red_high->imageData + y*red_high->widthStep);
- unsigned char * red_row_first = (unsigned char *)(red->imageData + y*red->widthStep);
- unsigned char * black_dilate_row_first = (unsigned char *)(black_dilate->imageData + y*black_dilate->widthStep);
- for (int x = 0; x<w; x++)
- {
- red_row_first[x] = (red1_row_first[x] && !black_dilate_row_first[x] && ((!binary_row_first[x]) || red2_row_first[x])) ? 255 : 0;
- }
- }
- rename_image(red_high, red_dilate);
- cvDilate(red, red_dilate, element, 2);//膨胀图像
- for (int y = 0; y<h; y++)
- {
- unsigned char * red1_row_first = (unsigned char *)(red_low->imageData + y*red_low->widthStep);
- unsigned char * red_row_first = (unsigned char *)(red->imageData + y*red->widthStep);
- unsigned char * black_row_first = (unsigned char *)(black->imageData + y*black->widthStep);
- unsigned char * red_dilate_row_first = (unsigned char *)(red_dilate->imageData + y*red_dilate->widthStep);
- for (int x = 0; x<w; x++)
- {
- red_row_first[x] = (red_row_first[x] || (red_dilate_row_first[x] && (red1_row_first[x] && !black_row_first[x]))) ? 255 : 0;
- }
- }
- cvDilate(red, red_dilate, element, 1);//膨胀图像
- for (int y = 0; y<h; y++)
- {
- unsigned char * red_row_first = (unsigned char *)(red->imageData + y*red->widthStep);
- unsigned char * black_row_first = (unsigned char *)(black->imageData + y*black->widthStep);
- unsigned char * red_dilate_row_first = (unsigned char *)(red_dilate->imageData + y*red_dilate->widthStep);
- for (int x = 0; x<w; x++)
- {
- if (!red_row_first[x] && black_row_first[x] && red_dilate_row_first[x]){
- red_row_first[x] = 255;
- }
- }
- }
- cvReleaseStructuringElement(&element);
- *red_binary = red;
- cvReleaseImage(&hsv);
- cvReleaseImage(&binary);
- cvReleaseImage(&black);
- cvReleaseImage(&black_dilate);
- cvReleaseImage(&red_low);
- cvReleaseImage(&red_dilate);
- return TRUE;
- }
- int COnLineCardPageIdentifier::mycaculate_global_background(SchemaItem items[], int itemCount, IplImage * dst)
- {
- int global_background_color_count = 0;
- int global_background_color_avg = 0;
- for (int i = 0; i<itemCount; i++)
- {
- //SchemaItem & item = schemaPage.items[i];
- SchemaItem & item = items[i];
- RESULT_RECT result_rect;
- GetRect(item.centerx, item.centery, item.width, item.height, result_rect);
- int left = int(result_rect.x);
- int top = int(result_rect.y);
- int right = int(result_rect.x + result_rect.width);
- int bottom = int(result_rect.y + result_rect.height);
- int vtop = (int)(result_rect.y - (result_rect.width + 2) / 4);
- int vbottom = (int)(result_rect.y + result_rect.height + (result_rect.height + 2) / 4);
- int background_color_count = 0, background_color_avg = 0;
- int gray;
- int(*GetGray)(const IplImage * dst, int x, int y);
- if (dst->nChannels == 1)GetGray = GetGrayValue;
- else GetGray = GetBGRGray;
- for (int x = left; x <= right; x++)
- {
- gray = GetGray(dst, x, vtop);
- if (gray>160){ background_color_avg += gray; background_color_count++; }
- gray = GetGray(dst, x, vbottom);
- if (gray>160){ background_color_avg += gray; background_color_count++; }
- }
- background_color_avg = background_color_count>0 ? background_color_avg / background_color_count : 0;
- if (background_color_avg>100){
- global_background_color_avg += background_color_avg;
- global_background_color_count++;
- }
- }
- global_background_color_avg = global_background_color_count>0 ? global_background_color_avg / global_background_color_count : 0;
- return global_background_color_avg;
- }
- //选做题分析全局属性
- int COnLineCardPageIdentifier::myanalyseOmrPanoramic(OnlineAnalyseResult& anlyseResultTemp, int count)
- {
- int i;
- int lev;
- //int count; // 所有涂点个数
- int numAblePnt; // 参与分析的点的个数
- double maxblk[16];
- int numBlk[16];
- double maxBlur[16];
- int numBlur[16];
- double stdBlur;
- memset(numBlk, 0, sizeof(int) * 16);
- memset(maxblk, 0, sizeof(double) * 16);
- memset(maxBlur, 0, sizeof(double) * 16);
- memset(numBlur, 0, sizeof(int) * 16);
- //count = schemaPage.itemCount;
- numAblePnt = 0;
- double& m_avaMaxBlk = anlyseResultTemp.avgMax_heidu;
- double& m_benchmarkBlk = anlyseResultTemp.benchmarkBlk;
- double& m_benchmarkArea = anlyseResultTemp.benchmarkAreaBlk;
- m_avaMaxBlk = 0;
- for (i = 0; i<count; i++)
- {
- OnlineAnalyseResult::itemResult& itemr = anlyseResultTemp.itemAnalyseResult[i];
- if (itemr.heidu < m_benchmarkBlk || itemr.xiangdui_value < m_benchmarkArea)
- continue;
- if (itemr.heidu< 4.0) continue;
- m_avaMaxBlk += itemr.heidu;
- numAblePnt++;
- lev = int(itemr.heidu);
- maxblk[lev] += itemr.heidu;
- numBlk[lev] ++;
- lev = int(itemr.mohudu);
- maxBlur[lev] += itemr.mohudu;
- numBlur[lev] ++;
- //pPnt++;
- }
- if (numAblePnt > 0)
- m_avaMaxBlk /= numAblePnt;
- else
- m_avaMaxBlk = 12;
- int stdId = 2;
- int numStd = numBlk[0] + numBlk[1] + numBlk[2];
- int numCur = numStd;
- for (i = 3; i<16; i++)
- {
- numCur += (numBlk[i] - numBlk[i - 3]);
- if (numCur > numStd)
- {
- numStd = numCur;
- stdId = i;
- }
- }
- double stdBlk = maxblk[stdId - 2] + maxblk[stdId - 1] + maxblk[stdId];
- if (numStd > 0)
- stdBlk /= numStd;
- else
- stdBlk = 12;
- // 计算模糊度代表值
- stdId = 2;
- numStd = numBlur[0] + numBlur[1] + numBlur[2];
- numCur = numStd;
- for (i = 3; i<16; i++)
- {
- numCur += (numBlur[i] - numBlur[i - 3]);
- if (numCur > numStd)
- {
- numStd = numCur;
- stdId = i;
- }
- }
- stdBlur = maxBlur[stdId - 2] + maxBlur[stdId - 1] + maxBlur[stdId];
- if (numStd > 0)
- stdBlur /= numStd;
- else
- stdBlur = 0;
- if (stdBlur < 2.0)
- stdBlk -= stdBlur;
- else
- stdBlk -= 2.0;
- if (stdBlk < m_avaMaxBlk)
- m_avaMaxBlk = stdBlk;
- //统计字符区域的黑色点数的平均值
- int max_item = count;
- int * char_area_black_counts = new int[1];
- int cur_item_count;//当前选项的数量
- for (int ii = 0; ii<max_item; ii++)
- {
- cur_item_count = 0;
- long total_char_area_size = 0;
- for (int gi = 0; gi<1; gi++)
- {
- if (max_item > ii){
- OnlineAnalyseResult::itemResult & ir = anlyseResultTemp.itemAnalyseResult[ii];
- char_area_black_counts[cur_item_count] = ir.char_area_black_count;
- total_char_area_size += ir.char_area_size;
- cur_item_count++;
- }
- }
- double char_area_size_avg = total_char_area_size / (double)cur_item_count;
- int temp;
- for (int m = 0; m<cur_item_count; m++)
- {
- for (int n = m + 1; n<cur_item_count; n++)
- {
- if (char_area_black_counts[n]<char_area_black_counts[m]){
- temp = char_area_black_counts[n];
- char_area_black_counts[n] = char_area_black_counts[m];
- char_area_black_counts[m] = temp;
- }
- }
- }
- anlyseResultTemp.char_area_black_avg[ii] = -1;
- if (char_area_black_counts[0] * 1.4<char_area_black_counts[cur_item_count - 1] || char_area_black_counts[cur_item_count - 1] * 1.4<char_area_size_avg){
- double t = char_area_black_counts[0] * 1.15;
- double f = 0;
- int count__ = 0;
- for (int l = 0; l<cur_item_count; l++)
- {
- if (t<char_area_black_counts[l]){
- f += char_area_black_counts[l];
- count__++;
- }
- }
- anlyseResultTemp.char_area_black_avg[ii] = f / count__;
- }
- }
- delete[]char_area_black_counts;
- return(0);
- }
- /************************************************************************/
- /* 获取选做题选择项 */
- /************************************************************************/
- int COnLineCardPageIdentifier::myGenerateOmrStr(OnlineAnalyseResult& anlyseResultTemp, int count)
- {
- int omr_str_len = 0;
- //标记是否被选中
- SelectType sel[MAX_ITEM] = { SelectType::UNSELECT };
- int pn = min(MAX_ITEM, count);
- OnlineAnalyseResult::itemResult* results[MAX_ITEM];
- for (int i = 0; i<pn; i++){
- results[i] = &anlyseResultTemp.itemAnalyseResult[i];
- }
- int maxgraynum = -1;
- int mingraynum = 0xffffff;
- for (int i = 0; i<pn; i++)
- {
- if (results[i]->gray_num>maxgraynum)maxgraynum = results[i]->gray_num;
- if (results[i]->gray_num<mingraynum)mingraynum = results[i]->gray_num;
- }
- int selected_num = 0;
- int unselect_num = 0;
- int uncertain_num = 0;
- for (int i = 0; i<pn; i++)
- {
- //被涂面积小于10%
- if (results[i]->gray_num<results[i]->cell_size*0.1){
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- //面积超过65%
- if (results[i]->gray_num>results[i]->cell_size*0.65){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%15,将面积不小于最大点填涂面积的总面积%10的涂点视为填涂
- if (maxgraynum - mingraynum>results[i]->cell_size*0.15&&results[i]->gray_num>maxgraynum - results[i]->cell_size*0.1){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%50,将面积不小于最大点填涂面积的总面积%30的涂点视为填涂
- if (maxgraynum - mingraynum>results[i]->cell_size*0.5&&results[i]->gray_num>maxgraynum - results[i]->cell_size*0.3){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- if (maxgraynum - results[i]->gray_num>results[i]->cell_size*0.2){
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- sel[i] = UNCERTAIN;
- uncertain_num++;
- }
- identify::result::OMR_QUESTION_STATE question_state = identify::result::OMR_QUESTION_STATE::OMR_QUESTION_STATE_NORMAL;
- if (selected_num>1){
- int maxgrayindex = -1;
- int maxgraynum = -101;
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED){
- if ((results[i]->gray_num - maxgraynum > 100) || (abs(results[i]->gray_num - maxgraynum) <= 100 && results[i]->heidu > results[maxgrayindex]->heidu))
- {
- maxgraynum = results[i]->gray_num;
- maxgrayindex = i;
- }
- }
- }
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED&&i != maxgrayindex){
- sel[i] = UNSELECT;
- }
- }
- }
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED){
- return i;
- }
- }
- return -1;
- }
- //读取选做题选项数据
- int COnLineCardPageIdentifier::ReadXuanZuoTi(SchemaPage& schemaPage, SchemaQuestionScore& qs, IplImage * dst)
- {
- int global_background_color_avg = mycaculate_global_background(qs.item, qs.countNum, dst);
- //模糊度,面积,高黑度,平均黑度
- double mo_hu_du, refArea, gao_heidu, avg_gray;
- //黑色像素数,涂点大小
- int grayNum, cellSize;
- //高黑度和
- double topGraySum = 0;
- //高黑度面积
- double topGrayAreaSum = 0;
- OnlineAnalyseResult anlyseResultTemp;
- anlyseResultTemp.backGroundGray = global_background_color_avg;
- anlyseResultTemp.cellAvgGray = 0;
- anlyseResultTemp.cellNum = 0;
- int numTopGray = 0;
- int ret;
- for (int i = 0; i<qs.countNum; i++)
- {
- SchemaItem & item = qs.item[i];
- ret = caculate_cell_property(schemaPage, item, dst, cellSize, refArea, avg_gray, grayNum, mo_hu_du, gao_heidu, anlyseResultTemp.itemAnalyseResult[i].char_area_size, anlyseResultTemp.itemAnalyseResult[i].char_area_black_count, anlyseResultTemp.itemAnalyseResult[i].char_area_avg_gray);
- if (ret != identify::result::IDF_SUCCESS)return ret;
- topGraySum += gao_heidu;
- topGrayAreaSum += refArea;
- numTopGray++;
- anlyseResultTemp.cellAvgGray += static_cast<int>(avg_gray);
- anlyseResultTemp.cellNum++;
- anlyseResultTemp.itemAnalyseResult[i].avg_gray = static_cast<int>(avg_gray);
- anlyseResultTemp.itemAnalyseResult[i].cell_size = cellSize;
- anlyseResultTemp.itemAnalyseResult[i].gray_num = grayNum;
- anlyseResultTemp.itemAnalyseResult[i].heidu = gao_heidu;
- anlyseResultTemp.itemAnalyseResult[i].mohudu = mo_hu_du;
- anlyseResultTemp.itemAnalyseResult[i].xiangdui_mianji = refArea;
- anlyseResultTemp.itemAnalyseResult[i].xiangdui_value = refArea;
- }
- anlyseResultTemp.cellAvgGray = anlyseResultTemp.cellNum>0 ? anlyseResultTemp.cellAvgGray / anlyseResultTemp.cellNum : 256;
- anlyseResultTemp.avg_heidu = topGrayAreaSum>0 ? topGraySum / topGrayAreaSum : 6;
- if (numTopGray >= int(schemaPage.itemCount / 5)){
- anlyseResultTemp.float_heidu = anlyseResultTemp.avg_heidu / schemaPage.user_float_heidu;
- anlyseResultTemp.benchmarkBlk = schemaPage.worthwhileBlk + anlyseResultTemp.float_heidu;
- }
- else{
- anlyseResultTemp.benchmarkBlk = numTopGray>0 ? min(6.0, schemaPage.worthwhileBlk + anlyseResultTemp.avg_heidu / schemaPage.user_float_heidu) : 6;
- anlyseResultTemp.float_heidu = anlyseResultTemp.benchmarkBlk - schemaPage.worthwhileBlk;
- }
- if (numTopGray>0){
- anlyseResultTemp.avg_heidu = topGrayAreaSum / numTopGray;
- anlyseResultTemp.float_heidu = anlyseResultTemp.avg_heidu / schemaPage.user_float_heidu;
- anlyseResultTemp.benchmarkAreaBlk = anlyseResultTemp.float_heidu;
- }
- else{
- anlyseResultTemp.avg_heidu = 0;
- anlyseResultTemp.float_heidu = 0;
- anlyseResultTemp.benchmarkAreaBlk = 0.1;
- }
- int r = myanalyseOmrPanoramic(anlyseResultTemp, qs.countNum);
- r = myGenerateOmrStr(anlyseResultTemp, qs.countNum);
- return r;
- }
- int COnLineCardPageIdentifier::GenerateOmrStr(SchemaPage& schemaPage, string &ret)
- {
- char omr_str[512] = { 0 };
- //标记是否被选中
- SelectType sel[200] = { SelectType::UNSELECT };
-
- for (int groupIndex = 0; groupIndex<schemaPage.stuGroupsCount; groupIndex++)
- {
- int omr_str_len = 0;
- memset(sel, UNSELECT, sizeof(sel));
- SchemaGroup& group = schemaPage.stuGroups[groupIndex];
- int pn = min(200, group.itemCount);
- OnlineAnalyseResult::itemResult* results[200];
- SchemaItem* items[200];
- int maxgraynum = -1;
- int mingraynum = 0xffffff;
- for (int i = 0; i<pn; i++){
- results[i] = &anlyseResult.itemAnalyseResult[group.itemIndex[i]];
- items[i] = &m_items[group.itemIndex[i]];
- if (results[i]->gray_num > maxgraynum)maxgraynum = results[i]->gray_num;
- if (results[i]->gray_num < mingraynum)mingraynum = results[i]->gray_num;
- }
- int selected_num = 0;
- int unselect_num = 0;
- int uncertain_num = 0;
- for (int i = 0; i<pn; i++)
- {
- //面积超过65%
- if (results[i]->gray_num>results[i]->cell_size*0.65){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%20,将面积不小于最大点填涂面积的总面积%10的涂点视为填涂
- if (maxgraynum - mingraynum>results[i]->cell_size*0.2&&results[i]->gray_num>maxgraynum - results[i]->cell_size*0.1){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%50,将面积不小于最大点填涂面积的总面积%30的涂点视为填涂
- if (maxgraynum - mingraynum>results[i]->cell_size*0.5&&results[i]->gray_num>maxgraynum - results[i]->cell_size*0.3){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- sel[i] = UNCERTAIN;
- uncertain_num++;
- }
- if (group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT){
- if (selected_num > 1){
- int maxgrayindex = -1;
- int maxgraynum = -101;
- int countSel = 0;
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED)
- {
- countSel++;
- if ((results[i]->gray_num - maxgraynum>100) || (abs(results[i]->gray_num - maxgraynum) <= 100 && results[i]->heidu > results[maxgrayindex]->heidu))
- {
- maxgraynum = results[i]->gray_num;
- maxgrayindex = i;
- }
- }
- }
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED&&i != maxgrayindex){
- sel[i] = UNSELECT;
- }
- }
- }
- int out_count = 0;
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED){
- if (out_count > 0)omr_str[omr_str_len++] = schemaPage.option_spacer;
- omr_str[omr_str_len++] = items[i]->OutChar;
- out_count++;
- }
- }
- if (omr_str_len != 1){
- return 1;
- }
- omr_str[omr_str_len] = '\0';
- ret += omr_str;
- }
- }
- return 0;
- }
- //读取缺考标记
- bool COnLineCardPageIdentifier::ReadQuekaoFlag(SchemaPage &schemaPage, IplImage * dst)
- {
- if (schemaPage.quekaoLocatePointIndex.size() < 1)
- return false;
- SchemaItem item;
- item.centerx = schemaPage.quekao.centerx;
- item.centery = schemaPage.quekao.centery;
- item.width = schemaPage.quekao.width;
- item.height = schemaPage.quekao.height;
- int cellSize, grayNum, char_area_size, char_area_black_count;
- double refArea, avg_gray, mo_hu_du, gao_heidu, char_area_avg_gray;
- if (schemaPage.itemCount == 0 && schemaPage.stuQuestionLocatePointIndex.size() < 1)
- {
- anlyseResult.backGroundGray = 225;
- }
- int ret = caculate_cell_property(schemaPage, item, dst, cellSize, refArea, avg_gray, grayNum, mo_hu_du, gao_heidu, char_area_size, char_area_black_count, char_area_avg_gray);
- OnlineAnalyseResult anlyseResult;
- anlyseResult.cellAvgGray += static_cast<int>(avg_gray);
- anlyseResult.cellNum++;
- anlyseResult.itemAnalyseResult[0].avg_gray = static_cast<int>(avg_gray);
- anlyseResult.itemAnalyseResult[0].cell_size = cellSize;
- anlyseResult.itemAnalyseResult[0].gray_num = grayNum;
- anlyseResult.itemAnalyseResult[0].heidu = gao_heidu;
- anlyseResult.itemAnalyseResult[0].mohudu = mo_hu_du;
- anlyseResult.itemAnalyseResult[0].xiangdui_mianji = refArea;
- anlyseResult.itemAnalyseResult[0].xiangdui_value = refArea;
- //标记是否被选中
- SelectType sel = UNSELECT;
- OnlineAnalyseResult::itemResult* results;
- results = &anlyseResult.itemAnalyseResult[0];
-
- int maxgraynum = -1;
- int mingraynum = 0xffffff;
- if (results->gray_num>maxgraynum)maxgraynum = results->gray_num;
- if (results->gray_num<mingraynum)mingraynum = results->gray_num;
- //面积超过65%
- if (results->gray_num>results->cell_size*0.65){
- sel = SELECTED;
- return true;
- }
- //填涂面积相差达%20,将面积不小于最大点填涂面积的总面积%10的涂点视为填涂
- if (maxgraynum - mingraynum>results->cell_size*0.2&&results->gray_num>maxgraynum - results->cell_size*0.1){
- sel = SELECTED;
- return true;
- }
- //填涂面积相差达%50,将面积不小于最大点填涂面积的总面积%30的涂点视为填涂
- if (maxgraynum - mingraynum>results->cell_size*0.5&&results->gray_num>maxgraynum - results->cell_size*0.3){
- sel = SELECTED;
- return true;
- }
- return false;
- }
- void COnLineCardPageIdentifier::DrawSchema(IplImage*dst_img, SchemaPage* & pageSchema)
- {
- // 绘制定位点
- for (std::size_t i = 0; i < pageSchema->questionLocatePoints.size(); i++){
- cvDrawRect(dst_img,
- cvPoint(pageSchema->questionLocatePoints[i].centerx - pageSchema->questionLocatePoints[i].width / 2.0, pageSchema->questionLocatePoints[i].centery - pageSchema->questionLocatePoints[i].height / 2.0),
- cvPoint(pageSchema->questionLocatePoints[i].centerx + pageSchema->questionLocatePoints[i].width / 2.0, pageSchema->questionLocatePoints[i].centery + pageSchema->questionLocatePoints[i].height / 2.0),
- cvScalar(0, 255, 0));
- }
- // 绘制二维码 条形码
- for (std::size_t i = 0; i < pageSchema->codes.size(); i++){
- cvDrawRect(dst_img,
- cvPoint(pageSchema->codes[i].centerx - pageSchema->codes[i].width / 2.0, pageSchema->codes[i].centery - pageSchema->codes[i].height / 2.0),
- cvPoint(pageSchema->codes[i].centerx + pageSchema->codes[i].width / 2.0, pageSchema->codes[i].centery + pageSchema->codes[i].height / 2.0),
- cvScalar(0, 255, 0));
- }
- // 绘制
- for (std::size_t i = 0; i < pageSchema->items.size(); i++){
- cvDrawRect(dst_img,
- cvPoint(pageSchema->items[i].centerx - pageSchema->items[i].width / 2.0, pageSchema->items[i].centery - pageSchema->items[i].height / 2.0),
- cvPoint(pageSchema->items[i].centerx + pageSchema->items[i].width / 2.0, pageSchema->items[i].centery + pageSchema->items[i].height / 2.0),
- cvScalar(0, 255, 0));
- }
- // 主观题
- for (std::size_t i = 0; i < pageSchema->question_score.size(); i++){
- if (pageSchema->question_score[i].scoreBox.bXuanZuoTi){
- for (int j = 0; j < pageSchema->question_score[i].countNum; j++){
- cvDrawRect(dst_img,
- cvPoint(pageSchema->question_score[i].item[j].centerx - pageSchema->question_score[i].item[j].width / 2.0, pageSchema->question_score[i].item[j].centery - pageSchema->question_score[i].item[j].height / 2.0),
- cvPoint(pageSchema->question_score[i].item[j].centerx + pageSchema->question_score[i].item[j].width / 2.0, pageSchema->question_score[i].item[j].centery + pageSchema->question_score[i].item[j].height / 2.0),
- cvScalar(0, 255, 0));
- }
- }
- cvDrawRect(dst_img,
- cvPoint(pageSchema->question_score[i].centerx - pageSchema->question_score[i].width / 2.0, pageSchema->question_score[i].centery - pageSchema->question_score[i].height / 2.0),
- cvPoint(pageSchema->question_score[i].centerx + pageSchema->question_score[i].width / 2.0, pageSchema->question_score[i].centery + pageSchema->question_score[i].height / 2.0),
- cvScalar(0, 255, 0));
- // 绘制打分区域
- int x = pageSchema->question_score[i].scoreBox.pos.x,
- y = pageSchema->question_score[i].scoreBox.pos.y,
- w = pageSchema->question_score[i].scoreBox.pos.w,
- h = pageSchema->question_score[i].scoreBox.pos.h;
- cvDrawRect(dst_img,
- cvPoint(x, y),
- cvPoint(x + w, y + h),
- cvScalar(255, 0,0));
- }
- // 学号
- for (std::size_t i = 0; i < pageSchema->stuItems.size(); i++){
- cvDrawRect(dst_img,
- cvPoint(pageSchema->stuItems[i].centerx - pageSchema->stuItems[i].width / 2.0, pageSchema->stuItems[i].centery - pageSchema->stuItems[i].height / 2.0),
- cvPoint(pageSchema->stuItems[i].centerx + pageSchema->stuItems[i].width / 2.0, pageSchema->stuItems[i].centery + pageSchema->stuItems[i].height / 2.0),
- cvScalar(0, 255, 0));
- }
- //缺考标识
- if (pageSchema->quekaoLocatePointIndex.size()>0){
- cvDrawRect(dst_img,
- cvPoint(pageSchema->quekao.centerx - pageSchema->quekao.width / 2.0, pageSchema->quekao.centery - pageSchema->quekao.height / 2.0),
- cvPoint(pageSchema->quekao.centerx + pageSchema->quekao.width / 2.0, pageSchema->quekao.centery + pageSchema->quekao.height / 2.0),
- cvScalar(0, 0, 255));
- }
- }
- }
|