Util.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. #include "StdAfx.h"
  2. #include "Util.h"
  3. #include "..\zxinglib\zxing\BinaryBitmap.h"
  4. #include "..\zxinglib\zxing\qrcode\QRCodeReader.h"
  5. #include "GrayImageSource.h"
  6. #include "..\zxinglib\zxing\common\GlobalHistogramBinarizer.h"
  7. #include "schema_struct.h"
  8. #include "zxing\MultiFormatReader.h"
  9. #include "zxing\oned\Code128Reader.h"
  10. using namespace std;
  11. using namespace identify::result;
  12. bool sort_locate_point_by_x(const CvRect c1, const CvRect c2)
  13. {
  14. return c1.x < c2.x;
  15. }
  16. bool sort_locate_point_by_y(const CvRect c1, const CvRect c2)
  17. {
  18. return c1.y < c2.y;
  19. }
  20. bool sortx(const CvContour * c1, const CvContour * c2)
  21. {
  22. return c1->rect.x < c2->rect.x;
  23. }
  24. bool sorty(const CvContour * c1, const CvContour * c2)
  25. {
  26. return c1->rect.y < c2->rect.y;
  27. }
  28. struct parrent_desc
  29. {
  30. CvPoint2D32f center;
  31. double angle;
  32. double d;
  33. };
  34. template<class P1, class P2> inline double get_distance(P1 p1, P2 p2){
  35. double dx = p1.x - p2.x;
  36. double dy = p1.y - p2.y;
  37. return sqrt(dx*dx + dy*dy);
  38. }
  39. //该函数主要用于修复二维码,通过轮廓查找二维码的3个定位点,保证3个定位点完整性,其他区域不做处理
  40. int RepairQrCode(IplImage* gray, IplImage*& dst){
  41. #define REPAIRQRCODE_DEBUG 0
  42. try{
  43. CvSize size = cvGetSize(gray);
  44. int w = size.width;
  45. int h = size.height;
  46. #if REPAIRQRCODE_DEBUG
  47. IplImage* gray_debug=cvCloneImage(gray);
  48. IplImage* color=cvCreateImage(cvSize(w,h),IPL_DEPTH_8U,3);
  49. cvCvtColor(gray,color,CV_GRAY2BGR);
  50. #endif
  51. IplImage* binary = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
  52. cvThreshold(gray, binary, 150, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
  53. //cvThreshold(gray,binary,150,255,CV_THRESH_BINARY_INV);
  54. //cvAdaptiveThreshold(gray,binary,255,CV_ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY_INV,21,20);
  55. CvSeq * contour = NULL;
  56. CvMemStorage * storage = cvCreateMemStorage();
  57. IplImage* temp_binary = cvCloneImage(binary);
  58. int contours = cvFindContours(temp_binary, storage, &contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
  59. std::vector<parrent_desc> parrents;
  60. for (CvContour * c = (CvContour *)contour; c != NULL; c = (CvContour *)c->h_next)
  61. {
  62. CvBox2D box = cvMinAreaRect2(c, storage);
  63. if (box.size.width >= 20 && box.size.height >= 20
  64. && box.size.width < max((double)box.size.height + 1, box.size.height*1.2)
  65. && box.size.height < max((double)box.size.width + 1, box.size.width*1.2)){
  66. double area = cvContourArea(c);
  67. if (area < box.size.width*box.size.height*0.8)continue;
  68. double d = sqrt(box.size.width*box.size.height);
  69. //可能的半径
  70. double r[] = { d / (3.0 / 7.0) / 2.0, d / (5.0 / 7.0) / 2.0, d / (7.0 / 7.0) / 2.0 };
  71. double sina = sin(box.angle);
  72. double cosa = cos(box.angle);
  73. int w[10], b[10];
  74. BOOL _find = FALSE;
  75. for (int i = 0; i < 3; i++)
  76. {
  77. memset(w, 0, sizeof(w));
  78. memset(b, 0, sizeof(b));
  79. int xx, yy;
  80. for (int x = (int)-(r[i] + 1); x < r[i] + 1; x++)
  81. {
  82. for (int y = (int)-(r[i] + 1); y < r[i] + 1; y++)
  83. {
  84. xx = static_cast<int>( cosa*x + sina*y + box.center.x);
  85. yy = static_cast<int>(-sina*x + cosa*y + box.center.y);
  86. if (xx < 0 || yy < 0 || xx >= binary->width || yy >= binary->height){
  87. continue;
  88. }
  89. if (CV_IMAGE_ELEM(binary, unsigned char, yy, xx)){
  90. if (max(abs(x), abs(y)) <= 1.5 / 3.5*r[i]){
  91. b[0]++;
  92. }
  93. else if (max(abs(x), abs(y)) <= 2.5 / 3.5*r[i]){
  94. b[1]++;
  95. }
  96. else if (max(abs(x), abs(y)) <= 3.5 / 3.5*r[i]){
  97. b[2]++;
  98. }
  99. }
  100. else{
  101. if (max(abs(x), abs(y)) <= 1.5 / 3.5*r[i]){
  102. w[0]++;
  103. }
  104. else if (max(abs(x), abs(y)) <= 2.5 / 3.5*r[i]){
  105. w[1]++;
  106. }
  107. else if (max(abs(x), abs(y)) <= 3.5 / 3.5*r[i]){
  108. w[2]++;
  109. }
  110. }
  111. }
  112. }
  113. if (w[0]<b[0] && w[1]>b[1] && w[2] < b[2]){
  114. _find = TRUE;
  115. parrent_desc parrent_t;
  116. parrent_t.center = box.center;
  117. parrent_t.d = r[i] * 2;
  118. parrent_t.angle = box.angle;
  119. parrents.push_back(parrent_t);
  120. break;
  121. }
  122. }
  123. if (!_find)continue;
  124. }
  125. }
  126. vector<int> flags(parrents.size());
  127. vector<parrent_desc> marged;
  128. for (std::size_t i = 0; i < parrents.size(); i++)
  129. {
  130. if (flags[i] == 1)continue;
  131. flags[i] = 1;
  132. vector<parrent_desc*> temp_v;
  133. temp_v.push_back(&parrents[i]);
  134. for (std::size_t j = i + 1; j < parrents.size(); j++)
  135. {
  136. if (flags[j] == 0){
  137. if (
  138. parrents[i].d<max(parrents[j].d + 2, parrents[j].d*1.2)
  139. && parrents[i].d>min(parrents[j].d - 2, parrents[j].d*0.8)
  140. && get_distance(parrents[i].center, parrents[j].center) < max((double)2, parrents[i].d * 5 / 7)
  141. ){
  142. temp_v.push_back(&parrents[j]);
  143. flags[j] = 1;
  144. }
  145. }
  146. }
  147. parrent_desc parrent_de;
  148. parrent_de.angle = 0;
  149. parrent_de.d = 0;
  150. parrent_de.center.x = 0;
  151. parrent_de.center.y = 0;
  152. for (std::size_t j = 0; j < temp_v.size(); j++)
  153. {
  154. parrent_de.angle += temp_v[j]->angle;
  155. parrent_de.d += temp_v[j]->d;
  156. parrent_de.center.x += temp_v[j]->center.x;
  157. parrent_de.center.y += temp_v[j]->center.y;
  158. }
  159. parrent_de.angle /= temp_v.size();
  160. parrent_de.d /= temp_v.size();
  161. parrent_de.center.x /= temp_v.size();
  162. parrent_de.center.y /= temp_v.size();
  163. marged.push_back(parrent_de);
  164. #if REPAIRQRCODE_DEBUG
  165. cvDrawRect(color,cvPoint(parrent_de.center.x-parrent_de.d/2,parrent_de.center.y-parrent_de.d/2),cvPoint(parrent_de.center.x+parrent_de.d/2,parrent_de.center.y+parrent_de.d/2),cvScalar(0,0,255),1,CV_AA);
  166. #endif
  167. }
  168. BOOL success = FALSE;
  169. if (marged.size() == 3){//如果找到3个定位点//生成二维码
  170. double d = (marged[0].d + marged[1].d + marged[2].d) / 3;
  171. CvPoint2D32f center; CvPoint2D32f o;
  172. double d0_1 = get_distance(marged[0].center, marged[1].center);
  173. double d1_2 = get_distance(marged[1].center, marged[2].center);
  174. double d2_0 = get_distance(marged[2].center, marged[0].center);
  175. double maxd;
  176. if (d0_1 > d2_0){
  177. if (d0_1 > d1_2){
  178. center = cvPoint2D32f((marged[0].center.x + marged[1].center.x) / 2, (marged[0].center.y + marged[1].center.y) / 2);
  179. o = marged[2].center;
  180. maxd = d0_1;
  181. }
  182. else{
  183. center = cvPoint2D32f((marged[2].center.x + marged[1].center.x) / 2, (marged[2].center.y + marged[1].center.y) / 2);
  184. o = marged[0].center;
  185. maxd = d1_2;
  186. }
  187. }
  188. else{
  189. if (d2_0 > d1_2){
  190. center = cvPoint2D32f((marged[0].center.x + marged[2].center.x) / 2, (marged[0].center.y + marged[2].center.y) / 2);
  191. o = marged[1].center;
  192. maxd = d2_0;
  193. }
  194. else{
  195. center = cvPoint2D32f((marged[2].center.x + marged[1].center.x) / 2, (marged[2].center.y + marged[1].center.y) / 2);
  196. o = marged[0].center;
  197. maxd = d1_2;
  198. }
  199. }
  200. double qr_size = maxd*sqrt(2.0) / 2 + d;
  201. double per_size = (d / 7);
  202. int qr_count = static_cast<int>(qr_size / per_size + 0.5);
  203. per_size = qr_size / qr_count;
  204. double sin_dst; double cos_dst;
  205. double sin_src; double cos_src;
  206. double da, db;
  207. caculate_sc(cvPoint2D32f(100, 100), cvPoint2D32f(0, 0), sin_src, cos_src, db);
  208. caculate_sc(center, o, sin_dst, cos_dst, da);
  209. double sina_b = -sin_dst*cos_src + cos_dst*sin_src;
  210. double cosa_b = cos_dst*cos_src + sin_dst*sin_src;
  211. int xx, yy;
  212. int * wf = new int[qr_count*qr_count];
  213. int * bf = new int[qr_count*qr_count];
  214. int * gh = new int[qr_count*qr_count];
  215. memset(wf, 0, sizeof(int)*qr_count*qr_count);
  216. memset(bf, 0, sizeof(int)*qr_count*qr_count);
  217. memset(gh, 0, sizeof(int)*qr_count*qr_count);
  218. double dddx = -3.5*per_size;
  219. for (int x = 0; x <= qr_size; x++, dddx++)
  220. {
  221. double dddy = -3.5*per_size;
  222. for (int y = 0; y <= qr_size; y++, dddy++)
  223. {
  224. xx = static_cast<int>(cosa_b*dddx + sina_b*dddy + o.x);
  225. yy = static_cast<int>(-sina_b*dddx + cosa_b*dddy + o.y);
  226. if (xx < 0 || yy < 0 || xx >= binary->width || yy >= binary->height){
  227. continue;
  228. }
  229. int indexx = static_cast<int>(x / per_size);
  230. int indexy = static_cast<int>(y / per_size);
  231. #if REPAIRQRCODE_DEBUG
  232. CV_IMAGE_ELEM(gray_debug,unsigned char,yy,xx) /= 2;
  233. if(x-indexx*per_size<1||y-indexy*per_size<1)CV_IMAGE_ELEM(gray_debug,unsigned char,yy,xx) = 255;
  234. #endif
  235. if (indexx < 0 || indexx >= qr_count || indexy < 0 || indexy >= qr_count){
  236. continue;
  237. }
  238. gh[indexy*qr_count + indexx] += CV_IMAGE_ELEM(gray, unsigned char, yy, xx);
  239. if (CV_IMAGE_ELEM(binary, unsigned char, yy, xx)){
  240. bf[indexy*qr_count + indexx]++;
  241. }
  242. else{
  243. wf[indexy*qr_count + indexx]++;
  244. }
  245. #if REPAIRQRCODE_DEBUG
  246. CV_IMAGE_ELEM(gray_debug,unsigned char,yy,xx) /= 2;
  247. if(x-indexx*per_size<1||y-indexy*per_size<1)CV_IMAGE_ELEM(binary,unsigned char,yy,xx) = 128;
  248. #endif
  249. }
  250. }
  251. long sum_gray = 0;
  252. for (int i = 0; i < qr_count*qr_count; i++)
  253. {
  254. sum_gray += gh[i];
  255. }
  256. double gray_avg = sum_gray / (double)(qr_count*qr_count);
  257. #if REPAIRQRCODE_DEBUG
  258. cvShowImage("binary",binary);
  259. cvShowImage("gray_debug",gray_debug);
  260. cvShowImage("color",color);
  261. #endif
  262. //生成二维码
  263. IplImage* _img = cvCreateImage(cvSize(qr_count * 5, qr_count * 5), IPL_DEPTH_8U, 1);
  264. for (int x = 0; x < qr_count; x++)
  265. {
  266. for (int y = 0; y<qr_count; y++)
  267. {
  268. unsigned char v = (bf[y*qr_count + x] * 100>wf[y*qr_count + x] * 70) ? 0 : 255;
  269. v = gh[y*qr_count + x] < gray_avg ? 0 : 255;
  270. for (int mm = 0; mm < 5; mm++)
  271. {
  272. for (int nn = 0; nn < 5; nn++)
  273. {
  274. CV_IMAGE_ELEM(_img, unsigned char, (y * 5 + mm), (x * 5 + nn)) = v;
  275. }
  276. }
  277. }
  278. }
  279. delete bf;
  280. delete wf;
  281. #if REPAIRQRCODE_DEBUG
  282. cvShowImage("_img",_img);
  283. cvWaitKey(0);
  284. #endif
  285. //重画3个定位点,保证正确无误
  286. CvPoint p[3] = { cvPoint(3, 3), cvPoint(qr_count - 4, 3), cvPoint(3, qr_count - 4) };
  287. int vs[5] = { 0, 0, 255, 0, 255 };
  288. int fx[] = { 1, 1, -1, -1 };
  289. int fy[] = { 1, -1, 1, -1 };
  290. for (int i = 0; i < 3; i++)
  291. {
  292. for (int k = 0; k < 4; k++)
  293. {
  294. for (int m = 0; m < 5; m++)
  295. {
  296. int x = p[i].x + fx[k] * m;
  297. if (x < 0 || x >= qr_count)continue;
  298. for (int n = 0; n < 5; n++)
  299. {
  300. int y = p[i].y + fy[k] * n;
  301. if (y < 0 || y >= qr_count)continue;
  302. for (int mm = 0; mm < 5; mm++)
  303. {
  304. for (int nn = 0; nn < 5; nn++)
  305. {
  306. CV_IMAGE_ELEM(_img, unsigned char, (y * 5 + mm), (x * 5 + nn)) = vs[max(m, n)];
  307. }
  308. }
  309. }
  310. }
  311. }
  312. }
  313. dst = _img;
  314. #if REPAIRQRCODE_DEBUG
  315. cvShowImage("_img",_img);
  316. cvWaitKey(0);
  317. #endif
  318. success = TRUE;
  319. }
  320. cvReleaseImage(&binary);
  321. return success ? IDF_SUCCESS : IDF_FAILURE;
  322. }
  323. catch (...){ return IDF_FAILURE; }
  324. }
  325. int PraseQRCode_Normal(IplImage* img, std::string & resultString){
  326. try
  327. {
  328. Ref<LuminanceSource> source(new CGrayImageSource(img));
  329. Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
  330. Ref<BinaryBitmap> image(new BinaryBitmap(binarizer));
  331. DecodeHints hints(DecodeHints::DEFAULT_HINT);
  332. hints.setTryHarder(true);
  333. zxing::qrcode::QRCodeReader reader;
  334. Ref<Result> result(reader.decode(image, hints));
  335. resultString = result->getText()->getText();
  336. }
  337. catch (...){
  338. return IDF_FAILURE;
  339. }
  340. return IDF_SUCCESS;
  341. }
  342. int PraseBarCode_Normal(IplImage* img, std::string & resultString){
  343. try
  344. {
  345. Ref<LuminanceSource> source(new CGrayImageSource(img));
  346. Ref<Binarizer> binarizer(new GlobalHistogramBinarizer(source));
  347. Ref<BinaryBitmap> image(new BinaryBitmap(binarizer));
  348. //DecodeHints hints(DecodeHints::CODE_128_HINT|DecodeHints::CODE_39_HINT);
  349. DecodeHints hints;
  350. hints.setTryHarder(true);
  351. //zxing::MultiFormatReader reader;
  352. zxing::oned::Code128Reader reader;
  353. Ref<Result> result(reader.decode(image, hints));
  354. resultString = result->getText()->getText();
  355. }
  356. catch (std::exception e){
  357. const char* str = e.what();
  358. return IDF_FAILURE;
  359. }
  360. return IDF_SUCCESS;
  361. }
  362. int PraseQRCode(IplImage* img, std::string & resultString)
  363. {
  364. int ret;
  365. ret = PraseQRCode_Normal(img, resultString);
  366. if (ret == IDF_SUCCESS) return ret;
  367. CvRect rect = cvGetImageROI(img);
  368. IplImage* resized_gray = cvCreateImage(cvSize(rect.width * 3, rect.height * 3), IPL_DEPTH_8U, 1);
  369. IplImage* resized_binary = cvCreateImage(cvSize(rect.width * 3, rect.height * 3), IPL_DEPTH_8U, 1);
  370. if (img->nChannels > 1){
  371. IplImage* tmp_gray = cvCreateImage(cvSize(rect.width, rect.height), IPL_DEPTH_8U, 1);
  372. cvCvtColor(img, tmp_gray, CV_BGR2GRAY);
  373. cvResize(tmp_gray, resized_gray);
  374. cvReleaseImage(&tmp_gray);
  375. }
  376. else{
  377. cvResize(img, resized_gray);
  378. }
  379. cvThreshold(resized_gray, resized_binary, 80, 255, CV_THRESH_BINARY);
  380. ret = PraseQRCode_Normal(resized_binary, resultString);
  381. if (ret == IDF_SUCCESS) {
  382. cvReleaseImage(&resized_gray);
  383. cvReleaseImage(&resized_binary);
  384. return ret;
  385. }
  386. cvThreshold(resized_gray, resized_binary, 170, 255, CV_THRESH_BINARY);
  387. ret = PraseQRCode_Normal(resized_binary, resultString);
  388. if (ret == IDF_SUCCESS) {
  389. cvReleaseImage(&resized_gray);
  390. cvReleaseImage(&resized_binary);
  391. return ret;
  392. }
  393. cvThreshold(resized_gray, resized_binary, 200, 255, CV_THRESH_BINARY);
  394. ret = PraseQRCode_Normal(resized_binary, resultString);
  395. if (ret == IDF_SUCCESS) {
  396. cvReleaseImage(&resized_gray);
  397. cvReleaseImage(&resized_binary);
  398. return ret;
  399. }
  400. IplImage * repaired_img = NULL;
  401. int repaired = RepairQrCode(resized_gray, repaired_img);
  402. if (repaired == IDF_SUCCESS){
  403. ret = PraseQRCode_Normal(repaired_img, resultString);
  404. cvReleaseImage(&repaired_img);
  405. if (ret == IDF_SUCCESS) {
  406. cvReleaseImage(&resized_gray);
  407. cvReleaseImage(&resized_binary);
  408. return ret;
  409. }
  410. }
  411. if (TRUE) {
  412. cvReleaseImage(&resized_gray);
  413. cvReleaseImage(&resized_binary);
  414. return IDF_PRASE_QR_ERROR;
  415. }
  416. }
  417. int PraseBarCode0(IplImage* img, std::string & resultString);
  418. int PraseBarCode(IplImage* img, std::string & resultString){
  419. int ret;
  420. ret = PraseBarCode_Normal(img, resultString);
  421. if (ret == IDF_SUCCESS) return ret;
  422. IplImage *temp = cvCreateImage(cvSize(img->height, img->width), img->depth, img->nChannels);
  423. cvTranspose(img, temp);
  424. cvFlip(temp, temp, 0);
  425. ret = PraseBarCode_Normal(temp, resultString);
  426. if (ret == IDF_SUCCESS){
  427. cvReleaseImage(&temp);
  428. return ret;
  429. }
  430. ret = PraseBarCode0(img, resultString);
  431. if (ret == IDF_SUCCESS){
  432. cvReleaseImage(&temp);
  433. return ret;
  434. }
  435. ret = PraseBarCode0(temp, resultString);
  436. {
  437. cvReleaseImage(&temp);
  438. return ret;
  439. }
  440. }
  441. int PraseBarCode0(IplImage* img, std::string & resultString)
  442. {
  443. int ret;
  444. IplImage *temp = cvCreateImage(cvSize(img->height, img->width), img->depth, img->nChannels);
  445. cvTranspose(img, temp);
  446. cvFlip(temp, temp, 0);
  447. ret = PraseBarCode_Normal(temp, resultString);
  448. cvReleaseImage(&temp);
  449. if (ret == IDF_SUCCESS) return ret;
  450. ret = PraseBarCode_Normal(img, resultString);
  451. if (ret == IDF_SUCCESS) return ret;
  452. CvRect rect = cvGetImageROI(img);
  453. IplImage* resized_gray = cvCreateImage(cvSize(rect.width * 3, rect.height * 3), IPL_DEPTH_8U, 1);
  454. IplImage* resized_binary = cvCreateImage(cvSize(rect.width * 3, rect.height * 3), IPL_DEPTH_8U, 1);
  455. if (img->nChannels > 1){
  456. IplImage* tmp_gray = cvCreateImage(cvSize(rect.width, rect.height), IPL_DEPTH_8U, 1);
  457. cvCvtColor(img, tmp_gray, CV_BGR2GRAY);
  458. cvResize(tmp_gray, resized_gray);
  459. cvReleaseImage(&tmp_gray);
  460. }
  461. else{
  462. cvResize(img, resized_gray);
  463. }
  464. cvThreshold(resized_gray, resized_binary, 80, 255, CV_THRESH_BINARY);
  465. ret = PraseBarCode_Normal(resized_binary, resultString);
  466. if (ret == IDF_SUCCESS) {
  467. cvReleaseImage(&resized_gray);
  468. cvReleaseImage(&resized_binary);
  469. return ret;
  470. }
  471. cvThreshold(resized_gray, resized_binary, 170, 255, CV_THRESH_BINARY);
  472. ret = PraseBarCode_Normal(resized_binary, resultString);
  473. if (ret == IDF_SUCCESS) {
  474. cvReleaseImage(&resized_gray);
  475. cvReleaseImage(&resized_binary);
  476. return ret;
  477. }
  478. cvThreshold(resized_gray, resized_binary, 200, 255, CV_THRESH_BINARY);
  479. ret = PraseBarCode_Normal(resized_binary, resultString);
  480. if (ret == IDF_SUCCESS) {
  481. cvReleaseImage(&resized_gray);
  482. cvReleaseImage(&resized_binary);
  483. return ret;
  484. }
  485. cvThreshold(resized_gray, resized_binary, 215, 255, CV_THRESH_BINARY);
  486. ret = PraseBarCode_Normal(resized_binary, resultString);
  487. if (ret == IDF_SUCCESS) {
  488. cvReleaseImage(&resized_gray);
  489. cvReleaseImage(&resized_binary);
  490. return ret;
  491. }
  492. cvThreshold(resized_gray, resized_binary, 230, 255, CV_THRESH_BINARY);
  493. ret = PraseBarCode_Normal(resized_binary, resultString);
  494. if (ret == IDF_SUCCESS) {
  495. cvReleaseImage(&resized_gray);
  496. cvReleaseImage(&resized_binary);
  497. return ret;
  498. }
  499. cvThreshold(resized_gray, resized_binary, 240, 255, CV_THRESH_BINARY);
  500. ret = PraseBarCode_Normal(resized_binary, resultString);
  501. if (ret == IDF_SUCCESS) {
  502. cvReleaseImage(&resized_gray);
  503. cvReleaseImage(&resized_binary);
  504. return ret;
  505. }
  506. cvThreshold(resized_gray, resized_binary, 250, 255, CV_THRESH_BINARY);
  507. ret = PraseBarCode_Normal(resized_binary, resultString);
  508. if (ret == IDF_SUCCESS) {
  509. cvReleaseImage(&resized_gray);
  510. cvReleaseImage(&resized_binary);
  511. return ret;
  512. }
  513. if (TRUE) {
  514. cvReleaseImage(&resized_gray);
  515. cvReleaseImage(&resized_binary);
  516. return IDF_PRASE_QR_ERROR;
  517. }
  518. }
  519. double degree(const int& x1, const int& y1, const int& x2, const int& y2)
  520. {
  521. return acos((x2 - x1) / sqrt((double)(y2 - y1)*(y2 - y1) + (x2 - x1)*(x2 - x1)));
  522. }
  523. int GetBlackArea(const IplImage * dst, int valve /*=180*/)
  524. {
  525. int blackArea = 0;
  526. CvRect rect = cvGetImageROI(dst);
  527. int(*GetGray)(const IplImage * dst, int x, int y);
  528. if (dst->nChannels == 1)GetGray = GetGrayValue;
  529. else GetGray = GetBGRGray;
  530. for (int y = rect.y, endy = rect.y + rect.height; y < endy; y++)
  531. {
  532. for (int x = rect.x, endx = rect.x + rect.width; x < endx; x++)
  533. {
  534. if (GetGray(dst, x, y) < valve)blackArea++;
  535. }
  536. }
  537. return blackArea;
  538. }
  539. void rgb2hsv(const int& r, const int& g, const int& b, float& h, float& s, float& v)
  540. {
  541. float _min = r<g ? (r < b ? r : b) : (g < b ? g : b);
  542. float _max = r > g ? (r > b ? r : b) : (g>b ? g : b);
  543. v = _max;
  544. s = (_max == 0) ? 0 : (_max - _min) / _max;
  545. if (_max == _min)h = 0;
  546. else if (_max == r)h = 60 * (g - b) / (_max - _min);
  547. else if (_max == g)h = 60 * (b - r) / (_max - _min) + 120;
  548. else if (_max == b)h = 60 * (r - g) / (_max - _min) + 240;
  549. if (h < 0)h = h + 360;
  550. }
  551. int GetBGRGray(const IplImage * dst, int x, int y)
  552. {
  553. /*http://blog.sina.com.cn/s/blog_74cf26810100rjc3.html
  554. Gray = (R*38 + G*75 + B*15) >> 7
  555. */
  556. return ((0xff & dst->imageData[y*dst->widthStep + x*dst->nChannels]) * 15 +
  557. (0xff & dst->imageData[y*dst->widthStep + x*dst->nChannels + 1]) * 75 +
  558. (0xff & dst->imageData[y*dst->widthStep + x*dst->nChannels + 2]) * 38) >> 7;
  559. }
  560. int GetGrayValue(const IplImage * dst, int x, int y)
  561. {
  562. return 0xff & dst->imageData[y*dst->widthStep + x];
  563. }
  564. IplImage* CutRotateImage(const IplImage* img, CvPoint center, CvSize size, float degree)
  565. {
  566. double angle = degree*CV_PI / 180.;
  567. IplImage * result = cvCreateImage(size, img->depth, img->nChannels);
  568. float m[6] = { cos(angle), sin(angle), center.x, -sin(angle), cos(angle), center.y };
  569. CvMat M = cvMat(2, 3, CV_32F, m);
  570. cvGetQuadrangleSubPix(img, result, &M);
  571. return result;
  572. }
  573. IplImage* CutImage(IplImage* img, CvRect rect)
  574. {
  575. IplImage* result = cvCreateImage(cvSize(rect.width, rect.height), img->depth, img->nChannels);
  576. cvGetRectSubPix(img, result, cvPoint2D32f(rect.x + rect.width*0.5, rect.y + rect.height*0.5));
  577. return result;
  578. }
  579. //注意:当字符串为空时,也会返回一个空字符串
  580. void split(std::string& s, std::string& delim, std::vector< std::string >* ret)
  581. {
  582. size_t last = 0;
  583. size_t index = s.find_first_of(delim, last);
  584. while (index != std::string::npos)
  585. {
  586. ret->push_back(s.substr(last, index - last));
  587. last = index + 1;
  588. index = s.find_first_of(delim, last);
  589. }
  590. if (index - last > 0)
  591. {
  592. ret->push_back(s.substr(last, index - last));
  593. }
  594. }
  595. void SetTBLR(identify::autoschema::ASCH_SchemaQuestionScore& score)
  596. {
  597. score.lt.x = score.lb.x = (int)(0.5 + score.centerx - score.width / 2.0);
  598. score.rt.x = score.rb.x = (int)(0.5 + score.centerx + score.width / 2.0);
  599. score.lt.y = score.rt.y = (int)(0.5 + score.centery - score.height / 2.0);
  600. score.lb.y = score.rb.y = (int)(0.5 + score.centery + score.height / 2.0);
  601. }