Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
45
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.68 KB | None | 0 0
  1. /**
  2. ********************************************************************************
  3. *
  4. * @file panorama.cxx
  5. *
  6. * @brief A program using OpenCV to stitch images together.
  7. *
  8. * @version 1.0
  9. *
  10. * @date 27/02/2017
  11. *
  12. * @author Franck Vidal
  13. *
  14. *
  15. ********************************************************************************
  16. */
  17.  
  18.  
  19. //******************************************************************************
  20. // Includes
  21. //******************************************************************************
  22. #include <exception> // Header for catching exceptions
  23. #include <iostream> // Header to display text in the console
  24. #include <sstream> // Header to create stings using a stream
  25. #include <vector>
  26. #include <opencv2/opencv.hpp> // Main OpenCV header
  27. #include <opencv2/features2d.hpp> // Header for the feature detectors
  28.  
  29.  
  30. //******************************************************************************
  31. // Namespaces
  32. //******************************************************************************
  33. using namespace std;
  34.  
  35.  
  36. //******************************************************************************
  37. // Global variables
  38. //******************************************************************************
  39. std::vector<cv::Mat> g_p_input_image_set;
  40.  
  41. //******************************************************************************
  42. // Function declaration
  43. //******************************************************************************
  44. cv::Mat autoCrop(const cv::Mat& anImage);
  45.  
  46.  
  47. //******************************************************************************
  48. // Implementation
  49. //******************************************************************************
  50.  
  51.  
  52. //-----------------------------
  53. int main(int argc, char** argv)
  54. //-----------------------------
  55. {
  56. try
  57. {
  58. //**********************************************************************
  59. // Process the command line arguments
  60. //**********************************************************************
  61.  
  62. std::string input_filename_1, input_filename_2, output_filename;
  63.  
  64. // Add your code here to check the number of command line arguments
  65. // If invalid, throw an error
  66. if (argc != 4)
  67. {
  68. // Create an error message
  69. std::string error_message;
  70. error_message = "Usage: ";
  71. error_message += argv[0];
  72. error_message += " <input_image_1>";
  73. error_message += " <input_image_2>";
  74. error_message += " [output_image]";
  75.  
  76. // Throw an error
  77. throw error_message;
  78. }
  79.  
  80.  
  81. //**********************************************************************
  82. // Load the data
  83. //**********************************************************************
  84.  
  85. // Add your code here
  86. input_filename_1 = argv[1];
  87. input_filename_2 = argv[2];
  88. cv::Mat image1 = cv::imread(input_filename_1, CV_LOAD_IMAGE_COLOR);
  89. cv::Mat image2 = cv::imread(input_filename_2, CV_LOAD_IMAGE_COLOR);
  90. g_p_input_image_set.push_back(image1);
  91. g_p_input_image_set.push_back(image2);
  92.  
  93.  
  94. // If either image didn't load, throw error
  95. if (g_p_input_image_set.size() != 2) {
  96. std::string error_message;
  97. error_message = "Could not open or find the images \"";
  98. error_message += input_filename_1;
  99. error_message += "\" \"";
  100. error_message += input_filename_2;
  101. error_message += "\".";
  102. // Throw an error
  103. throw error_message;
  104. }
  105.  
  106.  
  107.  
  108. //**********************************************************************
  109. // Display every image
  110. //**********************************************************************
  111.  
  112. // Add your code here
  113. cv::namedWindow(input_filename_1, cv::WINDOW_AUTOSIZE);
  114. cv::namedWindow(input_filename_2, cv::WINDOW_AUTOSIZE);
  115.  
  116. cv::imshow(input_filename_1, image1);
  117. cv::imshow(input_filename_2, image2);
  118. //**********************************************************************
  119. // Find features
  120. //**********************************************************************
  121.  
  122. // Add your code here
  123. cv::Mat total_image = g_p_input_image_set[0];
  124. cv::Mat current_image = g_p_input_image_set[1];
  125.  
  126. // Create a feature detector
  127. cv::Ptr<cv::FeatureDetector> p_feature_detector;
  128. p_feature_detector = cv::ORB::create();
  129.  
  130. // Detect the keypoints
  131. std::vector<cv::KeyPoint> p_total_image_keypoint_set;
  132. std::vector<cv::KeyPoint> p_current_image_keypoint_set;
  133. p_feature_detector->detect(total_image, p_total_image_keypoint_set);
  134. p_feature_detector->detect(current_image, p_current_image_keypoint_set);
  135.  
  136. //**********************************************************************
  137. // Describe/Extract features
  138. //**********************************************************************
  139.  
  140. // Add your code here
  141. // Calculate descriptors (feature vectors)
  142. cv::Ptr<cv::DescriptorExtractor> p_feature_extractor;
  143. p_feature_extractor = cv::ORB::create();
  144.  
  145. // The descriptors
  146. cv::Mat total_image_descriptors;
  147. cv::Mat current_image_descriptors;
  148. // Extract the features corresponding to the keypoints and the pictures
  149. p_feature_extractor->compute(total_image, p_total_image_keypoint_set, total_image_descriptors);
  150. p_feature_extractor->compute(current_image, p_current_image_keypoint_set, current_image_descriptors);
  151.  
  152.  
  153. //**********************************************************************
  154. // Match the features
  155. //**********************************************************************
  156.  
  157. // Add your code here
  158. // Match the features
  159. cv::Ptr<cv::DescriptorMatcher> p_feature_matcher;
  160. p_feature_matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
  161. std::vector< cv::DMatch > p_match_set;
  162. p_feature_matcher->match(total_image_descriptors, current_image_descriptors, p_match_set);
  163.  
  164.  
  165.  
  166.  
  167. //**********************************************************************
  168. // Compute some basic statitics (e.g. min, max) to filter the matches
  169. //**********************************************************************
  170. double min_distance(DBL_MAX);
  171. double max_distance(-DBL_MAX);
  172.  
  173. // Add your code here
  174. for (int i = 0; i < total_image_descriptors.rows; i++)
  175. {
  176. double dist = p_match_set[i].distance;
  177. if (dist < min_distance) min_distance = dist;
  178. if (dist > max_distance) max_distance = dist;
  179. }
  180.  
  181.  
  182.  
  183.  
  184. //**********************************************************************
  185. // Only use "good" matches (i.e. whose distance is less than 8 * min_distance)
  186. //**********************************************************************
  187.  
  188. std::vector<cv::DMatch> p_good_match_set;
  189. for (std::vector< cv::DMatch >::const_iterator ite(p_match_set.begin());
  190. ite != p_match_set.end();
  191. ++ite)
  192. {
  193. if (ite->distance < 8 * min_distance)
  194. {
  195. p_good_match_set.push_back(*ite);
  196. }
  197. }
  198.  
  199.  
  200.  
  201.  
  202. //**********************************************************************
  203. // Get the 2D points in the key points from the good matches
  204. //**********************************************************************
  205.  
  206. // Add your code here
  207. // Store the 2D points in the keypoint lists from the good matches
  208. std::vector<cv::Point2f> p_total_image_point_set;
  209. std::vector<cv::Point2f> p_current_image_point_set;
  210.  
  211. // Look at each good match
  212. for (std::vector< cv::DMatch >::const_iterator ite(p_good_match_set.begin()); ite != p_good_match_set.end(); ++ite)
  213. {
  214. // Get the keypoints from the good match
  215. cv::KeyPoint total_image_keypoint(p_total_image_keypoint_set[ite->queryIdx]);
  216. cv::KeyPoint current_image_keypoint(p_current_image_keypoint_set[ite->trainIdx]);
  217. // Add the corresponding 2D points
  218. p_total_image_point_set.push_back(total_image_keypoint.pt);
  219. p_current_image_point_set.push_back(current_image_keypoint.pt);
  220. }
  221.  
  222.  
  223. //**********************************************************************
  224. // Find the Homography Matrix
  225. //**********************************************************************
  226.  
  227. // Add your code here
  228. // Find the Homography Matrix
  229. cv::Mat homography_matrix(cv::findHomography(p_total_image_point_set, p_current_image_point_set, CV_RANSAC));
  230.  
  231.  
  232. //**********************************************************************
  233. // Use the Homography Matrix to warp the images
  234. //**********************************************************************
  235. cv::Mat output;
  236.  
  237. // Add your code here
  238. // Use the Homography Matrix to warp the images
  239. cv::warpPerspective(total_image, output, homography_matrix, cv::Size(total_image.cols + current_image.cols, total_image.rows + 1));
  240. cv::Mat half(output(cv::Rect(0, 0, current_image.cols, current_image.rows)));
  241. current_image.copyTo(half);
  242. cv::imshow("Result", output);
  243.  
  244.  
  245. //**********************************************************************
  246. // Remove black edges
  247. //**********************************************************************
  248. output = autoCrop(output);
  249. cv::imshow("autoCrop", output);
  250.  
  251. // Write the output
  252. cv::imwrite(argv[argc - 1], output);
  253.  
  254. // Wait
  255. cv::waitKey(0);
  256. }
  257. // An error occured
  258. catch (const std::exception& error)
  259. {
  260. // Display an error message in the console
  261. cerr << error.what() << endl;
  262. }
  263. catch (const std::string& error)
  264. {
  265. // Display an error message in the console
  266. cerr << error << endl;
  267. }
  268. catch (const char* error)
  269. {
  270. // Display an error message in the console
  271. cerr << error << endl;
  272. }
  273.  
  274. // Exit the program
  275. return 0;
  276. }
  277.  
  278.  
  279. //--------------------------------------
  280. cv::Mat autoCrop(const cv::Mat& anImage)
  281. //--------------------------------------
  282. {
  283. // Convert to grey scale
  284. cv::Mat grey_image;
  285. cv::cvtColor(anImage, grey_image, cv::COLOR_BGR2GRAY);
  286.  
  287. // Convert to binary
  288. cv::Mat binary_image;
  289. cv::threshold(grey_image, binary_image, 1, 255, cv::THRESH_BINARY);
  290.  
  291. // Find contours
  292. std::vector<std::vector<cv::Point> > p_contour_set;
  293. std::vector<cv::Vec4i> p_hierarchy_set;
  294.  
  295. cv::findContours(binary_image, p_contour_set, p_hierarchy_set, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
  296. cv::Rect bounding_rectangle(cv::boundingRect(p_contour_set.front()));
  297.  
  298. // Crop the input image using the bounding rectangle
  299. cv::Mat output(anImage(bounding_rectangle));
  300.  
  301. return output;
  302. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement