modified data matrix detection interface (that does not use any new data structures...
authorVadim Pisarevsky <no@email>
Fri, 27 Apr 2012 16:10:10 +0000 (16:10 +0000)
committerVadim Pisarevsky <no@email>
Fri, 27 Apr 2012 16:10:10 +0000 (16:10 +0000)
modules/core/include/opencv2/core/core.hpp
modules/objdetect/include/opencv2/objdetect/objdetect.hpp
modules/objdetect/src/datamatrix.cpp
samples/cpp/video_dmtx.cpp
samples/python2/video_dmtx.py [new file with mode: 0644]

index f284ac7..a2bb752 100644 (file)
@@ -2142,11 +2142,11 @@ CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx);
         
 CV_EXPORTS void hconcat(const Mat* src, size_t nsrc, OutputArray dst);
 CV_EXPORTS void hconcat(InputArray src1, InputArray src2, OutputArray dst);
-CV_EXPORTS_W void hconcat(InputArray src, OutputArray dst);
+CV_EXPORTS_W void hconcat(InputArrayOfArrays src, OutputArray dst);
 
 CV_EXPORTS void vconcat(const Mat* src, size_t nsrc, OutputArray dst);
 CV_EXPORTS void vconcat(InputArray src1, InputArray src2, OutputArray dst);
-CV_EXPORTS_W void vconcat(InputArray src, OutputArray dst);
+CV_EXPORTS_W void vconcat(InputArrayOfArrays src, OutputArray dst);
     
 //! computes bitwise conjunction of the two arrays (dst = src1 & src2)
 CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2,
index e3eb07d..130cc1b 100644 (file)
@@ -586,16 +586,13 @@ public:
 };
 
 
-    
-    
-struct CV_EXPORTS DataMatrixCode {
-  char msg[4]; //TODO std::string
-  Mat original;
-  Point corners[4]; //TODO vector
-};
-
-CV_EXPORTS void findDataMatrix(const Mat& image, std::vector<DataMatrixCode>& codes);
-CV_EXPORTS  void drawDataMatrixCodes(const std::vector<DataMatrixCode>& codes, Mat& drawImage);
+CV_EXPORTS_W void findDataMatrix(InputArray image,
+                                 CV_OUT vector<string>& codes,
+                                 OutputArray corners=noArray(),
+                                 OutputArrayOfArrays dmtx=noArray());
+CV_EXPORTS_W void drawDataMatrixCodes(InputOutputArray image,
+                                      const vector<string>& codes,
+                                      InputArray corners);
 }
 
 /****************************************************************************************\
index 549d77a..a4258bd 100644 (file)
@@ -496,60 +496,80 @@ endo: ; // end search for this o
 
 namespace cv
 {
-namespace
+    
+void findDataMatrix(InputArray _image,
+                    vector<string>& codes,
+                    OutputArray _corners,
+                    OutputArrayOfArrays _dmtx)
 {
-  struct CvDM2DM_transform
-  {
-    DataMatrixCode operator()(CvDataMatrixCode& cvdm)
+    Mat image = _image.getMat();
+    CvMat m(image);
+    deque <CvDataMatrixCode> rc = cvFindDataMatrix(&m);
+    int i, n = (int)rc.size();
+    Mat corners;
+    
+    if( _corners.needed() )
     {
-      DataMatrixCode dm;
-      memcpy(dm.msg,cvdm.msg,sizeof(cvdm.msg));
-      dm.original = cv::Mat(cvdm.original,true);
-      cvReleaseMat(&cvdm.original);
-      cv::Mat c(cvdm.corners,true);
-      dm.corners[0] = c.at<Point>(0,0);
-      dm.corners[1] = c.at<Point>(1,0);
-      dm.corners[2] = c.at<Point>(2,0);
-      dm.corners[3] = c.at<Point>(3,0);
-      cvReleaseMat(&cvdm.corners);
-      return dm;
+        _corners.create(n, 4, CV_32SC2);
+        corners = _corners.getMat();
     }
-  };
-  
-  struct DrawDataMatrixCode
-  {
-    DrawDataMatrixCode(cv::Mat& image):image(image){}
-    void operator()(const DataMatrixCode& code)
+    
+    if( _dmtx.needed() )
+        _dmtx.create(n, 1, CV_8U);
+    
+    codes.resize(n);
+    
+    for( i = 0; i < n; i++ )
     {
-      Scalar c(0, 255, 0);
-      Scalar c2(255, 0,0);
-      line(image, code.corners[0], code.corners[1], c);
-      line(image, code.corners[1], code.corners[2], c);
-      line(image, code.corners[2], code.corners[3], c);
-      line(image, code.corners[3], code.corners[0], c);
-      string code_text(code.msg,4);
-      //int baseline = 0;
-      //Size sz = getTextSize(code_text, CV_FONT_HERSHEY_SIMPLEX, 1, 1, &baseline);
-      putText(image, code_text, code.corners[0], CV_FONT_HERSHEY_SIMPLEX, 0.8, c2, 1, CV_AA, false);
+        CvDataMatrixCode& rc_i = rc[i];
+        codes[i] = string(rc_i.msg);
+        
+        if( corners.data )
+        {
+            const Point* srcpt = (Point*)rc_i.corners->data.ptr;
+            Point* dstpt = (Point*)corners.ptr(i);
+            for( int k = 0; k < 4; k++ )
+                dstpt[k] = srcpt[k];
+        }
+        cvReleaseMat(&rc_i.corners);
+        
+        if( _dmtx.needed() )
+        {
+            _dmtx.create(rc_i.original->rows, rc_i.original->cols, rc_i.original->type, i);
+            Mat dst = _dmtx.getMat(i);
+            Mat(rc_i.original).copyTo(dst);
+        }
+        cvReleaseMat(&rc_i.original);
     }
-    cv::Mat& image;
-
-    DrawDataMatrixCode& operator=(const DrawDataMatrixCode&);
-  };
 }
 
-void findDataMatrix(const cv::Mat& image, std::vector<DataMatrixCode>& codes)
+void drawDataMatrixCodes(InputOutputArray _image,
+                         const vector<string>& codes,
+                         InputArray _corners)
 {
-  CvMat m(image);
-  deque <CvDataMatrixCode> rc = cvFindDataMatrix(&m);
-  codes.clear();
-  codes.resize(rc.size());
-  std::transform(rc.begin(),rc.end(),codes.begin(),CvDM2DM_transform());  
-}
-
-void drawDataMatrixCodes(const std::vector<DataMatrixCode>& codes, Mat& drawImage)
-{
-  std::for_each(codes.begin(),codes.end(),DrawDataMatrixCode(drawImage));
+    Mat image = _image.getMat();
+    Mat corners = _corners.getMat();
+    int i, n = corners.rows;
+    
+    if( n > 0 )
+    {
+        CV_Assert( corners.depth() == CV_32S &&
+                  corners.cols*corners.channels() == 8 &&
+                  n == (int)codes.size() );
+    }
+    
+    for( i = 0; i < n; i++ )
+    {
+        Scalar c(0, 255, 0);
+        Scalar c2(255, 0,0);
+        const Point* pt = (const Point*)corners.ptr(i);
+        
+        for( int k = 0; k < 4; k++ )
+            line(image, pt[k], pt[(k+1)%4], c);
+        //int baseline = 0;
+        //Size sz = getTextSize(code_text, CV_FONT_HERSHEY_SIMPLEX, 1, 1, &baseline);
+        putText(image, codes[i], pt[0], CV_FONT_HERSHEY_SIMPLEX, 0.8, c2, 1, CV_AA, false);
+    }
 }
-
+    
 }
index 946aa35..a3981c9 100644 (file)
@@ -21,80 +21,81 @@ using namespace std;
 //hide the local functions in an anon namespace
 namespace
 {
-void help(char** av)
-{
-  cout << "\nThis program justs gets you started reading images from video\n"
-    "Usage:\n./" << av[0] << " <video device number>\n" << "q,Q,esc -- quit\n"
-      << "space   -- save frame\n\n"
-      << "\tThis is a starter sample, to get you up and going in a copy pasta fashion\n"
-      << "\tThe program captures frames from a camera connected to your computer.\n"
-      << "\tTo find the video device number, try ls /dev/video* \n"
-      << "\tYou may also pass a video file, like my_vide.avi instead of a device number"
-      << "\n"
-      << "DATA:\n"
-      << "Generate a datamatrix from  from http://datamatrix.kaywa.com/  \n"
-      << "  NOTE: This only handles strings of len 3 or less\n"
-      << "  Resize the screen to be large enough for your camera to see, and it should find an read it.\n\n"
-      << endl;
-}
-
-int process(VideoCapture& capture)
-{
-  std::vector<DataMatrixCode> codes;
-  int n = 0;
-  char filename[200];
-  string window_name = "video | q or esc to quit";
-  cout << "press space to save a picture. q or esc to quit" << endl;
-  namedWindow(window_name, CV_WINDOW_KEEPRATIO); //resizable window;
-  Mat frame;
-  for (;;)
-  {
-    capture >> frame;
-    if (frame.empty())
-      break;
-    cv::Mat gray;
-    cv::cvtColor(frame,gray,CV_RGB2GRAY);
-    findDataMatrix(gray, codes);
-    drawDataMatrixCodes(codes, frame);
-    imshow(window_name, frame);
-    char key = (char) waitKey(5); //delay N millis, usually long enough to display and capture input
-    switch (key)
+    void help(char** av)
     {
-    case 'q':
-    case 'Q':
-    case 27: //escape key
-      return 0;
-    case ' ': //Save an image
-      sprintf(filename, "filename%.3d.jpg", n++);
-      imwrite(filename, frame);
-      cout << "Saved " << filename << endl;
-      break;
-    default:
-      break;
+        cout << "\nThis program justs gets you started reading images from video\n"
+        "Usage:\n./" << av[0] << " <video device number>\n" << "q,Q,esc -- quit\n"
+        << "space   -- save frame\n\n"
+        << "\tThis is a starter sample, to get you up and going in a copy pasta fashion\n"
+        << "\tThe program captures frames from a camera connected to your computer.\n"
+        << "\tTo find the video device number, try ls /dev/video* \n"
+        << "\tYou may also pass a video file, like my_vide.avi instead of a device number"
+        << "\n"
+        << "DATA:\n"
+        << "Generate a datamatrix from  from http://datamatrix.kaywa.com/  \n"
+        << "  NOTE: This only handles strings of len 3 or less\n"
+        << "  Resize the screen to be large enough for your camera to see, and it should find an read it.\n\n"
+        << endl;
     }
-  }
-  return 0;
-}
-
+    
+    int process(VideoCapture& capture)
+    {
+        int n = 0;
+        char filename[200];
+        string window_name = "video | q or esc to quit";
+        cout << "press space to save a picture. q or esc to quit" << endl;
+        namedWindow(window_name, CV_WINDOW_KEEPRATIO); //resizable window;
+        Mat frame;
+        for (;;)
+        {
+            capture >> frame;
+            if (frame.empty())
+                break;
+            cv::Mat gray;
+            cv::cvtColor(frame,gray,CV_RGB2GRAY);
+            vector<string> codes;
+            Mat corners;
+            findDataMatrix(gray, codes, corners);
+            drawDataMatrixCodes(frame, codes, corners);
+            imshow(window_name, frame);
+            char key = (char) waitKey(5); //delay N millis, usually long enough to display and capture input
+            switch (key)
+            {
+                case 'q':
+                case 'Q':
+                case 27: //escape key
+                    return 0;
+                case ' ': //Save an image
+                    sprintf(filename, "filename%.3d.jpg", n++);
+                    imwrite(filename, frame);
+                    cout << "Saved " << filename << endl;
+                    break;
+                default:
+                    break;
+            }
+        }
+        return 0;
+    }
+    
 }
 
 int main(int ac, char** av)
 {
-
-  if (ac != 2)
-  {
-    help(av);
-    return 1;
-  }
-  std::string arg = av[1];
-  VideoCapture capture(arg); //try to open string, this will attempt to open it as a video file
-  if (!capture.isOpened()) //if this fails, try to open as a video camera, through the use of an integer param
-    capture.open(atoi(arg.c_str()));
-  if (!capture.isOpened())
-  {
-    cerr << "Failed to open a video device or video file!\n" << endl;
-    help(av);
-    return 1;
-  }
-  return process(capture);
+    
+    if (ac != 2)
+    {
+        help(av);
+        return 1;
+    }
+    std::string arg = av[1];
+    VideoCapture capture(arg); //try to open string, this will attempt to open it as a video file
+    if (!capture.isOpened()) //if this fails, try to open as a video camera, through the use of an integer param
+        capture.open(atoi(arg.c_str()));
+    if (!capture.isOpened())
+    {
+        cerr << "Failed to open a video device or video file!\n" << endl;
+        help(av);
+        return 1;
+    }
+    return process(capture);
 }
diff --git a/samples/python2/video_dmtx.py b/samples/python2/video_dmtx.py
new file mode 100644 (file)
index 0000000..d26efb5
--- /dev/null
@@ -0,0 +1,68 @@
+help='''
+Data matrix detector sample.
+Usage:
+   video_dmtx {<video device number>|<video file name>}
+
+   Generate a datamatrix from  from http://datamatrix.kaywa.com/ and print it out.
+   NOTE: This only handles data matrices, generated for text strings of max 3 characters
+
+   Resize the screen to be large enough for your camera to see, and it should find an read it.
+   
+Keyboard shortcuts:
+
+   q or ESC - exit
+   space - save current image as datamatrix<frame_number>.jpg
+'''
+
+import cv2
+import numpy as np
+import sys
+
+def data_matrix_demo(cap):
+    window_name = "Data Matrix Detector"
+    frame_number = 0
+    need_to_save = False
+    
+    while 1:
+        ret, frame = cap.read()
+        if not ret:
+            break
+            
+        gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
+        codes, corners, dmtx = cv2.findDataMatrix(gray)
+        
+        cv2.drawDataMatrixCodes(frame, codes, corners)
+        cv2.imshow(window_name, frame)
+        
+        key = cv2.waitKey(30)
+        c = chr(key & 255)
+        if c in ['q', 'Q', chr(27)]:
+            break
+            
+        if c == ' ':
+            need_to_save = True
+            
+        if need_to_save and codes:
+            filename = ("datamatrix%03d.jpg" % frame_number)
+            cv2.imwrite(filename, frame)
+            print "Saved frame to " + filename
+            need_to_save = False
+            
+        frame_number += 1
+
+
+if __name__ == '__main__':
+    print help
+
+    if len(sys.argv) == 1:
+        cap = cv2.VideoCapture(0)
+    else:
+        cap = cv2.VideoCapture(sys.argv[1])
+        if not cap.isOpened():
+            cap = cv2.VideoCapture(int(sys.argv[1]))
+        
+    if not cap.isOpened():
+        print 'Cannot initialize video capture'
+        sys.exit(-1)
+        
+    data_matrix_demo(cap)