karma
All Modules
module.cpp
1 /*
2  * Copyright (C) 2011 Department of Robotics Brain and Cognitive Sciences - Istituto Italiano di Tecnologia
3  * Author: Vadim Tikhanoff Ugo Pattacini
4  * email: vadim.tikhanoff@iit.it
5  * Permission is granted to copy, distribute, and/or modify this program
6  * under the terms of the GNU General Public License, version 2 or any
7  * later version published by the Free Software Foundation.
8  *
9  * A copy of the license can be found at
10  * http://www.robotcub.org/icub/license/gpl.txt
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details
16 */
17 #include <sstream>
18 #include <cstdio>
19 
20 #include <yarp/math/Rand.h>
21 #include <yarp/math/Math.h>
22 #include <yarp/cv/Cv.h>
23 #include "iCub/module.h"
24 
25 using namespace cv;
26 using namespace std;
27 using namespace yarp::os;
28 using namespace yarp::sig;
29 using namespace yarp::math;
30 using namespace yarp::cv;
31 
32 
33 /**********************************************************/
34 bool Manager::configure(ResourceFinder &rf)
35 {
36  name=rf.find("name").asString();
37 
38  //incoming
39  motionFeatures.open("/"+name+"/motionFilter:i"); //port for incoming blobs from motionCut
40 
41  //outgoing
42  toolPoint.open("/"+name+"/target:o"); //port to send off target Points to segmentator
43  imgOutPort.open("/"+name+"/img:o"); //port to send off target Points to segmentator
44 
45  //rpc
46  rpcHuman.open("/"+name+"/human:rpc"); //rpc server to interact with the user
47 
48  motionFeatures.setManager(this);
49  lineDetails = new lineData [10];
50  //attach(rpcHuman);
51  return true;
52 }
53 /**********************************************************/
54 bool Manager::interruptModule()
55 {
56  motionFeatures.interrupt();
57  toolPoint.interrupt();
58  imgOutPort.interrupt();
59  rpcHuman.interrupt();
60  return true;
61 }
62 /**********************************************************/
63 bool Manager::close()
64 {
65  delete[] lineDetails;
66  motionFeatures.close();
67  toolPoint.close();
68  imgOutPort.close();
69  rpcHuman.close();
70  return true;
71 }
72 /**********************************************************/
73 int Manager::processHumanCmd(const Bottle &cmd, Bottle &b)
74 {
75  int ret=Vocab::encode(cmd.get(0).asString());
76  b.clear();
77  if (cmd.size()>1)
78  {
79  if (cmd.get(1).isList())
80  b=*cmd.get(1).asList();
81  else
82  b=cmd.tail();
83  }
84  return ret;
85 }
86 /**********************************************************/
87 bool Manager::updateModule()
88 {
89  if (isStopping())
90  return false;
91 
92  Bottle cmd, val, reply;
93  rpcHuman.read(cmd, true);
94  int rxCmd=processHumanCmd(cmd,val);
95  if (rxCmd==Vocab::encode("action"))
96  {
97  reply.addString("ack");
98  rpcHuman.reply(reply);
99  }
100  return true;
101 }
102 /**********************************************************/
103 double Manager::getPeriod()
104 {
105  return 0.1;
106 }
107 
108 /**********************************************************/
109 void Manager::processMotionPoints(Bottle &b)
110 {
111  //create MAT image
112  cv::Mat imgMat(Size(320,240),CV_8UC3);
113  cv::Mat imgClean(Size(320,240),CV_8UC3);
114  imgMat = Scalar::all(0);
115  imgClean = Scalar::all(255);
116 
117  for (int x=1; x<b.size(); x++)
118  {
119  Point pt;
120  pt.x = b.get(x).asList()->get(0).asInt();
121  pt.y = b.get(x).asList()->get(1).asInt();
122  imgMat.at<cv::Vec3b>(pt.y,pt.x)[0] = 255 ;
123  imgMat.at<cv::Vec3b>(pt.y,pt.x)[1] = 0 ;
124  imgMat.at<cv::Vec3b>(pt.y,pt.x)[2] = 0 ;
125  imgClean.at<cv::Vec3b>(pt.y,pt.x)[0] = 255 ;
126  imgClean.at<cv::Vec3b>(pt.y,pt.x)[1] = 0 ;
127  imgClean.at<cv::Vec3b>(pt.y,pt.x)[2] = 0 ;
128  }
129 
130  int n = 10;
131  int an = n > 0 ? n : -n;
132  int element_shape = MORPH_RECT;
133  Mat element = getStructuringElement(element_shape, Size(an*2+1, an*2+1), Point(an, an) );
134  morphologyEx(imgMat, imgMat, CV_MOP_CLOSE, element);
135 
136  Bottle data;
137  data = processImage(b, imgMat, imgClean, lineDetails); //image analysis and bottle cleaning
138 
139  if (data.size() > 0)
140  processBlobs(data, imgClean, lineDetails); // kmeans
141 
142  ImageOf<PixelRgb> &outImg = imgOutPort.prepare();
143  outImg.resize( imgClean.cols, imgClean.rows );
144  imgClean.copyTo(toCvMat(outImg));
145  imgOutPort.write();
146 }
147 
148 /**********************************************************/
149 void Manager::processBlobs(Bottle &b, cv::Mat &dest, lineData *lineDetails)
150 {
151  int sampleCount = b.size();
152  int dimensions = 2;
153  int clusterCount = 2;
154  Mat points(sampleCount, dimensions, CV_32F);
155  Mat labels;
156  Mat centers(clusterCount, dimensions, points.type());
157  for(int i = 0; i<sampleCount;i++)
158  {
159  points.at<float>(i,0) = (float) b.get(i).asList()->get(0).asInt();
160  points.at<float>(i,1) = (float) b.get(i).asList()->get(1).asInt();
161  }
162 
163  if (sampleCount<clusterCount)
164  {
165  printf("sampleCount < clusterCount!\n");
166  return;
167  }
168 
169  kmeans(points, clusterCount, labels, TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 3, KMEANS_PP_CENTERS, centers);
170 
171  Point pts[10];
172  for (int i = 0; i < clusterCount; i++)
173  {
174  int clusterIdx = labels.at<int>(i);
175  Point ipt;
176  ipt.x = (int) centers.at<float>(i,0);
177  ipt.y = (int) centers.at<float>(i,1);
178 
179  pts[i] = ipt;
180  circle( dest, ipt, 5, CV_RGB(255,255,255), cv::FILLED, cv::LINE_AA );
181  }
182  double gradient = 0;
183  double intercept = 0;
184 
185  if (pts[1].y < pts[0].y )
186  {
187  double pow1 = pow( fabs((double)pts[0].x - (double)pts[1].x),2);
188  double pow2 = pow( fabs((double)pts[0].y - (double)pts[1].y),2);
189  double lenAB = sqrt( pow1 + pow2 );
190  Point endPoint;
191  endPoint.x = (int)(pts[1].x + (double)(pts[1].x - pts[0].x) / lenAB * 50);
192  endPoint.y = (int)(pts[1].y + (double) (pts[1].y - pts[0].y) / lenAB * 50);
193  line(dest, pts[0], endPoint, Scalar(0,0,0), 2, cv::LINE_AA);
194  gradient = (double)( endPoint.y - pts[0].y ) / (double)( endPoint.x - pts[0].x );
195  intercept = (double)( pts[0].y - (double)(pts[0].x * gradient) );
196  lineDetails[1].gradient = gradient;
197  lineDetails[1].intercept = intercept;
198  }
199  else
200  {
201  double pow1 = pow( fabs((double)pts[1].x - (double)pts[0].x), 2);
202  double pow2 = pow( fabs((double)pts[1].y - (double)pts[0].y), 2);
203  double lenAB = sqrt( pow1 + pow2 );
204  Point endPoint;
205  endPoint.x = (int)(pts[0].x + (double)(pts[0].x - pts[1].x) / lenAB * 50);
206  endPoint.y = (int)(pts[0].y + (double)(pts[0].y - pts[1].y) / lenAB * 50);
207  line(dest, pts[1], endPoint, Scalar(0,0,0), 2, cv::LINE_AA);
208 
209  gradient = (double)( endPoint.y - pts[1].y) / (double)(endPoint.x - pts[1].x);
210  intercept = (double)( endPoint.y - (double)(endPoint.x * gradient) );
211  lineDetails[1].gradient = gradient;
212  lineDetails[1].intercept = intercept;
213  }
214  //find
215  getIntersection(dest, lineDetails);
216 }
217 /**********************************************************/
218 void Manager::getIntersection(cv::Mat &dest, lineData *lineDetails)
219 {
220  int thickness = -1;
221  int lineType = 8;
222  Point intersect;
223 
224  intersect.x = (int)( (lineDetails[1].intercept - lineDetails[0].intercept) / (lineDetails[0].gradient-lineDetails[1].gradient));
225  intersect.y = (int)( (lineDetails[0].gradient * intersect.x) + lineDetails[0].intercept);
226 
227  if (intersect.x > 0 && intersect.y >0 && intersect.x < dest.cols && intersect.y < dest.rows)
228  {
229  circle( dest, intersect, dest.rows/(int)32.0, Scalar( 255, 0, 0 ), thickness, lineType );
230  Bottle output;
231  output.clear();
232  output.addInt(intersect.x);
233  output.addInt(intersect.y);
234  toolPoint.write(output);
235  }
236 }
237 
238 /**********************************************************/
239 Bottle Manager::processImage(Bottle &b, cv::Mat &dest, cv::Mat &clean, lineData *lineDetails)
240 {
241  Bottle botListDel, botPointsDel;
242  Bottle correctList, correctElements;
243  vector<vector<Point> > contours;
244  cv::Mat imgGray(Size(320,240),CV_8UC1);
245  cv::cvtColor( dest, imgGray, CV_RGB2GRAY);
246  double gradient = 0;
247  double intercept = 0;
248  findContours(imgGray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
249  for(size_t i = 0; i < contours.size(); i++)
250  {
251  size_t count = contours[i].size();
252  if( count < 6 )
253  continue;
254 
255  Mat pointsf;
256  Mat(contours[i]).convertTo(pointsf, CV_32F);
257  RotatedRect box = fitEllipse(pointsf);
258 
259  if( MAX(box.size.width, box.size.height) > MIN(box.size.width, box.size.height)*30 )
260  continue;
261 
262  double area = contourArea( Mat(contours[i]) );
263  if ( area > 10 && area < 4000)
264  {
265  for (int x = (int)box.center.x - (int)box.size.width; x < (int)box.center.x + (int)box.size.width; x++){
266  for (int y = (int)box.center.y - (int)box.size.height; y < (int)box.center.y + (int)box.size.height; y++)
267  {
268  if (y< imgGray.rows-1 && x< imgGray.cols-1 && y > 0 && x > 0)
269  {
270  if( dest.at<cv::Vec3b>(y,x)[0] == 255 )
271  {
272  dest.at<cv::Vec3b>(y,x)[0] = 0;
273  botPointsDel.clear();
274  botPointsDel.addInt(x);
275  botPointsDel.addInt(y);
276  botListDel.addList() = botPointsDel;
277  }
278  }
279  }
280  }
281  }
282  else
283  {
284  for (int v = 1; v<b.size(); v++)
285  {
286  bool found=false;
287  for (int w = 0; w<botListDel.size(); w++)
288  {
289  if ( ((float) b.get(v).asList()->get(0).asInt() == botListDel.get(w).asList()->get(0).asInt() ) &&
290  ((float) b.get(v).asList()->get(1).asInt() == botListDel.get(w).asList()->get(1).asInt() ) )
291  {
292  found=true;
293  break;
294  }
295  }
296  if(!found)
297  correctList.addList() = *b.get(v).asList();
298  }
299  drawContours(dest, contours, (int)i, Scalar::all(255), 1, 8);
300  Point2f vtx[4];
301  box.points(vtx);
302 
303  int j = 0;
304  if ( vtx[1].y < vtx[3].y )
305  {
306  j = 1;
307  fprintf(stdout,"3 < 0 %lf smaller than %lf \n", vtx[3].y, vtx[1].y);
308  }
309  else
310  {
311  j = 3;
312  fprintf(stdout,"0 < 3 %lf smaller than %lf \n", vtx[1].y, vtx[3].y);
313  }
314 
315  line(clean, vtx[j], vtx[(j+1)%4], Scalar(0,0,0), 2, cv::LINE_AA);
316  gradient = ( vtx[(j+1)%4].y - vtx[j].y) / (vtx[(j+1)%4].x - vtx[j].x);
317  intercept = ( vtx[j].y - (vtx[j].x *gradient) );
318 
319  lineDetails[0].gradient = gradient;
320  lineDetails[0].intercept = intercept;
321  }
322  }
323  return correctList;
324 }