getLines.cpp
Go to the documentation of this file.
00001 #include <opencv2/imgproc/imgproc.hpp>
00002 #include <opencv2/highgui/highgui.hpp>
00003 #include <boost/lexical_cast.hpp>
00004 #include <ros/package.h>
00005 #include <algorithm>
00006 #include <stdio.h>
00007 #include <string>
00008 #include <iostream>
00009 #include <stdlib.h>
00010 #include <fstream>
00011 #include <utility>
00012 #include <assert.h>
00013 #include <portrait_painter/getLines.h>
00014 
00015 using namespace cv;
00016 using namespace std;
00017 using namespace portrait_painter;
00018 
00019 GetLines::GetLines() {
00020         _size = -1;
00021         params.turdSize = 2;
00022         params.maxDistance = 1000;
00023         params.maxDistanceBetweenPoints = 3;
00024         params.maxDistanceBetweenLines = 1000;
00025         params.minDistanceWithinVector = 2;
00026         params.minLineSize = 1;
00027         params.invert = true;
00028         params.splitFactor = 7;
00029         params.threshold = 5;
00030 }
00031 
00032 vector<pair<CvPoint2D32f, vector<CvPoint2D32f> > > GetLines::getLines(
00033                 string& image) {
00034         assert(image.length() > 0);
00035         vector<string> file;
00036         src = imread(image, CV_LOAD_IMAGE_GRAYSCALE);
00037 
00038         if (params.maxDistanceBetweenLines == 1000)
00039                 params.maxDistanceBetweenLines = src.rows / 70;
00040         if (params.maxDistance == 1000)
00041                 params.maxDistance = src.rows / 200;
00042         //thinContours(image);
00043         readInFile(image, &file);
00044         // Now analyse the string vector
00045         // The first two characters describe what to do next
00046 
00047         CvPoint2D32f absolute, absoluteTmp;
00048         bool penUp = true;
00049         bool newLine = false;
00050         size_t numOfPoints = 0;
00051         vector<CvPoint2D32f> relative;
00052         for (size_t i = 0; i < file.size(); i++) {
00053                 // Get the hpglCommand and erase it from the line
00054                 if (file[i][0] == '\n')
00055                         file[i].erase(0, 1);
00056                 string hpglCode = file[i].substr(0, 2);
00057                 file[i].erase(0, 2);
00058 
00059                 if (hpglCode == "PM") // Polygon Mode
00060                                 {
00061                 } else if (hpglCode == "PA") // abs. Coords
00062                                 {
00063                         // New line. Set the absolute point to the coords.
00064                         int comma = file[i].find(",");
00065                         absoluteTmp.x = atoi(file[i].substr(0, comma).c_str()) - 1;
00066                         absoluteTmp.y = src.rows
00067                                         - (atoi(file[i].substr(comma + 1).c_str()) - 1);
00068 
00069                         newLine = true;
00070                         penUp = false;
00071                 } else if (hpglCode == "PD") // Pen down
00072                                 {
00073                         // Obviously the pen is down.
00074                         penUp = false;
00075                         // If it is really a new line, push into vector and set
00076                         // the new absolute point
00077                         if (!relative.empty() && newLine) {
00078                                 numOfPoints += relative.size();
00079                                 lines.push_back(make_pair(absolute, relative));
00080                                 relative.clear();
00081                         }
00082                         if (newLine) {
00083                                 relative.clear();
00084                                 absolute = absoluteTmp;
00085                                 newLine = false;
00086                         }
00087                         // Get all the relative Coords.
00088                         for (size_t j = 0; j < file[i].size(); j++) {
00089                                 // Therefore find the first two commas.
00090                                 // The first is separating x and y and the second
00091                                 // is the end of y. After storing them go on starting
00092                                 // from the second comma.
00093                                 size_t commaFirst = file[i].find(",", j + 1);
00094                                 if (commaFirst == string::npos)
00095                                         break;
00096                                 size_t commaSecond = file[i].find(",", commaFirst + 1);
00097                                 string points = file[i].substr(j, commaSecond - j);
00098                                 CvPoint2D32f point;
00099                                 point.x = atoi(points.substr(0, commaFirst - j).c_str());
00100                                 point.y = -atoi(points.substr(commaFirst + 1 - j).c_str());
00101                                 relative.push_back(point);
00102                                 absoluteTmp.x += point.x;
00103                                 absoluteTmp.y += point.y;
00104                                 if (commaSecond == string::npos)
00105                                         break;
00106                                 j = commaSecond;
00107                         }
00108                 } else if (hpglCode == "PU") // Pen up
00109                                 {
00110                         penUp = true;
00111                 } else if (hpglCode == "PR") // rel. Coords
00112                                 {
00113                         // Be sure something should be done.
00114                         if (!penUp)
00115                                 continue;
00116                         // Now get the relative Coords.
00117                         // If they are smaller than the threshold, don't
00118                         // put the pen up, just go on.
00119                         size_t comma = file[i].find(",");
00120                         CvPoint2D32f point;
00121                         point.x = atoi(file[i].substr(0, comma).c_str());
00122                         point.y = -atoi(file[i].substr(comma + 1).c_str());
00123                         newLine = true;
00124                         absoluteTmp.x += point.x;
00125                         absoluteTmp.y += point.y;
00126                         penUp = false;
00127                 } else if (hpglCode == "EP") // Edge Polygon
00128                                 {
00129                 } else if (hpglCode == "FP") // Fill Polygon
00130                                 {
00131                 } else if (hpglCode == "IN") // Initialize
00132                                 {
00133                 }
00134         }
00135         // Since the last vector is not pushed back, so it manually.
00136         lines.push_back(make_pair(absolute, relative));
00137         minimize();
00138         return lines;
00139 }
00140 
00141 void GetLines::minimize() {
00142         size_t numOfLines = lines.size();
00143         size_t numOfPoints = 0;
00144         // Count number of points.
00145         for (size_t i = 0; i < lines.size(); i++)
00146                 numOfPoints += lines[i].second.size();
00147 
00148         cout << "Num of points before minimizing: " << numOfPoints << endl;
00149         cout << "Num of lines before minimizing: " << numOfLines << endl;
00150 
00151         // Now minimize the number of lines.
00152         eraseDoubleLines(params.maxDistanceBetweenPoints);
00153         connectLines(params.maxDistanceBetweenLines, lines);
00154         minimizeLines(params.maxDistance, params.threshold);
00155 
00156         numOfLines = lines.size();
00157         numOfPoints = 0;
00158         // Count number of points.
00159         for (size_t i = 0; i < lines.size(); i++)
00160                 numOfPoints += lines[i].second.size();
00161 
00162         cout << "Num of lines after minimizing: " << lines.size() << endl;
00163         cout << "Num of points after minimizing: " << numOfPoints << endl;
00164 }
00165 
00166 void GetLines::minimizeLines(size_t maxDistance, size_t threshold) {
00167         // If lines are very similiar, just say it is one line.
00168         for (size_t i = 0; i < lines.size(); i++) {
00169                 // Initialize.
00170                 CvPoint2D32f newPoint;
00171                 newPoint.x = 0;
00172                 newPoint.y = 0;
00173                 unsigned int num = 0;
00174                 int start = -1;
00175                 for (size_t j = 0; j < lines[i].second.size(); j++) {
00176                         CvPoint2D32f actPoint = lines[i].second[j];
00177                         size_t distance = sqrt(
00178                                         newPoint.x * newPoint.x + newPoint.y * newPoint.y);
00179                         if (distance <= maxDistance
00180                                         && num <= lines[i].second.size() / threshold) {
00181                                 if (start == -1)
00182                                         start = j;
00183                                 num++;
00184                                 newPoint.x += actPoint.x;
00185                                 newPoint.y += actPoint.y;
00186                         } else if (start != -1) {
00187                                 // Erase unnessecary points and add the new relative point.
00188                                 lines[i].second.erase(lines[i].second.begin() + start,
00189                                                 lines[i].second.begin() + j);
00190                                 lines[i].second.insert(lines[i].second.begin() + start + 1,
00191                                                 newPoint);
00192                                 // Initialize again.
00193                                 j = start + 1;
00194                                 start = -1;
00195                                 newPoint.x = 0;
00196                                 newPoint.y = 0;
00197                         }
00198                         // Don't forgot to do the last minimization.
00199                         if (start != -1 && j == lines[i].second.size() - 1) {
00200                                 lines[i].second.erase(lines[i].second.begin() + start,
00201                                                 lines[i].second.begin() + j);
00202                                 lines[i].second.insert(lines[i].second.begin() + start + 1,
00203                                                 newPoint);
00204                         }
00205                 }
00206         }
00207 }
00208 
00209 void GetLines::eraseNearestNeighbours(size_t maxDistance, size_t distance,
00210                 vector<CvPoint2D32f>& absolutePoints) {
00211         // In this array (in)valid points are going to be stored. At the end every
00212         // point, who is not valid is going to be erased.
00213         size_t size = absolutePoints.size();
00214         bool validPoints[size];
00215         // Initialize with true.
00216         for (size_t i = 0; i < size; i++)
00217                 validPoints[i] = true;
00218 
00219         for (size_t j = 0; j < absolutePoints.size(); j++) {
00220                 // Points which are marked as erased are not going to be analysed.
00221                 if (!validPoints[j])
00222                         continue;
00223                 // Now eliminate neighbors with a radius of at least distance.
00224                 for (size_t end = j + distance; end < absolutePoints.size(); end++) {
00225                         if (!validPoints[end])
00226                                 continue;
00227                         CvPoint2D32f diff;
00228                         diff.x = (absolutePoints[end].x - absolutePoints[j].x);
00229                         diff.y = (absolutePoints[end].y - absolutePoints[j].y);
00230                         float distanceX = sqrt(diff.x * diff.x + diff.y * diff.y);
00231                         if (distanceX <= maxDistance)
00232                                 validPoints[end] = false;
00233                 }
00234 
00235                 for (size_t begin = 0;
00236                                 begin < j - distance && begin < absolutePoints.size();
00237                                 begin++) {
00238                         if (!validPoints[begin])
00239                                 continue;
00240                         CvPoint2D32f diff;
00241                         diff.x = (absolutePoints[begin].x - absolutePoints[j].x);
00242                         diff.y = (absolutePoints[begin].y - absolutePoints[j].y);
00243                         float distanceX = sqrt(diff.x * diff.x + diff.y * diff.y);
00244                         if (distanceX <= maxDistance)
00245                                 validPoints[begin] = false;
00246                 }
00247         }
00248 
00249         // Temporary vector to avoid position problems when "deleting".
00250         vector<CvPoint2D32f> tmp = absolutePoints;
00251         absolutePoints.clear();
00252         for (size_t i = 0; i < tmp.size(); i++)
00253                 if (validPoints[i])
00254                         absolutePoints.push_back(tmp[i]);
00255 
00256         // Now look for every point if there are points near to him. If not erase him.
00257         for (size_t i = 0; i < absolutePoints.size() && absolutePoints.size() > 10;
00258                         i++) {
00259                 bool neighbourFound = false;
00260                 for (size_t j = 0; j < absolutePoints.size(); j++) {
00261                         if (j == i)
00262                                 continue;
00263                         CvPoint2D32f diff;
00264                         diff.x = (absolutePoints[i].x - absolutePoints[j].x);
00265                         diff.y = (absolutePoints[i].y - absolutePoints[j].y);
00266                         float distance = sqrt(diff.x * diff.x + diff.y * diff.y);
00267                         if (distance <= maxDistance * 10) {
00268                                 neighbourFound = true;
00269                                 break;
00270                         }
00271                 }
00272                 if (!neighbourFound)
00273                         absolutePoints.erase(absolutePoints.begin() + i);
00274         }
00275 }
00276 
00277 void GetLines::eraseDoubleLines(size_t maxDistance) {
00278         for (size_t i = 0; i < lines.size(); i++) {
00279                 // Make all points absolute.
00280                 vector<CvPoint2D32f> absolutePoints;
00281                 CvPoint2D32f absolute;
00282                 absolute.x = lines[i].first.x;
00283                 absolute.y = lines[i].first.y;
00284                 absolutePoints.push_back(absolute);
00285                 int distance = 0;
00286                 for (size_t j = 0; j < lines[i].second.size(); j++) {
00287                         absolute.x += lines[i].second[j].x;
00288                         absolute.y += lines[i].second[j].y;
00289                         absolutePoints.push_back(absolute);
00290                         CvPoint2D32f diff;
00291                         diff.x = absolutePoints[j + 1].x - absolutePoints[j].x;
00292                         diff.y = absolutePoints[j + 1].y - absolutePoints[j].y;
00293                         distance += sqrt(diff.x * diff.x + diff.y * diff.y);
00294                 }
00295                 // Erase double line.
00296                 eraseNearestNeighbours(maxDistance, params.minDistanceWithinVector,
00297                                 absolutePoints);
00298 
00299                 // Compute the line length.
00300                 lines[i].second.clear();
00301                 lines[i].first = absolutePoints[0];
00302                 float lineLength = 0;
00303                 for (size_t j = 1; j < absolutePoints.size(); j++) {
00304                         CvPoint2D32f newRelPoint;
00305                         newRelPoint.x = absolutePoints[j].x - absolutePoints[j - 1].x;
00306                         newRelPoint.y = absolutePoints[j].y - absolutePoints[j - 1].y;
00307                         float length = sqrt(
00308                                         newRelPoint.x * newRelPoint.x
00309                                                         + newRelPoint.y * newRelPoint.y);
00310                         lineLength += length;
00311                 }
00312 
00313                 // These lines are going to be splitted because of a too big distance. Store their
00314                 // indices to look, if there is a shorter distance and connect them.
00315                 vector<int> linesToConnect;
00316 
00317                 // Make lines relative again, push them into the lines vector and erase too big sublines.
00318                 for (size_t j = 1; j < absolutePoints.size(); j++) {
00319                         CvPoint2D32f newRelPoint;
00320                         newRelPoint.x = absolutePoints[j].x - absolutePoints[j - 1].x;
00321                         newRelPoint.y = absolutePoints[j].y - absolutePoints[j - 1].y;
00322                         // Erase to big sublines.
00323                         if (sqrt(
00324                                         newRelPoint.x * newRelPoint.x
00325                                                         + newRelPoint.y * newRelPoint.y)
00326                                         > (lineLength * params.splitFactor) / absolutePoints.size()
00327                                         && absolutePoints.size() > 5) {
00328                                 // Mark it.
00329                                 linesToConnect.push_back(i);
00330                                 CvPoint2D32f absolute = absolutePoints[j];
00331                                 vector<CvPoint2D32f> relative;
00332                                 i++;
00333                                 lines.insert(lines.begin() + i, make_pair(absolute, relative));
00334                                 continue;
00335                         }
00336                         lines[i].second.push_back(newRelPoint);
00337                 }
00338 
00339                 // Now try to connect the splitted lines.
00340                 for (size_t j = 0; j < linesToConnect.size(); j++) {
00341                         int position = linesToConnect[linesToConnect.size() - 1 - j];
00342                         vector<pair<CvPoint2D32f, vector<CvPoint2D32f> > > linesToConnectVec;
00343                         linesToConnectVec.push_back(lines[position]);
00344                         linesToConnectVec.push_back(lines[position + 1]);
00345                         vector<Lines> connectedLines = connectLines(maxDistance,
00346                                         linesToConnectVec);
00347                         // If a connection was possible.
00348                         if (linesToConnectVec.size() == 1) {
00349                                 lines[position] = linesToConnectVec[0];
00350                                 lines.erase(lines.begin() + position + 1);
00351                                 //j++;
00352                         }
00353                         // If no connection was possible.
00354                         // Unfortunately not working. Too many lines, which don't belong there.
00355                         /*else
00356                          {
00357                          CvPoint2D32f diff;
00358                          diff.x = connectedLines[1].start.x - connectedLines[0].end.x;
00359                          diff.y = connectedLines[1].start.y - connectedLines[0].end.y;
00360                          lines[position].second.push_back(diff);
00361                          for (size_t k = 0; k < connectedLines[1].relative.size(); k++)
00362                          lines[position].second.push_back(connectedLines[1].relative[k]);
00363                          lines.erase(lines.begin() + position + 1);
00364                          }*/
00365 
00366                 }
00367         }
00368 
00369         // Erase very small lines. Probably better to do this depending on the line
00370         // length instead of its size.
00371         for (int i = lines.size() - 1; i >= 0; i--)
00372                 if (lines[i].second.size() <= params.minLineSize)
00373                         lines.erase(lines.begin() + i);
00374 }
00375 
00376 vector<GetLines::Lines> GetLines::connectLines(size_t maxDistance,
00377                 vector<pair<CvPoint2D32f, vector<CvPoint2D32f> > >& linesToConnect) {
00378         // Initialize Lines vector for analysing more simple.
00379         vector<Lines> connectedLines;
00380         for (size_t i = 0; i < linesToConnect.size(); i++) {
00381                 Lines act;
00382                 act.id = i;
00383                 act.start = linesToConnect[i].first;
00384                 act.end = linesToConnect[i].first;
00385                 for (size_t j = 0; j < linesToConnect[i].second.size(); j++) {
00386                         act.relative.push_back(linesToConnect[i].second[j]);
00387                         act.end.x += linesToConnect[i].second[j].x;
00388                         act.end.y += linesToConnect[i].second[j].y;
00389                 }
00390                 connectedLines.push_back(act);
00391         }
00392 
00393         // Append lines with less distance to each other
00394         for (size_t i = 0; i < connectedLines.size(); i++)
00395                 for (size_t j = 0; j < connectedLines.size(); j++) {
00396                         if (connectedLines[i].id == connectedLines[j].id)
00397                                 continue;
00398                         CvPoint2D32f diff;
00399 
00400                         // erase those lines with near starting / endpoint
00401                         diff.x = (connectedLines[i].start.x - connectedLines[j].end.x);
00402                         diff.y = (connectedLines[i].start.y - connectedLines[j].end.y);
00403                         float distance = sqrt(diff.x * diff.x + diff.y * diff.y);
00404                         if (distance <= maxDistance) {
00405                                 connectedLines[j].relative.push_back(diff);
00406                                 for (size_t k = 0; k < connectedLines[i].relative.size(); k++)
00407                                         connectedLines[j].relative.push_back(
00408                                                         connectedLines[i].relative[k]);
00409                                 connectedLines[j].end = connectedLines[i].end;
00410                                 connectedLines.erase(connectedLines.begin() + i);
00411                                 i = 0;
00412                                 break;
00413                         }
00414 
00415                         // erase those lines with near starting points
00416                         diff.x = (connectedLines[i].start.x - connectedLines[j].start.x);
00417                         diff.y = (connectedLines[i].start.y - connectedLines[j].start.y);
00418                         distance = sqrt(diff.x * diff.x + diff.y * diff.y);
00419                         if (distance <= maxDistance) {
00420                                 // Invert connectedLines[j]:
00421                                 // end == start, start == end, negate relatives
00422                                 Lines tmp;
00423                                 tmp.start = connectedLines[j].end;
00424                                 tmp.end = connectedLines[j].start;
00425                                 for (size_t k = 0; k < connectedLines[j].relative.size(); k++) {
00426                                         CvPoint2D32f newRelPoint =
00427                                                         connectedLines[j].relative[connectedLines[j].relative.size()
00428                                                                         - 1 - k];
00429                                         newRelPoint.x = -newRelPoint.x;
00430                                         newRelPoint.y = -newRelPoint.y;
00431                                         tmp.relative.push_back(newRelPoint);
00432                                 }
00433                                 connectedLines[j] = tmp;
00434                                 connectedLines[j].relative.push_back(diff);
00435                                 for (size_t k = 0; k < connectedLines[i].relative.size(); k++)
00436                                         connectedLines[j].relative.push_back(
00437                                                         connectedLines[i].relative[k]);
00438                                 connectedLines[j].end = connectedLines[i].end;
00439                                 connectedLines.erase(connectedLines.begin() + i);
00440                                 i = 0;
00441                                 break;
00442                         }
00443 
00444                         // erase those lines with near end points
00445                         diff.x = (connectedLines[i].end.x - connectedLines[j].end.x);
00446                         diff.y = (connectedLines[i].end.y - connectedLines[j].end.y);
00447                         distance = sqrt(diff.x * diff.x + diff.y * diff.y);
00448                         if (distance <= maxDistance) {
00449                                 // Invert connectedLines[i]:
00450                                 // end == start, start == end, negate relatives
00451                                 Lines tmp;
00452                                 tmp.start = connectedLines[i].end;
00453                                 tmp.end = connectedLines[i].start;
00454                                 for (size_t k = 0; k < connectedLines[i].relative.size(); k++) {
00455                                         CvPoint2D32f newRelPoint =
00456                                                         connectedLines[i].relative[connectedLines[i].relative.size()
00457                                                                         - 1 - k];
00458                                         newRelPoint.x = -newRelPoint.x;
00459                                         newRelPoint.y = -newRelPoint.y;
00460                                         tmp.relative.push_back(newRelPoint);
00461                                 }
00462                                 connectedLines[i] = tmp;
00463                                 connectedLines[j].relative.push_back(diff);
00464                                 for (size_t k = 0; k < connectedLines[i].relative.size(); k++)
00465                                         connectedLines[j].relative.push_back(
00466                                                         connectedLines[i].relative[k]);
00467                                 connectedLines[j].end = connectedLines[i].end;
00468                                 connectedLines.erase(connectedLines.begin() + i);
00469                                 i = 0;
00470                                 break;
00471                         }
00472                 }
00473 
00474         // Clear the vector and push in the new lines.
00475         linesToConnect.clear();
00476         for (size_t i = 0; i < connectedLines.size(); i++) {
00477                 linesToConnect.push_back(
00478                                 make_pair(connectedLines[i].start, connectedLines[i].relative));
00479         }
00480         return connectedLines;
00481 }
00482 
00483 void GetLines::readInFile(string& image, vector<string>* output) {
00484         // Look which format image has.
00485         size_t formatPos = image.find_last_of(".");
00486         string format = image.substr(formatPos + 1);
00487         image_name = image.substr(0, formatPos);
00488 
00489         // If it is not bmp, just convert it.
00490         // First convert it to pbm, since "convert" has problems with pngs directly
00491         // converting to bmp.
00492         if (format != "bmp") {
00493                 string command = "convert " + image + " " + image_name + ".pbm";
00494                 if (system(command.c_str())) {
00495                         cout << "Could not convert to pbm." << endl;
00496                         exit(1);
00497                 }
00498                 command = "convert " + image_name + ".pbm " + image_name + ".bmp";
00499                 if (system(command.c_str())) {
00500                         cout << "Could not convert to bmp." << endl;
00501                         exit(1);
00502                 }
00503         }
00504 
00505         // Now create the hpgl file.
00506         string pltfile = image_name + ".plt";
00507         string path = ros::package::getPath("portrait_painter") + "/bin/";
00508         string invert = "";
00509         if (params.invert)
00510                 invert = "-i ";
00511         string command = path + "potrace " + invert + "-a 1000 -n -b hpgl -u 1 -t "
00512                         + boost::lexical_cast<string>(params.turdSize) + " -o " + image_name
00513                         + ".plt " + image_name + ".bmp";
00514         if (system(command.c_str())) {
00515                 cout << "Could not execute potrace without an error." << endl;
00516                 exit(1);
00517         }
00518 
00519         // Read in the file.
00520         ifstream infile(pltfile.c_str());
00521         if (!infile.is_open()) {
00522                 cout << "Error: " << pltfile << " could not be opened." << endl;
00523                 exit(1);
00524         }
00525         while (!infile.eof()) {
00526                 string buff;
00527                 getline(infile, buff, ';');
00528                 output->push_back(buff);
00529         }
00530         return;
00531 }
00532 
00533 vector<pair<CvPoint2D32f, vector<CvPoint2D32f> > > GetLines::scaleTo(
00534                 size_t size, bool preserveRatio) {
00535         if (lines.size() == 0) {
00536                 cout
00537                                 << "There are no lines stored. Probably you forgot to compute them. Use getLines(string& image) first."
00538                                 << endl;
00539                 exit(1);
00540         }
00541         // Initialize
00542         size_t size_x = _size, size_y = _size;
00543         size_t offset_x = 0, offset_y = 0;
00544         if (_size == -1) {
00545                 size_x = src.cols;
00546                 size_y = src.rows;
00547 
00548                 // The robot is working with a quadratic szene, ... so make it quadratic.
00549                 if (src.cols >= src.rows && preserveRatio) {
00550                         _size = src.cols;
00551                         size_y = src.cols;
00552                         offset_y = src.cols - src.rows;
00553                 } else if (src.rows > src.cols && preserveRatio) {
00554                         offset_x = src.rows - src.cols;
00555                         _size = src.rows;
00556                         size_x = src.rows;
00557                 }
00558         }
00559 
00560         // Now compute the new points.
00561         for (size_t i = 0; i < lines.size(); i++) {
00562                 lines[i].first.x += floor(offset_x / 2.0);
00563                 lines[i].first.y += floor(offset_y / 2.0);
00564                 lines[i].first.x *= (size / (float) size_x);
00565                 lines[i].first.y *= (size / (float) size_y);
00566                 if (lines[i].first.x > size || lines[i].first.y > size)
00567                         cout << "Too high absolute value: " << lines[i].first.x << " "
00568                                         << lines[i].first.y << endl;
00569                 for (size_t j = 0; j < lines[i].second.size(); j++) {
00570                         lines[i].second[j].x *= (size / (float) size_x);
00571                         lines[i].second[j].y *= (size / (float) size_y);
00572                 }
00573         }
00574         _size = size;
00575         return lines;
00576 }
00577 
00578 void GetLines::drawLines() {
00579         if (lines.size() == 0) {
00580                 cout
00581                                 << "There are no lines stored. Probably you forgot to compute them. Use getLines(string& image) first."
00582                                 << endl;
00583                 exit(1);
00584         } else if (_size >= 0 && _size < 30) {
00585                 cout
00586                                 << "Your image has a size of "
00587                                 << _size
00588                                 << " pixels. Actually that's too small for OpenCV to draw the lines accurately. Use drawLines() after scaleTo(size_t size, bool preserveRatio)."
00589                                 << endl;
00590                 exit(1);
00591         }
00592 
00593         IplImage* out;
00594         if (_size == -1)
00595                 out = cvCreateImage(cvSize(src.cols, src.rows), IPL_DEPTH_8U, 3);
00596         else
00597                 out = cvCreateImage(cvSize(_size, _size), IPL_DEPTH_8U, 3);
00598         // Draw image by converting all points to absolute points.
00599         for (size_t i = 0; i < lines.size(); i++) {
00600                 CvPoint2D32f absolute, absoluteOld;
00601                 absolute.x = lines[i].first.x;
00602                 absolute.y = lines[i].first.y;
00603                 std::cerr << "Absolute Coordinates:" << absolute.x << " " << absolute.y
00604                                 << std::endl;
00605                 std::cerr << "Out Dimensions:" << out->width << " " << out->height
00606                                 << std::endl;
00607                 assert(absolute.x >= 0 && absolute.x < out->width);
00608                 assert(absolute.y >= 0 && absolute.y < out->height);
00609                 absoluteOld = absolute;
00610                 // Mark starting point.
00611                 //cvCircle (out, cvPointFrom32f(absoluteOld), 2, CV_RGB(0, 255, 255), 1);
00612                 // Draw lines.
00613                 for (size_t j = 0; j < lines[i].second.size(); j++) {
00614                         absoluteOld = absolute;
00615                         assert(absolute.x >= 0 && absolute.x < out->width);
00616                         assert(absolute.y >= 0 && absolute.y < out->height);
00617                         CvPoint2D32f rel = lines[i].second[j];
00618                         absolute.x += rel.x;
00619                         absolute.y += rel.y;
00620                         cvLine(out, cvPointFrom32f(absoluteOld), cvPointFrom32f(absolute),
00621                                         CV_RGB(255,255,0), 1);
00622                 }
00623                 // Mark end point.
00624                 //cvCircle(out, cvPointFrom32f(absolute), 3, CV_RGB(255,0,0), 1);
00625         }
00626         cvSaveImage((image_name + "_lines.bmp").c_str(), out);
00627 }
00628 
00629 void GetLines::drawPR2(float percentualHeightOfImage) {
00630         if (percentualHeightOfImage < 0 || percentualHeightOfImage > 1) {
00631                 cout << "Percent not expected as \"k \%\", but as \"k/100\"." << endl;
00632                 exit(1);
00633         }
00634 
00635         // Initialize.
00636         size_t heightOfImage = _size, widthOfImage = _size;
00637         if (_size == -1) {
00638                 heightOfImage = src.rows;
00639                 widthOfImage = src.cols;
00640         }
00641 
00642         float height = heightOfImage * percentualHeightOfImage;
00643         float widthPerLetter = height / 1.5;
00644         float offsetBetweenLetters = widthPerLetter / 1.5;
00645         float diagonal = height / 20.0;
00646         float position_y = heightOfImage - height / 4.0;
00647         float position_x = widthOfImage - 4 * widthPerLetter
00648                         - 2 * offsetBetweenLetters;
00649         pair<CvPoint2D32f, vector<CvPoint2D32f> > letter_P, letter_R, letter_2;
00650 
00651         // Insert lines.
00652         // Letter P.
00653         letter_P.first = cvPoint2D32f(position_x, position_y);
00654         letter_P.second.push_back(cvPoint2D32f(0, -height));
00655         letter_P.second.push_back(cvPoint2D32f(widthPerLetter - 2 * diagonal, 0));
00656         letter_P.second.push_back(cvPoint2D32f(2 * diagonal, 2 * diagonal));
00657         letter_P.second.push_back(cvPoint2D32f(0, height / 3.0));
00658         int pos = letter_P.second.size() - 1;
00659         letter_P.second.push_back(cvPoint2D32f(-2 * diagonal, 2 * diagonal));
00660         letter_P.second.push_back(
00661                         cvPoint2D32f(-(widthPerLetter - 2 * diagonal), 0));
00662 
00663         // Letter R.
00664         letter_R.first = cvPoint2D32f(
00665                         position_x + widthPerLetter + offsetBetweenLetters, position_y);
00666         letter_R.second = letter_P.second;
00667         letter_R.second[pos] = cvPoint2D32f(0, height / 4.0);
00668         letter_R.second.push_back(
00669                         cvPoint2D32f(widthPerLetter,
00670                                         height - letter_R.second[pos].y - 4 * diagonal));
00671 
00672         // Letter 2.
00673         diagonal = widthPerLetter / 25.0;
00674         letter_2.first = cvPoint2D32f(
00675                         position_x + widthPerLetter * 2 + 2 * offsetBetweenLetters,
00676                         position_y - height + 15 * diagonal);
00677         letter_2.second.push_back(cvPoint2D32f(0, -5 * diagonal));
00678         letter_2.second.push_back(cvPoint2D32f(1 * diagonal, -4 * diagonal));
00679         letter_2.second.push_back(cvPoint2D32f(2 * diagonal, -3 * diagonal));
00680         letter_2.second.push_back(cvPoint2D32f(3 * diagonal, -2 * diagonal));
00681         letter_2.second.push_back(cvPoint2D32f(4 * diagonal, -1 * diagonal));
00682         letter_2.second.push_back(cvPoint2D32f(5 * diagonal, 0));
00683         letter_2.second.push_back(cvPoint2D32f(4 * diagonal, 1 * diagonal));
00684         letter_2.second.push_back(cvPoint2D32f(3 * diagonal, 2 * diagonal));
00685         letter_2.second.push_back(cvPoint2D32f(2 * diagonal, 3 * diagonal));
00686         letter_2.second.push_back(cvPoint2D32f(1 * diagonal, 4 * diagonal));
00687         letter_2.second.push_back(cvPoint2D32f(0, 5 * diagonal));
00688         letter_2.second.push_back(cvPoint2D32f(-1 * diagonal, 4 * diagonal));
00689         letter_2.second.push_back(
00690                         cvPoint2D32f(-widthPerLetter + diagonal,
00691                                         height - 19 * diagonal - height / 10.0));
00692         letter_2.second.push_back(cvPoint2D32f(0, height / 10.0));
00693         letter_2.second.push_back(cvPoint2D32f(widthPerLetter, 0));
00694 
00695         lines.push_back(letter_P);
00696         lines.push_back(letter_R);
00697         lines.push_back(letter_2);
00698         // Set more points, so PR2 is really going to draw the whole letters.
00699         // Little improvement, but not much.
00700         for (size_t i = lines.size() - 4; i < lines.size(); i++) {
00701                 for (size_t j = 0; j < lines[i].second.size(); j++) {
00702                         // Split each line from point to point into numOfSplits parts.
00703                         CvPoint2D32f divided;
00704                         size_t numOfSplits = 3;
00705                         divided = cvPoint2D32f(lines[i].second[j].x / (float) numOfSplits,
00706                                         lines[i].second[j].y / (float) numOfSplits);
00707                         lines[i].second[j] = divided;
00708                         for (size_t k = 0; k < numOfSplits - 1; k++)
00709                                 lines[i].second.insert(lines[i].second.begin() + j, divided);
00710                         j += numOfSplits - 1;
00711                 }
00712         }
00713 }
00714 
00715 void GetLines::setPotraceParams(size_t turdSize, bool invert) {
00716         params.turdSize = turdSize;
00717         params.invert = invert;
00718 }
00719 
00720 void GetLines::setErasingParams(size_t maxDistanceBetweenPoints,
00721                 size_t minDistanceWithinVector, float splitFactor, size_t minLineSize) {
00722         params.maxDistanceBetweenPoints = maxDistanceBetweenPoints;
00723         params.minDistanceWithinVector = minDistanceWithinVector;
00724         params.splitFactor = splitFactor;
00725         params.minLineSize = minLineSize;
00726 }
00727 
00728 void GetLines::setConnectingParams(size_t maxDistanceBetweenLines) {
00729         params.maxDistanceBetweenLines = maxDistanceBetweenLines;
00730 }
00731 
00732 void GetLines::setMinimizeLinesParams(size_t maxDistance, size_t threshold) {
00733         params.maxDistance = maxDistance;
00734         params.threshold = threshold;
00735 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


portrait_painter
Author(s): Niklas Meinzer, Ina Baumgarten
autogenerated on Wed Dec 26 2012 16:00:43