zoukankan      html  css  js  c++  java
  • OpenCV条码(6)简单实现

    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 <iostream> 2 #include <map> 3 #include <string> 4 #include <algorithm> 5 #include <cv.h> 6 #include <highgui.h> 7 8 using namespace std; 9 using namespace cv; 10 11 #define SPACE 0 12 #define BAR 255 13 14 typedef Mat_<uchar> MatU; 15 map<string, int> 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<s.length(); i++) 23 if(s[i]=='0') s[i]='1'; 24 else s[i]='0'; 25 } 26 27 void setup_map(){ //设定解码映射表table[], table[0]为左侧条码奇数型,table[1]为左侧条码偶数型,table[2]为右侧条码偶数型 28 string zode[10]={"0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011"}; 29 for(int i=0; i<10; i++){ 30 table[0][zode[i]]=i; 31 string tmp=zode[i]; 32 change01(tmp); 33 table[2][tmp]=i; 34 reverse(tmp.begin(), tmp.end()); 35 table[1][tmp]=i; 36 } 37 } 38 void align_boundary(const MatU& img, Point& cur, int begin, int end){ 39 if (img(cur) == end){ 40 while (img(cur)==end) 41 ++cur.x; 42 }else{ 43 while (img(cur.y, cur.x-1)==begin) 44 --cur.x; 45 } 46 } 47 48 /*int read_digit(...) 49 *返回解析后得到的数字*/ 50 int read_digit(const MatU& img, Point& cur, int unit_width, int position){ 51 // Read the 7 consecutive bits. 52 int pattern[7] = {0, 0, 0, 0, 0, 0, 0}; 53 for (int i = 0; i < 7; i++){ 54 for (int j = 0; j < unit_width; j++){ 55 if (img(cur) == 255) 56 ++pattern[i]; 57 ++cur.x; 58 } 59 // See below for explanation. 60 if (pattern[i] == 1 && img(cur) == BAR 61 || pattern[i] == unit_width - 1 && img(cur) == SPACE) 62 --cur.x; 63 } 64 // Convert to binary, consider that a bit is set if the number of 65 // bars encountered is greater than a threshold. 66 int threshold = unit_width / 2; 67 string v=""; 68 for (int i = 0; i < 7; i++){ 69 if(pattern[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<int> 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 <iostream> 2 #include <map> 3 #include <string> 4 #include <cmath> 5 #include <algorithm> 6 #include <cv.h> 7 #include <highgui.h> 8 9 using namespace std; 10 using namespace cv; 11 12 #define SPACE 0 13 #define BAR 255 14 15 typedef Mat_<uchar> MatU; 16 map<string, int> 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<pattern[3]) digit = 8; 107 else digit = 2; 108 } 109 else if(at2==4) { 110 mode[z++]=1; 111 if(pattern[1]+1<pattern[2]) digit = 7; 112 else digit = 1; 113 } 114 else if(at2==5) { 115 mode[z++]=0; 116 digit = 5; 117 } 118 } 119 else if(at1==4){ 120 if(at2==2) { 121 mode[z++]=0; 122 digit = 9; 123 } 124 else if(at2==3) { 125 mode[z++]=1; 126 if(pattern[1]+1<pattern[0]) digit = 8; 127 else digit = 2; 128 } 129 else if(at2==4) { 130 mode[z++]=0; 131 if(pattern[0]+1<pattern[1]) digit = 7; 132 else digit = 1; 133 } 134 else if(at2==5) { 135 mode[z++]=1; 136 digit = 5; 137 } 138 } 139 else if(at1==5){ 140 if(at2==2) { 141 mode[z++]=1; 142 digit = 6; 143 } 144 else if(at2==3) { 145 mode[z++]=0; 146 digit = 0; 147 } 148 else if(at2==4) { 149 mode[z++]=1; 150 digit = 4; 151 } 152 else if(at2==5) { 153 mode[z++]=0; 154 digit=3; 155 } 156 } 157 // align_boundary(img, cur, SPACE, BAR); 158 }else{ 159 if(at1==2){ 160 if(at2==2) digit = 6; 161 else if(at2==4) digit = 4; 162 } 163 else if(at1==3){ 164 if(at2==3) { 165 if(pattern[2]+1<pattern[3]) digit = 8; 166 else digit = 2; 167 } 168 else if(at2==5) digit = 5; 169 } 170 else if(at1==4){ 171 if(at2==2) digit = 9; 172 else if(at2==4) { 173 if(pattern[0]+1<pattern[1]) digit = 7; 174 else digit = 1; 175 } 176 } 177 else if(at1==5){ 178 if(at2==3) digit = 0; 179 else if(at2==5) digit=3; 180 } 181 // align_boundary(img, cur, SPACE, BAR); 182 } 183 return digit; 184 } 185 186 void skip_quiet_zone(const MatU& img, Point& cur){//略过空白区域 187 while (img(cur) == SPACE) 188 ++cur.x; 189 } 190 191 void read_lguard(const MatU& img, Point& cur){//通过读取左侧固定的“条空条”,获取单位长度。 192 int pattern[3] = { BAR, SPACE, BAR }; 193 for (int i=0; i<3; i++) 194 while (img(cur)==pattern[i]) 195 ++cur.x; 196 } 197 198 void skip_mguard(const MatU& img, Point& cur){ //略过左侧数据和右侧数据之间的分界 199 int pattern[5] = { SPACE, BAR, SPACE, BAR, SPACE }; 200 for (int i=0; i<5; i++) 201 while (img(cur)==pattern[i]) 202 ++cur.x; 203 } 204 205 void read_barcode(const string& filename){ //读取条码主程序 206 z=0; 207 MatU img = imread(filename, 0); //载入图像 208 Size size = img.size(); 209 Point cur(0, size.height / 2); //cur表示当前位置 210 bitwise_not(img, img); 211 threshold(img, img, 128, 255, THRESH_BINARY); 212 skip_quiet_zone(img, cur); 213 read_lguard(img, cur); 214 vector<int> 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 <iostream>
      2 #include <map>
      3 #include <string>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <cv.h>
      7 #include <highgui.h>
      8 
      9 using namespace std;
     10 using namespace cv;
     11 
     12 #define SPACE 0
     13 #define BAR 255
     14 
     15 typedef Mat_<uchar> MatU;
     16 map<string, int> 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<pattern[3]) digit = 8;
    119                 else digit = 2;
    120             }
    121             else if(at2==4) {
    122                 mode[z++]=1;
    123                 if(pattern[1]+1<pattern[2]) digit = 7;
    124                 else digit = 1;
    125             }
    126             else if(at2==5) {
    127                 mode[z++]=0;
    128                 digit = 5;
    129             }
    130         }
    131         else if(at1==4){
    132             if(at2==2) {
    133                 mode[z++]=0;
    134                 digit = 9;
    135             }
    136             else if(at2==3) {
    137                 mode[z++]=1;
    138                 if(pattern[1]+1<pattern[0]) digit = 8;
    139                 else digit = 2;
    140             }
    141             else if(at2==4) {
    142                 mode[z++]=0;
    143                 if(pattern[0]+1<pattern[1]) digit = 7;
    144                 else digit = 1;
    145             }
    146             else if(at2==5) {
    147                 mode[z++]=1;
    148                 digit = 5;
    149             }
    150         }
    151         else if(at1==5){
    152             if(at2==2) {
    153                 mode[z++]=1;
    154                 digit = 6;
    155             }
    156             else if(at2==3) {
    157                 mode[z++]=0;
    158                 digit = 0;
    159             }
    160             else if(at2==4) {
    161                 mode[z++]=1;
    162                 digit = 4;
    163             }
    164             else if(at2==5) {
    165                 mode[z++]=0;
    166                 digit=3;
    167             }
    168         }
    169      //   align_boundary(img, cur, SPACE, BAR);
    170     }else{
    171         if(at1==2){
    172             if(at2==2) digit = 6;
    173             else if(at2==4) digit = 4;
    174         }
    175         else if(at1==3){
    176             if(at2==3) {
    177                 if(pattern[2]+1<pattern[3]) digit = 8;
    178                 else digit = 2;
    179             }
    180             else if(at2==5) digit = 5;
    181         }
    182         else if(at1==4){
    183             if(at2==2) digit = 9;
    184             else if(at2==4) {
    185                 if(pattern[0]+1<pattern[1]) digit = 7;
    186                 else digit = 1;
    187             }
    188         }
    189         else if(at1==5){
    190             if(at2==3) digit = 0;
    191             else if(at2==5) digit=3;
    192         }
    193      //   align_boundary(img, cur, SPACE, BAR);
    194     }
    195     cout << "digit=" << digit << endl;
    196     return digit;
    197 }
    198 
    199 void skip_quiet_zone(const MatU& img, Point& cur){//ÂÔ¹ý¿Õ°×ÇøÓò
    200     while (img(cur) == SPACE)
    201         ++cur.x;
    202 }
    203 
    204 void read_lguard(const MatU& img, Point& cur){//ͨ¹ý¶ÁÈ¡×ó²à¹Ì¶¨µÄ¡°Ìõ¿ÕÌõ¡±£¬»ñÈ¡µ¥Î»³¤¶È¡£
    205     int pattern[3] = { BAR, SPACE, BAR };
    206     for (int i=0; i<3; i++)
    207         while (img(cur)==pattern[i])
    208             ++cur.x;
    209 }
    210 
    211 void skip_mguard(const MatU& img, Point& cur){      //ÂÔ¹ý×ó²àÊý¾ÝºÍÓÒ²àÊý¾ÝÖ®¼äµÄ·Ö½ç
    212     int pattern[5] = { SPACE, BAR, SPACE, BAR, SPACE };
    213     for (int i=0; i<5; i++)
    214         while (img(cur)==pattern[i])
    215             ++cur.x;
    216 }
    217 
    218 void read_barcode(MatU& img/*const string& filename*/){      //¶ÁÈ¡ÌõÂëÖ÷³ÌÐò
    219     z=0;
    220   //  MatU img = imread(filename, 0);         //ÔØÈëͼÏñ
    221     Size size = img.size();
    222     Point cur(0, size.height / 2);              //cur±íʾµ±Ç°Î»ÖÃ
    223 
    224     bitwise_not(img, img);
    225     threshold(img, img, 128, 255, THRESH_BINARY);
    226 
    227     if (img(cur) != SPACE) return;
    228 
    229     skip_quiet_zone(img, cur);
    230 
    231     read_lguard(img, cur);
    232 
    233     vector<int> digits;
    234     for (int i=0; i<6; i++){               //×ó²àÊý¾Ý½âÂë
    235         int d = read_digit(img, cur, LEFT);
    236         digits.push_back(d);
    237     }
    238 
    239     skip_mguard(img, cur);
    240 
    241     for (int i = 0; i < 6; i++){        //ÓÒ²àÊý¾Ý½âÂë
    242         int d = read_digit(img, cur, RIGHT);
    243         digits.push_back(d);
    244     }
    245   //  cout << front;                      //Êä³ö½âÂë½á¹û
    246     int front=get_front();
    247     cout << front << " ";
    248     for (int i = 0; i < 12; i++)
    249         cout << digits[i] << " ";
    250     cout << endl;
    251     //waitKey();
    252 }
    253 
    254 
    255 
    256 
    257 // The "Square Detector" program.
    258 // It loads several images sequentially and tries to find squares in
    259 // each image
    260 
    261 #include "opencv2/core/core.hpp"
    262 #include "opencv2/imgproc/imgproc.hpp"
    263 #include "opencv2/highgui/highgui.hpp"
    264 
    265 #include <iostream>
    266 #include <math.h>
    267 #include <string.h>
    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 vectors
    291 // from pt0->pt1 and from pt0->pt2
    292 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 storage
    303 static void findSquares( const Mat& image, vector<vector<Point> >& 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 noise
    310     pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
    311     pyrUp(pyr, timg, image.size());
    312     vector<vector<Point> > contours;
    313 
    314     // find squares in every color plane of the image
    315     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 levels
    321         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 shading
    325             if( l == 0 )
    326             {
    327                 // apply Canny. Take the upper threshold from slider
    328                 // and set the lower to 0 (which forces edges merging)
    329                 Canny(gray0, gray, 0, thresh, 5);
    330                 // dilate canny output to remove potential
    331                 // holes between edge segments
    332                 dilate(gray, gray, Mat(), Point(-1,-1));
    333             }
    334             else
    335             {
    336                 // apply threshold if l!=0:
    337                 //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
    338                 gray = gray0 >= (l+1)*255/N;
    339             }
    340 
    341             // find contours and store them all as a list
    342             findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    343 
    344             vector<Point> approx;
    345 
    346             // test each contour
    347             for( size_t i = 0; i < contours.size(); i++ )
    348             {
    349                 // approximate contour with accuracy proportional
    350                 // to the contour perimeter
    351                 approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
    352 
    353                 // square contours should have 4 vertices after approximation
    354                 // relatively large area (to filter out noisy contours)
    355                 // and be convex.
    356                 // Note: absolute value of an area is used because
    357                 // area may be positive or negative - in accordance with the
    358                 // contour orientation
    359                 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 edges
    368                         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 small
    373                     // (all angles are ~90 degree) then write quandrange
    374                     // vertices to resultant sequence
    375                     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 image
    395 static void drawSquares( Mat& image, const vector<vector<Point> >& 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 4
    401      //   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<Point>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 video
    439     string window_name="Extracted Frame";
    440     namedWindow(window_name);
    441     while(true){
    442         capture >> image;
    443         vector<vector<Point> > 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<vector<Point> > 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 removed
    505    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.name
    512 \*------------------------------------------------------------------------------------------*/
    513 /*
    514 
    515 #include <vector>
    516 #include <opencv2/core/core.hpp>
    517 #include <opencv2/highgui/highgui.hpp>
    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 operator
    544     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 images
    552     std::vector<cv::Mat> planes;
    553     // split 1 3-channel image into 3 1-channel images
    554     cv::split(image1,planes);
    555     // add to blue channel
    556     planes[0]+= image2;
    557     // merge the 3 1-channel images into 1 3-channel image
    558     cv::merge(planes,result);
    559 
    560     cv::namedWindow("Result on blue channel");
    561     cv::imshow("Result on blue channel",result);
    562 
    563     // read images
    564     cv::Mat image= cv::imread("boldt.jpg");
    565     cv::Mat logo= cv::imread("logo.bmp");
    566 
    567     // define image ROI
    568     cv::Mat imageROI;
    569     imageROI= image(cv::Rect(385,270,logo.cols,logo.rows));
    570 
    571     // add logo to image
    572     cv::addWeighted(imageROI,1.0,logo,0.3,0.,imageROI);
    573 
    574     // show result
    575     cv::namedWindow("with logo");
    576     cv::imshow("with logo",image);
    577 
    578     // read images
    579     image= cv::imread("boldt.jpg");
    580     logo= cv::imread("logo.bmp");
    581 
    582     // define ROI
    583     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 mask
    589     logo.copyTo(imageROI,mask);
    590 
    591     // show result
    592     cv::namedWindow("with logo 2");
    593     cv::imshow("with logo 2",image);
    594 
    595     // read images
    596     logo= cv::imread("logo.bmp",0);
    597     image1= cv::imread("boldt.jpg");
    598 
    599     // split 3-channel image into 3 1-channel images
    600     std::vector<cv::Mat> 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 <iostream>
      6 #include <math.h>
      7 #include <string.h>
      8 
      9 using namespace cv;
     10 using namespace std;
     11 
     12 
     13 #define SPACE 0
     14 #define BAR 255
     15 
     16 typedef Mat_<uchar> MatU;
     17 map<string, int> 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<pattern[3]) digit = 8;
    120                 else digit = 2;
    121             }
    122             else if(at2==4) {
    123                 mode[z++]=1;
    124                 if(pattern[1]+1<pattern[2]) digit = 7;
    125                 else digit = 1;
    126             }
    127             else if(at2==5) {
    128                 mode[z++]=0;
    129                 digit = 5;
    130             }
    131         }
    132         else if(at1==4){
    133             if(at2==2) {
    134                 mode[z++]=0;
    135                 digit = 9;
    136             }
    137             else if(at2==3) {
    138                 mode[z++]=1;
    139                 if(pattern[1]+1<pattern[0]) digit = 8;
    140                 else digit = 2;
    141             }
    142             else if(at2==4) {
    143                 mode[z++]=0;
    144                 if(pattern[0]+1<pattern[1]) digit = 7;
    145                 else digit = 1;
    146             }
    147             else if(at2==5) {
    148                 mode[z++]=1;
    149                 digit = 5;
    150             }
    151         }
    152         else if(at1==5){
    153             if(at2==2) {
    154                 mode[z++]=1;
    155                 digit = 6;
    156             }
    157             else if(at2==3) {
    158                 mode[z++]=0;
    159                 digit = 0;
    160             }
    161             else if(at2==4) {
    162                 mode[z++]=1;
    163                 digit = 4;
    164             }
    165             else if(at2==5) {
    166                 mode[z++]=0;
    167                 digit=3;
    168             }
    169         }
    170      //   align_boundary(img, cur, SPACE, BAR);
    171     }else{
    172         if(at1==2){
    173             if(at2==2) digit = 6;
    174             else if(at2==4) digit = 4;
    175         }
    176         else if(at1==3){
    177             if(at2==3) {
    178                 if(pattern[2]+1<pattern[3]) digit = 8;
    179                 else digit = 2;
    180             }
    181             else if(at2==5) digit = 5;
    182         }
    183         else if(at1==4){
    184             if(at2==2) digit = 9;
    185             else if(at2==4) {
    186                 if(pattern[0]+1<pattern[1]) digit = 7;
    187                 else digit = 1;
    188             }
    189         }
    190         else if(at1==5){
    191             if(at2==3) digit = 0;
    192             else if(at2==5) digit=3;
    193         }
    194      //   align_boundary(img, cur, SPACE, BAR);
    195     }
    196     cout << "digit=" << digit << endl;
    197     return digit;
    198 }
    199 
    200 void skip_quiet_zone(const MatU& img, Point& cur){//ÂÔ¹ý¿Õ°×ÇøÓò
    201     while (img(cur) == SPACE)
    202         ++cur.x;
    203 }
    204 
    205 void read_lguard(const MatU& img, Point& cur){//ͨ¹ý¶ÁÈ¡×ó²à¹Ì¶¨µÄ¡°Ìõ¿ÕÌõ¡±£¬»ñÈ¡µ¥Î»³¤¶È¡£
    206     int pattern[3] = { BAR, SPACE, BAR };
    207     for (int i=0; i<3; i++)
    208         while (img(cur)==pattern[i])
    209             ++cur.x;
    210 }
    211 
    212 void skip_mguard(const MatU& img, Point& cur){      //ÂÔ¹ý×ó²àÊý¾ÝºÍÓÒ²àÊý¾ÝÖ®¼äµÄ·Ö½ç
    213     int pattern[5] = { SPACE, BAR, SPACE, BAR, SPACE };
    214     for (int i=0; i<5; i++)
    215         while (img(cur)==pattern[i])
    216             ++cur.x;
    217 }
    218 
    219 bool isBar(MatU& img){
    220     Size size = img.size();
    221     Point cur(0, size.height / 2);
    222     int cnt=0;//count the number of BAR-and-SPACE regions
    223     if(img(cur)!=SPACE){
    224         cnt=0;
    225         return false;
    226     }else{
    227         while(img(cur)==SPACE)
    228             cur.x++;
    229         int statue=SPACE;
    230         while(cur.x<img.cols){
    231             if(img(cur)!=statue)
    232                 cnt++;
    233             if(cnt>20) return true;
    234         }
    235         return false;
    236     }
    237 }
    238 
    239 void read_barcode(MatU& img/*const string& filename*/){      //¶ÁÈ¡ÌõÂëÖ÷³ÌÐò
    240 
    241   //  if(isBar(img)) //isBar():judge weather img is a barcode region or not
    242    //     return;
    243 
    244     z=0;
    245   //  MatU img = imread(filename, 0);         //ÔØÈëͼÏñ
    246     Size size = img.size();
    247     Point cur(0, size.height / 2);              //cur±íʾµ±Ç°Î»ÖÃ
    248 
    249     bitwise_not(img, img);
    250     threshold(img, img, 128, 255, THRESH_BINARY);
    251 
    252     if (img(cur) != SPACE) return;
    253 
    254     skip_quiet_zone(img, cur);
    255 
    256     read_lguard(img, cur);
    257 
    258     vector<int> digits;
    259     for (int i=0; i<6; i++){               //×ó²àÊý¾Ý½âÂë
    260         int d = read_digit(img, cur, LEFT);
    261         digits.push_back(d);
    262     }
    263 
    264     skip_mguard(img, cur);
    265 
    266     for (int i = 0; i < 6; i++){        //ÓÒ²àÊý¾Ý½âÂë
    267         int d = read_digit(img, cur, RIGHT);
    268         digits.push_back(d);
    269     }
    270   //  cout << front;                      //Êä³ö½âÂë½á¹û
    271     int front=get_front();
    272     cout << front << " ";
    273     for (int i = 0; i < 12; i++)
    274         cout << digits[i] << " ";
    275     cout << endl;
    276     //waitKey();
    277 }
    278 
    279 static void help()
    280 {
    281     cout <<
    282     "\nA program using pyramid scaling, Canny, contours, contour simpification and\n"
    283     "memory storage (it's got it all folks) to find\n"
    284     "squares in a list of images pic1-6.png\n"
    285     "Returns sequence of squares detected on the image.\n"
    286     "the sequence is stored in the specified memory storage\n"
    287     "Call:\n"
    288     "./squares\n"
    289     "Using OpenCV version %s\n" << CV_VERSION << "\n" << endl;
    290 }
    291 
    292 
    293 int thresh = 50, N = 11;
    294 const char* wndname = "Square Detection Demo";
    295 
    296 // helper function:
    297 // finds a cosine of angle between vectors
    298 // from pt0->pt1 and from pt0->pt2
    299 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 storage
    310 static void findSquares( const Mat& image, vector<vector<Point> >& 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 noise
    317     pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
    318     pyrUp(pyr, timg, image.size());
    319     vector<vector<Point> > contours;
    320 
    321     // find squares in every color plane of the image
    322     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 levels
    328         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 shading
    332             if( l == 0 )
    333             {
    334                 // apply Canny. Take the upper threshold from slider
    335                 // and set the lower to 0 (which forces edges merging)
    336                 Canny(gray0, gray, 0, thresh, 5);
    337                 // dilate canny output to remove potential
    338                 // holes between edge segments
    339                 dilate(gray, gray, Mat(), Point(-1,-1));
    340             }
    341             else
    342             {
    343                 // apply threshold if l!=0:
    344                 //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
    345                 gray = gray0 >= (l+1)*255/N;
    346             }
    347 
    348             // find contours and store them all as a list
    349             findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    350 
    351             vector<Point> approx;
    352 
    353             // test each contour
    354             for( size_t i = 0; i < contours.size(); i++ )
    355             {
    356                 // approximate contour with accuracy proportional
    357                 // to the contour perimeter
    358                 approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
    359 
    360                 // square contours should have 4 vertices after approximation
    361                 // relatively large area (to filter out noisy contours)
    362                 // and be convex.
    363                 // Note: absolute value of an area is used because
    364                 // area may be positive or negative - in accordance with the
    365                 // contour orientation
    366                 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 edges
    375                         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 small
    380                     // (all angles are ~90 degree) then write quandrange
    381                     // vertices to resultant sequence
    382                     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 image
    395 static void drawSquares( Mat& image, const vector<vector<Point> >& 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<vector<Point> > 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 }
    Greatness is never a given, it must be earned.
  • 相关阅读:
    单个 js 文件禁用 ESLint 语法校验
    meta标签整合
    安装es6编译babel
    JSON.parse()和JSON.stringify()的区别
    preventDefault()、stopPropagation()、return false 的区别
    excel 表格内容读取
    redis 小例
    多文件打包下载
    随笔
    js数组删除元素
  • 原文地址:https://www.cnblogs.com/zjutzz/p/3059533.html
Copyright © 2011-2022 走看看