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
00043 readInFile(image, &file);
00044
00045
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
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")
00060 {
00061 } else if (hpglCode == "PA")
00062 {
00063
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")
00072 {
00073
00074 penUp = false;
00075
00076
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
00088 for (size_t j = 0; j < file[i].size(); j++) {
00089
00090
00091
00092
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")
00109 {
00110 penUp = true;
00111 } else if (hpglCode == "PR")
00112 {
00113
00114 if (!penUp)
00115 continue;
00116
00117
00118
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")
00128 {
00129 } else if (hpglCode == "FP")
00130 {
00131 } else if (hpglCode == "IN")
00132 {
00133 }
00134 }
00135
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
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
00152 eraseDoubleLines(params.maxDistanceBetweenPoints);
00153 connectLines(params.maxDistanceBetweenLines, lines);
00154 minimizeLines(params.maxDistance, params.threshold);
00155
00156 numOfLines = lines.size();
00157 numOfPoints = 0;
00158
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
00168 for (size_t i = 0; i < lines.size(); i++) {
00169
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
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
00193 j = start + 1;
00194 start = -1;
00195 newPoint.x = 0;
00196 newPoint.y = 0;
00197 }
00198
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
00212
00213 size_t size = absolutePoints.size();
00214 bool validPoints[size];
00215
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
00221 if (!validPoints[j])
00222 continue;
00223
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
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
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
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
00296 eraseNearestNeighbours(maxDistance, params.minDistanceWithinVector,
00297 absolutePoints);
00298
00299
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
00314
00315 vector<int> linesToConnect;
00316
00317
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
00323 if (sqrt(
00324 newRelPoint.x * newRelPoint.x
00325 + newRelPoint.y * newRelPoint.y)
00326 > (lineLength * params.splitFactor) / absolutePoints.size()
00327 && absolutePoints.size() > 5) {
00328
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
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
00348 if (linesToConnectVec.size() == 1) {
00349 lines[position] = linesToConnectVec[0];
00350 lines.erase(lines.begin() + position + 1);
00351
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 }
00367 }
00368
00369
00370
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
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
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
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
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
00421
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
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
00450
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
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
00485 size_t formatPos = image.find_last_of(".");
00486 string format = image.substr(formatPos + 1);
00487 image_name = image.substr(0, formatPos);
00488
00489
00490
00491
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
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
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
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
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
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
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
00611
00612
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
00624
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
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
00652
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
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
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
00699
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
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 }