Commit 9b382d07 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

modified data matrix detection interface (that does not use any new data…

modified data matrix detection interface (that does not use any new data structures). Added Python sample for data matrix detection. Ticket #1664
parent 1046f50a
...@@ -2142,11 +2142,11 @@ CV_EXPORTS Mat repeat(const Mat& src, int ny, int nx); ...@@ -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(const Mat* src, size_t nsrc, OutputArray dst);
CV_EXPORTS void hconcat(InputArray src1, InputArray src2, 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(const Mat* src, size_t nsrc, OutputArray dst);
CV_EXPORTS void vconcat(InputArray src1, InputArray src2, 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) //! computes bitwise conjunction of the two arrays (dst = src1 & src2)
CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2, CV_EXPORTS_W void bitwise_and(InputArray src1, InputArray src2,
......
...@@ -586,16 +586,13 @@ public: ...@@ -586,16 +586,13 @@ public:
}; };
CV_EXPORTS_W void findDataMatrix(InputArray image,
CV_OUT vector<string>& codes,
struct CV_EXPORTS DataMatrixCode { OutputArray corners=noArray(),
char msg[4]; //TODO std::string OutputArrayOfArrays dmtx=noArray());
Mat original; CV_EXPORTS_W void drawDataMatrixCodes(InputOutputArray image,
Point corners[4]; //TODO vector const vector<string>& codes,
}; InputArray corners);
CV_EXPORTS void findDataMatrix(const Mat& image, std::vector<DataMatrixCode>& codes);
CV_EXPORTS void drawDataMatrixCodes(const std::vector<DataMatrixCode>& codes, Mat& drawImage);
} }
/****************************************************************************************\ /****************************************************************************************\
......
...@@ -496,60 +496,80 @@ endo: ; // end search for this o ...@@ -496,60 +496,80 @@ endo: ; // end search for this o
namespace cv namespace cv
{ {
namespace
void findDataMatrix(InputArray _image,
vector<string>& codes,
OutputArray _corners,
OutputArrayOfArrays _dmtx)
{ {
struct CvDM2DM_transform Mat image = _image.getMat();
{ CvMat m(image);
DataMatrixCode operator()(CvDataMatrixCode& cvdm) deque <CvDataMatrixCode> rc = cvFindDataMatrix(&m);
int i, n = (int)rc.size();
Mat corners;
if( _corners.needed() )
{ {
DataMatrixCode dm; _corners.create(n, 4, CV_32SC2);
memcpy(dm.msg,cvdm.msg,sizeof(cvdm.msg)); corners = _corners.getMat();
dm.original = cv::Mat(cvdm.original,true); }
cvReleaseMat(&cvdm.original);
cv::Mat c(cvdm.corners,true); if( _dmtx.needed() )
dm.corners[0] = c.at<Point>(0,0); _dmtx.create(n, 1, CV_8U);
dm.corners[1] = c.at<Point>(1,0);
dm.corners[2] = c.at<Point>(2,0); codes.resize(n);
dm.corners[3] = c.at<Point>(3,0);
cvReleaseMat(&cvdm.corners); for( i = 0; i < n; i++ )
return dm;
}
};
struct DrawDataMatrixCode
{ {
DrawDataMatrixCode(cv::Mat& image):image(image){} CvDataMatrixCode& rc_i = rc[i];
void operator()(const DataMatrixCode& code) codes[i] = string(rc_i.msg);
if( corners.data )
{ {
Scalar c(0, 255, 0); const Point* srcpt = (Point*)rc_i.corners->data.ptr;
Scalar c2(255, 0,0); Point* dstpt = (Point*)corners.ptr(i);
line(image, code.corners[0], code.corners[1], c); for( int k = 0; k < 4; k++ )
line(image, code.corners[1], code.corners[2], c); dstpt[k] = srcpt[k];
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);
} }
cv::Mat& image; cvReleaseMat(&rc_i.corners);
DrawDataMatrixCode& operator=(const DrawDataMatrixCode&); 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);
}
} }
void findDataMatrix(const cv::Mat& image, std::vector<DataMatrixCode>& codes) void drawDataMatrixCodes(InputOutputArray _image,
const vector<string>& codes,
InputArray _corners)
{ {
CvMat m(image); Mat image = _image.getMat();
deque <CvDataMatrixCode> rc = cvFindDataMatrix(&m); Mat corners = _corners.getMat();
codes.clear(); int i, n = corners.rows;
codes.resize(rc.size());
std::transform(rc.begin(),rc.end(),codes.begin(),CvDM2DM_transform());
}
void drawDataMatrixCodes(const std::vector<DataMatrixCode>& codes, Mat& drawImage) if( n > 0 )
{ {
std::for_each(codes.begin(),codes.end(),DrawDataMatrixCode(drawImage)); 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);
}
} }
} }
...@@ -21,8 +21,8 @@ using namespace std; ...@@ -21,8 +21,8 @@ using namespace std;
//hide the local functions in an anon namespace //hide the local functions in an anon namespace
namespace namespace
{ {
void help(char** av) void help(char** av)
{ {
cout << "\nThis program justs gets you started reading images from video\n" 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" "Usage:\n./" << av[0] << " <video device number>\n" << "q,Q,esc -- quit\n"
<< "space -- save frame\n\n" << "space -- save frame\n\n"
...@@ -36,11 +36,10 @@ void help(char** av) ...@@ -36,11 +36,10 @@ void help(char** av)
<< " NOTE: This only handles strings of len 3 or less\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" << " Resize the screen to be large enough for your camera to see, and it should find an read it.\n\n"
<< endl; << endl;
} }
int process(VideoCapture& capture) int process(VideoCapture& capture)
{ {
std::vector<DataMatrixCode> codes;
int n = 0; int n = 0;
char filename[200]; char filename[200];
string window_name = "video | q or esc to quit"; string window_name = "video | q or esc to quit";
...@@ -54,8 +53,10 @@ int process(VideoCapture& capture) ...@@ -54,8 +53,10 @@ int process(VideoCapture& capture)
break; break;
cv::Mat gray; cv::Mat gray;
cv::cvtColor(frame,gray,CV_RGB2GRAY); cv::cvtColor(frame,gray,CV_RGB2GRAY);
findDataMatrix(gray, codes); vector<string> codes;
drawDataMatrixCodes(codes, frame); Mat corners;
findDataMatrix(gray, codes, corners);
drawDataMatrixCodes(frame, codes, corners);
imshow(window_name, frame); imshow(window_name, frame);
char key = (char) waitKey(5); //delay N millis, usually long enough to display and capture input char key = (char) waitKey(5); //delay N millis, usually long enough to display and capture input
switch (key) switch (key)
...@@ -74,7 +75,7 @@ int process(VideoCapture& capture) ...@@ -74,7 +75,7 @@ int process(VideoCapture& capture)
} }
} }
return 0; return 0;
} }
} }
......
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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment