fixed many warnings from GCC 4.6.1
[profile/ivi/opencv.git] / modules / objdetect / src / datamatrix.cpp
1 #include "precomp.hpp"
2
3 #if CV_SSE2
4 #include <xmmintrin.h>
5 #endif
6
7 #include <deque>
8 #include <algorithm>
9
10 using namespace std;
11
12 #undef NDEBUG
13 #include <assert.h>
14
15 class Sampler {
16 public:
17   CvMat *im;
18   CvPoint o;
19   CvPoint c, cc;
20   CvMat *perim;
21   CvPoint fcoord(float fx, float fy);
22   CvPoint coord(int ix, int iy);
23   Sampler(CvMat *_im, CvPoint _o, CvPoint _c, CvPoint _cc);
24   uchar getpixel(int ix, int iy);
25   int isinside(int x, int y);
26   int overlap(Sampler &other);
27   int hasbars();
28   void timing();
29   CvMat *extract();
30   Sampler():im(0),perim(0){}
31   ~Sampler(){}
32 };
33
34 class code {    // used in this file only
35 public:
36   char msg[4];
37   CvMat *original;
38   Sampler sa;
39 };
40
41 unsigned char cblk[256] = { 34,19,36,36,51,19,51,51,66,19,36,36,66,19,66,66,49,19,36,36,51,19,51,51,49,19,36,36,
42     49,19,49,49,32,19,36,36,51,19,51,51,66,19,36,36,66,19,66,66,32,19,36,36,51,19,51,51,32,19,36,36,32,19,32,32,
43     17,19,36,36,51,19,51,51,66,19,36,36,66,19,66,66,49,19,36,36,51,19,51,51,49,19,36,36,49,19,49,49,17,19,36,36,
44     51,19,51,51,66,19,36,36,66,19,66,66,17,19,36,36,51,19,51,51,17,19,36,36,17,19,17,17,2,19,2,36,2,19,2,51,2,19,
45     2,36,2,19,2,66,2,19,2,36,2,19,2,51,2,19,2,36,2,19,2,49,2,19,2,36,2,19,2,51,2,19,2,36,2,19,2,66,2,19,2,36,2,19,
46     2,51,2,19,2,36,2,19,2,32,2,19,2,36,2,19,2,51,2,19,2,36,2,19,2,66,2,19,2,36,2,19,2,51,2,19,2,36,2,19,2,49,2,19,
47     2,36,2,19,2,51,2,19,2,36,2,19,2,66,2,19,2,36,2,19,2,51,2,19,2,36,2,19,2,34 };
48 unsigned char ccblk[256] = { 34,17,2,17,19,19,2,17,36,36,2,36,19,19,2,17,51,51,2,51,19,19,2,51,36,36,2,36,19,19,2,17,
49     66,66,2,66,19,19,2,66,36,36,2,36,19,19,2,66,51,51,2,51,19,19,2,51,36,36,2,36,19,19,2,17,49,49,2,49,19,19,2,49,36,
50     36,2,36,19,19,2,49,51,51,2,51,19,19,2,51,36,36,2,36,19,19,2,49,66,66,2,66,19,19,2,66,36,36,2,36,19,19,2,66,51,51,
51     2,51,19,19,2,51,36,36,2,36,19,19,2,17,32,32,2,32,19,19,2,32,36,36,2,36,19,19,2,32,51,51,2,51,19,19,2,51,36,36,2,
52     36,19,19,2,32,66,66,2,66,19,19,2,66,36,36,2,36,19,19,2,66,51,51,2,51,19,19,2,51,36,36,2,36,19,19,2,32,49,49,2,49,
53     19,19,2,49,36,36,2,36,19,19,2,49,51,51,2,51,19,19,2,51,36,36,2,36,19,19,2,49,66,66,2,66,19,19,2,66,36,36,2,36,19,
54     19,2,66,51,51,2,51,19,19,2,51,36,36,2,36,19,19,2,34 };
55 static const CvPoint pickup[64] = { {7,6},{8,6},{7,5},{8,5},{1,5},{7,4},{8,4},{1,4},{1,8},{2,8},{1,7},{2,7},{3,7},
56     {1,6},{2,6},{3,6},{3,2},{4,2},{3,1},{4,1},{5,1},{3,8},{4,8},{5,8},{6,1},{7,1},{6,8},{7,8},{8,8},{6,7},{7,7},{8,7},
57     {4,7},{5,7},{4,6},{5,6},{6,6},{4,5},{5,5},{6,5},{2,5},{3,5},{2,4},{3,4},{4,4},{2,3},{3,3},{4,3},{8,3},{1,3},{8,2},
58     {1,2},{2,2},{8,1},{1,1},{2,1},{5,4},{6,4},{5,3},{6,3},{7,3},{5,2},{6,2},{7,2} };
59 static const uchar Alog[256] = { 1,2,4,8,16,32,64,128,45,90,180,69,138,57,114,228,229,231,227,235,251,219,155,27,
60     54,108,216,157,23,46,92,184,93,186,89,178,73,146,9,18,36,72,144,13,26,52,104,208,141,55,110,220,149,7,14,28,
61     56,112,224,237,247,195,171,123,246,193,175,115,230,225,239,243,203,187,91,182,65,130,41,82,164,101,202,185,95,
62     190,81,162,105,210,137,63,126,252,213,135,35,70,140,53,106,212,133,39,78,156,21,42,84,168,125,250,217,159,19,
63     38,76,152,29,58,116,232,253,215,131,43,86,172,117,234,249,223,147,11,22,44,88,176,77,154,25,50,100,200,189,87,
64     174,113,226,233,255,211,139,59,118,236,245,199,163,107,214,129,47,94,188,85,170,121,242,201,191,83,166,97,194,
65     169,127,254,209,143,51,102,204,181,71,142,49,98,196,165,103,206,177,79,158,17,34,68,136,61,122,244,197,167,99,
66     198,161,111,222,145,15,30,60,120,240,205,183,67,134,33,66,132,37,74,148,5,10,20,40,80,160,109,218,153,31,62,
67     124,248,221,151,3,6,12,24,48,96,192,173,119,238,241,207,179,75,150,1 };
68 static const uchar Log[256] = { (uchar)-255,255,1,240,2,225,241,53,3,38,226,133,242,43,54,210,4,195,39,
69     114,227,106,134,28,243,140,44,23,55,118,211,234,5,219,196,96,40,222,115,103,228,78,107,125,
70     135,8,29,162,244,186,141,180,45,99,24,49,56,13,119,153,212,199,235,91,6,76,220,217,197,11,97,
71     184,41,36,223,253,116,138,104,193,229,86,79,171,108,165,126,145,136,34,9,74,30,32,163,84,245,
72     173,187,204,142,81,181,190,46,88,100,159,25,231,50,207,57,147,14,67,120,128,154,248,213,167,
73     200,63,236,110,92,176,7,161,77,124,221,102,218,95,198,90,12,152,98,48,185,179,42,209,37,132,
74     224,52,254,239,117,233,139,22,105,27,194,113,230,206,87,158,80,189,172,203,109,175,166,62,127,
75     247,146,66,137,192,35,252,10,183,75,216,31,83,33,73,164,144,85,170,246,65,174,61,188,202,205,
76     157,143,169,82,72,182,215,191,251,47,178,89,151,101,94,160,123,26,112,232,21,51,238,208,131,
77     58,69,148,18,15,16,68,17,121,149,129,19,155,59,249,70,214,250,168,71,201,156,64,60,237,130,
78     111,20,93,122,177,150 };
79
80 #define dethresh 0.92f
81 #define eincO    (2 * dethresh)         // e increment orthogonal
82 #define eincD    (1.414f * dethresh)     // e increment diagonal
83
84 static const float eincs[] = {
85   eincO, eincD,
86   eincO, eincD,
87   eincO, eincD,
88   eincO, eincD,
89   999 };
90
91 #define Ki(x) _mm_set_epi32((x),(x),(x),(x))
92 #define Kf(x) _mm_set_ps((x),(x),(x),(x))
93
94 static const int CV_DECL_ALIGNED(16) absmask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
95 #define _mm_abs_ps(x) _mm_and_ps((x), *(const __m128*)absmask)
96
97 static void writexy(CvMat *m, int r, CvPoint p)
98 {
99   int *pdst = (int*)cvPtr2D(m, r, 0);
100   pdst[0] = p.x;
101   pdst[1] = p.y;
102 }
103
104 Sampler::Sampler(CvMat *_im, CvPoint _o, CvPoint _c, CvPoint _cc)
105 {
106   im = _im;
107   o = _o;
108   c = _c;
109   cc = _cc;
110   perim = cvCreateMat(4, 1, CV_32SC2);
111   writexy(perim, 0, fcoord(-.2f,-.2f));
112   writexy(perim, 1, fcoord(-.2f,1.2f));
113   writexy(perim, 2, fcoord(1.2f,1.2f));
114   writexy(perim, 3, fcoord(1.2f,-.2f));
115   // printf("Sampler %d,%d %d,%d %d,%d\n", o.x, o.y, c.x, c.y, cc.x, cc.y);
116 }
117
118 CvPoint Sampler::fcoord(float fx, float fy)
119 {
120   CvPoint r;
121   r.x = (int)(o.x + fx * (cc.x - o.x) + fy * (c.x - o.x));
122   r.y = (int)(o.y + fx * (cc.y - o.y) + fy * (c.y - o.y));
123   return r;
124 }
125
126 CvPoint Sampler::coord(int ix, int iy)
127 {
128   return fcoord(0.05f + 0.1f * ix, 0.05f + 0.1f * iy);
129 }
130
131 uchar Sampler::getpixel(int ix, int iy)
132 {
133   CvPoint pt = coord(ix, iy);
134   if ((0 <= pt.x) && (pt.x < im->cols) && (0 <= pt.y) && (pt.y < im->rows))
135     return *cvPtr2D(im, pt.y, pt.x);
136   else
137     return 0;
138 }
139
140 int Sampler::isinside(int x, int y)
141 {
142   CvPoint2D32f pt;
143   pt.x = (float)x;
144   pt.y = (float)y;
145   if ((0 <= pt.x) && (pt.x < im->cols) && (0 <= pt.y) && (pt.y < im->rows))
146     return cvPointPolygonTest(perim, pt, 0) < 0;
147   else
148     return 0;
149 }
150
151 int Sampler::overlap(Sampler &other)
152 {
153   for (int i = 0; i < 4; i++) {
154     CvScalar p;
155     p = cvGet2D(other.perim, i, 0);
156     if (isinside((int)p.val[0], (int)p.val[1]))
157       return 1;
158     p = cvGet2D(perim, i, 0);
159     if (other.isinside((int)p.val[0], (int)p.val[1]))
160       return 1;
161   }
162   return 0;
163 }
164
165 int Sampler::hasbars()
166 {
167   return getpixel(9, 1) > getpixel(9, 0);
168 }
169
170 void Sampler::timing()
171 {
172   /*uchar light, dark = getpixel(9, 0);
173   for (int i = 1; i < 3; i += 2) {
174     light = getpixel(9, i);
175     // if (light <= dark)
176     //  goto endo;
177     dark = getpixel(9, i + 1);
178     // if (up <= down)
179     //  goto endo;
180   }*/
181 }
182
183 CvMat *Sampler::extract()
184 {
185   // return a 10x10 CvMat for the current contents, 0 is black, 255 is white
186   // Sampler has (0,0) at bottom left, so invert Y
187   CvMat *r = cvCreateMat(10, 10, CV_8UC1);
188   for (int x = 0; x < 10; x++)
189     for (int y = 0; y < 10; y++)
190       *cvPtr2D(r, 9 - y, x) = (getpixel(x, y) < 128) ? 0 : 255;
191   return r;
192 }
193
194 #if CV_SSE2
195 static void apron(CvMat *v)
196 {
197   int r = v->rows;
198   int c = v->cols;
199   memset(cvPtr2D(v, 0, 0), 0x22, c);
200   memset(cvPtr2D(v, 1, 0), 0x22, c);
201   memset(cvPtr2D(v, r - 2, 0), 0x22, c);
202   memset(cvPtr2D(v, r - 1, 0), 0x22, c);
203   int y;
204   for (y = 2; y < r - 2; y++) {
205     uchar *lp = cvPtr2D(v, y, 0);
206     lp[0] = 0x22;
207     lp[1] = 0x22;
208     lp[c-2] = 0x22;
209     lp[c-1] = 0x22;
210   }
211 }
212
213 static void cfollow(CvMat *src, CvMat *dst)
214 {
215   int sx, sy;
216   uchar *vpd = cvPtr2D(src, 0, 0);
217   for (sy = 0; sy < src->rows; sy++) {
218     short *wr = (short*)cvPtr2D(dst, sy, 0);
219     for (sx = 0; sx < src->cols; sx++) {
220       int x = sx;
221       int y = sy;
222       float e = 0;
223       int ontrack = true;
224       int dir;
225
226       while (ontrack) {
227         dir = vpd[y * src->step + x];
228         int xd = ((dir & 0xf) - 2);
229         int yd = ((dir >> 4) - 2);
230         e += (dir == 0x22) ? 999 : ((dir & 1) ? eincD : eincO);
231         x += xd;
232         y += yd;
233         if (e > 10.) {
234           float d = (float)(((x - sx) * (x - sx)) + ((y - sy) * (y - sy)));
235           ontrack = d > (e * e);
236         }
237       }
238       if ((24 <= e) && (e < 999)) {
239         // printf("sx=%d, sy=%d, x=%d, y=%d\n", sx, sy, x, y);
240         *wr++ = (short)(x - sx);
241         *wr++ = (short)(y - sy);
242       } else {
243         *wr++ = 0;
244         *wr++ = 0;
245       }
246     }
247   }
248 }
249
250 static uchar gf256mul(uchar a, uchar b)
251 {
252     return Alog[(Log[a] + Log[b]) % 255];
253 }
254
255 static int decode(Sampler &sa, code &cc)
256 {
257   uchar binary[8] = {0,0,0,0,0,0,0,0};
258   uchar b = 0;
259   int i, sum;
260
261   sum = 0;
262
263   for (i = 0; i < 64; i++)
264     sum += sa.getpixel(1 + (i & 7), 1 + (i >> 3));
265   uchar mean = (uchar)(sum / 64);
266   for (i = 0; i < 64; i++) {
267     b = (b << 1) + (sa.getpixel(pickup[i].x, pickup[i].y) <= mean);
268     if ((i & 7) == 7) {
269       binary[i >> 3] = b;
270       b = 0;
271     }
272   }
273
274   // Compute the 5 RS codewords for the 3 datawords
275
276   uchar c[5] = {0,0,0,0,0};
277   {
278     int i, j;
279     uchar a[5] = {228, 48, 15, 111, 62};
280     int k = 5;
281     for (i = 0; i < 3; i++) {
282       uchar t = binary[i] ^ c[4];
283       for (j = k - 1; j != -1; j--) {
284         if (t == 0)
285             c[j] = 0;
286         else
287             c[j] = gf256mul(t, a[j]);
288         if (j > 0)
289             c[j] = c[j - 1] ^ c[j];
290       }
291     }
292   }
293
294   if ((c[4] == binary[3]) &&
295       (c[3] == binary[4]) &&
296       (c[2] == binary[5]) &&
297       (c[1] == binary[6]) &&
298       (c[0] == binary[7])) {
299     uchar x = 0xff & (binary[0] - 1);
300     uchar y = 0xff & (binary[1] - 1);
301     uchar z = 0xff & (binary[2] - 1);
302     cc.msg[0] = x;
303     cc.msg[1] = y;
304     cc.msg[2] = z;
305     cc.msg[3] = 0;
306     cc.sa = sa;
307     cc.original = sa.extract();
308     return 1;
309   } else {
310     return 0;
311   }
312 }
313
314 static deque<CvPoint> trailto(CvMat *v, int x, int y, CvMat *terminal)
315 {
316   CvPoint np;
317   /* Return the last 10th of the trail of points following v from (x,y)
318    * to terminal
319    */
320
321   int ex = x + ((short*)cvPtr2D(terminal, y, x))[0];
322   int ey = y + ((short*)cvPtr2D(terminal, y, x))[1];
323   deque<CvPoint> r;
324   while ((x != ex) || (y != ey)) {
325     np.x = x;
326     np.y = y;
327     r.push_back(np);
328     int dir = *cvPtr2D(v, y, x);
329     int xd = ((dir & 0xf) - 2);
330     int yd = ((dir >> 4) - 2);
331     x += xd;
332     y += yd;
333   }
334
335   int l = (int)(r.size() * 9 / 10);
336   while (l--)
337     r.pop_front();
338   return r;
339 }
340 #endif
341
342 deque <CvDataMatrixCode> cvFindDataMatrix(CvMat *im)
343 {
344 #if CV_SSE2
345   int r = im->rows;
346   int c = im->cols;
347
348 #define SAMESIZE(nm, ty) CvMat *nm = cvCreateMat(r, c, ty);
349
350   SAMESIZE(thresh, CV_8UC1)
351   SAMESIZE(vecpic, CV_8UC1)
352   SAMESIZE(vc, CV_8UC1)
353   SAMESIZE(vcc, CV_8UC1)
354   SAMESIZE(cxy, CV_16SC2)
355   SAMESIZE(ccxy, CV_16SC2)
356
357   cvAdaptiveThreshold(im, thresh, 255.0, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 13);
358   {
359     int x, y;
360     int sstride = thresh->step;
361     int sw = thresh->cols; // source width
362     for (y = 2; y < thresh->rows - 2; y++) {
363       uchar *ps = cvPtr2D(thresh, y, 0);
364       uchar *pd = cvPtr2D(vecpic, y, 0);
365       uchar *pvc = cvPtr2D(vc, y, 0);
366       uchar *pvcc = cvPtr2D(vcc, y, 0);
367       for (x = 0; x < sw; x++) {
368         uchar v =
369             (0x01 & ps[-2 * sstride]) |
370             (0x02 & ps[-sstride + 1]) |
371             (0x04 & ps[2]) |
372             (0x08 & ps[sstride + 1]) |
373             (0x10 & ps[2 * sstride]) |
374             (0x20 & ps[sstride - 1]) |
375             (0x40 & ps[-2]) |
376             (0x80 & ps[-sstride -1]);
377         *pd++ = v;
378         *pvc++ = cblk[v];
379         *pvcc++ = ccblk[v];
380         ps++;
381       }
382     }
383     apron(vc);
384     apron(vcc);
385   }
386
387   cfollow(vc, cxy);
388   cfollow(vcc, ccxy);
389
390   deque <CvPoint> candidates;
391   {
392     int x, y;
393     int r = cxy->rows;
394     int c = cxy->cols;
395     for (y = 0; y < r; y++) {
396       const short *cd = (const short*)cvPtr2D(cxy, y, 0);
397       const short *ccd = (const short*)cvPtr2D(ccxy, y, 0);
398       for (x = 0; x < c; x += 4, cd += 8, ccd += 8) {
399         __m128i v = _mm_loadu_si128((const __m128i*)cd);
400         __m128 cyxyxA = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(v, v), 16));
401         __m128 cyxyxB = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(v, v), 16));
402         __m128 cx = _mm_shuffle_ps(cyxyxA, cyxyxB, _MM_SHUFFLE(2, 0, 2, 0));
403         __m128 cy = _mm_shuffle_ps(cyxyxA, cyxyxB, _MM_SHUFFLE(3, 1, 3, 1));
404         __m128 cmag = _mm_sqrt_ps(_mm_add_ps(_mm_mul_ps(cx, cx), _mm_mul_ps(cy, cy)));
405         __m128 crmag = _mm_rcp_ps(cmag);
406         __m128 ncx = _mm_mul_ps(cx, crmag);
407         __m128 ncy = _mm_mul_ps(cy, crmag);
408
409         v = _mm_loadu_si128((const __m128i*)ccd);
410         __m128 ccyxyxA = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpacklo_epi16(v, v), 16));
411         __m128 ccyxyxB = _mm_cvtepi32_ps(_mm_srai_epi32(_mm_unpackhi_epi16(v, v), 16));
412         __m128 ccx = _mm_shuffle_ps(ccyxyxA, ccyxyxB, _MM_SHUFFLE(2, 0, 2, 0));
413         __m128 ccy = _mm_shuffle_ps(ccyxyxA, ccyxyxB, _MM_SHUFFLE(3, 1, 3, 1));
414         __m128 ccmag = _mm_sqrt_ps(_mm_add_ps(_mm_mul_ps(ccx, ccx), _mm_mul_ps(ccy, ccy)));
415         __m128 ccrmag = _mm_rcp_ps(ccmag);
416         __m128 nccx = _mm_mul_ps(ccx, ccrmag);
417         __m128 nccy = _mm_mul_ps(ccy, ccrmag);
418
419         __m128 dot = _mm_mul_ps(_mm_mul_ps(ncx, nccx), _mm_mul_ps(ncy, nccy));
420         // iscand = (cmag > 30) & (ccmag > 30) & (numpy.minimum(cmag, ccmag) * 1.1 > numpy.maximum(cmag, ccmag)) & (abs(dot) < 0.25)
421         __m128 iscand = _mm_and_ps(_mm_cmpgt_ps(cmag, Kf(30)), _mm_cmpgt_ps(ccmag, Kf(30)));
422
423         iscand = _mm_and_ps(iscand, _mm_cmpgt_ps(_mm_mul_ps(_mm_min_ps(cmag, ccmag), Kf(1.1f)), _mm_max_ps(cmag, ccmag)));
424         iscand = _mm_and_ps(iscand, _mm_cmplt_ps(_mm_abs_ps(dot),  Kf(0.25f)));
425
426         unsigned int CV_DECL_ALIGNED(16) result[4];
427         _mm_store_ps((float*)result, iscand);
428         int ix;
429         CvPoint np;
430         for (ix = 0; ix < 4; ix++) {
431           if (result[ix]) {
432             np.x = x + ix;
433             np.y = y;
434             candidates.push_back(np);
435           }
436         }
437       }
438     }
439   }
440
441   deque <code> codes;
442   size_t i, j, k;
443   while (!candidates.empty()) {
444     CvPoint o = candidates.front();
445     candidates.pop_front();
446     deque<CvPoint> ptc = trailto(vc, o.x, o.y, cxy);
447     deque<CvPoint> ptcc = trailto(vcc, o.x, o.y, ccxy);
448     for (j = 0; j < ptc.size(); j++) {
449       for (k = 0; k < ptcc.size(); k++) {
450         code cc;
451         Sampler sa(im, o, ptc[j], ptcc[k]);
452         for (i = 0; i < codes.size(); i++) {
453           if (sa.overlap(codes[i].sa))
454           {
455             cvReleaseMat(&sa.perim);
456             goto endo;
457           }
458         }
459         if (codes.size() > 0) {
460           //printf("searching for more\n");
461         }
462         if (decode(sa, cc)) {
463           codes.push_back(cc);
464           goto endo;
465         }
466
467         cvReleaseMat(&sa.perim);
468       }
469     }
470 endo: ; // end search for this o
471   }
472
473   cvReleaseMat(&thresh);
474   cvReleaseMat(&vecpic);
475   cvReleaseMat(&vc);
476   cvReleaseMat(&vcc);
477   cvReleaseMat(&cxy);
478   cvReleaseMat(&ccxy);
479
480   deque <CvDataMatrixCode> rc;
481   for (i = 0; i < codes.size(); i++) {
482     CvDataMatrixCode cc;
483     strcpy(cc.msg, codes[i].msg);
484     cc.original = codes[i].original;
485     cc.corners = codes[i].sa.perim;
486     rc.push_back(cc);
487   }
488   return rc;
489 #else
490   deque <CvDataMatrixCode> rc;
491   return rc;
492 #endif
493 }
494
495 #include <opencv2/imgproc/imgproc.hpp>
496
497 namespace cv
498 {
499 namespace
500 {
501   struct CvDM2DM_transform
502   {
503     DataMatrixCode operator()(CvDataMatrixCode& cvdm)
504     {
505       DataMatrixCode dm;
506       memcpy(dm.msg,cvdm.msg,sizeof(cvdm.msg));
507       dm.original = cv::Mat(cvdm.original,true);
508       cvReleaseMat(&cvdm.original);
509       cv::Mat c(cvdm.corners,true);
510       dm.corners[0] = c.at<Point>(0,0);
511       dm.corners[1] = c.at<Point>(1,0);
512       dm.corners[2] = c.at<Point>(2,0);
513       dm.corners[3] = c.at<Point>(3,0);
514       cvReleaseMat(&cvdm.corners);
515       return dm;
516     }
517   };
518   
519   struct DrawDataMatrixCode
520   {
521     DrawDataMatrixCode(cv::Mat& image):image(image){}
522     void operator()(const DataMatrixCode& code)
523     {
524       Scalar c(0, 255, 0);
525       Scalar c2(255, 0,0);
526       line(image, code.corners[0], code.corners[1], c);
527       line(image, code.corners[1], code.corners[2], c);
528       line(image, code.corners[2], code.corners[3], c);
529       line(image, code.corners[3], code.corners[0], c);
530       string code_text(code.msg,4);
531       //int baseline = 0;
532       //Size sz = getTextSize(code_text, CV_FONT_HERSHEY_SIMPLEX, 1, 1, &baseline);
533       putText(image, code_text, code.corners[0], CV_FONT_HERSHEY_SIMPLEX, 0.8, c2, 1, CV_AA, false);
534     }
535     cv::Mat& image;
536
537     DrawDataMatrixCode& operator=(const DrawDataMatrixCode&);
538   };
539 }
540
541 void findDataMatrix(const cv::Mat& image, std::vector<DataMatrixCode>& codes)
542 {
543   CvMat m(image);
544   deque <CvDataMatrixCode> rc = cvFindDataMatrix(&m);
545   codes.clear();
546   codes.resize(rc.size());
547   std::transform(rc.begin(),rc.end(),codes.begin(),CvDM2DM_transform());  
548 }
549
550 void drawDataMatrixCodes(const std::vector<DataMatrixCode>& codes, Mat& drawImage)
551 {
552   std::for_each(codes.begin(),codes.end(),DrawDataMatrixCode(drawImage));
553 }
554
555 }