WaferBuild.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #ifndef _EXPORTING
  2. #define _EXPORTING
  3. #endif
  4. #include "WaferRebuild.h"
  5. #include "ArithPmd.h"
  6. WaferRebuild::WaferRebuild()
  7. {
  8. arith_pmd = new ArithPmd();
  9. }
  10. WaferRebuild::~WaferRebuild()
  11. {
  12. if (arith_pmd != nullptr)
  13. {
  14. delete arith_pmd;
  15. arith_pmd = nullptr;
  16. }
  17. }
  18. std::tuple<int, std::string> WaferRebuild::initParam(const nlohmann::json& param)
  19. {
  20. try
  21. {
  22. int retcode = arith_pmd->Initlization(param);
  23. return std::make_tuple(0, "sucess");
  24. }
  25. catch (const std::exception& e)
  26. {
  27. return std::make_tuple(-1, e.what());
  28. }
  29. }
  30. std::tuple<int, std::string> WaferRebuild::calcCloud(const std::vector<std::shared_ptr<infra::Image>>& image_list, std::shared_ptr<infra::CloudPoint<double>>& cloud_points, int32_t camera_index)
  31. {
  32. try
  33. {
  34. if (!cloud_points) {
  35. throw std::runtime_error("Error: cloud_points is nullptr!");
  36. }
  37. std::vector<Eigen::MatrixXf> img_pats;
  38. std::vector<cv::Mat> gray_images;
  39. img_pats.resize(image_list.size());
  40. for (int i = 0; i < image_list.size(); ++i) {
  41. int type = (image_list[i]->type() == -1) ? CV_8UC1 : CV_8UC3; // 假设 -1 是灰度图,其他都是三通道图像
  42. cv::Mat mat;
  43. cv::Mat grayMat;
  44. if (type == CV_8UC1) {
  45. grayMat = cv::Mat(arith_pmd->img_size.height, arith_pmd->img_size.width, type, image_list[i]->data());
  46. gray_images.push_back(grayMat);
  47. }
  48. else {
  49. mat = cv::Mat(arith_pmd->img_size.height, arith_pmd->img_size.width, type, image_list[i]->data());
  50. cv::cvtColor(mat, grayMat, cv::COLOR_BGR2GRAY);
  51. gray_images.push_back(grayMat);
  52. }
  53. // cv::cv2eigen(grayMat, img_pats[i]);
  54. }
  55. std::vector<cv::Mat> gray_temp{ gray_images[gray_images.size() - 4], gray_images[gray_images.size() - 3], gray_images[gray_images.size() - 2], gray_images[gray_images.size() - 1] };
  56. for (int i = 0; i < gray_images.size(); ++i)
  57. {
  58. cv::Mat temp;
  59. if (camera_index == 0)
  60. {
  61. cv::bitwise_and(gray_images[i], gray_images[i], temp, arith_pmd->mask0);
  62. }
  63. else if (camera_index == 1)
  64. {
  65. cv::bitwise_and(gray_images[i], gray_images[i], temp, arith_pmd->mask1);
  66. }
  67. else if (camera_index == 2)
  68. {
  69. cv::bitwise_and(gray_images[i], gray_images[i], temp, arith_pmd->mask2);
  70. }
  71. else if (camera_index == 3)
  72. {
  73. cv::bitwise_and(gray_images[i], gray_images[i], temp, arith_pmd->mask3);
  74. }
  75. // cv::bitwise_and(gray_images[i], gray_images[i], temp, arith_pmd->mask);
  76. cv::imwrite("temp.bmp", temp);
  77. cv::cv2eigen(temp, img_pats[i]);
  78. }
  79. int retcode0 = arith_pmd->Preprocess(gray_temp, 500, camera_index);
  80. MatrixXfR pcl;
  81. int retcode = arith_pmd->Predict(img_pats, pcl, camera_index);
  82. // std::vector<infra::Point3d<float>> points;
  83. // 预留足够空间
  84. int numPoints = pcl.cols();
  85. cloud_points->cloud_point.resize(numPoints);
  86. // cloud_points->cloud_point.reserve(numPoints);
  87. // cloud_points.reserve(numPoints);
  88. // 遍历每一个点
  89. for (int i = 0; i < numPoints; ++i) {
  90. // 创建一个新的 Point3d 对象并添加到 vector
  91. infra::Point3d<double> point = infra::Point3d<double>(
  92. pcl(0, i), // X 坐标
  93. pcl(1, i), // Y 坐标 m
  94. pcl(2, i) // Z 坐标
  95. );
  96. cloud_points->cloud_point[i] = point;
  97. }
  98. save_matrix_as_ply(pcl, "surface.ply");
  99. return std::make_tuple(0, "sucess");
  100. }
  101. catch (const std::exception& e) {
  102. return std::make_tuple(-1, e.what());
  103. }
  104. }
  105. pcl::PointCloud<pcl::PointXYZ> convertToPCLPointCloud(const std::shared_ptr<infra::CloudPoint<double>>& cloud_points) {
  106. pcl::PointCloud<pcl::PointXYZ> cloud;
  107. if (!cloud_points) {
  108. std::cerr << "Error: Input cloud_points is nullptr." << std::endl;
  109. return cloud;
  110. }
  111. // Resize the PCL PointCloud to the size of cloud_points
  112. cloud.points.resize(cloud_points->size());
  113. // Convert each point from infra::CloudPoint<double> to pcl::PointXYZ
  114. for (size_t i = 0; i < cloud_points->size(); ++i) {
  115. const infra::Point3d<double>& point = cloud_points->cloud_point[i];
  116. cloud.points[i].x = static_cast<float>(point.x);
  117. cloud.points[i].y = static_cast<float>(point.y);
  118. cloud.points[i].z = static_cast<float>(point.z);
  119. }
  120. return cloud;
  121. }
  122. static std::shared_ptr<infra::CloudPoint<double>> convertToInfraCloudPoint(const pcl::PointCloud<pcl::PointXYZ>& cloud) {
  123. // Create a new infra::CloudPoint<double> object
  124. auto cloud_points = std::make_shared<infra::CloudPoint<double>>();
  125. // Resize the cloud_points->cloud_point vector to the size of cloud
  126. cloud_points->cloud_point.resize(cloud.points.size());
  127. // Convert each pcl::PointXYZ point to infra::Point3d<double> and store in cloud_points
  128. for (size_t i = 0; i < cloud.points.size(); ++i) {
  129. cloud_points->cloud_point[i].x = static_cast<double>(cloud.points[i].x);
  130. cloud_points->cloud_point[i].y = static_cast<double>(cloud.points[i].y);
  131. cloud_points->cloud_point[i].z = static_cast<double>(cloud.points[i].z);
  132. }
  133. return cloud_points;
  134. }
  135. std::tuple<int, std::string> WaferRebuild::mergeCloud(const std::map<int32_t, std::shared_ptr<infra::CloudPoint<double>>>& cloud_points_list,
  136. std::shared_ptr<infra::CloudPoint<double>>& cloud_points)
  137. {
  138. try
  139. {
  140. int error_code = 0;
  141. std::string error_message = "Success";
  142. pcl::PointCloud<pcl::PointXYZ> cloud_output;
  143. auto it = cloud_points_list.begin();
  144. if (it == cloud_points_list.end()) {
  145. error_code = -1;
  146. error_message = "Error: Input cloud_points_list is empty.";
  147. return std::make_tuple(error_code, error_message);
  148. }
  149. cloud_output = convertToPCLPointCloud(it->second);
  150. ++it;
  151. // Merge each subsequent cloud in the list
  152. while (it != cloud_points_list.end()) {
  153. pcl::PointCloud<pcl::PointXYZ> cloud_to_merge = convertToPCLPointCloud(it->second);
  154. // Call Stitch function to merge cloud_output and cloud_to_merge
  155. int stitch_result = arith_pmd->Stitch(cloud_output, cloud_to_merge, cloud_output, it->first);
  156. if (stitch_result != 0) {
  157. error_code = stitch_result;
  158. error_message = "Error: Stitching failed for camera index " + std::to_string(it->first);
  159. break;
  160. }
  161. ++it;
  162. }
  163. cloud_points = convertToInfraCloudPoint(cloud_output);
  164. return std::make_tuple(error_code, error_message);
  165. }
  166. catch (const std::exception& e) {
  167. return std::make_tuple(-1, e.what());
  168. }
  169. }
  170. static infra::Point3d<double> calculateCentroid(const pcl::PointCloud<pcl::PointXYZ>& pcl_cloud) {
  171. infra::Point3d<double> centroid;
  172. // Create an Eigen vector to store the centroid
  173. Eigen::Vector4f pcl_centroid;
  174. // Compute centroid using PCL function
  175. pcl::compute3DCentroid(pcl_cloud, pcl_centroid);
  176. // Convert the centroid from Eigen vector to infra::Point3d<double>
  177. centroid.x = pcl_centroid[0];
  178. centroid.y = pcl_centroid[1];
  179. centroid.z = pcl_centroid[2];
  180. return centroid;
  181. }
  182. std::tuple<int, std::string> WaferRebuild::warpage(const std::shared_ptr<infra::CloudPoint<double>>& cloud_points, int32_t filterMM, nlohmann::json& result)
  183. {
  184. try {
  185. if (!cloud_points) {
  186. throw std::runtime_error("Input cloud_points is nullptr.");
  187. }
  188. // Convert infra::CloudPoint<double> to pcl::PointCloud<pcl::PointXYZ>
  189. pcl::PointCloud<pcl::PointXYZ> pcl_cloud = convertToPCLPointCloud(cloud_points);
  190. // Calculate centroid (assuming centroid calculation is implemented in math_tool.h)
  191. infra::Point3d<double> centroid = calculateCentroid(pcl_cloud); // Example function, replace with actual implementation
  192. // Define x and y axes
  193. infra::Point3d<double> axis_x(1.0, 0.0, 0.0); // Assuming x-axis direction
  194. infra::Point3d<double> axis_y(0.0, 1.0, 0.0); // Assuming y-axis direction
  195. // Calculate heights and populate result JSON
  196. for (auto& axis : { "x", "y" }) {
  197. std::vector<double> heights;
  198. double bow = 0.0;
  199. double warpage = 0.0;
  200. infra::Point3d<double> axis_vector = (axis == "x") ? axis_x : axis_y;
  201. // Calculate heights and populate heights vector
  202. for (size_t i = 0; i < pcl_cloud.points.size(); ++i) {
  203. infra::Point3d<double>& point = cloud_points->cloud_point[i];
  204. double height = point.x * axis_vector.x + point.y * axis_vector.y + point.z * axis_vector.z;
  205. heights.push_back(height);
  206. }
  207. // Calculate bow (average height)
  208. if (!heights.empty()) {
  209. bow = std::accumulate(heights.begin(), heights.end(), 0.0) / heights.size();
  210. }
  211. // Calculate warpage (standard deviation of heights)
  212. if (heights.size() > 1) {
  213. double sum_sq_diff = std::inner_product(heights.begin(), heights.end(), heights.begin(), 0.0);
  214. double mean = bow;
  215. double variance = sum_sq_diff / heights.size() - mean * mean;
  216. warpage = std::sqrt(variance);
  217. }
  218. // Fill JSON result
  219. result[axis]["height"] = heights;
  220. result[axis]["bow"] = bow;
  221. result[axis]["warpage"] = warpage;
  222. }
  223. /*
  224. // Calculate max bow and max warpage
  225. double max_bow = 0.0;
  226. double max_warpage = 0.0;
  227. double angle_max_bow = 0.0;
  228. double angle_max_warpage = 0.0;
  229. // Calculate max_bow and max_warpage values
  230. // (example calculation, replace with actual implementation)
  231. // Assume you have functions to find maximum bow and warpage and their angles
  232. max_bow = calculateMaxBow(result);
  233. max_warpage = calculateMaxWarpage(result);
  234. angle_max_bow = calculateAngleMaxBow(result);
  235. angle_max_warpage = calculateAngleMaxWarpage(result);
  236. // Fill max bow and max warpage in JSON result
  237. result["max_bow"]["angle"] = angle_max_bow;
  238. result["max_bow"]["height"] = result[angle_max_bow]["height"];
  239. result["max_bow"]["max_bow"] = max_bow;
  240. result["max_warpage"]["angle"] = angle_max_warpage;
  241. result["max_warpage"]["height"] = result[angle_max_warpage]["height"];
  242. result["max_warpage"]["max_warpage"] = max_warpage;
  243. */
  244. return std::make_tuple(0, "Success");
  245. }
  246. catch (const std::exception& e) {
  247. return std::make_tuple(-1, e.what());
  248. }
  249. }