12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096 |
- #include "StdAfx.h"
- #include "ResultReader.h"
- #include "Affine2DEstimator0.h"
- #include <stdlib.h>
- #include "CrossDetector.h"
- #include "IdentifyArea.h"
- std::string g_appFilePathName;
- namespace identify{
- CResultReader::CResultReader(void)
- {
- 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());
- g_appFilePathName = strPath.substr(0, pos);
- strPath = strPath.substr(0, pos) + "\\..\\config.ini";
- int nType = GetPrivateProfileIntA("USER", "algorithm_boption", 1, strPath.c_str());
- m_nBxuanxiang = (nType == 1);
- knn = KNearest::create();
- }
- CResultReader::~CResultReader(void)
- {
- }
- inline unsigned char GetGrayFromBGR(const IplImage * img, int x, int y)
- {
- #define RGB_GRAY(B,G,R) ((R*38 + G*75 + B*15) >> 7)
- return RGB_GRAY(CV_IMAGE_ELEM(img, unsigned char, y, x * 3), CV_IMAGE_ELEM(img, unsigned char, y, x * 3 + 1), CV_IMAGE_ELEM(img, unsigned char, y, x * 3 + 2));
- }
- inline unsigned char GetGrayFromGray(const IplImage * img, int x, int y)
- {
- return CV_IMAGE_ELEM(img, unsigned char, y, x);
- }
- int CResultReader::ReadResult(const IplImage* img, int schemaIndex, cv::Mat transform, double scale, int dir, OMR_RESULT* out_result)
- {
- knn->clear();
- point_muban.clear();
- point_shijuan.clear();
- this->omr_result = (OMR_RESULT*)out_result;
- this->m_pageDirection = dir;
- m_AffineTransform = transform;
- m_Scaler0 = scale;
- SetDefaultOMR_Result(*omr_result);
- src = (IplImage*)img;
- if (src == NULL) return -1;
- if (src->nChannels == 1) _GetGray = &GetGrayFromGray;
- if (src->nChannels == 3) _GetGray = &GetGrayFromBGR;
- return ReadResult(schemaIndex);
- }
- //绘出识别位置
- void DrawIdentify(IplImage * dst_img, OMR_RESULT* omr_result)
- {
- cvResetImageROI(dst_img);
- if (omr_result->identified){
- for (int j = 0; j < omr_result->locatepoint_result.size(); j++){
- vector<LOCATE_POINT_RESULT>& option = omr_result->locatepoint_result;
- cvDrawRect(dst_img,
- cvPoint(cvRound(option[j].centerx - option[j].width / 2.0), cvRound(option[j].centery - option[j].height / 2.0)),
- cvPoint(cvRound(option[j].centerx + option[j].width / 2.0), cvRound(option[j].centery + option[j].height / 2.0)),
- cvScalar(0, 0, 255));
- }
- for (int i = 0; i < omr_result->group_result.size(); i++)
- {
- vector<KGUANTI_OPTION_RESULT> &option = omr_result->group_result[i].option;
- for (int j = 0; j < option.size(); j++)
- {
- cvDrawRect(dst_img,
- cvPoint(cvRound(option[j].centerx - option[j].width / 2.0), cvRound(option[j].centery - option[j].height / 2.0)),
- cvPoint(cvRound(option[j].centerx + option[j].width / 2.0), cvRound(option[j].centery + option[j].height / 2.0)),
- cvScalar(0, 0, 255));
- }
- }
- }
- }
- int CResultReader::ReadResult(int shemaIndex)
- {
- const ISCH_SCHEMA_PAGE& schemaPage = (*schemaPages)[shemaIndex];
- int ret;
- //查找辅助定位关系
- /************************定位点位置*********************************************/
- double fre = getTickFrequency();
- int64 t0 = cvGetTickCount();
- ret = findAssitLocate(schemaPage);
- int64 t1 = cvGetTickCount();
- double t = (t1 - t0) / fre;
- if (ret != IDF_SUCCESS) {
- return ret;
- }
- /************************定位点位置*********************************************/
- ret = ReadDingWeiDian(schemaPage);
- if (ret != IDF_SUCCESS) {
- return ret;
- }
- /************************根据给定区域识别二维码*********************************************/
- ret = ReadBarCode(schemaPage);
- if (ret != IDF_SUCCESS) {
- return ret;
- }
- /************************根据给定区域分析填涂项*********************************************/
- ret = ReadKeGuanTi(schemaPage);
- if (ret != IDF_SUCCESS) {
- return ret;
- }
- ret = ReadQuestionScore(schemaPage);
- if (ret != IDF_SUCCESS) {
- return ret;
- }
- /************************根据给定区域切割图片*********************************************/
- ret = ClipImg(schemaPage);
- if (ret != IDF_SUCCESS) {
- return ret;
- }
- omr_result->card_index = schemaPage.index;
- omr_result->identified = TRUE;
- //cvResetImageROI((IplImage*)src);
- //DrawIdentify((IplImage*)src,omr_result);
- //char file_name[512];
- //sprintf_s(file_name,"%sresult_%05d.png","D:\\img\\",(int)omr_result->phy_card_number);
- //cvSaveImage(file_name,src);
- {
- return IDF_SUCCESS;
- }
- }
- int CResultReader::caculate_cell_property(ISCH_SCHEMA_PAGE& schemaPage, ISCH_SCHEMA_ITEM &item, const 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 & diheidushu)
- {
- int gray;//临时变量,灰度值
- //int tembackcolor=max((anlyseResult.globalBackGround+200)/2,200);
- CvRect rr = GetJiaoZhengResultRect(item);
- int tembackcolor = max(anlyseResult.backGroundGray - 30, 200);
- int left = int(rr.x);
- int top = int(rr.y);
- int right = int(rr.x + rr.width);
- int bottom = int(rr.y + rr.height);
- int vtop = (int)(rr.y - rr.height*0.25 + 0.5);
- /*******************统计字符区域属性************************************/
- int cl = left + ((right - left + 1) + 2) / 4;
- int cr = left + ((right - left + 1) * 3 + 2) / 4;
- //int ct=top+((bottom-top+1)+2)/4;
- //int cb=top+((bottom-top+1)*3+2)/4;
- int ct = top;
- int cb = bottom;
- //初始化字符区域参数
- char_area_avg_gray = 0;
- char_area_black_count = 0;
- char_area_size = 0;
- for (int y = ct; y <= cb; y++)
- {
- for (int x = cl; x <= cr; x++)
- {
- gray = GetGray(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 = GetGray(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;
- diheidushu = 0;
- for (int i = min(255, tembackcolor - 1); i >= tembackcolor - 45 && i >= 0; i--)
- {
- diheidushu += gray256[i];
- }
- 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 < 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 IDF_DIVIDE_ZERO; }
- gao_heidu = max(0.0, gao_heidu);
- 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);
- mo_hu_du = max(0.0, mo_hu_du);
- return IDF_SUCCESS;
- }
- int CResultReader::ReadKeGuanTi(const ISCH_SCHEMA_PAGE &schemaPage)
- {
- if (m_nBxuanxiang){
- auto _items = schemaPage.items;
- if (m_nBxuanxiang == 1 && schemaPage.groups.size() > 0){
- try{
- auto pGetCVRect = [&](const ISCH_SCHEMA_ITEM* code)->CvRect{
- CvRect result_rect;
- if (code){
- result_rect = GetResultRect(*code);
- }
- return result_rect;
- };
- std::map<GROUP_TYPE, std::vector<int>> _map_groups_by_type;
- for (int groupIndex = 0; groupIndex < schemaPage.groups.size(); groupIndex++)
- {
- _map_groups_by_type[schemaPage.groups[groupIndex].group_type].push_back(groupIndex);
- }
- std::map<int, IdentifyGroup*> _map_group;
- std::vector<IdentifyArea*> _vct_release;
- for (auto it : _map_groups_by_type)
- {
- IdentifyArea *ptr_area = new IdentifyArea(it.second.size());
- ptr_area->type = static_cast<GROUP_TYPE_IDENTIFY>(it.first);
- _vct_release.push_back(ptr_area);
- int nIndex = 0;
- for (auto it_group : it.second)
- {
- const ISCH_IDENTIFY_GROUP& group = schemaPage.groups[it_group];
- IdentifyGroup*ptr_group = ptr_area->get_group_by_index(nIndex++);
- _map_group[it_group] = ptr_group;
- if (ptr_group){
- bool mul = true;
- switch (group.omr_out_type)
- {
- case OMR_OUT_TYPE_SINGLE_NONSTRICT_ERROR:
- case OMR_OUT_TYPE_SINGLE_NONSTRICT:
- case OMR_OUT_TYPE_SINGLE_STRICT:
- mul = false;
- break;
- case OMR_OUT_TYPE_MUTIL_STRICT:
- mul = true;
- break;
- }
- ptr_group->init(group.itemCount, std::to_string(group.nID).c_str(), mul);
- for (int itemindex = 0; itemindex < group.itemCount; itemindex++){
- IdentifyItem*ptr_item = ptr_group->get_item_by_index(itemindex);
- if (ptr_item){
- const ISCH_SCHEMA_ITEM*ptr_sc_item = &_items[group.itemIndex[itemindex]];
- auto rc = pGetCVRect(ptr_sc_item);
- ptr_item->x = rc.x;
- ptr_item->y = rc.y;
- ptr_item->w = rc.width;
- ptr_item->h = rc.height;
- strcpy(ptr_item->name, ptr_sc_item->OutChar);
- //ptr_item->name[0] = ptr_sc_item->OutChar[0];
- }
- }
- }
- }
- IplImage*dst_gray_img = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
- cvCvtColor(src, dst_gray_img, CV_BGR2GRAY);
- try{
- if (0 == api_ttpd_analysis_part(cv::cvarrToMat(dst_gray_img), ptr_area)){
- }
- }
- catch (cv::Exception e){
- const char *w = e.what();
- int i = 0; ++i;
- }
- cvReleaseImage(&dst_gray_img);
- }
- 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.groups.size() && groupIndex < _map_group.size(); groupIndex++)
- {
- const ISCH_IDENTIFY_GROUP& group = schemaPage.groups[groupIndex];
- bool mul = true;
- switch (group.omr_out_type)
- {
- case OMR_OUT_TYPE_SINGLE_NONSTRICT_ERROR:
- case OMR_OUT_TYPE_SINGLE_NONSTRICT:
- case OMR_OUT_TYPE_SINGLE_STRICT:
- mul = false;
- if (_map_group[groupIndex]->select_count == _map_group[groupIndex]->item_count) // 单选题如果全选,结果值会保留全部值
- {
- mul = true;
- }
- break;
- case OMR_OUT_TYPE_MUTIL_STRICT:
- mul = true;
- break;
- }
- std::string omr_str = get_str_by_identify_group(mul ? 1 : 0, _map_group[groupIndex], schemaPage.option_spacer);
- ketuanti_result_value[groupIndex].answer = omr_str;
- ketuanti_result_value[groupIndex].question_state = OMR_QUESTION_STATE::OMR_QUESTION_STATE_NORMAL;
- }
- for (auto it : _vct_release){
- delete it;
- }
- _vct_release.clear();
- }
- catch (cv::Exception e){
- const char * ss = e.what();
- return IDF_FAILURE;
- }
- int global_background_color_avg = caculate_global_background(schemaPage);
- anlyseResult.backGroundGray = global_background_color_avg;
- return IDF_SUCCESS;
- }
- }
- else{
- int global_background_color_avg = caculate_global_background(schemaPage);
- anlyseResult.backGroundGray = global_background_color_avg;
- int ret;
- for (int i = 0; i < schemaPage.items.size(); i++)
- {
- ret = caculate_item_property(schemaPage, schemaPage.items[i], src, anlyseResult.itemAnalyseResult[i]);
- if (ret != IDF_SUCCESS)return ret;
- }
- caculate_item_global_property(schemaPage);
- ret = GenerateOmrStr(schemaPage);
- }
- return IDF_SUCCESS;
- }
- int CResultReader::GenerateOmrStr(const ISCH_SCHEMA_PAGE& schemaPage)
- {
- #define MAX_ITEM 64
- #define QQM_ADD 0 // 马百泉 2020.08 针对空白卷未填涂识别错误的修改代码
- char omr_str[512];
- int omr_str_len = 0;
- enum SelectType{
- //未选中
- UNSELECT,
- //不确定
- UNCERTAIN,
- //选中
- SELECTED
- };
- //标记是否被选中
- SelectType sel[MAX_ITEM];
- SAMPLE_KEGUANTITUDIAN samples[MAX_ITEM];
- omr_result->group_result.resize(schemaPage.groups.size());
- KEGUANTI_RESULT* ketuanti_result_value = omr_result->group_result.data();
- for (int groupIndex = 0; groupIndex < schemaPage.groups.size(); groupIndex++)
- {
- omr_str_len = 0;
- memset(sel, UNSELECT, sizeof(sel));
- const ISCH_IDENTIFY_GROUP& group = schemaPage.groups[groupIndex];
- int pn = min(MAX_ITEM, group.itemCount);
- AnalyseResult::itemResult* results[MAX_ITEM];
- const ISCH_SCHEMA_ITEM* items[MAX_ITEM];
- #if QQM_ADD
- bool b_multiple = false; // 是否是多项填涂
- if (group.omr_out_type == OMR_OUT_TYPE_MUTIL_STRICT) // @林 确认是否正确
- b_multiple = true;
- #endif
- ketuanti_result_value[groupIndex].option.resize(pn);
- for (int i = 0; i < pn; i++){
- results[i] = &anlyseResult.itemAnalyseResult[group.itemIndex[i]];
- items[i] = &schemaPage.items[group.itemIndex[i]];
- SaveRect(results[i]->item_position, ketuanti_result_value[groupIndex].option[i]);
- }
- int maxgraynum = -1;
- int second_maxgraynum = -1;
- int mingraynum = 0xffffff;
- float max_balck_ref_area = 0;
- float min_balck_ref_area = 0;
- for (int i = 0; i < pn; i++)
- {
- if (results[i]->gray_num > maxgraynum){ if (maxgraynum > 0){ second_maxgraynum = maxgraynum; }maxgraynum = results[i]->gray_num; max_balck_ref_area = results[i]->gray_num / (float)results[i]->cell_size; }
- #if QQM_ADD
- else {
- if (results[i]->gray_num > second_maxgraynum) {
- second_maxgraynum = results[i]->gray_num;
- }
- }
- #endif
- if (results[i]->gray_num < mingraynum){ mingraynum = results[i]->gray_num; min_balck_ref_area = results[i]->gray_num / (float)results[i]->cell_size; }
- }
- #if QQM_ADD
- if (!b_multiple) {
- for (int i = 0; i < pn; i++) {
- results[i]->same_group_unselected_gray_num = mingraynum;
- }
- }
- #endif
- 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.2){
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- #if QQM_ADD
- // 小面积的填涂项 小于 0.6直接pass 太****
- if (results[i]->cell_size < 700 && results[i]->gray_num < results[i]->cell_size*0.6) {
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- // 填涂面积超过0.8的 直接按填涂处理 怕被下面的误伤 0.8的占比即使是没有填涂图像,也是涂抹之类的
- if (results[i]->gray_num > results[i]->cell_size*0.8) {
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- // 单选填涂面积中填涂的背景区域要超过0.2 & 面积不能太大 目前来说出问题的都是小填涂规格
- // 但是 确实也有0.75-0.8之间的填涂,最小的可能超过0.6这时候出错
- if (!b_multiple && results[i]->gray_num > results[i]->cell_size*0.6 && results[i]->cell_size < 1200 && results[i]->gray_num < (results[i]->same_group_unselected_gray_num + results[i]->cell_size*0.2)) {
- if (results[i]->gray_num < (results[i]->same_group_unselected_gray_num + results[i]->cell_size*0.1)) {
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- else { // 前景 0.1 - 0.2的 借用(灰度数-模糊边缘数)的数据再次判断下
- float fmin = 1.0; float ri = 0.0;
- for (int x = 0; x < pn; x++) {
- float tmp = (results[x]->gray_num - results[x]->mo_hu_bianyu_shu)*1.0 / results[x]->cell_size;
- if (x == i) { ri = tmp; continue; }
- if (tmp < fmin) { fmin = tmp; }
- }
- if (ri > (fmin + 0.2)) {
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- else {
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- }
- }
- #endif
- if (results[i]->gray_num < max(results[i]->same_page_unselected_gray_num*1.3, results[i]->same_page_unselected_gray_num + 35.)){
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- /*if(results[i]->diheidushu>80&&results[i]->diheidushu>results[i]->gray_num*0.45){
- sel[i] =UNSELECT;
- unselect_num++;
- continue;
- }*/
- //面积超过65%
- if (results[i]->gray_num > results[i]->cell_size*0.60){
- #if QQM_ADD
- // 还有 占比 0.6-0.7之间的 & 大于最小值+0.2 但是仍然是空白的 只能按照硬规则处理
- // 202009.04 英语小填涂项 正常填涂(稍浅色) 0.6-0.7 未填涂0.2-0.3 出错. 添加限制
- if (results[i]->gray_num < results[i]->cell_size*0.7 && results[i]->cell_size < 700
- && (maxgraynum - second_maxgraynum) < results[i]->cell_size*0.25) {
- sel[i] = UNSELECT;
- unselect_num++;
- continue;
- }
- #endif
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%50,将面积不小于最大点填涂面积的总面积%20的涂点视为填涂
- if (results[i]->gray_num > results[i]->cell_size*0.30&&maxgraynum - mingraynum > results[i]->cell_size*0.5&&results[i]->gray_num > maxgraynum - results[i]->cell_size*0.2){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%30,将面积不小于最大点填涂面积的总面积%18的涂点视为填涂
- if (results[i]->gray_num > results[i]->cell_size*0.30&&maxgraynum - mingraynum > results[i]->cell_size*0.3&&results[i]->gray_num > maxgraynum - results[i]->cell_size*0.28){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //填涂面积相差达%20,将面积不小于最大点填涂面积的总面积%18的涂点视为填涂
- if (results[i]->gray_num > results[i]->cell_size*0.30&&maxgraynum - mingraynum > results[i]->cell_size*0.2&&results[i]->gray_num > maxgraynum - results[i]->cell_size*0.23){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- //if (results[i]->gray_num > results[i]->cell_size*0.40&&results[i]->gray_num > max(results[i]->same_page_unselected_gray_num*1.6, results[i]->same_page_unselected_gray_num + 70.)){
- // 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++;
- }
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED){
- if (results[i]->gray_num > results[i]->cell_size*0.7)continue;
- int not_mo_hu_bianyu_gray_num = results[i]->gray_num - results[i]->mo_hu_bianyu_shu;
- if (not_mo_hu_bianyu_gray_num < results[i]->cell_size*0.45){
- for (int j = 0; j < pn; j++){
- if (sel[j] == UNSELECT){
- if (results[i]->gray_num < (results[j]->gray_num - results[j]->mo_hu_bianyu_shu)*1.5&¬_mo_hu_bianyu_gray_num < (results[j]->gray_num - results[j]->mo_hu_bianyu_shu)*1.3){
- sel[i] = UNSELECT;
- selected_num--;
- unselect_num++;
- break;
- }
- if (results[i]->gray_num<max(results[j]->gray_num*1.2, (double)results[j]->gray_num + 35)){
- sel[i] = UNSELECT;
- selected_num--;
- unselect_num++;
- break;
- }
- }
- }
- }
- }
- }
- if (selected_num<1 && maxgraynum>mingraynum*1.7&&maxgraynum>mingraynum + 100){
- for (int i = 0; i < pn; i++)
- {
- //面积超过65%
- if (results[i]->gray_num > results[i]->cell_size*0.35&&results[i]->mohudu<2.0&&results[i]->gray_num>second_maxgraynum*1.4&&results[i]->gray_num > mingraynum*1.6){
- sel[i] = SELECTED;
- selected_num++;
- continue;
- }
- }
- }
- // 处理一下填涂后 橡皮擦拭后 干扰的
- #if QQM_ADD
- if (selected_num > 1 && !b_multiple) {
- int max_gaoheidu_index_ture = 0; // 高黑度.真
- for (int i = 0; i < pn; i++) {
- if (sel[i] == SELECTED) {
- if (results[i]->gaoheidushu > results[max_gaoheidu_index_ture]->gaoheidushu)
- max_gaoheidu_index_ture = i;
- }
- }
- for (int i = 0; i < pn; i++) {
- if (sel[i] == SELECTED) {
- if (results[i]->gaoheidushu < results[max_gaoheidu_index_ture]->gaoheidushu*0.5) {
- sel[i] = UNSELECT;
- selected_num--;
- unselect_num++;
- }
- }
- }
- }
- #endif
- double max_avg_gray = -1;
- double min_avg_gray = 99999999999;
- if (selected_num > 1){
- switch (group.omr_out_type){
- case OMR_OUT_TYPE_SINGLE_NONSTRICT_ERROR:
- case OMR_OUT_TYPE_SINGLE_NONSTRICT:
- case OMR_OUT_TYPE_SINGLE_STRICT:
- //单选题
- int max_gaoheidu_index = 0;
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED){
- if (results[i]->gray_num - results[i]->diheidushu>results[max_gaoheidu_index]->gray_num - results[max_gaoheidu_index]->diheidushu){
- max_gaoheidu_index = i;
- }
- }
- }
- for (int i = 0; i < pn; i++){
- if (sel[i] == SELECTED){
- if (results[i]->gray_num - results[i]->diheidushu < results[max_gaoheidu_index]->gray_num*0.62&&results[i]->gray_num - results[i]->diheidushu < results[max_gaoheidu_index]->gray_num - results[max_gaoheidu_index]->diheidushu - 40){
- sel[i] = UNSELECT;
- selected_num--;
- unselect_num++;
- }
- }
- }
- for (int i = 0; i < pn; i++){
- if (sel[i] == SELECTED && i != max_gaoheidu_index)
- {
- sel[i] = UNSELECT;
- selected_num--;
- unselect_num++;
- }
- }
- break;
- }
- }
- for (int i = 0; i < pn; i++){
- samples[i].BlackRefArea = results[i]->gray_num / (float)results[i]->cell_size;
- samples[i].HighBlackRefArea = results[i]->gaoheidushu / (float)results[i]->cell_size;
- samples[i].LowBlackRefArea = results[i]->diheidushu / (float)results[i]->cell_size;
- samples[i].Blur = (float)results[i]->mohudu;
- samples[i].RefAvgGray = results[i]->avg_gray;
- }
- float maxblackrefarea = 0;
- float minblackrefarea = 99999;
- float maxhighblackrefarea = 0;
- float minrefavggray = 9999;
- for (int i = 0; i < pn; i++){
- if (maxblackrefarea < samples[i].BlackRefArea)maxblackrefarea = samples[i].BlackRefArea;
- if (minblackrefarea > samples[i].BlackRefArea)minblackrefarea = samples[i].BlackRefArea;
- if (maxhighblackrefarea < samples[i].HighBlackRefArea)maxhighblackrefarea = samples[i].HighBlackRefArea;
- float avgGray = (results[i]->gray_num>0 && results[i]->cell_size>0) ? (results[i]->gray_num*results[i]->avg_gray + (results[i]->cell_size - results[i]->gray_num) * 255) / (float)results[i]->cell_size : 255;
- if (minrefavggray > avgGray)minrefavggray = avgGray;
- }
- for (int i = 0; i < pn; i++){
- samples[i].MaxBlackRefArea = maxblackrefarea;
- samples[i].MinBlackRefArea = minblackrefarea;
- samples[i].MaxHighBlackRefArea = maxhighblackrefarea;
- samples[i].MinRefAvgGray = minrefavggray;
- }
- //
- //for(int i=0;i<pn;i++){
- // cv::Mat sampleMat(1,9,CV_32F,&samples[i]);
- // Mat responseMat;
- // float response=0;
- // switch(group.omr_out_type){
- // case OMR_OUT_TYPE_MUTIL_STRICT:
- // ClassBB::ann_mutil->predict(sampleMat,responseMat);
- // break;
- // default:
- // ClassBB::ann_signal->predict(sampleMat,responseMat);
- // break;
- // }
- // float * p = responseMat.ptr<float>();
- // for (int m=0;m<9;m++)
- // {
- // response+=p[m];
- // }
- // memcpy(ketuanti_result_value[groupIndex].option[i].features,&samples[i],sizeof(float)*9);
- // /*
- // int selected=(response>4?SELECTED:UNSELECT);
- // if(sel[i]!=selected){
- // if(sel[i]==SELECTED||selected==SELECTED){
- // if(samples[i].BlackRefArea>0.65)sel[i]=SELECTED;
- // else if(samples[i].BlackRefArea<0.35)sel[i]=UNSELECT;
- // else sel[i]=(SelectType)selected;
- // if(samples[i].RefAvgGray>samples[i].MinRefAvgGray+50)sel[i]=UNSELECT;
- // }
- // }*/
- //}
- selected_num = 0;
- for (int i = 0; i < pn; i++){
- if (sel[i] == SELECTED){
- selected_num++;
- }
- }
- if (selected_num > 1){
- float max_not_bianyuan = 0;
- for (int i = 0; i < pn; i++){
- if (sel[i] == SELECTED&&max_not_bianyuan < results[i]->gray_num - results[i]->mo_hu_bianyu_shu){
- max_not_bianyuan = results[i]->gray_num - results[i]->mo_hu_bianyu_shu;
- }
- }
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED&&max_not_bianyuan>(results[i]->gray_num - results[i]->mo_hu_bianyu_shu) * 2){
- sel[i] = UNSELECT;
- selected_num--;
- }
- //if (sel[i] == SELECTED&&max_not_bianyuan > (results[i]->gray_num - results[i]->mo_hu_bianyu_shu)*1.7&&results[i]->gray_num < results[i]->same_page_unselected_gray_num*1.6){
- // sel[i] = UNSELECT;
- // selected_num--;
- //}
- }
- }
- int omr_out_type = group.omr_out_type;
- if (selected_num > 1 && (omr_out_type&OTF_SINGLE)){
- float min_agv = 999;
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED&&min_agv>samples[i].RefAvgGray){
- min_agv = samples[i].RefAvgGray;
- }
- }
- for (int i = 0; i < pn; i++){
- if (sel[i] == SELECTED&&min_agv < samples[i].RefAvgGray - 25){
- sel[i] = UNSELECT;
- selected_num--;
- }
- }
- }
- if (selected_num > 1 && (omr_out_type&OTF_MUTIL)){
- float min_agv = 999;
- for (int i = 0; i<pn; i++){
- if (sel[i] == SELECTED&&min_agv>samples[i].RefAvgGray){
- min_agv = samples[i].RefAvgGray;
- }
- }
- for (int i = 0; i < pn; i++){
- if (sel[i] == SELECTED&&min_agv < samples[i].RefAvgGray - 50){
- sel[i] = UNSELECT;
- selected_num--;
- }
- }
- }
- /*
- if(selected_num<1){
- float max_raynum=0;
- for(int i=0;i<pn;i++){
- if(max_raynum<results[i]->gray_num)max_raynum=results[i]->gray_num;
- }
- int ss_count=0;const int min_threshold =80;
- int threshold =max(min_threshold ,(int)(results[0]->cell_size*0.2));
- for(int i=0;i<pn;i++){
- if(max_raynum<results[i]->gray_num+threshold)ss_count++;
- }
- for(int i=0;ss_count==1&&i<pn;i++){
- if(max_raynum>results[i]->gray_num+threshold){sel[i]==SELECTED;selected_num++;}
- }
- }*/
- int out_count;
- OMR_QUESTION_STATE question_state = OMR_QUESTION_STATE_NORMAL;
- switch (group.omr_out_type){
- case OMR_OUT_TYPE_SINGLE_NONSTRICT_ERROR:
- out_count = 0;
- if (selected_num == 1){
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED){
- if (out_count > 0)omr_str[omr_str_len++] = schemaPage.option_spacer;
- strcpy(&omr_str[omr_str_len], items[i]->OutChar);
- omr_str_len += strlen(items[i]->OutChar);
- out_count++;
- }
- }
- }
- else if (selected_num > 1){
- question_state = OMR_QUESTION_STATE_DUOTU;
- }
- else if (selected_num < 1){
- question_state = OMR_QUESTION_STATE_LOUTU;
- }
- if (out_count == 0){
- //omr_str[omr_str_len++]=schemaPage.unselect_char;
- }
- break;
- case OMR_OUT_TYPE_MUTIL_STRICT:
- case OMR_OUT_TYPE_SINGLE_STRICT:
- out_count = 0;
- for (int i = 0; i < pn; i++)
- {
- if (sel[i] == SELECTED){
- if (out_count > 0)omr_str[omr_str_len++] = schemaPage.option_spacer;
- strcpy(&omr_str[omr_str_len], items[i]->OutChar);
- omr_str_len += strlen(items[i]->OutChar);
- out_count++;
- }
- }
- if (out_count == 0){
- //omr_str[omr_str_len++]=schemaPage.unselect_char;
- question_state = OMR_QUESTION_STATE_LOUTU;
- }
- else if (out_count > 1 && group.omr_out_type == OMR_OUT_TYPE_SINGLE_STRICT){
- question_state = OMR_QUESTION_STATE_DUOTU;
- }
- break;
- case OMR_OUT_TYPE_SINGLE_NONSTRICT:
- if (selected_num > 1){
- int maxgrayindex = -1;
- int maxgraynum = -1;
- for (int i = 0; i<pn; i++)
- {
- if (sel[i] == SELECTED&&results[i]->gray_num>maxgraynum){
- 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;
- strcpy(&omr_str[omr_str_len], items[i]->OutChar);
- omr_str_len += strlen(items[i]->OutChar);
- out_count++;
- }
- }
- if (out_count == 0){
- //omr_str[omr_str_len++]=schemaPage.unselect_char;
- question_state = OMR_QUESTION_STATE_LOUTU;
- }
- break;
- }
- omr_str[omr_str_len] = '\0';
- ketuanti_result_value[groupIndex].answer = omr_str;
- ketuanti_result_value[groupIndex].question_state = OMR_QUESTION_STATE::OMR_QUESTION_STATE_NORMAL;
- }
- return 0;
- }
- int CResultReader::analyseOmrPanoramic(ISCH_SCHEMA_PAGE& 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.items.size();
- 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++)
- {
- AnalyseResult::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.groups.size()>0){
- int max_item =1;
- for (int gi=0;gi<schemaPage.groups.size();gi++)
- {
- if(schemaPage.groups[gi].itemCount>max_item) max_item = schemaPage.groups[gi].itemCount;
- }
- int * char_area_black_counts = new int[schemaPage.groups.size()];
- 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.groups.size();gi++)
- {
- if(schemaPage.groups[gi].itemCount>ii){
- AnalyseResult::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;
- }
- }
- }
- }
- }*/
- return(0);
- }
- int CResultReader::caculate_global_background(const ISCH_SCHEMA_PAGE& schemaPage)
- {
- IplImage t;
- cvInitImageHeader(&t, cvSize(src->width, src->height), src->depth, src->nChannels, src->origin, src->align);
- cvSetData(&t, src->imageData, src->widthStep);
- IplImage * dst = &t;
- int global_background_color_count = 0;
- int global_background_color_avg = 0;
- for (int i = 0; i < schemaPage.items.size(); i++)
- {
- CvRect result_rect = GetJiaoZhengResultRect(schemaPage.items[i]);
- 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.height + 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;
- left = max(0, left);
- vtop = max(0, vtop);
- right = min(dst->width - 1, right);
- vbottom = min(dst->height - 1, vbottom);
- 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;
- }
- unsigned char CResultReader::GetGray(const IplImage * dst, int x, int y)
- {
- return _GetGray(dst, x, y);
- }
- int CResultReader::ReadBarCode(const ISCH_SCHEMA_PAGE& schemaPage)
- {
- #define BARCODE_DEBUG_ENABLE 0
- omr_result->qr_result.resize(schemaPage.codes.size());
- CODE_RESULT* qr_result_value = omr_result->qr_result.data();
- int success_count = 0;
- int ret;
- IplImage t;
- cvInitImageHeader(&t, cvSize(src->width, src->height), src->depth, src->nChannels, src->origin, src->align);
- cvSetData(&t, src->imageData, src->widthStep);
- IplImage * img0 = &t;
- cvResetImageROI(img0);
- for (int i = 0; i < schemaPage.codes.size(); i++)
- {
- const ISCH_SCHEMA_CODE& code = schemaPage.codes[i];
- CvRect rect = GetResultRect(code);
- if ((rect.x + rect.width) > src->width)
- {
- rect.x = src->width - rect.width - 1;
- }
- if (rect.x<0)
- {
- rect.x = 0;
- }
- if (rect.y<0)
- {
- rect.y = 0;
- }
- if (rect.width + rect.x>src->width)
- {
- rect.width = src->width - rect.x;
- }
- if (rect.height + rect.y>src->height)
- {
- rect.height = src->height - rect.y;
- }
- SaveRect(rect, qr_result_value[i]);
- IplImage* img = cvCreateImage(cvSize(rect.width, rect.height), src->depth, src->nChannels);
- cvSetImageROI(img0, rect);
- cvCopy(img0, img);
- //cvSaveImage("D:\\img.jpg", img);
- /*
- IplImage* img= cvCreateImage(cvSize(cvRound(code.width),cvRound(code.height)),src->depth,src->nChannels) ;
- Mat m =m_AffineTransform.clone();
- CvMat map_matrix =m;
- CvPoint2D32f p1 =warpAffinePoint<CvPoint2D32f,CvPoint2D32f>(cvPoint2D32f(0,0),&m_AffineTransform);
- CvPoint2D32f p2 =warpAffinePoint<CvPoint2D32f,CvPoint2D32f>(cvPoint2D32f(code.centerx,code.centery),&m_AffineTransform);
- CV_MAT_ELEM(map_matrix,double,0,2)+=(p2.x-p1.x);
- CV_MAT_ELEM(map_matrix,double,1,2)+=(p2.y-p1.y);
- cvGetQuadrangleSubPix(src,img,&map_matrix);
- cvShowImage("img",img);
- cvWaitKey(0);
- */
- std::string result;
- //ret = PraseBarCode(img, result);
- {
- cv::Mat matDstGray = cvarrToMat(img);
- char szRes[1024];
- ret = api_parse_barcode_qrcode(matDstGray, CODE_BAR, szRes, 1024);
- result = szRes;
- }
- // result = std::string(result, 1, result.size());
- cvReleaseImage(&img);
- if (ret == IDF_SUCCESS){
- qr_result_value[i].qr_str = result;
- omr_result->card_qrFlag = 1;
- success_count++;
- }
- else{
- omr_result->card_qrFlag = -1;
- qr_result_value[i].qr_str = "";
- }
- }
- return IDF_SUCCESS;
- }
- void CResultReader::SetDefaultOMR_Result(OMR_RESULT& omr_result)
- {
- omr_result.logic_page_number = -1;
- omr_result.identified = FALSE;
- omr_result.identify_msg = "没有匹配的模板";
- omr_result.time = 0;
- omr_result.card_index = -1;
- omr_result.card_qrFlag = 0;
- omr_result.card_name[0] = '\0';
- }
- int CResultReader::ClipImg(const ISCH_SCHEMA_PAGE& schemaPage)
- {
- IplImage t;
- cvInitImageHeader(&t, cvSize(src->width, src->height), src->depth, src->nChannels, src->origin, src->align);
- cvSetData(&t, src->imageData, src->widthStep);
- IplImage * img0 = &t;
- cvResetImageROI(img0);
- omr_result->cut_area_result.resize(schemaPage.cutAreas.size());
- CUT_AREA_RESULT* cut_area_result_value = omr_result->cut_area_result.data();
- for (int i = 0; i < schemaPage.cutAreas.size(); i++)
- {
- const ISCH_SCHEMA_CLIP& 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]);
- const double scale = 3 / 3.0;
- IplImage* img = cvCreateImage(cvSize(cvRound(cutArea.width*scale), cvRound(cutArea.height*scale)), src->depth, src->nChannels);
- Mat m = m_AffineTransform.clone();
- CvMat map_matrix = m;
- CvPoint2D32f p1 = warpAffinePoint<CvPoint2D32f, CvPoint2D32f>(cvPoint2D32f(0, 0), &m);
- CvPoint2D32f p2 = warpAffinePoint<CvPoint2D32f, CvPoint2D32f>(cvPoint2D32f(cutArea.centerx, cutArea.centery), &m);
- CV_MAT_ELEM(map_matrix, double, 0, 0) /= scale;
- CV_MAT_ELEM(map_matrix, double, 0, 1) /= scale;
- CV_MAT_ELEM(map_matrix, double, 1, 0) /= scale;
- CV_MAT_ELEM(map_matrix, double, 1, 1) /= scale;
- CV_MAT_ELEM(map_matrix, double, 0, 2) += (p2.x - p1.x);
- CV_MAT_ELEM(map_matrix, double, 1, 2) += (p2.y - p1.y);
- cvGetQuadrangleSubPix(img0, img, &map_matrix);
- if (img->nChannels == 3){
- IplImage * temp = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_8U, 1);
- cvCvtColor(img, temp, CV_BGR2GRAY);
- cvReleaseImage(&img);
- img = temp;
- }
- vector<uchar> dst;
- //cv::Mat _img(img);
- cv::Mat _img = cv::cvarrToMat(img);
- /*直方图拉伸增强图像*/
- cv::Mat hist;
- vector<float> range; range.push_back(0); range.push_back(255);
- calcHist(vector<Mat>(1, _img), vector<int>(1, 0), Mat(), hist, vector<int>(1, 256), range);
- int type = hist.type();
- double sum_low = 0;
- double sum_low2 = 0;
- double sum_high = 0;
- double sum_high2 = 0;
- double imin = 0, imax = 255;
- for (int idx_i = 0; idx_i < 128; idx_i++)
- {
- sum_low += hist.at<float>(idx_i, 0);
- }
- sum_low *= 0.5;
- for (int idx_i = 0; idx_i < 128; idx_i++)
- {
- sum_low2 += hist.at<float>(idx_i, 0);
- if (sum_low < sum_low2){ imin = idx_i; break; }
- }
- for (int idx_i = 255; idx_i > 220; idx_i--)
- {
- sum_high += hist.at<float>(idx_i, 0);
- }
- sum_high *= 0.8;
- for (int idx_i = 255; idx_i > 220; idx_i--)
- {
- sum_high2 += hist.at<float>(idx_i, 0);
- if (sum_high < sum_high2){ imax = idx_i; break; }
- }
- Mat lookup(1, 256, CV_8U);
- for (int idx_i = 0; idx_i < imin; idx_i++)
- {
- lookup.at<unsigned char>(idx_i) = 0;
- }
- for (int idx_i = imin; idx_i <= imax; idx_i++)
- {
- lookup.at<unsigned char>(idx_i) = static_cast<uchar>(255 * (idx_i - imin) / (imax - imin) + 0.5);
- }
- for (int idx_i = imax + 1; idx_i < 256; idx_i++)
- {
- lookup.at<unsigned char>(idx_i) = 255;
- }
- cv::LUT(_img, lookup, _img);
- /*保存图像*/
- imencode(".png", _img, dst);
- cut_area_result_value[i].obj_id = cutArea.nID;
- cut_area_result_value[i].centerx = cutArea.centerx;
- cut_area_result_value[i].centery = cutArea.centery;
- cut_area_result_value[i].width = img->width;
- cut_area_result_value[i].height = img->height;
- cut_area_result_value[i].area_name = cutArea.area_name_by_questionNo;
- cut_area_result_value[i].area_index = cutArea.markUnit;
- cut_area_result_value[i].area_sub_index = cutArea.markUnitPart;
- cut_area_result_value[i].img_data = dst;
- cvReleaseImage(&img);
- }
- return IDF_SUCCESS;
- }
- void CResultReader::SetSchemaPages(boost::shared_ptr<const ISCH_Schema>schema)
- {
- this->schemaPages = schema;
- }
- template<typename T1, typename T2>
- T2 CResultReader::warpAffinePoint(T1& src, Mat * map_matrix)
- {
- T2 r;
- r.x = map_matrix->at<double>(0, 0)*src.x + map_matrix->at<double>(0, 1)*src.y + map_matrix->at<double>(0, 2);
- r.y = map_matrix->at<double>(1, 0)*src.x + map_matrix->at<double>(1, 1)*src.y + map_matrix->at<double>(1, 2);
- return r;
- }
- template<typename T1>
- CvRect CResultReader::GetResultRect(T1& item)
- {
- CvRect r;
- CvPoint2D32f p = warpAffinePoint<CvPoint2D32f, CvPoint2D32f>(cvPoint2D32f(item.centerx, item.centery), &m_AffineTransform);
- if (m_pageDirection &(ROTATION_0 | ROTATION_180)){
- r.width = cvRound(item.width*m_Scaler0);
- r.height = cvRound(item.height*m_Scaler0);
- }
- else{
- r.height = cvRound(item.width*m_Scaler0);
- r.width = cvRound(item.height*m_Scaler0);
- }
- r.x = cvRound(p.x - r.width / 2.0);
- r.y = cvRound(p.y - r.height / 2.0);
- return r;
- }
- template<typename T1>
- CvRect CResultReader::GetJiaoZhengResultRect(T1& item)
- {
- CvRect r;
- CvPoint2D32f p = GetJiaoZhengResultPoint<CvPoint2D32f, CvPoint2D32f>(cvPoint2D32f(item.centerx, item.centery));
- if (m_pageDirection &(ROTATION_0 | ROTATION_180)){
- r.width = cvRound(item.width*m_Scaler0);
- r.height = cvRound(item.height*m_Scaler0);
- }
- else{
- r.height = cvRound(item.width*m_Scaler0);
- r.width = cvRound(item.height*m_Scaler0);
- }
- r.x = cvRound(p.x - r.width / 2.0);
- r.y = cvRound(p.y - r.height / 2.0);
- return r;
- }
- template<class T>
- void CResultReader::SaveRect(CvRect& rect, T& result)
- {
- result.centerx = rect.x + rect.width / 2.0;
- result.centery = rect.y + rect.height / 2.0;
- result.width = rect.width;
- result.height = rect.height;
- result.angle = 0;
- }
- int CResultReader::ReadDingWeiDian(const ISCH_SCHEMA_PAGE& schemaPage)
- {
- #define BARCODE_DEBUG_ENABLE 0
- omr_result->locatepoint_result.resize(schemaPage.locatePoints.size());
- LOCATE_POINT_RESULT* locatepoint_result_value = omr_result->locatepoint_result.data();
- for (int i = 0; i < schemaPage.locatePoints.size(); i++)
- {
- const ISCH_SCHEMA_LOCATE_POINT& code = schemaPage.locatePoints[i];
- CvRect rect = GetResultRect(code);
- SaveRect(rect, locatepoint_result_value[i]);
- }
- return IDF_SUCCESS;
- }
- int CResultReader::caculate_item_property(const ISCH_SCHEMA_PAGE& schemaPage, const ISCH_SCHEMA_ITEM &item, const IplImage * dst0, AnalyseResult::itemResult& item_result)
- {
- IplImage t;
- cvInitImageHeader(&t, cvSize(dst0->width, dst0->height), dst0->depth, dst0->nChannels, dst0->origin, dst0->align);
- cvSetData(&t, dst0->imageData, dst0->widthStep);
- IplImage * dst = &t;
- int gray;
- CvRect item_roi = GetJiaoZhengResultRect(item);
- if (item_roi.x<0 || item_roi.y<0 || item_roi.x + item_roi.width>src->width || item_roi.y + item_roi.height>src->height)return IDF_FAILURE;
- int tembackcolor = max(anlyseResult.backGroundGray - 30, 200);
- GetCorrectedRect(item_roi, src, tembackcolor);
- item_result.item_position = item_roi;
- //模糊边缘点数
- int mo_hu_bianyu_shu = 0;
- for (int y = item_roi.y, endy = item_roi.y + item_roi.height; y < endy; y++)
- {
- for (int x = item_roi.x, endx = item_roi.x + item_roi.width; x < endx; x++)
- {
- int gray = GetGray(dst, x, y);
- if (gray <= 128)continue;
- if (gray >= tembackcolor)continue;
- int sxx = min(dst->width - 1, max(0, x - 2));
- int exx = min(dst->width - 1, max(0, x + 2));
- int syy = min(dst->height - 1, max(0, y - 2));
- int eyy = min(dst->height - 1, max(0, y + 2));
- int gray_thresold = gray - 70;
- //标记当前点是否是模糊的边缘点
- bool ismohubianyuandian = false;
- for (int yy = syy; !ismohubianyuandian&&yy <= eyy; yy++)
- {
- for (int xx = sxx; !ismohubianyuandian&&xx <= exx; xx++)
- {
- if (GetGray(dst, xx, yy) < gray_thresold){
- ismohubianyuandian = true;
- break;
- }
- }
- }
- if (ismohubianyuandian)mo_hu_bianyu_shu++;
- }
- }
- int left = int(item_roi.x);
- int top = int(item_roi.y);
- int right = int(item_roi.x + item_roi.width);
- int bottom = int(item_roi.y + item_roi.height);
- //灰度直方图
- int gray256[260];
- memset(gray256, 0, sizeof(gray256));
- for (int y = top; y <= bottom; y++)
- {
- for (int x = left; x <= right; x++)
- {
- gray = GetGray(dst, x, y);
- gray256[gray]++;
- }
- }
- int cellSize = (right - left + 1)*(bottom - top + 1);
- int idx_first = 0;
- for (int idx_gray = 0; idx_gray < 256; idx_gray++)
- {
- if (gray256[idx_gray] > 0){ idx_first = idx_gray; break; }
- }
- int sum_gray = 0;
- int gray_num = 0;
- for (int idx_gray = idx_first; idx_gray < tembackcolor&&idx_gray<256; idx_gray++)
- {
- gray_num += gray256[idx_gray];
- sum_gray += (idx_gray*gray256[idx_gray]);
- }
- float avg_gray = gray_num > 0 ? sum_gray / (float)gray_num : 255;
- int diheidushu = 0;
- for (int idx_gray = tembackcolor - 1; idx_gray > tembackcolor - 40 && idx_gray > 128; idx_gray--)
- {
- diheidushu += gray256[idx_gray];
- }
- int gaoheidushu = 0;
- for (int idx_gray = idx_first, end = idx_first + 40; idx_gray < tembackcolor&&idx_gray < end; idx_gray++)
- {
- gaoheidushu += gray256[idx_gray];
- }
- int midheidushu = max(0, gray_num - gaoheidushu - diheidushu);
- double mo_hu_du = ((diheidushu + midheidushu) / (double)gaoheidushu + diheidushu / (double)(gaoheidushu + midheidushu)) / 2.0;
- mo_hu_du = std::min(std::max(0.0, mo_hu_du), 5.0);
- item_result.mo_hu_bianyu_shu = mo_hu_bianyu_shu;
- item_result.gray_num = gray_num;
- item_result.diheidushu = diheidushu;
- item_result.gaoheidushu = gaoheidushu;
- item_result.mohudu = mo_hu_du;
- item_result.avg_gray = avg_gray;
- item_result.cell_size = cellSize;
- item_result.xiangdui_mianji = gray_num / (double)cellSize;
- return IDF_SUCCESS;
- }
- bool sort_item_by_xiangdui_mianji(AnalyseResult::itemResult*item1, AnalyseResult::itemResult*item2){
- return item1->xiangdui_mianji < item2->xiangdui_mianji;
- }
- void CResultReader::caculate_item_global_property(const ISCH_SCHEMA_PAGE & schemaPage)
- {
- vector<AnalyseResult::itemResult*> items;
- int item_count = schemaPage.items.size();
- for (int idx_item = 0; idx_item < item_count; idx_item++){
- items.push_back(&anlyseResult.itemAnalyseResult[idx_item]);
- }
- std::sort(items.begin(), items.end(), sort_item_by_xiangdui_mianji);
- if (items.size() >= 2 && items[0]->xiangdui_mianji < 0.6&&items[0]->xiangdui_mianji*1.5 < items[items.size() - 1]->xiangdui_mianji){
- double sum_xiangdu_mianji = 0;
- int xiangdui_mianji_count = 0;
- double max_xiangduimianji = (items[items.size() - 1]->xiangdui_mianji - items[0]->xiangdui_mianji) / 3 + items[0]->xiangdui_mianji;
- for (int idx_item = 0; idx_item < item_count&&items[idx_item]->xiangdui_mianji < max_xiangduimianji; idx_item++){
- sum_xiangdu_mianji += items[idx_item]->xiangdui_mianji;
- xiangdui_mianji_count++;
- }
- for (int idx_item = 0; idx_item < item_count; idx_item++){
- items[idx_item]->same_page_unselected_gray_num = items[idx_item]->cell_size*(sum_xiangdu_mianji / xiangdui_mianji_count);
- }
- }
- else {
- for (int idx_item = 0; idx_item < item_count; idx_item++){
- items[idx_item]->same_page_unselected_gray_num = items[idx_item]->cell_size*0.35;
- }
- }
- }
- bool sort_key_point_by_response(const KeyPoint& k1, const KeyPoint& k2){
- return k1.response > k2.response;
- }
- int CResultReader::findAssitLocate(const ISCH_SCHEMA_PAGE& schemaPage)
- {
- IplImage t;
- cvInitImageHeader(&t, cvSize(src->width, src->height), src->depth, src->nChannels, src->origin, src->align);
- cvSetData(&t, src->imageData, src->widthStep);
- IplImage * img = &t;
- for (int i = 0; i < schemaPage.assistLocateArea.size(); i++)
- {
- cvResetImageROI(img);
- int left, top, right, bottom;
- const ISCH_SCHEMA_LOCATE_AREA& locateArea = schemaPage.assistLocateArea[i].locate_area;
- const vector<KeyPoint>& locateAreaKeys = schemaPage.assistLocateArea[i].locateAreasKeyPoints;
- const CvPoint locateAreaOffset = schemaPage.assistLocateArea[i].locateAreasOffset;
- const Mat& locateAreaDescriptor = schemaPage.assistLocateArea[i].locateAreasDescriptor;
- if (locateAreaDescriptor.rows < 1)continue;
- const int ww0 = 100; const int hh0 = 100;
- double tw = locateArea.width + ww0, th = locateArea.height + hh0;
- CvRect rect = GetResultRect(locateArea);
- left = std::max(0.0, std::min((double)img->width - 1, rect.x + (rect.width - tw) / 2));
- right = std::max(0.0, std::min((double)img->width - 1, rect.x + (rect.width + tw) / 2));
- top = std::max(0.0, std::min((double)img->height - 1, rect.y + (rect.height - th) / 2));
- bottom = std::max(0.0, std::min((double)img->height - 1, rect.y + (rect.height + th) / 2));
- cvSetImageROI(img, cvRect(left, top, right - left + 1, bottom - top + 1));
- IplImage * grayImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
- int64 t0 = cvGetTickCount();
- cvCvtColor(img, grayImg, CV_BGR2GRAY);
- int64 t01 = cvGetTickCount();
- cvSmooth(grayImg, grayImg, CV_GAUSSIAN, 5);
- Mat m_m = cv::cvarrToMat(grayImg, false);
- std::vector<KeyPoint> keyPoints;
- Mat descriptor;
- int64 t1 = cvGetTickCount();
- Ptr<FeatureDetector>pDetector = SurfFeatureDetector::create();// 这里我们用了SURF特征点
- cv::Mat mask = cv::Mat::zeros(m_m.rows, m_m.cols, CV_8U);
- const int ww = 100; const int ww_2 = (ww0 - ww) / 2;
- const int hh = 100; const int hh_2 = (hh0 - hh) / 2;
- mask(cvRect(ww_2, hh_2, ww, hh)).setTo(cv::Scalar(1));
- mask(cvRect(mask.cols - ww - ww_2, hh_2, ww, hh)).setTo(cv::Scalar(1));
- mask(cvRect(ww_2, mask.rows - hh0 - hh_2, ww, hh)).setTo(cv::Scalar(1));
- mask(cvRect(mask.cols - ww - ww_2, mask.rows - hh0 - hh_2, ww, hh)).setTo(cv::Scalar(1));
- mask(cvRect((mask.cols - ww) / 2, (mask.rows - hh) / 2, ww, hh)).setTo(cv::Scalar(1));
- pDetector->detect(m_m, keyPoints, mask);
- /*std::sort(keyPoints.begin(),keyPoints.end(),sort_key_point_by_response);
- int size =std::max(min((int)keyPoints.size(),50),std::min(200,(int)keyPoints.size()*2/3));
- keyPoints.resize(size);*/
- int64 t2 = cvGetTickCount();
- Ptr<DescriptorExtractor>pExtractor = SurfDescriptorExtractor::create(); // 提取SURF描述向量
- pExtractor->compute(m_m, keyPoints, descriptor);
- int64 t3 = cvGetTickCount();
- vector<DMatch> Matches;
- Ptr<DescriptorMatcher>pMatcher = new FlannBasedMatcher(); // 使用Flann匹配算法
- int64 t3_1 = cvGetTickCount();
- if (descriptor.rows > 0 && locateAreaDescriptor.rows > 0)pMatcher->match(descriptor, locateAreaDescriptor, Matches);
- int64 t4 = cvGetTickCount();
- if (Matches.size() >= 3){
- vector<Point2f> _from;
- vector<Point2f> _to;
- for (int n = 0; n < Matches.size(); n++)
- {
- Point2f to0 = warpAffinePoint<const Point2f, Point2f >(Point2f(locateAreaKeys[Matches[n].trainIdx].pt.x + locateAreaOffset.x, locateAreaKeys[Matches[n].trainIdx].pt.x + locateAreaOffset.y), &m_AffineTransform);
- Point2f to1 = Point2f(keyPoints[Matches[n].queryIdx].pt.x + left, keyPoints[Matches[n].queryIdx].pt.x + top);
- if (((to0.x - to1.x)*(to0.x - to1.x) + (to0.y - to1.y)*(to0.y - to1.y))>35 * 35)continue;
- _to.push_back(keyPoints[Matches[n].queryIdx].pt);
- _from.push_back(locateAreaKeys[Matches[n].trainIdx].pt);
- }
- if (_from.size() >= 3){
- // Show result
- Mat _out; Mat _inliers;
- int64 t5 = cvGetTickCount();
- int su = estimateAffine2D0(_from, _to, _out, _inliers, 2);
- int64 t6 = cvGetTickCount();
- double tickFre = getTickFrequency();
- double tt[] = { (t01 - t0) / tickFre, (t1 - t01) / tickFre, (t2 - t1) / tickFre, (t3 - t2) / tickFre, (t3_1 - t3) / tickFre, (t4 - t3_1) / tickFre, (t5 - t4) / tickFre, (t6 - t5) / tickFre, (t6 - t0) / tickFre };
- if (su > cv::max(5.0, _from.size()*0.1))
- {
- Point2f src[] = { Point2f(0, 0), Point2f(1000, 0), Point2f(0, 1000), Point2f(1000, 1000) };
- Point2f dst[] = { warpAffinePoint<Point2f, Point2f>(src[0], &_out), warpAffinePoint<Point2f, Point2f>(src[1], &_out), warpAffinePoint<Point2f, Point2f>(src[2], &_out), warpAffinePoint<Point2f, Point2f>(src[3], &_out) };
- double d_src[] = { GetDistance(src[0], src[1]), GetDistance(src[0], src[2]), GetDistance(src[1], src[2]), GetDistance(src[0], src[3]) };
- double d_dst[] = { GetDistance(dst[0], dst[1]), GetDistance(dst[0], dst[2]), GetDistance(dst[1], dst[2]), GetDistance(dst[0], dst[3]) };
- double scales[] = { d_dst[0] / d_src[0], d_dst[1] / d_src[1], d_dst[2] / d_src[2], d_dst[3] / d_src[3] };
- double scale = 0;
- for (int idx_s_i = 0, length_s = sizeof(scales) / sizeof(scales[0]); idx_s_i < length_s; idx_s_i++)
- {
- for (int idx_s_j = idx_s_i + 1; idx_s_j < length_s; idx_s_j++)
- {
- scale = max(scale, abs(scales[idx_s_i] - scales[idx_s_j]));
- }
- }
- double d_duijiaoxian = abs(d_dst[2] / d_src[3] * d_dst[3] - d_dst[2]);
- if (scale < 0.09&&d_duijiaoxian < 100){//变形过大
- double centerx0 = locateArea.centerx;
- double centery0 = locateArea.centery;
- double centerx1 = locateArea.centerx - locateAreaOffset.x;
- double centery1 = locateArea.centery - locateAreaOffset.y;
- Point2f point_src0[] = { Point2f(centerx0, centery0), Point2f(centerx0 - 100, centery0 - 100), Point2f(centerx0 - 100, centery0 + 100), Point2f(centerx0 + 100, centery0 - 100), Point2f(centerx0 + 100, centery0 + 100) };
- Point2f point_src1[] = { Point2f(centerx1, centery1), Point2f(centerx1 - 100, centery1 - 100), Point2f(centerx1 - 100, centery1 + 100), Point2f(centerx1 + 100, centery1 - 100), Point2f(centerx1 + 100, centery1 + 100) };
- double dist[5];
- bool is_all_less_thresold = true;
- const double thresold = 20;
- for (int idx_dist = 0; idx_dist < 5; idx_dist++)
- {
- Point2f point_dst0 = warpAffinePoint<Point2f, Point2f>(point_src0[idx_dist], &m_AffineTransform);
- Point2f point_dst1 = warpAffinePoint<Point2f, Point2f>(point_src1[idx_dist], &_out);
- double dx = point_dst1.x + left - point_dst0.x;
- double dy = point_dst1.y + top - point_dst0.y;
- dist[idx_dist] = sqrt(dx*dx + dy*dy);
- if (dist[idx_dist] >= thresold){ is_all_less_thresold = false; break; }
- }
- if (is_all_less_thresold){
- for (float x = locateArea.centerx - locateArea.width / 2.0 - locateAreaOffset.x, endx = locateArea.centerx + locateArea.width / 2.0 - locateAreaOffset.x; x < endx; x += 10)
- {
- for (float y = locateArea.centery - locateArea.height / 2.0 - locateAreaOffset.y, endy = locateArea.centery + locateArea.height / 2.0 - locateAreaOffset.y; y < endy; y += 10)
- {
- Point2f dst = warpAffinePoint<Point2f, Point2f>(Point2f(x, y), &_out);
- point_muban.push_back(Point2f(locateAreaOffset.x + x, locateAreaOffset.y + y));
- point_shijuan.push_back(Point2f(left + dst.x, top + dst.y));
- }
- }
- }
- }
- }
- }
- }
- cvReleaseImage(&grayImg);
- }
- if (point_muban.size() > 0){
- cv::Mat response(point_muban.size(), 1, CV_32F);
- cv::Mat trainData(point_muban.size(), 2, CV_32F);
- for (int i = 0; i < point_muban.size(); i++)
- {
- trainData.at<float>(i, 0) = point_muban[i].x;
- trainData.at<float>(i, 1) = point_muban[i].y;
- response.at<float>(i, 0) = i;
- }
- Ptr<TrainData> traind = cv::ml::TrainData::create(trainData, ROW_SAMPLE, response);
- knn->train(traind);
- }
- return IDF_SUCCESS;
- }
- void CResultReader::GetCorrectedRect(CvRect &rr, const IplImage * src, int tembackcolor)
- {
- IplImage t;
- cvInitImageHeader(&t, cvSize(src->width, src->height), src->depth, src->nChannels, src->origin, src->align);
- cvSetData(&t, src->imageData, src->widthStep);
- IplImage * dst = &t;
- const int detect_size = 3;
- int w = rr.width;
- int h = rr.height;
- int detect_src_left = max(0, rr.x - detect_size);
- int detect_src_top = max(0, rr.y - detect_size);
- int detect_src_right = min(dst->width - 1, rr.x + w + detect_size * 2 - 1);
- int detect_src_bottom = min(dst->height - 1, rr.y + h + detect_size * 2 - 1);
- int detect_w = detect_src_right - detect_src_left + 1;
- int detect_h = detect_src_bottom - detect_src_top + 1;
- IplImage * timg = cvCreateImage(cvSize(detect_w, detect_h), IPL_DEPTH_8U, 1);
- cvSetImageROI(dst, cvRect(detect_src_left, detect_src_top, detect_w, detect_h));
- if (dst->nChannels == 3){
- cvCvtColor(dst, timg, CV_BGR2GRAY);
- cvThreshold(timg, timg, tembackcolor, 1, CV_THRESH_BINARY_INV);
- }
- else{
- cvThreshold(dst, timg, tembackcolor, 1, CV_THRESH_BINARY_INV);
- }
- IplImage * iter = cvCreateImage(cvSize(detect_w + 1, detect_h + 1), IPL_DEPTH_32S, 1);
- cvIntegral(timg, iter);
- int max_gray_count = -1;
- CvRect max_gray_count_rect;
- for (int xx = detect_src_left - rr.x; xx <= detect_src_right - (rr.x + rr.width - 1); xx++)
- {
- for (int yy = detect_src_top - rr.y; yy <= detect_src_bottom - (rr.y + rr.height - 1); yy++)
- {
- int iter_left = max(0, detect_size + xx);
- int iter_right = min(rr.width + detect_size * 2, detect_size + xx + rr.width);
- int iter_top = max(0, detect_size + yy);
- int iter_bottom = min(rr.height + detect_size * 2, detect_size + yy + rr.height);
- int gray_count = CV_IMAGE_ELEM(iter, int, iter_bottom, iter_right) - CV_IMAGE_ELEM(iter, int, iter_top, iter_right) - CV_IMAGE_ELEM(iter, int, iter_bottom, iter_left) + CV_IMAGE_ELEM(iter, int, iter_top, iter_left);
- if (gray_count > max_gray_count){
- max_gray_count = gray_count;
- max_gray_count_rect = cvRect(rr.x + xx, rr.y + yy, rr.width, rr.height);
- }
- }
- }
- if (max_gray_count > 0){
- rr = max_gray_count_rect;
- }
- cvReleaseImage(&timg);
- cvReleaseImage(&iter);
- }
- template<typename T1, typename T2>
- T2 CResultReader::GetJiaoZhengResultPoint(T1& point)
- {
- float data[] = { point.x, point.y };
- T2 resultPoint;
- cv::Mat samples(1, 2, CV_32F, data);
- cv::Mat results;
- cv::Mat nresponse;
- cv::Mat dist;
- if (knn->isTrained()){
- float response = knn->findNearest(samples, 1, results, nresponse, dist);
- int idx = response;
- if (0 <= idx&&idx < point_shijuan.size()){
- cv::Point2f pm = point_muban[idx];
- if (GetDistance(pm, point) < 50){
- cv::Point2f ps0 = warpAffinePoint<cv::Point2f, cv::Point2f>(pm, &m_AffineTransform);
- cv::Point2f ps1 = point_shijuan[idx];
- float dx = ps1.x - ps0.x;
- float dy = ps1.y - ps0.y;
- cv::Point2f ps0_0 = warpAffinePoint<cv::Point2f, cv::Point2f>(Point2f(point.x, point.y), &m_AffineTransform);
- resultPoint.x = ps0_0.x + dx;
- resultPoint.y = ps0_0.y + dy;
- }
- else{
- resultPoint = warpAffinePoint<cv::Point2f, T2>(Point2f(point.x, point.y), &m_AffineTransform);
- }
- }
- else{
- resultPoint = warpAffinePoint<cv::Point2f, T2>(Point2f(point.x, point.y), &m_AffineTransform);
- }
- }
- else{
- resultPoint = warpAffinePoint<cv::Point2f, T2>(Point2f(point.x, point.y), &m_AffineTransform);
- }
- return resultPoint;
- }
- int CResultReader::ReadQuestionScore(const ISCH_SCHEMA_PAGE &schemaPage)
- {
- IplImage t;
- cvInitImageHeader(&t, cvSize(src->width, src->height), src->depth, src->nChannels, src->origin, src->align);
- cvSetData(&t, src->imageData, src->widthStep);
- IplImage * dst = &t;
- omr_result->zhutuanti_result.resize(schemaPage.zhuguantis.size());
- vector<ZHUGUANTI_RESULT> & zhutuanti_result_value = omr_result->zhutuanti_result;
- for (int i = 0, score_count=0; i < schemaPage.zhuguantis.size(); i++){
- const ISCH_SCHEMA_ZHUGUANTI& qs = schemaPage.zhuguantis[i];
- double pscale = m_Scaler0;
- int redcount[30];
- int red_in_count[30];
- float w = qs.width*pscale / qs.options.size();
- float h = qs.height*pscale;
- float dy = 0;// (ry - ly) / (float)qs.count;
- BOOL hasSelect = FALSE;
- double lx = m_AffineTransform.at<double>(0, 0)*(qs.centerx - qs.width / 2) + m_AffineTransform.at<double>(0, 1)*(qs.centery - qs.height / 2) + m_AffineTransform.at<double>(0, 2);
- double rx = m_AffineTransform.at<double>(0, 0)*(qs.centerx + qs.width / 2) + m_AffineTransform.at<double>(0, 1)*(qs.centery + qs.height / 2) + m_AffineTransform.at<double>(0, 2);
- int detect_l = lx;
- int detect_r = rx;
- double ly = m_AffineTransform.at<double>(1, 0)*(qs.centerx - qs.width / 2) + m_AffineTransform.at<double>(1, 1)*(qs.centery - qs.height / 2) + m_AffineTransform.at<double>(1, 2);
- int detect_t = max(0, int(ly - h / 2 - 1));
- int detect_b = min(dst->height - 1, int(ly + 3 * h / 2 - 1));
- CvRect detect_rect = cvRect(detect_l, detect_t, detect_r - detect_l + 1, detect_b - detect_t + 1);
- CvRect normal_rect = cvRect(lx, ly, rx - lx + 1, h);
- GetZhuGuanTiRedCount(dst, cvRect(detect_l, detect_t, detect_r - detect_l + 1, detect_b - detect_t + 1), normal_rect, redcount, red_in_count, qs.options.size());
- zhutuanti_result_value[score_count].option.resize(qs.options.size());
- for (int j = 0; j < qs.options.size(); j++){
- CvRect rect = cvRect(detect_r - (j + 1)*(detect_r - detect_l + 1) / qs.options.size(), detect_t, (detect_r - detect_l + 1) / qs.options.size(), detect_b - detect_t + 1);
- SaveRect(rect, zhutuanti_result_value[score_count].option[j]);
- }
- float score = 0;
- BOOL bx = FALSE;//是否判分小数位
- BOOL bg = FALSE;//是否判分个位
- BOOL bs = FALSE;//是否判分十位
- {
- //小数位
- int red_area = 0;
- int red_area_index = -1;
- int red_area_index0 = -1;
- for (int m = 0, n = 0; m < 1; m++, n++)
- {
- if (red_in_count[n] > red_area){ red_area = red_in_count[n]; red_area_index = m; red_area_index0 = n; }
- }
- if (red_area_index >= 0 && redcount[red_area_index0] > 25){
- score = score + 0.5*(red_area_index + 1);
- bx = TRUE;
- }
- }
- {
- //个位
- int red_area = 0;
- int red_area_index = -1;
- int red_area_index0 = -1;
- for (int m = 0, n = 2; m < 10 && n < qs.valid_option_count; m++, n++)
- {
- if (red_in_count[n] > red_area){ red_area = red_in_count[n]; red_area_index = m; red_area_index0 = n; }
- }
- if (red_area_index >= 0 && redcount[red_area_index0] > 25){
- score = score + 1 * (red_area_index);
- bg = TRUE;
- }
- }
- {
- //十位
- int red_area = 0;
- int red_area_index = -1;
- int red_area_index0 = -1;
- for (int m = 0, n = 13; m < 9 && n < qs.valid_option_count; m++, n++)
- {
- if (red_in_count[n] > red_area){ red_area = red_in_count[n]; red_area_index = m; red_area_index0 = n; }
- }
- if (red_area_index >= 0 && redcount[red_area_index0] > 25){
- score = score + 10 * (red_area_index + 1);
- bs = TRUE;
- }
- }
- zhutuanti_result_value[score_count].question_score = score;
- zhutuanti_result_value[score_count].question_state = (bx || bg || bs) ? OMR_QUESTION_STATE_NORMAL : OMR_QUESTION_STATE_LOUPI;
- //zhutuanti_result_value[score_count].question_index = qs.question_index;
- zhutuanti_result_value[score_count].question_code = qs.question_code;
- zhutuanti_result_value[score_count].maxscore = 0;
- zhutuanti_result_value[score_count].omr_question_type = ZHUTUANTI;
- score_count++;
- }
- omr_result->tiankongti_result.resize(schemaPage.tiankongtis.size());
- vector<TIANKONGTI_RESULT> & tiankongti_result_value = omr_result->tiankongti_result;
- for (int i = 0, tiankong_count = 0; i < schemaPage.tiankongtis.size(); i++){
- const ISCH_SCHEMA_TIANKONGTI& qs = schemaPage.tiankongtis[i];
- double pscale = m_Scaler0;
- float w = qs.width*pscale;
- float h = qs.height*pscale;
- double rx = m_AffineTransform.at<double>(0, 0)*(qs.centerx + qs.width / 2) + m_AffineTransform.at<double>(0, 1)*(qs.centery + qs.height / 2) + m_AffineTransform.at<double>(0, 2);
- double ly = m_AffineTransform.at<double>(1, 0)*(qs.centerx - qs.width / 2) + m_AffineTransform.at<double>(1, 1)*(qs.centery - qs.height / 2) + m_AffineTransform.at<double>(1, 2);
- for (int j = 0; j < 1; j++){
- CvRect rect = cvRect((int)(rx - (j + 1)*w - 3), (int)(ly - 3), (int)(w + 6), (int)(h + 6));
- SaveRect(rect, tiankongti_result_value[tiankong_count]);
- cvSetImageROI(dst, rect);
- int detect_l = max(0, rect.x - rect.width);
- int detect_t = max(0, rect.y - rect.height);
- int detect_r = min(dst->width - 1, rect.x + 2 * rect.width - 1);
- int detect_b = min(dst->height - 1, rect.y + 2 * rect.height - 1);
- CvRect rect_detect = cvRect(detect_l, detect_t, detect_r - detect_l + 1, detect_b - detect_t + 1);
- int red_area = GetTianKongTiRedCount(dst, rect, rect_detect);
- if (red_area > 25){
- tiankongti_result_value[tiankong_count].isright = TRUE;
- break;
- }
- else{
- tiankongti_result_value[tiankong_count].isright = FALSE;
- }
- }
- //tiankongti_result_value[tiankong_count].question_index = qs.question_index;
- tiankongti_result_value[tiankong_count].question_code = qs.question_code;
- tiankongti_result_value[tiankong_count].maxscore = 0;
- tiankongti_result_value[tiankong_count].omr_question_type = TIANKONGTI;
- tiankong_count++;
- }
- return IDF_SUCCESS;
- }
- int CResultReader::GetZhuGuanTiRedCount(IplImage * dst, const CvRect& rect, const CvRect& normal_rect, int * red_counts, int * red_in_counts, int count)
- {
- if (dst->nChannels != 3){ return 0; }
- IplImage* red = NULL;
- BOOL s = GetRedBinary(dst, rect, &red);
- if (!s)return 0;
- #define GET_ZHUGUANTI_REDCOUNT_DEBUG 0
- #if GET_ZHUGUANTI_REDCOUNT_DEBUG
- cvShowImage("sss", red);
- cvWaitKey(0);
- #endif
- 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);
- /***求出轮廓重心*****/
- /*cvDrawRect(temp,cvPoint(b_rect.x,b_rect.y),cvPoint(b_rect.x+b_rect.width-1,b_rect.y+b_rect.height-1),cvScalar(0),CV_FILLED);
- cvDrawContours(temp,(CvSeq *)c,cvScalar(255),cvScalar(255),0,CV_FILLED,8);
- int sum_x=0,sum_y=0,sum_count=0;
- for (int y=b_rect.y,end_y=b_rect.y+b_rect.height,end_x=b_rect.x+b_rect.width;y<end_y;y++)
- {
- for (int x = b_rect.x;x<end_x;x++)
- {
- if(CV_IMAGE_ELEM(temp,unsigned char,y,x)){
- sum_x+=x;
- sum_y+=y;
- sum_count++;
- }
- }
- }
- float avgx = sum_x/(float)sum_count;
- float avgy = sum_y/(float)sum_count;
- */
- }
- }
- cvReleaseImage(&temp);
- cvReleaseMemStorage(&storage);
- #if GET_ZHUGUANTI_REDCOUNT_DEBUG
- cvShowImage("sss", red);
- cvWaitKey(0);
- #endif
- 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 IDF_SUCCESS;
- }
- int CResultReader::GetTianKongTiRedCount(IplImage * dst, const CvRect& rect_normal, const CvRect& rect_detect)
- {
- CvRect rect = cvGetImageROI(dst);
- if (dst->nChannels != 3){ 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));
- }
- }
- }
- #define GET_TIANKONGTI_REDCOUNT_DEBUG 0
- #if GET_TIANKONGTI_REDCOUNT_DEBUG
- cvShowImage("sss", red);
- cvWaitKey(0);
- #endif
- 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 (int 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;
- }
- BOOL CResultReader::GetRedBinary(IplImage * dst, const CvRect& rect_detect, IplImage ** red_binary)
- {
- #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);
- cvCvtColor(dst, hsv, CV_BGR2HSV);
- cvCvtColor(dst, gray, CV_BGR2GRAY);
- cvAdaptiveThreshold(gray, gray, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, 9, 10.0);
- rename_image(gray, binary);
- #define HSV_VALUE_H hsv_row_first[hsv_offset]
- #define HSV_VALUE_S hsv_row_first[hsv_offset+1]
- #define HSV_VALUE_V hsv_row_first[hsv_offset+2]
- const int hsv_v_valve = 255 * 50 / 100;
- const int hsv_h_max_valve = 180 * 20 / 360;
- const int hsv_h_min_valve = 180 * 315 / 360;
- const int hsv_s_valve_1 = 255 * 13 / 100;
- const int hsv_s_valve_2 = 255 * 23 / 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;
- }
- }
- cvThreshold(red_high, red_high, 0, 255, CV_THRESH_OTSU);
- int an = 1;
- IplConvKernel * element = cvCreateStructuringElementEx(an * 2 + 1, an * 2 + 1, an, an, CV_SHAPE_RECT, 0);//创建结构元素
- cvDilate(binary, binary, element, 1);//膨胀图像
- cvDilate(red_high, red_high, element, 1);//膨胀图像
- cvDilate(black, black_dilate, element, 1);//膨胀图像
- 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;
- //red1作为返回图像 不释放
- cvReleaseImage(&hsv);
- //cvReleaseImage(&gray);
- cvReleaseImage(&binary);
- cvReleaseImage(&black);
- cvReleaseImage(&black_dilate);
- cvReleaseImage(&red_low);
- //cvReleaseImage(&red_high);
- return TRUE;
- }
- }
|