1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336 |
- #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"
- #include "IdentifyArea.h"
- #include <atomic>
- #include <mutex>
- #define POSITION_JUGDMENT_THRESHOLD 0.6184074853897741
- std::atomic<int> g_examid_by_qr_code = 0;
- std::mutex g_mtx_examid;
- extern std::string g_appFilePathName;
- static std::string GetExePath()
- {
- HMODULE module = GetModuleHandle(0);
- char pFileName[MAX_PATH + 2] = { 0 };
- GetModuleFileNameA(module, pFileName, MAX_PATH);
- std::string csFullPath(pFileName);
- std::size_t nPos = csFullPath.find_last_of('\\');
- if (nPos == std::string::npos)
- return "";
- else
- return csFullPath.substr(0, nPos);
- }
- /********************************************************
- * @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_ttpdd.lib")
- #pragma comment(lib,"../Win32/Debug/client_interactive_api_d.lib")
- #pragma comment(lib,"../Win32/Debug/client_interactive_api_code_d.lib")
- #else
- #pragma comment(lib,"../lib/myqr/Release/GetQR.lib")
- #pragma comment(lib,"../Win32/Release/client_interactive_api_ttpd.lib")
- #pragma comment(lib,"../Win32/Release/client_interactive_api.lib")
- #pragma comment(lib,"../Win32/Release/client_interactive_api_code.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()
- {
- HMODULE module = GetModuleHandle(0);
- char pFileName[MAX_PATH + 2] = { 0 };
- GetModuleFileNameA(module, pFileName, MAX_PATH);
- std::string strPath = pFileName;
- int pos = strPath.find_last_of('\\', strPath.length());
- strPath = strPath.substr(0, pos) + "\\..\\config.ini";
- int nType = GetPrivateProfileIntA("USER", "algorithm_boption", 1, strPath.c_str());
- m_nBxuanxiang = (nType == 1);
- 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){
- //LOGI("COnLineCardPageIdentifier::Identify 异常");
- 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::SetOnlineScanType(int nOnlineScanType)
- {
- m_nOnlineScanType = nOnlineScanType;
- }
- 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)
- {
- int range = m_pTemplate->dingweidian_range_top;
- //LOGFMTI("MyFindDingWeiDian 1 range=%d", range);
- CvRect roi[4] = {//上下左右 roi
- cvRect(0, 0, src_gray_img->width, min(range, src_gray_img->height)),
- cvRect(0, src_gray_img->height - min(range, src_gray_img->height) - 1, src_gray_img->width, min(range, src_gray_img->height)),
- cvRect(0, 0, min(range, src_gray_img->width), src_gray_img->height),
- cvRect(src_gray_img->width - min(range, src_gray_img->width) - 1, 0, min(range, src_gray_img->width), src_gray_img->height)
- };
- //LOGFMTI("MyFindDingWeiDian 2 range=%d", range);
- 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));
- //LOGFMTI("MyFindDingWeiDian 3 x=%d y= %d,w = %d h = %d", roi[dir].x, roi[dir].y, roi[dir].width, roi[dir].height);
- 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);
- if (m_pTemplate->open_save_debug_img){
- char szImageName[1024] = { 0 };
- sprintf_s(szImageName, "%s\\image\\Debug\\find_dingweidian_top%d.jpg", g_appFilePathName, dir);
- cvSaveImage(szImageName, 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));
- 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] * m_pTemplate->dingweidian_w_max_rate)continue;
- if (c->rect.height > schema_param.maxh[dir] * m_pTemplate->dingweidian_h_max_rate)continue;
- if (c->rect.width < schema_param.minw[dir] * m_pTemplate->dingweidian_w_min_rate)continue;
- if (c->rect.height < schema_param.minh[dir] * m_pTemplate->dingweidian_h_min_rate)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)
- {
- //LOGFMTI("MyFindDingWeiDian 4 range=%d", range);
- _dir = dir;
- if (MyFindBottomDingWeiDian(src_gray_img, storage, schema_param, locate_point_list, dir) == identify::result::IDF_FAILURE)
- return identify::result::IDF_FAILURE;
- //LOGFMTI("MyFindDingWeiDian 5 range=%d", range);
- 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)
- {
- int nRange = m_pTemplate->dingweidian_rang_buttom;
- CvRect roi[4] = {//上下左右 roi
- cvRect(0, 0, src_gray_img->width, min(nRange, src_gray_img->height)),
- cvRect(0, src_gray_img->height - min(nRange, src_gray_img->height) - 1, src_gray_img->width, min(nRange, src_gray_img->height)),
- cvRect(0, 0, min(nRange, src_gray_img->width), src_gray_img->height),
- cvRect(src_gray_img->width - min(nRange, src_gray_img->width) - 1, 0, min(nRange, 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);
- if (m_pTemplate->open_save_debug_img){
- char szImageName[1024] = { 0 };
- sprintf_s(szImageName, "%s\\image\\Debug\\find_dingweidian_buttom%d.jpg", g_appFilePathName, dir);
- cvSaveImage(szImageName, 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] * m_pTemplate->dingweidian_w_max_rate)continue;
- if (c->rect.height > schema_param.maxh[dir] * m_pTemplate->dingweidian_h_max_rate)continue;
- if (c->rect.width < schema_param.minw[dir] * m_pTemplate->dingweidian_w_min_rate)continue;
- if (c->rect.height < schema_param.minh[dir] * m_pTemplate->dingweidian_h_min_rate)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
- {
- // 大于要求数量
- if (contourList.size()>2)
- {
- //查找顶部定位点,宽高最大最小值
- int minw = locate_point_list[0].width;
- int maxw = locate_point_list[0].width;
- int minh = locate_point_list[0].height;
- int maxh = locate_point_list[0].height;
- for (int i = 1; i < locate_point_list.size(); i++)
- {
- //宽度计算
- if (locate_point_list[i].width > maxw)
- {
- maxw = locate_point_list[i].width;
- }
- else if (locate_point_list[i].width < minw)
- {
- minw = locate_point_list[i].width;
- }
- //高度计算
- if (locate_point_list[i].height > maxh)
- {
- maxh = locate_point_list[i].height;
- }
- else if (locate_point_list[i].height < minh)
- {
- minh = locate_point_list[i].height;
- }
- }
- minw = (schema_param.minw[dir] + minw) / 2;
- minh = (schema_param.minh[dir] + minh) / 2;
- maxw = (schema_param.maxw[dir] + maxw) / 2;
- maxh = (schema_param.maxh[dir] + maxh) / 2;
- // locate_point_list
- std::vector<CvRect> tempvecBottom;
- for (std::size_t i = 0; i < contourList.size(); i++){
- CvRect rect = contourList[i]->rect;
- if (rect.width >= minw && rect.width <= maxw && rect.height >= minh && rect.height <= maxh)
- {
- tempvecBottom.push_back(rect);
- }
- }
- if (tempvecBottom.size() == 2)
- {
- //成功找到数据
- for (std::size_t i = 0; i < tempvecBottom.size(); i++){
- m_vecBottom.push_back(tempvecBottom[i]);
- }
- 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 if (tempvecBottom.size() > 2)
- {
- //水平方向
- if (dir == 0 || dir == 1){
- std::sort(tempvecBottom.begin(), tempvecBottom.end(), sort_locate_point_by_x);
- //计算在识别区范围内
- float k = (float)(locate_point_list[locate_point_list.size() - 1].y - locate_point_list[0].y) / (locate_point_list[locate_point_list.size() - 1].x - locate_point_list[0].x);
- for (int i = 1; i < tempvecBottom.size() - 1; i++)
- {
- float y = tempvecBottom[0].y + k*(tempvecBottom[i].x - tempvecBottom[0].x);
- if ((tempvecBottom[i].y >(y - maxh)) && (tempvecBottom[i].y < (y + maxh)))
- return identify::result::IDF_FAILURE;
- }
- m_vecBottom.push_back(tempvecBottom[0]);
- m_vecBottom.push_back(tempvecBottom[tempvecBottom.size() - 1]);
- 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 {
- //水平方向垂直方向
- std::sort(tempvecBottom.begin(), tempvecBottom.end(), sort_locate_point_by_y);
- float k = (locate_point_list[locate_point_list.size() - 1].x - locate_point_list[0].x)/(float)(locate_point_list[locate_point_list.size() - 1].y - locate_point_list[0].y);
- for (int i = 1; i < tempvecBottom.size() - 1; i++)
- {
- float x = tempvecBottom[0].x + k*(tempvecBottom[i].y - tempvecBottom[0].y);
- if ((tempvecBottom[i].x >(x - maxw)) && (tempvecBottom[i].x < (x + maxw)))
- return identify::result::IDF_FAILURE;
- }
- m_vecBottom.push_back(tempvecBottom[0]);
- m_vecBottom.push_back(tempvecBottom[tempvecBottom.size() - 1]);
- 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;
- }
-
- }
-
- }
- return identify::result::IDF_FAILURE;
- }
- }
- }
- double COnLineCardPageIdentifier::CalcRectArea(IplImage* src, const std::vector<CvRect> & top_locate_point_list, const std::vector<CvRect> & bottom_locate_point_list)
- {
- int areaS = 0;
- int h = 0;
- int w = 0;
- std::vector<int> xVec;
- std::vector<int> yVec;
- for (int i = 0; i < top_locate_point_list.size(); i++)
- {
- xVec.push_back(top_locate_point_list[i].x);
- yVec.push_back(top_locate_point_list[i].y);
- }
- for (int i = 0; i < bottom_locate_point_list.size(); i++)
- {
- xVec.push_back(bottom_locate_point_list[i].x);
- yVec.push_back(bottom_locate_point_list[i].y);
- }
- std::sort(xVec.begin(), xVec.end());
- std::sort(yVec.begin(), yVec.end());
- areaS = (xVec[yVec.size() - 1] - xVec[0]) *(yVec[yVec.size() - 1] - yVec[0]);
- return (double)areaS / (double)(src->width*src->height);
- }
- 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, int code_type)
- {
- std::string result;
- CvRect myRect = cvRect( main_locate_point[0].x + schema_param.paper_bar_offsetx1,
- 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);
- m_pTemplate->open_save_debug_img = 1;
- if (m_pTemplate->open_save_debug_img)
- {
- string tempfile = g_appFilePathName + "\\image\\Debug\\GetQrCode.JPG";
- cv::imwrite(tempfile.c_str(), cvarrToMat(mydst_gray_img));
- }
- cv::Mat matDstGray = cvarrToMat(mydst_gray_img);
- int ret = 0;
- try{
- // ret = GetQR(matDstGray, result);
- char szRes[1024];
- ret = api_parse_barcode_qrcode(matDstGray, code_type, szRes, 1024);
- result = szRes;
- }
- 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;
- }
- }
- }
- }
- #ifdef _draw_debug
- void drawDebug(IplImage* dst_img, PageTemplate*page)
- {
- if (!dst_img)return;
- double w_rate = dst_img->width*1.0 / page->w;
- double h_rate = dst_img->height*1.0 / page->h;
- auto pDrawFunc = [&](const OnLineCard::Pos&pos, CvScalar clr,bool flag){
- cvDrawRect(dst_img,
- cvPoint(((flag ? 0 : page->location[0].pos.x) + pos.x)*w_rate, ((flag ? 0 : page->location[0].pos.y) + pos.y)*h_rate),
- cvPoint(((flag ? 0 : page->location[0].pos.x) + pos.x + pos.w)*w_rate, ((flag ? 0 : page->location[0].pos.y) + pos.y + pos.h)*h_rate),
- clr);
- };
- // 绘制定位点
- for (auto it : page->location){
- pDrawFunc(it.pos, CvScalar(0, 255, 0),true);
- }
- if (page->pageNo==1){ // 首页
- for (auto it : page->studentcode_fill){
- for (auto it1:it){
- pDrawFunc(it1.pos, CvScalar(0, 255, 0), false);
- }
- }
- pDrawFunc(page->absent, CvScalar(0, 255, 0), false);
- pDrawFunc(page->QrCode, CvScalar(0, 255, 0), false);
- }
- for (auto it: page->vctQuestions)
- {
- for (auto opt: it.opt){
- pDrawFunc(opt.pos, CvScalar(0, 255, 0), false);
- }
- pDrawFunc(it.scoreBox.pos, CvScalar(0, 255, 0), false);
- pDrawFunc(it.cut.pos, CvScalar(255, 255, 0), false);
- }
- 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();
- std::string filetemppath = g_appFilePathName + "\\image1\\";
- CreateDirectoryA(filetemppath.c_str(), NULL);
- std::string path = g_appFilePathName + std::string("\\image1\\") + std::to_string(timestamp) + ".jpg";
- cvSaveImage(path.c_str(), dst_img);
- }
- #endif
- //构建试卷的识别区域
- int COnLineCardPageIdentifier::createSchema(const IplImage* src, IplImage* *dst, SchemaPage* *pageSchema, const char * result_path, bool flag, std::string qr, bool bUseQr)
- {
- ////LOGI("createSchema 1");
- 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;
- //#ifdef _draw_debug
- // IplImage*src_debug = cvCloneImage(src);
- //#endif
- ////LOGI("createSchema 1.3");
- 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;
- int qrFlag = 0;
- ////LOGI("createSchema 1.31");
- CvMemStorage* storage = cvCreateMemStorage(0);
- IplImage * src_gray_img;
- int question_count = 0;
- int itemcount = 0;
- ////LOGI("createSchema 1.4");
- cvResetImageROI((IplImage*)src0);
- ////LOGI("createSchema 1.41");
- src_gray_img = cvCreateImage(cvGetSize(src0), IPL_DEPTH_8U, 1);
- ////LOGI("createSchema 1.42");
- #ifdef _DEBUG
- m_pTemplate->open_save_debug_img = true;
- cvSaveImage("d:\\image\\src0.png", src0);
- cvSaveImage("d:\\image\\src_gray_img.png", src_gray_img);
- #endif
- cvCvtColor(src0, src_gray_img, CV_BGR2GRAY);
- ////LOGI("createSchema 1.43");
- ////LOGI("createSchema 1.5");
- schema_const_param schema_param;
- std::vector<CvRect> main_locate_point;
- CvPoint offset_pt;
- int dir;//上下左右
- //1.查找定位点
- // 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;
- }
- }
- if (m_nOnlineScanType == 0)
- {
- // 魔法词汇宝
- if (CalcRectArea(src0, main_locate_point, m_vecBottom) < POSITION_JUGDMENT_THRESHOLD)
- {
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- cvSetImageROI(src0, roi_old);
- return identify::result::IDF_TEMPLATE_NOTFOUND_ENOUGH_LOCATEPOINT;
- }
- }
- IplImage * dst_img = NULL;
- //2.矫正图像
- 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;
- }
- 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();
- 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(dst_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;
- }
- }
- //3.确定模板和识别图片的比例关系
- 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);
- }
- std::string exam_id_by_qr_code;
- bool is_same_exam_id = true;
- 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];
- //#ifdef _draw_debug
- // drawDebug(src_debug, &page);
- // cvReleaseImage(&src_debug);
- //#endif
- #ifdef _draw_debug
- IplImage*src_debug = cvCloneImage(dst_img);
- #endif
- ////LOGI("createSchema 5");
- // 正面
- 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{
- // 二维码
- double x = page.QrCode.x*w_scale - 20;
- double y = page.QrCode.y*h_scale - 20;
- schema_param.paper_bar_width1 = page.QrCode.w*w_scale + 40;
- if (schema_param.paper_bar_width1 + x >= dst_gray_img->width)
- schema_param.paper_bar_width1 = dst_gray_img->width - x - 2;
- schema_param.paper_bar_height1 = page.QrCode.h*h_scale + 40;
- schema_param.paper_bar_offsetx1 = x;
- schema_param.paper_bar_offsety1 = y;
-
- 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, CODE_QR);
- if (student_code != "")
- qrFlag = 1;
- else
- qrFlag = -1;
- 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 (splits.size()> 0)
- {
- std::lock_guard<std::mutex> _lck(g_mtx_examid);
- if (g_examid_by_qr_code.load() == 0){
- g_examid_by_qr_code.store(1);
- exam_id_by_qr_code = paper_id;
- std::string str_cfg_path = GetExePath() + "\\paperinfo.ini";
- char cfg_exam_id[128] = { 0 };
- //paperinfo/exam_id
- GetPrivateProfileStringA("paperinfo", "exam_id", "", cfg_exam_id, 128, str_cfg_path.c_str());
- if (exam_id_by_qr_code != cfg_exam_id && m_nOnlineScanType != 0){
- is_same_exam_id = false;
- }
- }
- }
- if (student_code.empty()){
- if (!codev.empty())
- code_tmp = codev[0];
- codev.clear();
- }
- }
- is_stu_id = !student_code.empty();
- }
- else{
- std::lock_guard<std::mutex> _lck(g_mtx_examid);
- if (g_examid_by_qr_code.load() == 0){
- std::string paper_id, student_code;
- std::vector<SchemaCode> vct_tmp_codev;
- ret = GetQrCode(dst_gray_img, schema_param, main_locate_point, vct_tmp_codev, student_code, student_code, CODE_QR);
- if (!vct_tmp_codev.empty()){
- vector<std::string> splits;
- split(student_code, (std::string)"@", &splits);
- if (splits.size() == 1){
- paper_id = splits[0];
- student_code = "";
- }
- else if (splits.size() >= 2){
- student_code = splits[0];
- paper_id = splits[1];
- }
- g_examid_by_qr_code.store(1);
- exam_id_by_qr_code = paper_id;
- std::string str_cfg_path = GetExePath() + "\\paperinfo.ini";
- char cfg_exam_id[128] = { 0 };
- //paperinfo/exam_id
- GetPrivateProfileStringA("paperinfo", "exam_id", "", cfg_exam_id, 128, str_cfg_path.c_str());
- if (exam_id_by_qr_code != cfg_exam_id && m_nOnlineScanType != 0){
- is_same_exam_id = false;
- }
- }
- }
- }
- // 二维码中含有学生信息 不需要识别条形码和填涂考号
- 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, CODE_BAR);
- 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 || qt.type == 5){//选
- 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 : ((qt.type == 8) ? OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT : OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT_EX));
- 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 < (m_pTemplate->_version=="old" ?2:1)){
- SchemaQuestionScore sqs;
- 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 + (m_pTemplate->_version == "old" ? 0 : 1); // 加入0 老版没有这
- 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.question_code_temp = qt.all_id;
- }
- else
- {
- sqs.question_code_all = "";
- sqs.question_code_temp = "";
- }
- sqs.scoreBox.maxsorce = qt.scoreBox.maxsorce;
- 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);
- }
-
- if (qt.smallQtNo == -1 || qt.smallQtNo == 0)
- {
- SchemaCutArea cutarea;
- cutarea.index = obj_index++;
- cutarea.area_name = sqs.question_code;
- cutarea.isfirst = TRUE;
- cutarea.question_index = sqs.question_index;
- cutarea.iscut = 1;
- cutarea.marktype = qt.marktype;
- 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;
- cutarea.marktype = qt.marktype;
- 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;
- cutarea.marktype = qt.marktype;
- 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.scoreBox.maxsorce = qt.scoreBox.maxsorce;
- sqs.question_code = qt.id;
- sqs.question_code_all = "";
- sqs.question_code_temp = "";
- 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;
- if (qt.smallQtNo == -1)
- {
- cutarea.isfirst = TRUE;
- cutarea.iscut = 0;
- }
- else if (qt.smallQtNo == 0)
- {
- cutarea.isfirst = TRUE;
- cutarea.iscut = 2;
- }
- else
- {
- cutarea.isfirst = false;
- cutarea.iscut = 0;
- }
-
- cutarea.question_index = question_count;
- cutarea.marktype = qt.marktype;
-
- 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 if (qt.type == 4)
- {
- //题组概念
- //通过linkparm判断第一次还是第二次出现(第一次一定小于2)
- if (qt.cut.linkparm < 1){
- SchemaQuestionScore sqs;
- 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 + (m_pTemplate->_version == "old" ? 0 : 1); // 加入0 老版没有这
- 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.index = obj_index++;
- if (!qt.id.empty())
- sqs.question_index = std::stoi(qt.id);
- sqs.question_code = qt.id;
- bool flagcreateselect = false;
- sqs.question_code_temp = qt.all_id;
- //设置all_id
- {
- std::vector<std::string> _vct_all_questions;
- split(qt.all_id, (std::string)",", &_vct_all_questions);
- int idfisrtindex = -1;
- for (int i = 0; i < _vct_all_questions.size();i++)
- {
- if (_vct_all_questions[i] == qt.id)
- {
- idfisrtindex = i;
- flagcreateselect = (i == 0) ? true : false;
- }
- }
- sqs.question_code_all = qt.id;
- for (int i = idfisrtindex + _vct_all_questions.size() / qt.selTotal; i < _vct_all_questions.size(); i += _vct_all_questions.size() / qt.selTotal)
- {
- sqs.question_code_all += ",";
- sqs.question_code_all += _vct_all_questions[i];
- }
- }
- sqs.scoreBox.bXuanZuoTi = flagcreateselect;
-
- sqs.scoreBox.maxsorce = qt.scoreBox.maxsorce;
- 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);
- sqs.countItemSelete = qt.selItem;
- sqs.countNum = qt.selTotal;
- if (flagcreateselect){
- 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);
- }
- SetTBLR(sqs);
- }
- if (qt.smallQtNo == -1 || qt.smallQtNo == 0)
- {
- SchemaCutArea cutarea;
- cutarea.index = obj_index++;
- cutarea.area_name = sqs.question_code;
- cutarea.isfirst = TRUE;
- cutarea.question_index = sqs.question_index;
- cutarea.iscut = 1;
- cutarea.marktype = qt.marktype;
- 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;
- cutarea.marktype = qt.marktype;
- 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;
- cutarea.marktype = qt.marktype;
- cutareav.push_back(cutarea);
- }
- }
- }
- ////LOGI("createSchema 6");
- SchemaPage* schemapage = (SchemaPage*) new SchemaPage;
- SetPageDefault(*schemapage);
- schemapage->schoolCardStatus = m_pTemplate->schoolCardStatus;
- schemapage->isZaiXianDaTiKa = true;
- schemapage->qrFlag = qrFlag;
- 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;
- //if (!m_pTemplate->useQrCode){
- schemapage->is_same_exam_id = is_same_exam_id;
- //}
- {
- std::lock_guard<std::mutex> _lck(g_mtx_examid);
- schemapage->examid_by_qr_code = (g_examid_by_qr_code==1);
- }
- schemapage->is_front_page = front_page;
- schemapage->is_use_qr_code = m_pTemplate->useQrCode;
- //缺考标记相关参数
- 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);
- //}
- #ifdef _draw_debug
- //drawDebug(src_debug, &page);
- DrawSchema(src_debug, schemapage);
- {
- std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> tp = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
- auto tmp = std::chrono::duration_cast<std::chrono::microseconds>(tp.time_since_epoch());
- std::time_t timestamp = tmp.count();
- std::string imagePath = g_appFilePathName + "\\image1\\";
- CreateDirectoryA(imagePath.c_str(), NULL);
- std::string path = imagePath + std::to_string(timestamp) + ".jpg";
- cvSaveImage(path.c_str(), src_debug);
- }
- cvReleaseImage(&src_debug);
- #endif
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&src_gray_img);
- *dst = dst_img;
- ////LOGI("createSchema 7");
- 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 = g_appFilePathName + std::string("\\image\\") + getTimeStamp() + ".jpg";
- //LOGI("Identify_impl 1");
- ret = createSchema(src, &dst, &pschemaPage, path.c_str(), true, m_strQrClass, m_bUseQr);
- //LOGI("Identify_impl 2");
- if (ret != identify::result::IDF_SUCCESS){
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- return ret;
- }
- SchemaPage& schemaPage = *pschemaPage;
- omr_result->card_qrFlag = schemaPage.qrFlag;
- omr_result->is_same_exam_id = schemaPage.is_same_exam_id;
- omr_result->is_front_page = schemaPage.is_front_page;
- omr_result->is_use_qr_code = schemaPage.is_use_qr_code;
- omr_result->examid_by_qr_code = schemaPage.examid_by_qr_code;
- omr_result->strMagicClassId = schemaPage.paper_id;
- omr_result->strMagicStudentId = schemaPage.student_code;
- /************************读取学生学号*********************************************/
- ret = ReadStudentID(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- //LOGI("Identify_impl 3");
- /************************查找题目定位点,准备定位数据*********************************************/
- 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 = ReadKeGuanTi1(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- //LOGI("Identify_impl 4");
- /************************阅卷读取*************************************************/
- 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;
- }
- //LOGI("Identify_impl 6");
- /************************根据给定区域切割图片*********************************************/
- ret = ClipImg(schemaPage, dst);
- if (ret != identify::result::IDF_SUCCESS) {
- if (dst != NULL)cvReleaseImage(&dst);
- cvReleaseMemStorage(&storage);
- if (pschemaPage != NULL)delete pschemaPage;
- return ret;
- }
- //LOGI("Identify_impl 7");
- /************************读取缺考标记*********************************************/
- omr_result->quekaoFlag = ReadQuekaoFlag(schemaPage, dst);
- omr_result->card_index = schemaPage.index;
- /*
- if (1){
- DrawSchema(dst, pschemaPage);
- cvSaveImage(path.c_str(), dst);
- }
- */
- 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;
- // auto rcRoi = cvRect(cl, ct, cr - cl, cb - ct);
- // //auto rcRoi = cvRect(left, top, right - left, bottom - top);
- // cvSetImageROI(dst, rcRoi);
- // cvSaveImage("d:\\test_roi.png", dst);
- //初始化字符区域参数
- 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||
- group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT_EX)
- {
- 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 : (group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT_EX ? identify::DUOXUANTIEX : 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;
- if (m_nBxuanxiang == 1 && schemaPage.stuGroupsCount > 0){
- try{
- IdentifyArea *ptr_area = new IdentifyArea(schemaPage.stuGroupsCount);
- ptr_area->btiantu = true;
- ptr_area->type = GROUP_TYPE_IDENTIFY::TIANTUKAOHAO;
- for (int groupIndex = 0; groupIndex < schemaPage.stuGroupsCount; groupIndex++)
- {
- SchemaGroup& group = schemaPage.stuGroups[groupIndex];
- IdentifyGroup*ptr_group = ptr_area->get_group_by_index(groupIndex);
- if (ptr_group){
- ptr_group->init(group.itemCount, group.question_code.c_str(), false);
- for (int itemindex = 0; itemindex < group.itemCount; itemindex++){
- IdentifyItem*ptr_item = ptr_group->get_item_by_index(itemindex);
- if (ptr_item){
- SchemaItem*ptr_sc_item = &m_items[group.itemIndex[itemindex]];
- auto rc = GetCVRect(*ptr_sc_item);
- ptr_item->x = rc.x;
- ptr_item->y = rc.y;
- ptr_item->w = rc.width;
- ptr_item->h = rc.height;
- ptr_item->name[0] = ptr_sc_item->OutChar;
- }
- }
- }
- }
- IplImage*dst_gray_img = cvCreateImage(cvGetSize(dst), IPL_DEPTH_8U, 1);
- cvCvtColor(dst, dst_gray_img, CV_BGR2GRAY);
- //cvSaveImage("D:\\src_src.png", dst_gray_img);
- int bret = api_ttpd_analysis_part(cv::cvarrToMat(dst_gray_img), ptr_area);
- code_rst.qr_str = std::string();
- for (int i = 0; i < ptr_area->group_count; ++i){
- code_rst.qr_str += get_str_by_identify_group(0, ptr_area->get_group_by_index(i), schemaPage.option_spacer);
- }
- delete ptr_area; ptr_area = nullptr;
- cvReleaseImage(&dst_gray_img); dst_gray_img = nullptr;
- }
- catch (...){
- }
- }
- else{
- // 计算每个填图区域图像信息
- 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::ReadKeGuanTi1(SchemaPage &schemaPage, IplImage * dst)
- {
- m_items = schemaPage.items;
- if (m_nBxuanxiang == 1 && schemaPage.groups.size() > 0){
- try{
- omr_result->group_result.resize(schemaPage.groups.size());
- identify::result::KEGUANTI_RESULT* ketuanti_result_value = omr_result->group_result.data();
- IdentifyArea *ptr_area = new IdentifyArea(schemaPage.groupCount);
- ptr_area->type = GROUP_TYPE_IDENTIFY::KEGUANTI;
- for (int groupIndex = 0; groupIndex < schemaPage.groupCount; groupIndex++)
- {
- SchemaGroup& group = schemaPage.groups[groupIndex];
- IdentifyGroup*ptr_group = ptr_area->get_group_by_index(groupIndex);
- if (ptr_group){
- bool mul = (group.omr_out_type != OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT);
- ptr_group->init(group.itemCount, group.question_code.c_str(), mul);
- for (int itemindex = 0; itemindex < group.itemCount; itemindex++){
- IdentifyItem*ptr_item = ptr_group->get_item_by_index(itemindex);
- if (ptr_item){
- SchemaItem*ptr_sc_item = &m_items[group.itemIndex[itemindex]];
- auto rc = GetCVRect(*ptr_sc_item);
- ptr_item->x = rc.x;
- ptr_item->y = rc.y;
- ptr_item->w = rc.width;
- ptr_item->h = rc.height;
- ptr_item->name[0] = ptr_sc_item->OutChar;
- }
- }
- }
- }
- cvResetImageROI(dst);
- IplImage*dst_gray_img = cvCreateImage(cvGetSize(dst), IPL_DEPTH_8U, 1);
- cvCvtColor(dst, dst_gray_img, CV_BGR2GRAY);
- //cvSaveImage("D:\\src_src.png", dst_gray_img);
- if (0 == api_ttpd_analysis_part(cv::cvarrToMat(dst_gray_img), ptr_area)){
- omr_result->group_result.resize(schemaPage.groups.size());
- identify::result::KEGUANTI_RESULT* ketuanti_result_value = omr_result->group_result.data();
- for (int groupIndex = 0; groupIndex < schemaPage.groupCount &&groupIndex < ptr_area->group_count; groupIndex++)
- {
- SchemaGroup& group = schemaPage.groups[groupIndex];
- bool mul = (group.omr_out_type != OMR_OUT_TYPE::OMR_OUT_TYPE_SINGLE_NONSTRICT);
- IdentifyGroup* ptr_group = ptr_area->get_group_by_index(groupIndex);
- if (ptr_group->select_count == ptr_group->item_count) // 单选题如果全选,结果值会保留全部值
- {
- mul = true;
- }
- std::string omr_str = get_str_by_identify_group(mul ? 1 : 0, ptr_area->get_group_by_index(groupIndex), schemaPage.option_spacer);
- 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 : (group.omr_out_type == OMR_OUT_TYPE::OMR_OUT_TYPE_MUTIL_STRICT_EX ? identify::DUOXUANTIEX : identify::DUOXUANTI));
- }
- }
- cvReleaseImage(&dst_gray_img);
- }
- catch (cv::Exception e){
- const char * ss = e.what();
- return identify::result::IDF_FAILURE;
- }
- int global_background_color_avg = caculate_global_background(schemaPage, dst);
- anlyseResult.backGroundGray = global_background_color_avg;
- anlyseResult.cellAvgGray = 0;
- anlyseResult.cellNum = 0;
- return identify::result::IDF_SUCCESS;
- }
- 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);
- //LOGI("GetZhuGuanTiRedCount-BEIGIN");
- GetZhuGuanTiRedCount(dst, detect_rect, detect_rect, redcount, red_in_count, qs.count, qs.scoreBox.type != 1 || qs.scoreBox.bPoint, false);
- //LOGI("GetZhuGuanTiRedCount-END");
- 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);
- }
- }
- }
- if (score > qs.scoreBox.maxsorce && qs.scoreBox.maxsorce > 0)
- zhutuanti_result_value[score_count].question_score = qs.scoreBox.maxsorce;
- else
- 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].maxscore = qs.scoreBox.maxsorce;
- 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;
- zhutuanti_result_value[score_count].question_code_temp = qs.question_code_temp;
- }
- else if (qs.question_code_temp != "")
- {
- 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 = -2;
- zhutuanti_result_value[score_count].question_code_all = qs.question_code_all;
- zhutuanti_result_value[score_count].question_code_temp = qs.question_code_temp;
- }
- 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);
- }
- }
- if (qs.scoreBox.maxsorce > 0)
- {
- tiankongti_result_value[tiankong_count].question_score = qs.scoreBox.maxsorce > score ? score : qs.scoreBox.maxsorce;
- }
- else
- {
- tiankongti_result_value[tiankong_count].question_score = score;
- }
- tiankongti_result_value[tiankong_count].maxscore = qs.scoreBox.maxsorce;
- 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;
- }
- }
- if (qs.scoreBox.maxsorce > 0)
- {
- tiankongti_result_value[tiankong_count].question_score = tiankongti_result_value[tiankong_count].isright ? qs.scoreBox.maxsorce : 0;
- }
- tiankongti_result_value[tiankong_count].maxscore = qs.scoreBox.maxsorce;
- tiankongti_result_value[tiankong_count].omr_question_type = identify::OMR_QUESTION_TYPE::TIANKONGTI;
- }
- }else{
- tiankongti_result_value[tiankong_count].maxscore = qs.scoreBox.maxsorce;
- tiankongti_result_value[tiankong_count].isright = FALSE;
- if (qs.scoreBox.maxsorce > 0)
- {
- tiankongti_result_value[tiankong_count].question_score = 0;
- }
- 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 (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);
- m_pTemplate->open_save_debug_img = 1;
- if (m_pTemplate->open_save_debug_img)
- cv::imwrite("D:\\image\\Debug\\GetQrCode.PNG", img);
- 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());
- const char *error = e.what();
- LeaveCriticalSection(m_althom_rcs);
- }
- 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));
- }
- }
- }
- if (redPoints.size()==0)
- {
- return 0;
- }
- 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);
- #ifdef _DEBUG
- cvSaveImage("D:\\red_high.png", gray);
- #endif
- 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);
- #ifdef _DEBUG
- cvSaveImage("D:\\red_high.png", red_high);
- #endif
- 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)
- {
- if (m_nBxuanxiang == 1){
- auto m_items = qs.item;
- try{
- IdentifyArea *ptr_area = new IdentifyArea(1);
- ptr_area->type = GROUP_TYPE_IDENTIFY::XUANZUOTI;
- IdentifyGroup*ptr_group = ptr_area->get_group_by_index(0);
- if (ptr_group){
- ptr_group->init(qs.countNum, "", false);
- for (int itemindex = 0; itemindex < qs.countNum; itemindex++){
- SchemaItem & item = qs.item[itemindex];
- IdentifyItem*ptr_item = ptr_group->get_item_by_index(itemindex);
- if (ptr_item){
- SchemaItem*ptr_sc_item = &item;
- auto rc = GetCVRect(*ptr_sc_item);
- ptr_item->x = rc.x;
- ptr_item->y = rc.y;
- ptr_item->w = rc.width;
- ptr_item->h = rc.height;
- ptr_item->name[0] = ptr_sc_item->OutChar;
- }
- }
- }
- auto roi = cvGetImageROI(dst);
- cvResetImageROI(dst);
- IplImage*dst_gray_img = cvCreateImage(cvGetSize(dst), IPL_DEPTH_8U, 1);
- cvCvtColor(dst, dst_gray_img, CV_BGR2GRAY);
- //cv::imwrite("d:\\exception.png", cv::cvarrToMat(dst_gray_img));
- int bret = api_ttpd_analysis_part(cv::cvarrToMat(dst_gray_img), ptr_area);
- int n_ret = -1;
- if (ptr_group&&ptr_group->select){
- for (int i = 0; i < ptr_group->item_count; ++i){
- int *ptr_int = ptr_group->select + i;
- auto ptr_tmp = ptr_group->get_item_by_index(i);
- if (*ptr_int == 1 && ptr_tmp){
- n_ret = i;
- break;
- }
- }
- }
- cvSetImageROI(dst, roi);
- delete ptr_area; ptr_area = nullptr;
- cvReleaseImage(&dst_gray_img); dst_gray_img = nullptr;
- return n_ret;
- }
- catch (cv::Exception e){
- const char * er = e.what();
- return -1;
- }
- return -1;
- }
- else{
- 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));
- }
- }
- // 绘制打分区域
- 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(0, 0,255));
- }
- // 剪裁区域
- for (std::size_t i = 0; i < pageSchema->cutAreas.size(); ++i)
- {
- cvDrawRect(dst_img,
- cvPoint(pageSchema->cutAreas[i].centerx - pageSchema->cutAreas[i].width / 2.0, pageSchema->cutAreas[i].centery - pageSchema->cutAreas[i].height / 2.0),
- cvPoint(pageSchema->cutAreas[i].centerx + pageSchema->cutAreas[i].width / 2.0, pageSchema->cutAreas[i].centery + pageSchema->cutAreas[i].height / 2.0),
- cvScalar(0, 255, 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));
- }
- }
- }
|