ACT-CV - Machine Vision for Cognitive Modeling
Matcher.h
Go to the documentation of this file.
1 // -*- mode: c++; indent-tabs-mode: nil; c-basic-offset: 4; coding: iso-8859-1; -*-
2 
3 /*
4 ACT-CV - Machine Vision for Cognitive Modeling
5 Copyright (c) 2008 Marc Halbruegge
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 
27 #ifndef MATCHER_H_
28 #define MATCHER_H_
29 
30 #ifdef _WINDOWS
31 # include <windows.h>
32 # include <process.h>
33 #else
34 # ifndef HANDLE
35 typedef int HANDLE;
36 # endif
37 #endif
38 
39 #include <cv.h>
40 #include <garbagecoll.h>
41 #include <vector>
42 
43 
48 class MatchBase : virtual public ReferenceCount {
49 protected:
51  IplImage *target;
53  CvSize srcSize;
56 
57  MatchBase() : name(nullptr), target(nullptr) {
58  srcSize.width=0;
59  srcSize.height=0;
60  }
61 
62 public:
63 
64  MatchBase(const char *targetName) : name(new GCString(targetName)), target(nullptr) {
65  srcSize.width=0;
66  srcSize.height=0;
67  }
68 
69  MatchBase(const char *targetName, const char *fileName)
70  : name(new GCString(targetName)), target(nullptr) {
71  srcSize.width=0;
72  srcSize.height=0;
73 
74  target = cvLoadImage(fileName, CV_LOAD_IMAGE_UNCHANGED);
75  if (target==nullptr) throw FileLineException(__FILE__,__LINE__);
76  }
77 
78  MatchBase(const char *targetName, const char *fileName,
79  int posX, int posY, int sizeX, int sizeY)
80  : name(new GCString(targetName)), target(nullptr) {
81  srcSize.width=0;
82  srcSize.height=0;
83 
84  IplImage *container = cvLoadImage(fileName, CV_LOAD_IMAGE_UNCHANGED);
85  if (container==nullptr) throw FileLineException(__FILE__,__LINE__);
86 
87  CvMat roi;
88  cvGetSubRect(container, &roi, cvRect(posX,posY,sizeX,sizeY));
89 
90  target = cvCreateImage(cvSize(sizeX, sizeY), container->depth, container->nChannels);
91  if (target==nullptr) throw FileLineException(__FILE__,__LINE__);
92 
93  cvCopy(&roi, target);
94  cvReleaseImage(&container);
95  }
96 
97  virtual ~MatchBase() {
98  if (target!=nullptr) cvReleaseImage(&target);
99  }
100 
101  virtual void Match(const IplImage *src) =0;
102  virtual bool TargetFound() const =0;
103 
104  const char* GetVisiconName() const {
105  return name->GetString();
106  }
107 
108  int GetWidth() const {
109  return target->width;
110  }
111 
112  int GetHeight() const {
113  return target->height;
114  }
115 };
116 
117 
129 class MatchImage : public MatchBase {
130 
132  IplImage *result;
134  std::vector<CvPoint> points;
135 
137  double threshold;
138 public:
139 
140  MatchImage(const char *targetName, const char *fileName, double t=0.995)
141  : MatchBase(targetName,fileName), result(nullptr), threshold(t) {
142  }
143 
144  MatchImage(const char *targetName, const char *fileName,
145  int posX, int posY, int sizeX, int sizeY, double t=0.995)
146  : MatchBase(targetName,fileName,posX,posY,sizeX,sizeY), result(nullptr), threshold(t) {
147  }
148 
149 
150  virtual ~MatchImage() {
151  if (result!=nullptr) cvReleaseImage(&result);
152  }
153 
154  void Match(const IplImage *src) {
155  MHDBGMSG(__FILE__,__LINE__,__PRETTY_FUNCTION__);
156  if (result==nullptr) {
157  srcSize.width=src->width;
158  srcSize.height=src->height;
159  result = cvCreateImage(
160  cvSize(srcSize.width-target->width+1,srcSize.height-target->height+1),
161  IPL_DEPTH_32F, 1);
162  }
163  MHDBGMSG(__FILE__,__LINE__,__PRETTY_FUNCTION__);
164 
165  // TODO: Hier läuft was schief!!!
166  // MH 20070821 soweit ich weiß Fehler in OpenCV/Linux, dort gefixt
167  cvMatchTemplate(src, target, result, CV_TM_CCORR_NORMED);//CV_TM_CCORR;CV_TM_SQDIFF;CV_TM_CCOEFF
168 
169  MHDBGMSG(__FILE__,__LINE__,__PRETTY_FUNCTION__);
170  points.clear();
171  for (int x=0;x<result->width;x++) {
172  for (int y=0;y<result->height;y++) {
173  if (cvGetReal2D(result, y, x)>threshold) {
174  points.push_back(cvPoint(x+target->width/2,
175  y+target->height/2));
176  }
177  }
178  }
179  MHDBGMSG(__FILE__,__LINE__,__PRETTY_FUNCTION__);
180  }
181 
182  const std::vector<CvPoint>& GetPoints() const {
183  return points;
184  }
185 
186  bool TargetFound() const {
187  return points.size()>0;
188  }
189 
190  CvPoint GetRandomTarget() const {
191  return points[rand()%points.size()];
192  }
193 
194 };
195 
196 
201 class BGMatchers : public std::vector<GCPointer<MatchImage> > {
202 #define NUM_THREADS 2
203 
205  struct ThreadData {
206  const std::vector<GCPointer<MatchImage> > *matchers;
208  };
209 
210  std::vector<GCPointer<MatchImage> > matchers[NUM_THREADS];
213 
214  static void Func(void *p) {
215  ThreadData *_this = (ThreadData*)p;
216  for (const_iterator i=_this->matchers->begin();
217  i!=_this->matchers->end(); i++) {
218  (*i)->Match(_this->owner->curImg);
219  }
220 #ifdef _WINDOWS
221  _endthread();
222 #endif
223  }
224  const IplImage *curImg;
225 public:
226  void Match(const IplImage *src) {
227  curImg=src;
228 
229 #ifdef _WINDOWS
230  for (unsigned int i=0;i<NUM_THREADS;i++) {
231  threadIds[i]=(HANDLE) _beginthread(Func, 0, threadData + i);
232  }
233  WaitForMultipleObjects(NUM_THREADS, threadIds, TRUE, INFINITE);
234 #else
235  // Linux-Variante später mal bauen
236  for (unsigned int i=0;i<NUM_THREADS;i++) {
237  Func(threadData + i);
238  }
239 #endif
240  }
241 
242  void SetUpMatchers() {
243  for (unsigned int i=0;i<size(); i++) {
244  matchers[i % NUM_THREADS].push_back(at(i));
245  }
246  for (unsigned int i=0;i<NUM_THREADS; i++) {
247  threadData[i].matchers = matchers + i;
248  threadData[i].owner = this;
249  }
250  }
251 };
252 
253 
262 class MatchContour : public MatchBase {
263  double result;
264 
265  IplImage *cannyTarget;
266  CvMemStorage* trgtStorage;
267  CvSeq* trgtContour;
268 
269  IplImage *cannySrc;
270 
271  IplImage *forDisplay;
272 
273  CvMemStorage* storage;
274 
275  static const int MIN_THRES = 70;
276  static const int MAX_THRES = 200;
277 
279 
280  static void thres_cb(int newVal) {
281  }
282 public:
283  MatchContour(const char *targetName, const char *fileName)
284  : MatchBase(targetName,fileName), cannyTarget(nullptr), cannySrc(nullptr),
285  cur_thres(100) {
286 
287  cannyTarget = cvCreateImage(cvGetSize(target), IPL_DEPTH_8U, 1);
288  //cvSmooth((CvArr*)target,(CvArr*)target);
289  cvCanny(target, cannyTarget, 30, 60, 3);
290  trgtStorage = cvCreateMemStorage(0);
291  cvFindContours(cannyTarget, trgtStorage, &trgtContour, sizeof(CvContour),
292  CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
293 
294 
295  cvNamedWindow(name->GetString());
296  cvCreateTrackbar("Canny thresh:", name->GetString(), &cur_thres, 255, &thres_cb);
297 
298  storage = cvCreateMemStorage(0);
299 
300  }
302  if (cannyTarget!=nullptr) cvReleaseImage(&cannyTarget);
303  if (cannySrc!=nullptr) cvReleaseImage(&cannySrc);
304  if (forDisplay!=nullptr) cvReleaseImage(&forDisplay);
305 
306  cvDestroyWindow(name->GetString());
307  }
308  void Match(const IplImage *src) {
309 
310  if (cannySrc==nullptr) {
311  srcSize.width=src->width;
312  srcSize.height=src->height;
313  cannySrc = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
314 
315  forDisplay = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);
316  }
317  //cvSmooth((CvArr*)src,(CvArr*)src);
318  cvCanny(src, cannySrc, cur_thres, cur_thres*2, 3);
319 
320 #if 0
321  cvShowImage(name->GetString(), cannySrc);
322 #else
323  CvSeq* contours;
324  cvFindContours(cannySrc, storage, &contours, sizeof(CvContour),
325  CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
326 
327 
328  cvZero(forDisplay);
329  result=1e100;
330  for ( ; contours!=0; contours = contours->h_next) {
331 
332  //if (abs(contours->total-trgtContour->total)>trgtContour->total/2) continue;
333 
334  double curResult = cvMatchShapes(contours, trgtContour, CV_CONTOURS_MATCH_I1);
335  if (curResult>0.0 && curResult<result) result=curResult;
336 
337 #if 0
338  std::cout << "contours: "
339  << contours->total << " "
340  << curResult
341  << std::endl;
342 #endif
343  //CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );
344  double normedRes = (curResult - .2) / .2;
345 #ifdef max
346  normedRes = min(max(normedRes, -1.0), 1.0);
347 #else
348  normedRes = std::min(std::max(normedRes, -1.0), 1.0);
349 #endif
350  CvScalar color = CV_RGB(127+127*normedRes, 127+127*normedRes, 127-127*normedRes);
351 
352  if (curResult < .4) {
353  /* replace CV_FILLED with 1 to see the outlines */
354  cvDrawContours((CvArr*)forDisplay, contours, color, color, -1, 1 /*CV_FILLED*/, 8);
355  }
356  }
357 
358  cvShowImage(name->GetString(), forDisplay);
359 #endif
360 
361 #if 0
362  if (result < .4) {
363  std::cout << "cvMatchShapes: " << result << std::endl;
364  }
365 #endif
366  }
367  bool TargetFound() const {
368  return false;
369  }
370 };
371 
372 #endif /*MATCHER_H_*/


ACT-CV - Machine Vision for Cognitive Modeling
© 2015 Marc Halbruegge (actcvlibrary@googlemail.com)