博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV条码(6)简单实现
阅读量:6983 次
发布时间:2019-06-27

本文共 26027 字,大约阅读时间需要 86 分钟。

OpenCV读取条码图像,并利用EAN-13码的编码方式解码。

通过读入一张条码图像,识别对应的条码。

参考自  http://felix.abecassis.me/2011/10/opencv-barcode-reader-part-1/

 

/*version 0.01: * 只是把upc的识别换成了ean的识别 * 第一个数字只能识别6或者9 * 图像要求为只包含条码 * 清晰度要求太高,500w手机拍照的照片不能完全识别 *---- *    ChriZZ   2013.5.5 */   1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 8 using namespace std; 9 using namespace cv; 10 11 #define SPACE 0 12 #define BAR 255 13 14 typedef Mat_
MatU; 15 map
table[3]; 16 enum position{LEFT,RIGHT}; 17 int counter; //计数器,表示正在计算的条码编号(不包括起始编号) 18 int front; //起始编号 19 int mode[6]; //不同的起始编号对应着不同的左侧编码模式,比如起始编号为6对应“奇偶偶偶奇奇”,9对应“奇偶偶奇偶奇”。用1表示奇数,0表示偶数 20 21 void change01(string & s){ //0和1互换。解码时使用 22 for(int i=0; i
=threshold) v=v+"1"; 70 else v=v+"0"; 71 } 72 // Lookup digit value. 73 int digit; 74 if (position == LEFT){ 75 if(counter==0){ 76 if(v=="0001011"){ //说明左侧数据第一个字符是6,将模式设定为“奇偶偶偶奇奇” 77 mode[0]=1; 78 mode[1]=0; 79 mode[2]=0; 80 mode[3]=0; 81 mode[4]=1; 82 mode[5]=1; 83 front=6; 84 }else{ //在中国除了69*开头的条码 应该都是97*开头的(ISBN) 85 mode[0]=1; 86 mode[1]=0; 87 mode[2]=0; 88 mode[3]=1; 89 mode[4]=0; 90 mode[5]=1; 91 front=9; 92 } 93 } 94 if(mode[counter]==1) digit=table[0][v]; //对应左侧奇数的编码方式 95 else digit=table[1][v]; //对应左侧偶数的编码方式 96 align_boundary(img, cur, SPACE, BAR); 97 }else{ 98 // Bitwise complement (only on the first 7 bits). 99 digit = table[2][v]; //对应右侧偶数的编码方式100 align_boundary(img, cur, BAR, SPACE);101 }102 counter++;103 return digit;104 }105 106 void skip_quiet_zone(const MatU& img, Point& cur){ //略过空白区域107 while (img(cur) == SPACE)108 ++cur.x;109 }110 111 unsigned read_lguard(const MatU& img, Point& cur){ //读取起始编号和左侧数据之间的112 int widths[3] = { 0, 0, 0 };113 int pattern[3] = { BAR, SPACE, BAR };114 for (int i = 0; i < 3; i++)115 while (img(cur) == pattern[i]){116 ++cur.x;117 ++widths[i];118 }119 return widths[0];120 }121 122 void skip_mguard(const MatU& img, Point& cur){ //略过左侧数据和右侧数据之间的分界123 int pattern[5] = { SPACE, BAR, SPACE, BAR, SPACE };124 for (int i = 0; i < 5; i++)125 while (img(cur) == pattern[i])126 ++cur.x;127 }128 129 void read_barcode(const string& filename){ //读取条码主程序130 counter=0;131 MatU img = cv::imread(filename, 0); //载入图像132 Size size = img.size();133 Point cur(0, size.height / 2); //cur表示当前位置134 135 bitwise_not(img, img);136 threshold(img, img, 128, 255, THRESH_BINARY);137 skip_quiet_zone(img, cur);138 139 setup_map(); //初始化解析表140 141 int unit_width = read_lguard(img, cur);142 143 vector
digits;144 for (int i=0; i<6; i++){ //左侧数据解码145 int d = read_digit(img, cur, unit_width, LEFT);146 digits.push_back(d);147 }148 149 skip_mguard(img, cur);150 151 for (int i = 0; i < 6; i++){ //右侧数据解码152 int d = read_digit(img, cur, unit_width, RIGHT);153 digits.push_back(d);154 }155 cout << front; //输出解码结果156 for (int i = 0; i < 12; i++)157 cout << digits[i];158 cout << endl;159 waitKey();160 }161 int main(){162 string imgname="C:/testdir/left.jpg";163 read_barcode(imgname);164 return 0;165 }

 

通过改进测量方法,用数学的手段减小了误差,提高了识别率,代码如下

 

/*version 0.02 *提高了识别精度 *第一位字符通过左侧6个数据反推得到,不仅仅限定于6和9 *------ *     ChrisZZ  2012.5.5 */   1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 9 using namespace std; 10 using namespace cv; 11 12 #define SPACE 0 13 #define BAR 255 14 15 typedef Mat_
MatU; 16 map
table[3]; 17 enum position{LEFT,RIGHT}; 18 int front; //起始编号 19 int mode[6]; //不同的起始编号对应着不同的左侧编码模式,比如起始编号为6对应“奇偶偶偶奇奇”,9对应“奇偶偶奇偶奇”。用1表示奇数,0表示偶数 20 const double eps=1e-5; 21 int z; 22 23 int get_front(){ 24 string tmp=""; 25 int i; 26 for(i=0; i<6; i++){ 27 if(mode[i]==0) tmp=tmp+"0"; 28 else tmp=tmp+"1"; 29 } 30 if(tmp=="000000") return 0; 31 else if(tmp=="001011") return 1; 32 else if(tmp=="001101") return 2; 33 else if(tmp=="001110") return 3; 34 else if(tmp=="010011") return 4; 35 else if(tmp=="011001") return 5; 36 else if(tmp=="011100") return 6; 37 else if(tmp=="010101") return 7; 38 else if(tmp=="010110") return 8; 39 else if(tmp=="011010") return 9; 40 else return -1; 41 } 42 43 void align_boundary(const MatU& img, Point& cur, int begin, int end){ 44 if (img(cur) == end){ 45 while (img(cur)==end) 46 ++cur.x; 47 }else{ 48 while (img(cur.y, cur.x-1)==begin) 49 --cur.x; 50 } 51 } 52 53 /*int read_digit(...) 54 *返回解析后得到的数字*/ 55 int read_digit(const MatU& img, Point& cur, int position){ 56 int pattern[4] = { 0,0,0,0}, i; 57 for (i=0; i<4; i++){ 58 int cur_val=img(cur); 59 while(img(cur)==cur_val){ 60 ++pattern[i]; 61 ++cur.x; 62 } 63 } 64 double sum=pattern[0]+pattern[1]+pattern[2]+pattern[3]; 65 double tmp1=(pattern[0]+pattern[1])*1.0; 66 double tmp2=(pattern[1]+pattern[2])*1.0; 67 int at1, at2; 68 if(tmp1/sum < 2.5/7) at1=2; 69 else if(tmp1/sum < 3.5/7) at1=3; 70 else if(tmp1/sum < 4.5/7) at1=4; 71 else at1=5; 72 73 if(tmp2/sum < 2.5/7) at2=2; 74 else if(tmp2/sum < 3.5/7) at2=3; 75 else if(tmp2/sum < 4.5/7) at2=4; 76 else at2=5; 77 78 int digit=-1; 79 80 if(position==LEFT){ 81 if(at1==2){ 82 if(at2==2) { 83 mode[z++]=0; 84 digit = 6; 85 } 86 else if(at2==3) { 87 mode[z++]=1; 88 digit = 0; 89 } 90 else if(at2==4) { 91 mode[z++]=0; 92 digit = 4; 93 } 94 else if(at2==5) { 95 mode[z++]=1; 96 digit = 3; 97 } 98 } 99 else if(at1==3){100 if(at2==2) {101 mode[z++]=1;102 digit = 9;103 }104 else if(at2==3) {105 mode[z++]=0;106 if(pattern[2]+1
digits;215 for (int i=0; i<6; i++){ //左侧数据解码216 int d = read_digit(img, cur, LEFT);217 digits.push_back(d);218 }219 skip_mguard(img, cur);220 for (int i = 0; i < 6; i++){ //右侧数据解码221 int d = read_digit(img, cur, RIGHT);222 digits.push_back(d);223 }224 //输出解码结果225 int front=get_front();226 cout << front << " ";227 for (int i = 0; i < 12; i++)228 cout << digits[i] << " ";229 cout << endl;230 waitKey();231 }232 int main(){233 string imgname="C:/testdir/barcode3.jpg";234 read_barcode(imgname);235 return 0;236 }

 

目前把摄像头调用和条码图片检测联系在一起,发现有问题,矩形区域的确认还没做好。。使用了多边形。

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 9 using namespace std; 10 using namespace cv; 11 12 #define SPACE 0 13 #define BAR 255 14 15 typedef Mat_
MatU; 16 map
table[3]; 17 enum position{LEFT,RIGHT}; 18 int front; //Æðʼ±àºÅ 19 int mode[6]; //²»Í¬µÄÆðʼ±àºÅ¶ÔÓ¦×Ų»Í¬µÄ×ó²à±àÂëģʽ£¬±ÈÈçÆðʼ±àºÅΪ6¶ÔÓ¦¡°ÆæżżżÆæÆ桱£¬9¶ÔÓ¦¡°ÆæżżÆæżÆ桱¡£ÓÃ1±íʾÆæÊý£¬0±íʾżÊý 20 const double eps=1e-5; 21 int z; 22 23 int get_front(){ 24 string tmp=""; 25 int i; 26 for(i=0; i<6; i++){ 27 if(mode[i]==0) tmp=tmp+"0"; 28 else tmp=tmp+"1"; 29 } 30 if(tmp=="000000") return 0; 31 else if(tmp=="001011") return 1; 32 else if(tmp=="001101") return 2; 33 else if(tmp=="001110") return 3; 34 else if(tmp=="010011") return 4; 35 else if(tmp=="011001") return 5; 36 else if(tmp=="011100") return 6; 37 else if(tmp=="010101") return 7; 38 else if(tmp=="010110") return 8; 39 else if(tmp=="011010") return 9; 40 else return -1; 41 } 42 43 void align_boundary(const MatU& img, Point& cur, int begin, int end){ 44 if (img(cur) == end){ 45 while (img(cur)==end) 46 ++cur.x; 47 }else{ 48 while (img(cur.y, cur.x-1)==begin) 49 --cur.x; 50 } 51 } 52 53 /*int read_digit(...) 54 *·µ»Ø½âÎöºóµÃµ½µÄÊý×Ö*/ 55 int read_digit(const MatU& img, Point& cur, int position){ 56 // Read the 7 consecutive bits. 57 int pattern[4] = { 0,0,0,0}; 58 int i; 59 for (i=0; i<4; i++){ 60 int cur_val=img(cur); 61 while(img(cur)==cur_val){ 62 ++pattern[i]; 63 ++cur.x; 64 } 65 cout << endl; 66 cout << "pattern[" << i << "]=" << pattern[i] << endl; 67 // See below for explanation. 68 /* if ((pattern[i] == 1 && img(cur) == BAR) || (pattern[i] == unit_width - 1 && img(cur) == SPACE)) 69 --cur.x;*/ 70 } 71 72 73 74 // Convert to binary, consider that a bit is set if the number of 75 // bars encountered is greater than a threshold. 76 double sum=pattern[0]+pattern[1]+pattern[2]+pattern[3]; 77 double tmp1=(pattern[0]+pattern[1])*1.0; 78 double tmp2=(pattern[1]+pattern[2])*1.0; 79 int at1, at2; 80 if(tmp1/sum < 2.5/7) at1=2; 81 else if(tmp1/sum < 3.5/7) at1=3; 82 else if(tmp1/sum < 4.5/7) at1=4; 83 else at1=5; 84 85 if(tmp2/sum < 2.5/7) at2=2; 86 else if(tmp2/sum < 3.5/7) at2=3; 87 else if(tmp2/sum < 4.5/7) at2=4; 88 else at2=5; 89 90 int digit=-1; 91 92 if(position==LEFT){ 93 if(at1==2){ 94 if(at2==2) { 95 mode[z++]=0; 96 digit = 6; 97 } 98 else if(at2==3) { 99 mode[z++]=1;100 digit = 0;101 }102 else if(at2==4) {103 mode[z++]=0;104 digit = 4;105 }106 else if(at2==5) {107 mode[z++]=1;108 digit = 3;109 }110 }111 else if(at1==3){112 if(at2==2) {113 mode[z++]=1;114 digit = 9;115 }116 else if(at2==3) {117 mode[z++]=0;118 if(pattern[2]+1
266 #include
267 #include
268 269 using namespace cv;270 using namespace std;271 272 static void help()273 {274 cout <<275 "\nA program using pyramid scaling, Canny, contours, contour simpification and\n"276 "memory storage (it's got it all folks) to find\n"277 "squares in a list of images pic1-6.png\n"278 "Returns sequence of squares detected on the image.\n"279 "the sequence is stored in the specified memory storage\n"280 "Call:\n"281 "./squares\n"282 "Using OpenCV version %s\n" << CV_VERSION << "\n" << endl;283 }284 285 286 int thresh = 50, N = 11;287 const char* wndname = "Square Detection Demo";288 289 // helper function:290 // finds a cosine of angle between vectors291 // from pt0->pt1 and from pt0->pt2292 static double angle( Point pt1, Point pt2, Point pt0 )293 {294 double dx1 = pt1.x - pt0.x;295 double dy1 = pt1.y - pt0.y;296 double dx2 = pt2.x - pt0.x;297 double dy2 = pt2.y - pt0.y;298 return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);299 }300 301 // returns sequence of squares detected on the image.302 // the sequence is stored in the specified memory storage303 static void findSquares( const Mat& image, vector
>& squares )304 {305 squares.clear();306 307 Mat pyr, timg, gray0(image.size(), CV_8U), gray;308 309 // down-scale and upscale the image to filter out the noise310 pyrDown(image, pyr, Size(image.cols/2, image.rows/2));311 pyrUp(pyr, timg, image.size());312 vector
> contours;313 314 // find squares in every color plane of the image315 for( int c = 0; c < 3; c++ )316 {317 int ch[] = {c, 0};318 mixChannels(&timg, 1, &gray0, 1, ch, 1);319 320 // try several threshold levels321 for( int l = 0; l < N; l++ )322 {323 // hack: use Canny instead of zero threshold level.324 // Canny helps to catch squares with gradient shading325 if( l == 0 )326 {327 // apply Canny. Take the upper threshold from slider328 // and set the lower to 0 (which forces edges merging)329 Canny(gray0, gray, 0, thresh, 5);330 // dilate canny output to remove potential331 // holes between edge segments332 dilate(gray, gray, Mat(), Point(-1,-1));333 }334 else335 {336 // apply threshold if l!=0:337 // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0338 gray = gray0 >= (l+1)*255/N;339 }340 341 // find contours and store them all as a list342 findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);343 344 vector
approx;345 346 // test each contour347 for( size_t i = 0; i < contours.size(); i++ )348 {349 // approximate contour with accuracy proportional350 // to the contour perimeter351 approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);352 353 // square contours should have 4 vertices after approximation354 // relatively large area (to filter out noisy contours)355 // and be convex.356 // Note: absolute value of an area is used because357 // area may be positive or negative - in accordance with the358 // contour orientation359 if( approx.size() == 4 &&360 fabs(contourArea(Mat(approx))) > 1000 &&361 isContourConvex(Mat(approx)) )362 {363 double maxCosine = 0;364 365 for( int j = 2; j < 5; j++ )366 {367 // find the maximum cosine of the angle between joint edges368 double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));369 maxCosine = MAX(maxCosine, cosine);370 }371 372 // if cosines of all angles are small373 // (all angles are ~90 degree) then write quandrange374 // vertices to resultant sequence375 if( maxCosine < 0.3 )376 squares.push_back(approx);377 }378 }379 }380 }381 }382 383 bool zrange(const Point* p){384 385 386 for(int i=0; i<4; i++){387 if(!(p[i].x>0&&p[i].x<480&&p[i].y>0&&p[i].y<480))388 return false;389 cout << "(" << p[i].x << "," << p[i].y << ")" << endl;390 }391 return true;392 }393 394 // the function draws all the squares in the image395 static void drawSquares( Mat& image, const vector
>& squares )396 {397 for( size_t i = 0; i < squares.size(); i++ )398 {399 const Point* p = &squares[i][0];400 int n = (int)squares[i].size();//actually n is always equals to 4401 // polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);402 403 404 405 //read_barcode(Rect(p[0], p[2]));406 // if(zrange(p))407 // { 408 for(int j=0; j<4; j++){ //使用line()函数替代polyline()函数画四边形409 line(image, p[j], p[(j+1)%4], Scalar( 255 ), 3, 8);410 }411 412 // MatU imageROI=image(Rect(p[0], p[2]));413 // MatU zcopy=Mat(imageROI);414 415 // read_barcode(imageROI);416 // addWeighted(imageROI,1.0,zcopy,0.3,0.,image);417 // cout << endl;418 // }419 // vector
approxedRectangle;420 // approxPolyDP(squares[i], approxedRectangle, 0., true);421 // fillConvexPoly(image, &approxedRectangle[0], 4, 4);422 423 // fillConvexPoly(Inputimage, inputarrayPoints, scalarColor, lineType, shift);424 425 426 }427 428 imshow(wndname, image);429 }430 431 int main(){432 433 /*434 string msg="press q , Q or ESC to close this program";435 cout << msg << endl;436 VideoCapture capture(0);437 if(!capture.isOpened()) return 1;438 Mat image; //frame of video439 string window_name="Extracted Frame";440 namedWindow(window_name);441 while(true){442 capture >> image;443 vector
> squares;444 if(image.data){445 findSquares(image, squares);446 drawSquares(image, squares);447 }448 if(waitKey(30)>=0) break;449 }450 */451 MatU image=imread("C:/testdir/barcode11.jpg", 0);452 vector
> squares;453 findSquares(image, squares);454 drawSquares(image, squares);455 // read_barcode(image);456 waitKey(0);457 /*458 459 Mat image=imread("C:/testdir/test1.jpg");460 Mat roi=image(Rect(20, 20, 100, 100));461 462 Mat mask=Mat(roi);463 cvtColor(mask, mask, CV_RGB2GRAY);464 465 addWeighted(roi, 1.0, mask, 0.3, 0., image);466 467 imshow("dfds", image);468 waitKey(0);469 470 */471 472 473 474 475 return 0;476 }477 478 479 480 /*481 482 int main(){483 Mat image=imread("C:/testdir/barcode1.jpg");484 MatU logo=image(Rect(110, 200, 265, 230));485 486 read_barcode(logo);487 addWeighted(logo, 1.0, logo, 0.3, 0., logo);488 imshow("with logo", image);489 waitKey(0);490 491 492 }493 494 */495 496 497 /*------------------------------------------------------------------------------------------*\498 This file contains material supporting chapter 2 of the cookbook:499 Computer Vision Programming using the OpenCV Library.500 by Robert Laganiere, Packt Publishing, 2011.501 502 This program is free software; permission is hereby granted to use, copy, modify,503 and distribute this source code, or portions thereof, for any purpose, without fee,504 subject to the restriction that the copyright notice may not be removed505 or altered from any source or altered source distribution.506 The software is released on an as-is basis and without any warranties of any kind.507 In particular, the software is not guaranteed to be fault-tolerant or free from failure.508 The author disclaims all warranties with regard to this software, any use,509 and any consequent failure, is purely the responsibility of the user.510 511 Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name512 \*------------------------------------------------------------------------------------------*/513 /*514 515 #include
516 #include
517 #include
518 519 520 int main()521 {522 cv::Mat image1;523 cv::Mat image2;524 525 image1= cv::imread("C:/testdir/barcode1.jpg");526 image2= cv::imread("C:/testdir/barcode19.jpg");527 if (!image1.data)528 return 0;529 if (!image2.data)530 return 0;531 532 cv::namedWindow("Image 1");533 cv::imshow("Image 1",image1);534 cv::namedWindow("Image 2");535 cv::imshow("Image 2",image2);536 537 cv::Mat result;538 cv::addWeighted(image1,0.7,image2,0.9,0.,result);539 540 cv::namedWindow("result");541 cv::imshow("result",result);542 543 // using overloaded operator544 result= 0.7*image1+0.9*image2;545 546 cv::namedWindow("result with operators");547 cv::imshow("result with operators",result);548 /*549 image2= cv::imread("rain.jpg",0);550 551 // create vector of 3 images552 std::vector
planes;553 // split 1 3-channel image into 3 1-channel images554 cv::split(image1,planes);555 // add to blue channel556 planes[0]+= image2;557 // merge the 3 1-channel images into 1 3-channel image558 cv::merge(planes,result);559 560 cv::namedWindow("Result on blue channel");561 cv::imshow("Result on blue channel",result);562 563 // read images564 cv::Mat image= cv::imread("boldt.jpg");565 cv::Mat logo= cv::imread("logo.bmp");566 567 // define image ROI568 cv::Mat imageROI;569 imageROI= image(cv::Rect(385,270,logo.cols,logo.rows));570 571 // add logo to image572 cv::addWeighted(imageROI,1.0,logo,0.3,0.,imageROI);573 574 // show result575 cv::namedWindow("with logo");576 cv::imshow("with logo",image);577 578 // read images579 image= cv::imread("boldt.jpg");580 logo= cv::imread("logo.bmp");581 582 // define ROI583 imageROI= image(cv::Rect(385,270,logo.cols,logo.rows));584 585 // load the mask (must be gray-level)586 cv::Mat mask= cv::imread("logo.bmp",0);587 588 // copy to ROI with mask589 logo.copyTo(imageROI,mask);590 591 // show result592 cv::namedWindow("with logo 2");593 cv::imshow("with logo 2",image);594 595 // read images596 logo= cv::imread("logo.bmp",0);597 image1= cv::imread("boldt.jpg");598 599 // split 3-channel image into 3 1-channel images600 std::vector
channels;601 cv::split(image1,channels);602 603 imageROI= channels.at(1);604 605 cv::addWeighted(imageROI(cv::Rect(385,270,logo.cols,logo.rows)),1.0,606 logo,0.5,0.,imageROI(cv::Rect(385,270,logo.cols,logo.rows)));607 608 cv::merge(channels,image1);609 610 cv::namedWindow("with logo 3");611 cv::imshow("with logo 3",image1);612 613 cv::waitKey();614 615 return 0;616 }617 618 619 620 621 622 */

 今天打开Qt发现Qt抽了。。程序一直报错。把复杂的程序都注释了只剩下读入和显示一张图片的代码结果仍然报错。我确实有清理过项目和重新构建项目。诶,蛋疼。重新建立一个工程写吧。。

代码:读入图片,检测、圈出并截图显示 :宽度在50-280之间的矩形框

1 #include "opencv2/core/core.hpp"  2 #include "opencv2/imgproc/imgproc.hpp"  3 #include "opencv2/highgui/highgui.hpp"  4   5 #include 
6 #include
7 #include
8 9 using namespace cv; 10 using namespace std; 11 12 13 #define SPACE 0 14 #define BAR 255 15 16 typedef Mat_
MatU; 17 map
table[3]; 18 enum position{LEFT,RIGHT}; 19 int front; //Æðʼ±àºÅ 20 int mode[6]; //²»Í¬µÄÆðʼ±àºÅ¶ÔÓ¦×Ų»Í¬µÄ×ó²à±àÂëģʽ£¬±ÈÈçÆðʼ±àºÅΪ6¶ÔÓ¦¡°ÆæżżżÆæÆ桱£¬9¶ÔÓ¦¡°ÆæżżÆæżÆ桱¡£ÓÃ1±íʾÆæÊý£¬0±íʾżÊý 21 const double eps=1e-5; 22 int z; 23 24 int get_front(){ 25 string tmp=""; 26 int i; 27 for(i=0; i<6; i++){ 28 if(mode[i]==0) tmp=tmp+"0"; 29 else tmp=tmp+"1"; 30 } 31 if(tmp=="000000") return 0; 32 else if(tmp=="001011") return 1; 33 else if(tmp=="001101") return 2; 34 else if(tmp=="001110") return 3; 35 else if(tmp=="010011") return 4; 36 else if(tmp=="011001") return 5; 37 else if(tmp=="011100") return 6; 38 else if(tmp=="010101") return 7; 39 else if(tmp=="010110") return 8; 40 else if(tmp=="011010") return 9; 41 else return -1; 42 } 43 44 void align_boundary(const MatU& img, Point& cur, int begin, int end){ 45 if (img(cur) == end){ 46 while (img(cur)==end) 47 ++cur.x; 48 }else{ 49 while (img(cur.y, cur.x-1)==begin) 50 --cur.x; 51 } 52 } 53 54 /*int read_digit(...) 55 *·µ»Ø½âÎöºóµÃµ½µÄÊý×Ö*/ 56 int read_digit(const MatU& img, Point& cur, int position){ 57 // Read the 7 consecutive bits. 58 int pattern[4] = {
0,0,0,0}; 59 int i; 60 for (i=0; i<4; i++){ 61 int cur_val=img(cur); 62 while(img(cur)==cur_val){ 63 ++pattern[i]; 64 ++cur.x; 65 } 66 cout << endl; 67 cout << "pattern[" << i << "]=" << pattern[i] << endl; 68 // See below for explanation. 69 /* if ((pattern[i] == 1 && img(cur) == BAR) || (pattern[i] == unit_width - 1 && img(cur) == SPACE)) 70 --cur.x;*/ 71 } 72 73 74 75 // Convert to binary, consider that a bit is set if the number of 76 // bars encountered is greater than a threshold. 77 double sum=pattern[0]+pattern[1]+pattern[2]+pattern[3]; 78 double tmp1=(pattern[0]+pattern[1])*1.0; 79 double tmp2=(pattern[1]+pattern[2])*1.0; 80 int at1, at2; 81 if(tmp1/sum < 2.5/7) at1=2; 82 else if(tmp1/sum < 3.5/7) at1=3; 83 else if(tmp1/sum < 4.5/7) at1=4; 84 else at1=5; 85 86 if(tmp2/sum < 2.5/7) at2=2; 87 else if(tmp2/sum < 3.5/7) at2=3; 88 else if(tmp2/sum < 4.5/7) at2=4; 89 else at2=5; 90 91 int digit=-1; 92 93 if(position==LEFT){ 94 if(at1==2){ 95 if(at2==2) { 96 mode[z++]=0; 97 digit = 6; 98 } 99 else if(at2==3) {100 mode[z++]=1;101 digit = 0;102 }103 else if(at2==4) {104 mode[z++]=0;105 digit = 4;106 }107 else if(at2==5) {108 mode[z++]=1;109 digit = 3;110 }111 }112 else if(at1==3){113 if(at2==2) {114 mode[z++]=1;115 digit = 9;116 }117 else if(at2==3) {118 mode[z++]=0;119 if(pattern[2]+1
pt1 and from pt0->pt2299 static double angle( Point pt1, Point pt2, Point pt0 )300 {301 double dx1 = pt1.x - pt0.x;302 double dy1 = pt1.y - pt0.y;303 double dx2 = pt2.x - pt0.x;304 double dy2 = pt2.y - pt0.y;305 return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);306 }307 308 // returns sequence of squares detected on the image.309 // the sequence is stored in the specified memory storage310 static void findSquares( const Mat& image, vector
>& squares )311 {312 squares.clear();313 314 Mat pyr, timg, gray0(image.size(), CV_8U), gray;315 316 // down-scale and upscale the image to filter out the noise317 pyrDown(image, pyr, Size(image.cols/2, image.rows/2));318 pyrUp(pyr, timg, image.size());319 vector
> contours;320 321 // find squares in every color plane of the image322 for( int c = 0; c < 3; c++ )323 {324 int ch[] = {c, 0};325 mixChannels(&timg, 1, &gray0, 1, ch, 1);326 327 // try several threshold levels328 for( int l = 0; l < N; l++ )329 {330 // hack: use Canny instead of zero threshold level.331 // Canny helps to catch squares with gradient shading332 if( l == 0 )333 {334 // apply Canny. Take the upper threshold from slider335 // and set the lower to 0 (which forces edges merging)336 Canny(gray0, gray, 0, thresh, 5);337 // dilate canny output to remove potential338 // holes between edge segments339 dilate(gray, gray, Mat(), Point(-1,-1));340 }341 else342 {343 // apply threshold if l!=0:344 // tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0345 gray = gray0 >= (l+1)*255/N;346 }347 348 // find contours and store them all as a list349 findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);350 351 vector
approx;352 353 // test each contour354 for( size_t i = 0; i < contours.size(); i++ )355 {356 // approximate contour with accuracy proportional357 // to the contour perimeter358 approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);359 360 // square contours should have 4 vertices after approximation361 // relatively large area (to filter out noisy contours)362 // and be convex.363 // Note: absolute value of an area is used because364 // area may be positive or negative - in accordance with the365 // contour orientation366 if( approx.size() == 4 &&367 fabs(contourArea(Mat(approx))) > 1000 &&368 isContourConvex(Mat(approx)) )369 {370 double maxCosine = 0;371 372 for( int j = 2; j < 5; j++ )373 {374 // find the maximum cosine of the angle between joint edges375 double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));376 maxCosine = MAX(maxCosine, cosine);377 }378 379 // if cosines of all angles are small380 // (all angles are ~90 degree) then write quandrange381 // vertices to resultant sequence382 if( maxCosine < 0.3 )383 squares.push_back(approx);384 }385 }386 }387 }388 }389 390 double dist(Point p1, const Point p2){391 return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));392 }393 394 // the function draws all the squares in the image395 static void drawSquares( Mat& image, const vector
>& squares )396 {397 for( size_t i = 0; i < squares.size(); i++ )398 {399 const Point* p = &squares[i][0];400 double d1=dist(p[0], p[1]);401 double d2=dist(p[1], p[2]);402 if(d1<50 || d2<50 || d1>280 || d2>280) continue;//把宽度小于50和大于350的矩形过滤403 cout << dist(p[0], p[1]) << endl;404 cout << dist(p[1], p[2]) << endl;405 for(int j=0; j<4; j++){ //使用line()函数替代polyline()函数画四边形406 line(image, p[j], p[(j+1)%4], Scalar( 255 ), 3, 8);407 }408 409 MatU imageROI=image(Rect(Point(p[1].x,p[1].y), Point(p[3].x, p[3].y)));410 MatU zcopy=Mat(imageROI);411 imshow("sdfds", zcopy);412 413 414 if(isBar(imageROI)){415 cout << "yes" << endl;416 read_barcode(imageROI);417 addWeighted(imageROI,1.0,zcopy,0.3,0.,image);418 }419 420 }421 422 imshow(wndname, image);423 }424 425 int main(int /*argc*/, char** /*argv*/)426 {427 help();428 namedWindow( wndname, 1 );429 vector
> squares;430 431 432 string imgname="C:/testdir/barcode1.jpg";433 Mat image = imread(imgname, 1);434 if( image.empty() ) return -1;435 436 findSquares(image, squares);437 drawSquares(image, squares);438 439 waitKey(0);440 }

 

转载地址:http://epvpl.baihongyu.com/

你可能感兴趣的文章
手机芯片三国杀:高通、联发科、展讯都想成霸主
查看>>
企业移动办公市场格局将定 随办如何突围?
查看>>
六大技巧提升员工信息安全意识
查看>>
保利协鑫多晶硅产量再创历史记录
查看>>
爱屋及乌 年轻投资者因喜爱Snapchat亏钱也买Snap股票
查看>>
物联网产品背后潜藏着危机
查看>>
阿里云将增设马来西亚数据中心 中国技术获赞
查看>>
与Netflix合作 美电视运营商推出4K频道
查看>>
Struts2中的Action
查看>>
Balluff推出刀具识别系统
查看>>
怎么写ERP实施方案?
查看>>
Shadow Brokers扬言兜售新漏洞攻击工具
查看>>
低照度监控前景广阔 企业展开激烈角逐
查看>>
美国支付巨头Verifone遭遇网络攻击
查看>>
开平推进智慧城市等领域信息化建设及公共数据资源共享
查看>>
宜兴电信成功跨界合作开拓农村物联网市场
查看>>
Oracle业务适合用PostgreSQL去O的一些评判标准
查看>>
多个常见代码设计缺陷
查看>>
今年光伏市场规模可达30GW 分布式有望占据三分江山
查看>>
因新漏洞问题 Firefox 49发布时间将延期一周
查看>>