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);
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,
......
......@@ -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);
}
/****************************************************************************************\
......
......@@ -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);
}
}
}
......@@ -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);
}
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