adding c++ interface to the datamtrix codes of j.

pull/13383/head
Ethan Rublee 14 years ago
parent 89b5f40ce3
commit 355ad2993a
  1. 14
      modules/objdetect/include/opencv2/objdetect/objdetect.hpp
  2. 112
      modules/objdetect/src/datamatrix.cpp
  3. 4
      modules/python/src1/cv.cpp
  4. 94
      samples/cpp/video_dmtx.cpp

@ -690,7 +690,14 @@ protected:
std::vector<std::string> objectClassNames; std::vector<std::string> objectClassNames;
std::vector<DOTTemplate> dotTemplates; std::vector<DOTTemplate> dotTemplates;
}; };
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);
void drawDataMatrixCodes(const std::vector<DataMatrixCode>& codes, Mat& drawImage);
} }
/****************************************************************************************\ /****************************************************************************************\
@ -699,15 +706,14 @@ protected:
typedef unsigned char uint8; typedef unsigned char uint8;
class CV_EXPORTS DataMatrixCode { struct CV_EXPORTS CvDataMatrixCode {
public:
char msg[4]; char msg[4];
CvMat *original; CvMat *original;
CvMat *corners; CvMat *corners;
}; };
#include <deque>
CV_EXPORTS std::deque<DataMatrixCode> cvFindDataMatrix(CvMat *im);
#include <deque>
CV_EXPORTS std::deque<CvDataMatrixCode> cvFindDataMatrix(CvMat *im);
#endif #endif
#endif #endif

@ -5,11 +5,15 @@
#endif #endif
#include <deque> #include <deque>
#include <algorithm>
using namespace std; using namespace std;
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
class Sampler { class Sampler {
public: public:
CvMat *im; CvMat *im;
@ -18,7 +22,6 @@ public:
CvMat *perim; CvMat *perim;
CvPoint fcoord(float fx, float fy); CvPoint fcoord(float fx, float fy);
CvPoint coord(int ix, int iy); CvPoint coord(int ix, int iy);
Sampler() {}
Sampler(CvMat *_im, CvPoint _o, CvPoint _c, CvPoint _cc); Sampler(CvMat *_im, CvPoint _o, CvPoint _c, CvPoint _cc);
uint8 getpixel(int ix, int iy); uint8 getpixel(int ix, int iy);
int isinside(int x, int y); int isinside(int x, int y);
@ -26,6 +29,8 @@ public:
int hasbars(); int hasbars();
void timing(); void timing();
CvMat *extract(); CvMat *extract();
Sampler():im(0),perim(0){}
~Sampler(){}
}; };
class code { // used in this file only class code { // used in this file only
@ -128,16 +133,21 @@ CvPoint Sampler::coord(int ix, int iy)
uint8 Sampler::getpixel(int ix, int iy) uint8 Sampler::getpixel(int ix, int iy)
{ {
CvPoint pt = coord(ix, iy); CvPoint pt = coord(ix, iy);
// printf("%d,%d\n", pt.x, pt.y); if ((0 <= pt.x) && (pt.x < im->cols) && (0 <= pt.y) && (pt.y < im->rows))
return *cvPtr2D(im, pt.y, pt.x); return *cvPtr2D(im, pt.y, pt.x);
else
return 0;
} }
int Sampler::isinside(int x, int y) int Sampler::isinside(int x, int y)
{ {
CvPoint2D32f fp; CvPoint2D32f pt;
fp.x = (float)x; pt.x = (float)x;
fp.y = (float)y; pt.y = (float)y;
return cvPointPolygonTest(perim, fp, 0) < 0; if ((0 <= pt.x) && (pt.x < im->cols) && (0 <= pt.y) && (pt.y < im->rows))
return cvPointPolygonTest(perim, pt, 0) < 0;
else
return 0;
} }
int Sampler::overlap(Sampler &other) int Sampler::overlap(Sampler &other)
@ -329,7 +339,7 @@ static deque<CvPoint> trailto(CvMat *v, int x, int y, CvMat *terminal)
return r; return r;
} }
deque <DataMatrixCode> cvFindDataMatrix(CvMat *im) deque <CvDataMatrixCode> cvFindDataMatrix(CvMat *im)
{ {
#if CV_SSE2 #if CV_SSE2
int r = im->rows; int r = im->rows;
@ -411,7 +421,7 @@ deque <DataMatrixCode> cvFindDataMatrix(CvMat *im)
__m128 iscand = _mm_and_ps(_mm_cmpgt_ps(cmag, Kf(30)), _mm_cmpgt_ps(ccmag, Kf(30))); __m128 iscand = _mm_and_ps(_mm_cmpgt_ps(cmag, Kf(30)), _mm_cmpgt_ps(ccmag, Kf(30)));
iscand = _mm_and_ps(iscand, _mm_cmpgt_ps(_mm_mul_ps(_mm_min_ps(cmag, ccmag), Kf(1.1f)), _mm_max_ps(cmag, ccmag))); iscand = _mm_and_ps(iscand, _mm_cmpgt_ps(_mm_mul_ps(_mm_min_ps(cmag, ccmag), Kf(1.1f)), _mm_max_ps(cmag, ccmag)));
iscand = _mm_and_ps(iscand, _mm_cmplt_ps(_mm_abs_ps(dot), Kf(0.25f))); iscand = _mm_and_ps(iscand, _mm_cmplt_ps(_mm_abs_ps(dot), Kf(0.25f)));
unsigned int CV_DECL_ALIGNED(16) result[4]; unsigned int CV_DECL_ALIGNED(16) result[4];
_mm_store_ps((float*)result, iscand); _mm_store_ps((float*)result, iscand);
@ -441,7 +451,10 @@ deque <DataMatrixCode> cvFindDataMatrix(CvMat *im)
Sampler sa(im, o, ptc[j], ptcc[k]); Sampler sa(im, o, ptc[j], ptcc[k]);
for (i = 0; i < codes.size(); i++) { for (i = 0; i < codes.size(); i++) {
if (sa.overlap(codes[i].sa)) if (sa.overlap(codes[i].sa))
{
cvReleaseMat(&sa.perim);
goto endo; goto endo;
}
} }
if (codes.size() > 0) { if (codes.size() > 0) {
printf("searching for more\n"); printf("searching for more\n");
@ -450,21 +463,23 @@ deque <DataMatrixCode> cvFindDataMatrix(CvMat *im)
codes.push_back(cc); codes.push_back(cc);
goto endo; goto endo;
} }
cvReleaseMat(&sa.perim);
} }
} }
endo: ; // end search for this o endo: ; // end search for this o
} }
cvFree(&thresh); cvReleaseMat(&thresh);
cvFree(&vecpic); cvReleaseMat(&vecpic);
cvFree(&vc); cvReleaseMat(&vc);
cvFree(&vcc); cvReleaseMat(&vcc);
cvFree(&cxy); cvReleaseMat(&cxy);
cvFree(&ccxy); cvReleaseMat(&ccxy);
deque <DataMatrixCode> rc; deque <CvDataMatrixCode> rc;
for (i = 0; i < codes.size(); i++) { for (i = 0; i < codes.size(); i++) {
DataMatrixCode cc; CvDataMatrixCode cc;
strcpy(cc.msg, codes[i].msg); strcpy(cc.msg, codes[i].msg);
cc.original = codes[i].original; cc.original = codes[i].original;
cc.corners = codes[i].sa.perim; cc.corners = codes[i].sa.perim;
@ -472,7 +487,68 @@ endo: ; // end search for this o
} }
return rc; return rc;
#else #else
deque <DataMatrixCode> rc; deque <CvDataMatrixCode> rc;
return rc; return rc;
#endif #endif
} }
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
namespace cv
{
namespace
{
struct CvDM2DM_transform
{
DataMatrixCode operator()(CvDataMatrixCode& cvdm)
{
DataMatrixCode dm;
std::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;
}
};
struct DrawDataMatrixCode
{
DrawDataMatrixCode(cv::Mat& image):image(image){}
void operator()(const DataMatrixCode& code)
{
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);
}
cv::Mat& image;
};
}
void findDataMatrix(const cv::Mat& image, std::vector<DataMatrixCode>& codes)
{
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));
}
}

@ -3686,12 +3686,12 @@ static PyObject *pyfinddatamatrix(PyObject *self, PyObject *args)
CvMat *image; CvMat *image;
if (!convert_to_CvMat(pyim, &image, "image")) return NULL; if (!convert_to_CvMat(pyim, &image, "image")) return NULL;
std::deque <DataMatrixCode> codes; std::deque <CvDataMatrixCode> codes;
ERRWRAP(codes = cvFindDataMatrix(image)); ERRWRAP(codes = cvFindDataMatrix(image));
PyObject *pycodes = PyList_New(codes.size()); PyObject *pycodes = PyList_New(codes.size());
for (size_t i = 0; i < codes.size(); i++) { for (size_t i = 0; i < codes.size(); i++) {
DataMatrixCode *pc = &codes[i]; CvDataMatrixCode *pc = &codes[i];
PyList_SetItem(pycodes, i, Py_BuildValue("(sOO)", pc->msg, FROM_CvMat(pc->corners), FROM_CvMat(pc->original))); PyList_SetItem(pycodes, i, Py_BuildValue("(sOO)", pc->msg, FROM_CvMat(pc->corners), FROM_CvMat(pc->original)));
} }

@ -0,0 +1,94 @@
/*
* starter_video.cpp
*
* Created on: Nov 23, 2010
* Author: Ethan Rublee
*
* A starter sample for using opencv, get a video stream and display the images
* easy as CV_PI right?
*/
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace cv;
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"
<< 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())
continue;
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)
{
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);
}
Loading…
Cancel
Save