瀏覽代碼

profile dump

boyska 7 年之前
父節點
當前提交
0f344bd8ad
共有 1 個文件被更改,包括 125 次插入12 次删除
  1. 125 12
      lines.cpp

+ 125 - 12
lines.cpp

@@ -1,5 +1,8 @@
 #include<cmath>
 #include<algorithm>
+#include<unistd.h>
+#include<fstream>
+#include<iomanip>
 
 #ifdef HAS_OPENCV3
 #include <opencv2/core.hpp> //Any OPENCV3 code
@@ -22,18 +25,103 @@ auto BROWN = cv::Scalar(90,100,60);
 auto BLACK = cv::Scalar(0,0,0);
 auto YELLOW = cv::Scalar(20,200,200);
 
+void usage(char* program, std::ostream &buf) {
+	buf << "Usage: " << program << "[options] IMAGE-INPUT" << std::endl;
+	buf << "Identify the image as a book in perspective, get deperspectivized content" << std::endl;
+	buf << std::endl;
+	buf << "Options:" << std::endl;
+	buf << "  -p     PROFILE     Save the transformation matrix in PROFILE" << std::endl;
+	buf << "  -l     LEFTPAGE    Save the left page in LEFTPAGE" << std::endl;
+	buf << "  -r     RIGHTPAGE   Save the right page in RIGHTPAGE" << std::endl;
+	buf << "  -h     HELP        Show this help and exit" << std::endl;
+}
+
+class Options
+{
+	public:
+		char *left;
+		char *right;
+		char *profile;
+		char *input;
+		Options();
+		Options(int argc, char*argv[]);
+		bool parse(int argc, char*argv[]);
+		~Options();
+};
+Options::Options()
+{
+	left = right = profile = input = NULL;
+}
+Options::~Options()
+{
+	if(left == NULL) {
+		free(left);
+	}
+	if(right == NULL) {
+		free(right);
+	}
+	if(profile == NULL) {
+		free(profile);
+	}
+	//input doesn't need to be free-d: it points to argv[argc-1]
+}
+Options::Options(int argc, char *argv[])
+{
+	left = right = profile = input = NULL;
+	parse(argc, argv);
+}
+
+/* Options::parse  parse arguments, return true if help is requested */
+bool Options::parse(int argc, char *argv[])
+{
+	int c;
+	while((c=getopt(argc, argv, "p:l:r:h")) != -1)
+	{
+		switch(c)
+		{
+			case 'l':
+				left = strdup(optarg);
+				break;
+			case 'r':
+				right = strdup(optarg);
+				break;
+			case 'p':
+				profile = strdup(optarg);
+				break;
+			case 'h':
+				return true;
+				break;
+			default:
+				throw std::runtime_error("Parsing error: invalid argument");
+		}
+	}
+	if(optind >= argc) {
+		std::cerr << "Error: " << argv[0] << " needs an argument" << std::endl;
+		throw std::runtime_error("Parsing error: argument needed");
+	}
+	input = argv[optind++];
+	if(optind < argc) {
+		std::cerr << "Error: too many arguments supplied" << std::endl;
+		throw std::runtime_error("Parsing error: too many arguments");
+	}
+	return false;
+}
 
 int main(int argc, char *argv[])
 {
-	char const *fname = "files/masckera.png";
-	if( 1<argc )
-		fname = argv[1];
-	if( 3<argc) {
-		std::cerr << "Too many arguments" << std::endl;
+	Options args;
+	try{
+		if(args.parse(argc, argv)) {
+			usage(argv[0], std::cout);
+			return EXIT_SUCCESS;
+		}
+	} catch(std::runtime_error) {
+		usage(argv[0], std::cerr);
 		return EXIT_FAILURE;
 	}
+
 	cv::Mat img;
-	img=cv::imread(fname,CV_LOAD_IMAGE_GRAYSCALE);
+	img=cv::imread(args.input,CV_LOAD_IMAGE_GRAYSCALE);
 	if( img.empty() ) {
 		std::cerr << "Error opening image, aborting" << std::endl;
 		return EXIT_FAILURE;
@@ -76,7 +164,7 @@ int main(int argc, char *argv[])
 	corn_4 = hull[(maxdistances[1]+1)%hull.size()];
 
 #ifdef _DEBUG
-	img = cv::imread(fname,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
+	img = cv::imread(args.input,CV_LOAD_IMAGE_COLOR); // uncomment to this to display image with colors
 	std::cout << "Maxdist1:" << maxdistances[0] << " " << corn_1 << corn_2 << std::endl;
 	std::cout << "Maxdist2:" << maxdistances[1] << " " << corn_3 << corn_4 << std::endl;
 	cv::namedWindow("win", CV_GUI_NORMAL);
@@ -138,9 +226,28 @@ int main(int argc, char *argv[])
 	img = cv::imread(args.input,CV_LOAD_IMAGE_COLOR);
 	for(int i=0; i < 2; i++) {
 		trasf[i] = cv::getPerspectiveTransform(trapezoid[i], outsizes);
+		assert(9==trasf[i].total()); // 3x3
 		cv::warpPerspective(img, rect[i], trasf[i], cv::Size(xsize, ysize));
 	}
 
+	if(args.profile) {
+		// format: each line is a tab-delimited 3x3 transformation matrix (as get by getPerspectiveTransform)
+		//    first three elements is the first line, etc
+		std::ofstream profilebuf;
+		profilebuf.open(args.profile);
+		for(int t=0; t<2; t++) {
+			for(int i=0; i<3; i++) {
+				double* row= trasf[t].ptr<double>(i);
+				for(int j=0; j < 3; j++) {
+					profilebuf << std::fixed << std::setprecision(16);
+					profilebuf << row[j] << "\t"; //yes, there's a trailing tab
+				}
+			}
+			profilebuf << std::endl;
+		}
+		profilebuf.close();
+	}
+
 #ifdef _DEBUG
 	cv::line(img, corn_1, middle1, MAGENTA, dotwidth>>3);
 	cv::line(img, corn_2, middle1, MAGENTA, dotwidth>>3);
@@ -158,13 +265,19 @@ int main(int argc, char *argv[])
 			break;
 	}
 #endif
-	if(2<argc) {
-		std::vector<int> params;
+
+
+	//TODO: distinguish left and right
+	std::vector<int> params;
+	if(args.left || args.right) {
 		params.push_back(CV_IMWRITE_PNG_COMPRESSION);
 		params.push_back(9);
-		Mat dst;
-		img.convertTo(dst, CV_8UC3);
-		cv::imwrite(argv[2], dst, params);
+		if(args.left) {
+			cv::imwrite(args.left, rect[0], params);
+		}
+		if(args.right) {
+			cv::imwrite(args.right, rect[1], params);
+		}
 	}
 
 	return EXIT_SUCCESS;