|
@@ -7,6 +7,10 @@
|
|
|
#include <opencv2/core/core.hpp> //Any Opencv2 code
|
|
|
#endif
|
|
|
#include"lines.h"
|
|
|
+using namespace cv;
|
|
|
+
|
|
|
+#define likely(x) __builtin_expect(!!(x), 1)
|
|
|
+#define unlikely(x) __builtin_expect(!!(x), 0)
|
|
|
|
|
|
// all those colors are still visible on b/w (the first component is not so low)
|
|
|
auto WHITE = cv::Scalar(255,255,255);
|
|
@@ -76,15 +80,15 @@ bool similar_fit(cv::Point a, cv::Point b, cv::Point newpoint, float tolerance_d
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
-/* TODO: bool similar_fit(std::vector<cv::Point> group, cv::Point newpoint) {
|
|
|
- * TODO: such a prototype is better because it can do a fit on the group
|
|
|
- * instead of just taking the two sides
|
|
|
- */
|
|
|
+bool similar_fit(std::vector<cv::Point> group, cv::Point newpoint) {
|
|
|
+ // TODO: it should perform a fit instead of just taking first and last
|
|
|
+ assert(group.size()>=2);
|
|
|
+ return similar_fit(group[0], group[group.size()-1], newpoint);
|
|
|
+}
|
|
|
|
|
|
/* simplify_hull will group all the points of the hull in groups that fit
|
|
|
* each group is a "line"
|
|
|
*/
|
|
|
-
|
|
|
std::vector<std::vector<cv::Point>>
|
|
|
simplify_hull(std::vector<cv::Point> hull) {
|
|
|
return simplify_hull( hull, 0 );
|
|
@@ -120,6 +124,46 @@ simplify_hull(std::vector<cv::Point> hull, double mindistance) {
|
|
|
return pointgroups;
|
|
|
}
|
|
|
|
|
|
+/* find_longest_line: similar to simplify_hull, except it just returns the longest line.
|
|
|
+ * you must not expect to find the whole line in the returned vector
|
|
|
+ * just use the first and last point in it
|
|
|
+ * arg hull: the whole convex hull
|
|
|
+ * arg begin: index of the array to start from
|
|
|
+ * arg end: index of the array to end. It can be lower than start, in which case
|
|
|
+ * the hull is used "circularly"
|
|
|
+ */
|
|
|
+std::vector<cv::Point> //two points, actually
|
|
|
+find_longest_line(std::vector<cv::Point> hull, unsigned begin, unsigned end) //the hull can be open
|
|
|
+{
|
|
|
+ std::vector<cv::Point> bestline, thisline;
|
|
|
+ int bestdistance = 0;
|
|
|
+ thisline.push_back(hull[begin++]);
|
|
|
+ thisline.push_back(hull[(begin++)%hull.size()]);
|
|
|
+ for(unsigned i=begin; i!=end; i++)
|
|
|
+ {
|
|
|
+ if(unlikely(i==hull.size()))
|
|
|
+ i=0;
|
|
|
+ if(similar_fit(thisline, hull[i])) {
|
|
|
+ thisline.push_back(hull[i]);
|
|
|
+ } else { // considering if the just-finished line is the best
|
|
|
+ if(dist(thisline[0],thisline[thisline.size()-1])>bestdistance) {
|
|
|
+ bestline = thisline;
|
|
|
+ bestdistance = dist(thisline[0],thisline[thisline.size()-1]);
|
|
|
+ }
|
|
|
+ thisline.clear();
|
|
|
+ assert(bestline.size()>=2);
|
|
|
+ thisline.push_back(hull[(i-1)%hull.size()]);
|
|
|
+ thisline.push_back(hull[i]);
|
|
|
+ };
|
|
|
+ }
|
|
|
+ if(bestline.size()==0) { // this is the case only when the first line is the best line
|
|
|
+ assert(0==bestdistance);
|
|
|
+ bestline = thisline;
|
|
|
+ }
|
|
|
+ assert(bestline.size()>=2);
|
|
|
+ return bestline;
|
|
|
+}
|
|
|
+
|
|
|
int main(int argc, char *argv[])
|
|
|
{
|
|
|
char const *fname = "files/masckera.png";
|
|
@@ -162,42 +206,40 @@ int main(int argc, char *argv[])
|
|
|
std::vector<cv::Point> hull;
|
|
|
cv::convexHull(cv::Mat(contour),hull,false);
|
|
|
|
|
|
+ //these are the "horizontal" lines
|
|
|
int *maxdistances = max2_distance(hull);
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
//img = cv::imread(fname,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
|
|
|
- std::cout << "Maxdist1: " << hull[maxdistances[0]] << hull[(maxdistances[0]+1)%hull.size()] << std::endl;
|
|
|
- std::cout << "Maxdist2: " << hull[maxdistances[1]] << hull[(maxdistances[1]+1)%hull.size()] << std::endl;
|
|
|
- cv::circle(img,hull[maxdistances[0]],dotwidth,WHITE,-1);
|
|
|
- cv::circle(img,hull[(maxdistances[0]+1)%hull.size()],dotwidth,WHITE,-1);
|
|
|
- cv::circle(img,hull[maxdistances[1]],dotwidth>>1,WHITE,-1);
|
|
|
- cv::circle(img,hull[(maxdistances[1]+1)%hull.size()],dotwidth>>1,WHITE,-1);
|
|
|
- // cv::namedWindow("win", CV_GUI_NORMAL);
|
|
|
+ std::cout << "Maxdist1:" << maxdistances[0] << " " << hull[maxdistances[0]] << hull[(maxdistances[0]+1)%hull.size()] << std::endl;
|
|
|
+ std::cout << "Maxdist2:" << maxdistances[1] << " " << hull[maxdistances[1]] << hull[(maxdistances[1]+1)%hull.size()] << std::endl;
|
|
|
+ cv::circle(img,hull[maxdistances[0]],dotwidth>>2,BROWN,2);
|
|
|
+ cv::circle(img,hull[(maxdistances[0]+1)%hull.size()],dotwidth>>2,BROWN,2);
|
|
|
+ cv::circle(img,hull[maxdistances[1]],dotwidth>>2,BROWN,2);
|
|
|
+ cv::circle(img,hull[(maxdistances[1]+1)%hull.size()],dotwidth>>2,BROWN,2);
|
|
|
+ cv::namedWindow("win", CV_GUI_NORMAL);
|
|
|
// cv::imshow("4 corners",img);
|
|
|
// cv::waitKey(0);
|
|
|
#endif
|
|
|
|
|
|
- auto simplifiedHull = simplify_hull(hull, dist(
|
|
|
- hull[maxdistances[0]],
|
|
|
- hull[(maxdistances[0]+1)%hull.size()]) / 5
|
|
|
- );
|
|
|
+ std::vector<std::vector<cv::Point>> verticals;
|
|
|
+ verticals.push_back(find_longest_line(hull, (maxdistances[0]+1)%hull.size(), maxdistances[1]));
|
|
|
+ verticals.push_back(find_longest_line(hull, (maxdistances[1]+1)%hull.size(), maxdistances[0]));
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
//img = cv::imread(fname,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
|
|
|
auto color = MAGENTA;
|
|
|
- for( auto group: simplifiedHull )
|
|
|
+ for( auto line: verticals )
|
|
|
{
|
|
|
- color = (color==BLUE) ? MAGENTA : BLUE; //flip color at every group
|
|
|
- cv::Point p1 = group[0];
|
|
|
- cv::Point p2 = group[group.size()-1];
|
|
|
- cv::line(img, p1, p2, color, dotwidth>>2);
|
|
|
- std::cout << "simplified line: ";
|
|
|
- for(cv::Point p: group)
|
|
|
+ color = (color==BLUE) ? MAGENTA : BLUE; //flip color for the two lines
|
|
|
+ cv::Point p1 = line[0];
|
|
|
+ cv::Point p2 = line[line.size()-1];
|
|
|
+ cv::line(img, p1, p2, color, dotwidth>>4);
|
|
|
+ std::cout << "vertical: " << line[0] << line[line.size()-1] << std::endl;
|
|
|
+ for(cv::Point p: line)
|
|
|
{
|
|
|
- cv::circle(img,p,dotwidth>>2,color,dotwidth>>3);
|
|
|
- std::cout << "(" << p.x << "," << p.y << ") ";
|
|
|
+ cv::circle(img,p,dotwidth>>3,color,-1);
|
|
|
}
|
|
|
- std::cout << ";" << std::endl;
|
|
|
}
|
|
|
cv::imshow("win",img);
|
|
|
while(1)
|
|
@@ -207,6 +249,8 @@ int main(int argc, char *argv[])
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+
|
|
|
+
|
|
|
return EXIT_SUCCESS;
|
|
|
}
|
|
|
|