grab_occlusion.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. #include <sstream>
  2. #include <opencv2\highgui\highgui.hpp>
  3. #include "grab_occlusion.h"
  4. #include "utils.h"
  5. namespace graft_cv {
  6. CStemResultInfos::CStemResultInfos(double seedling_dist,
  7. int holes_number,
  8. double x_min,
  9. double x_max,
  10. double z_min,
  11. double z_max,
  12. double z_cent,
  13. std::string pcd_id,
  14. CGcvLogger*pLog)
  15. : m_pLogger(pLog)
  16. , m_seedling_dist(seedling_dist)
  17. , m_holes_number(holes_number)
  18. , m_xmin(x_min)
  19. , m_xmax(x_max)
  20. , m_zmin(z_min)
  21. , m_zmax(z_max)
  22. , m_zcent(z_cent)
  23. , m_pcdId(pcd_id)
  24. , m_max_size(50)
  25. {
  26. gen_root_centers();
  27. }
  28. CStemResultInfos::~CStemResultInfos()
  29. {}
  30. void CStemResultInfos::append(
  31. CStemResult& sr
  32. )
  33. {
  34. m_infos.insert(m_infos.begin(), sr);
  35. if (m_infos.size() > m_max_size) {
  36. m_infos.pop_back();
  37. }
  38. //m_append_counter += 1;
  39. //每次都更新
  40. _update_root_centers(sr);
  41. //if (m_append_counter % 10 == 0) {
  42. // //定期写入数据
  43. // _update_root_centers();
  44. // write_root_centers(m_json_filename);
  45. //}
  46. }
  47. void CStemResultInfos::clear()
  48. {
  49. m_infos.clear();
  50. }
  51. void CStemResultInfos::get_root_centers(
  52. std::vector<CStemResult>&rst
  53. )
  54. {
  55. rst.clear();
  56. for (auto& sr : m_root_centers) {
  57. rst.push_back(sr);
  58. }
  59. }
  60. void CStemResultInfos::_update_root_centers(CStemResult& sr) {
  61. //直接在m_root_centers中找到最接近的中心,如果小于指定距离,更新m_root_centers
  62. double d1 = m_seedling_dist / 4.0;
  63. double d_min = 1.0e6;
  64. int min_root_idx = -1;
  65. for (int i = 0; i < m_root_centers.size(); ++i) {
  66. double dist = m_root_centers.at(i).calcluate_distance(sr);
  67. if (dist < d_min) {
  68. d_min = dist;
  69. min_root_idx = i;
  70. }
  71. }
  72. if (d_min < d1 && min_root_idx >= 0) {
  73. //更新指定中心
  74. double mu_x, mu_y, mu_z;
  75. CStemResult& min_root = m_root_centers.at(min_root_idx);
  76. mu_x = min_root.root_x;
  77. if (min_root.root_count == 0) {
  78. mu_y = sr.root_y;
  79. mu_z = sr.root_z;
  80. }
  81. else {
  82. mu_y = (min_root.root_y * min_root.root_count +
  83. sr.root_y * sr.root_count) / (double)(min_root.root_count + sr.root_count);
  84. mu_z = (min_root.root_z * min_root.root_count +
  85. sr.root_z * sr.root_count) / (double)(min_root.root_count + sr.root_count);
  86. }
  87. min_root.root_x = mu_x;
  88. min_root.root_y = mu_y;
  89. min_root.root_z = mu_z;
  90. min_root.root_count += sr.root_count;
  91. }
  92. }
  93. void CStemResultInfos::gen_root_centers()
  94. {
  95. //根据 m_seedling_dist, m_holes_number, m_xmin, m_xmax生成初始的穴位中心
  96. //以m_xmin, m_xmax的中间点为中心,分别找到间隔m_seedling_dist的m_holes_number个穴位中心
  97. //初始的z设成-1,等待更新赋值
  98. double x_mid = 0.5 * (m_xmin + m_xmax);
  99. double holes_mid = 0.5 * (m_holes_number - 1) * m_seedling_dist;
  100. double x0 = x_mid - holes_mid;
  101. double z_mid = m_zcent;
  102. m_root_centers.clear();
  103. for (int i=0; i<m_holes_number; ++i) {
  104. double x = x0 + i * m_seedling_dist;
  105. double y = 0;
  106. double z = z_mid;
  107. int size = 0;
  108. int count = 0;
  109. CStemResult sr = CStemResult(x, y, z, size, std::string(""), count);
  110. m_root_centers.push_back(sr);
  111. }
  112. }
  113. CSeedlingStatus::CSeedlingStatus(
  114. int dtype,
  115. double step,
  116. double x_min,
  117. double x_max,
  118. double pc_mean_dist,
  119. CGcvLogger*pLog)
  120. : m_pLogger(pLog)
  121. , m_dtype(dtype)
  122. , m_bin_step(step)
  123. , m_xmin(x_min)
  124. , m_xmax(x_max)
  125. , m_record_cursor(-1)
  126. , m_global_cursor(-1)
  127. , m_max_size(50)
  128. , m_pc_mean_dist(pc_mean_dist)
  129. {
  130. int x0 = int(x_min);
  131. int x1 = int(x_max);
  132. m_hist_length = int((x1 - x0) / step);
  133. m_history_point_size = cv::Mat::zeros(m_max_size, 1, CV_32F);
  134. }
  135. CSeedlingStatus::~CSeedlingStatus()
  136. {}
  137. void CSeedlingStatus::set_x_centers(std::vector<double>&cx)
  138. {
  139. m_center_x.clear();
  140. for (auto&x : cx) {
  141. m_center_x.push_back(x);
  142. }
  143. std::sort(m_center_x.begin(), m_center_x.end());
  144. double seedling_distance = m_center_x.at(1) - m_center_x.at(0);
  145. m_idx_low.clear();
  146. m_idx_up.clear();
  147. for (int i = 0; i < m_center_x.size(); ++i) {
  148. int idx_low = int((m_center_x.at(i) - 0.5 * seedling_distance - m_xmin) / m_bin_step);
  149. int idx_up = int((m_center_x.at(i) + 0.5 * seedling_distance - m_xmin) / m_bin_step);
  150. m_idx_low.push_back(idx_low);
  151. m_idx_up.push_back(idx_up);
  152. }
  153. m_history_status = cv::Mat::zeros(m_max_size, m_center_x.size(), CV_8U);
  154. m_history_histogram = cv::Mat::zeros(m_max_size, m_center_x.size(), CV_32F);
  155. }
  156. void CSeedlingStatus::append_hist(
  157. std::vector<int>&xhist //input
  158. //std::vector<bool>&xstatus //output
  159. )
  160. {
  161. assert(xhist.size() == m_hist_length);
  162. std::vector<float>center_count;
  163. calculate_center_size(xhist, center_count);
  164. assert(center_count.size() == m_center_x.size());
  165. m_global_cursor++;
  166. if (m_record_cursor < m_max_size-1) {
  167. m_record_cursor++;
  168. float pc_size = 0.0;
  169. for (int i = 0; i < center_count.size(); ++i) {
  170. m_history_histogram.at<float>(m_record_cursor,i) = center_count.at(i);
  171. pc_size += center_count.at(i);
  172. }
  173. m_history_point_size.at<float>(m_record_cursor, 0) = pc_size;
  174. //get_status(xstatus);
  175. }
  176. else {
  177. //数据上移一行,数据放在最后一行
  178. for (int row = 0; row < m_history_histogram.rows - 1; ++row) {
  179. for (int col = 0; col < m_history_histogram.cols; ++col) {
  180. m_history_histogram.at<float>(row, col) = m_history_histogram.at<float>(row + 1, col);
  181. }
  182. }
  183. for (int row = 0; row < m_history_point_size.rows - 1; ++row) {
  184. m_history_point_size.at<float>(row, 0) = m_history_point_size.at<float>(row+1, 0);
  185. }
  186. float pc_size = 0.0;
  187. for (int i = 0; i < center_count.size(); ++i) {
  188. m_history_histogram.at<float>(m_history_histogram.rows - 1, i) = center_count.at(i);
  189. pc_size += center_count.at(i);
  190. }
  191. m_history_point_size.at<float>(m_history_point_size.rows - 1, 0) = pc_size;
  192. //get_status(xstatus);
  193. }
  194. }
  195. void CSeedlingStatus::calculate_center_size(std::vector<int>&xhist, std::vector<float>&x_count)
  196. {
  197. x_count.clear();
  198. for (int i = 0; i < m_center_x.size(); ++i) {
  199. int idx_low = m_idx_low.at(i);
  200. int idx_up = m_idx_up.at(i);
  201. float valid_pc_cnt = 0;
  202. for (int k = idx_low; k <= idx_up; ++k) {
  203. if (k < 0 || k >= xhist.size()) { continue; }
  204. valid_pc_cnt += xhist.at(k);
  205. }
  206. x_count.push_back(valid_pc_cnt);
  207. }
  208. }
  209. //void CSeedlingStatus::calculate_center_size(int cursor, std::vector<float>&x_count)
  210. //{
  211. // x_count.clear();
  212. // for (int i = 0; i < m_center_x.size(); ++i) {
  213. // int idx_low = m_idx_low.at(i);
  214. // int idx_up = m_idx_up.at(i);
  215. // float valid_pc_cnt = 0;
  216. // for (int k = idx_low; k <= idx_up; ++k) {
  217. // valid_pc_cnt += m_history_histogram.at<float>(cursor, i);
  218. // }
  219. // x_count.push_back(valid_pc_cnt);
  220. // }
  221. //}
  222. //void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
  223. //{
  224. // //根据历史信息评估:
  225. // // 1)位置上是否有苗
  226. // // 2)历史上是否已经取走苗
  227. // // 3)是否有新进的苗
  228. //
  229. // xstatus.clear();
  230. // xstatus.assign(m_center_x.size(), false);
  231. //
  232. // //1 如果没有记录输入,返回没有苗
  233. // if (m_record_cursor < 0) { return; }
  234. //
  235. // //2 如果是第一次,没有参考,用自身的分布阈值判断是否有苗(可能不准确,但没有其他办法)
  236. // //点云分布情况分析
  237. // // 每个bin的数量阈值设定m_bin_step宽度,至少有10毫米的点云,才认为有苗
  238. // float th_hist = m_bin_step * 10 / m_pc_mean_dist / m_pc_mean_dist;
  239. // if (m_record_cursor == 0) {
  240. // //std::vector<bool> hist_status;
  241. // //hist_status.assign(m_hist_length, false);
  242. // //for (int i = 0; i < m_hist_length; ++i) {
  243. // // if (m_history_histogram.at<float>(m_record_cursor, i) > th_hist) {
  244. // // hist_status.at(i) = true;
  245. // // }
  246. // //}
  247. // //for (int i = 0; i < m_center_x.size(); ++i) {
  248. // // int idx_low = m_idx_low.at(i);
  249. // // int idx_up = m_idx_up.at(i);
  250. // // int valid_bin_cnt = 0;
  251. // // for (int k = idx_low; k < idx_up; ++k) {
  252. // // if (hist_status.at(k)) { valid_bin_cnt++; }
  253. // // }
  254. // // double valid_ratio = (double)valid_bin_cnt / (double)(idx_up - idx_low);
  255. // // xstatus.at(i) = valid_ratio > 0.5;
  256. // //}
  257. // ////update m_history_status
  258. // //for (int i = 0; i < m_history_status.cols; ++i) {
  259. // // m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
  260. // //}
  261. // //return;
  262. //
  263. // std::vector<float> x_count;
  264. // calculate_center_size(m_record_cursor, x_count);
  265. // for (int i = 0; i < x_count.size(); ++i) {
  266. // int idx_low = m_idx_low.at(i);
  267. // int idx_up = m_idx_up.at(i);
  268. // xstatus.at(i) = x_count.at(i) > (idx_up - idx_low + 1) * th_hist;
  269. // }
  270. // //update m_history_status
  271. // for (int i = 0; i < m_history_status.cols; ++i) {
  272. // m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
  273. // }
  274. // return;
  275. // }
  276. //
  277. // //3 2次或更多,通过前后2次差分析苗取走的情况
  278. // //3.1 计算被取走的点云位置分布
  279. // std::vector<float>hist_diff;
  280. // hist_diff.assign(m_hist_length, 0.0);
  281. // float sum_dn = 0.0;
  282. // float sum_n = 0.0;
  283. // float diff_cnt = 0.0;
  284. // for (int i = 0; i < m_hist_length; ++i) {
  285. // diff_cnt = m_history_histogram.at<float>(m_record_cursor - 1, i) -
  286. // m_history_histogram.at<float>(m_record_cursor, i);
  287. // hist_diff.at(i) = diff_cnt;
  288. // sum_n += diff_cnt;
  289. // sum_dn += diff_cnt * i;
  290. // }
  291. // /*if (m_record_cursor < m_max_size) {
  292. // for (int i = 0; i < m_hist_length; ++i) {
  293. // diff_cnt = m_history_histogram.at<float>(m_record_cursor - 1, i) -
  294. // m_history_histogram.at<float>(m_record_cursor, i);
  295. // hist_diff.at(i) = diff_cnt;
  296. // sum_n += diff_cnt;
  297. // sum_dn += diff_cnt * i;
  298. // }
  299. // }
  300. // else {
  301. // for (int i = 0; i < m_hist_length; ++i) {
  302. // diff_cnt = m_history_histogram.at<float>(m_max_size - 2, i) -
  303. // m_history_histogram.at<float>(m_max_size - 1, i);
  304. // hist_diff.at(i) = diff_cnt;
  305. // sum_n += diff_cnt;
  306. // sum_dn += diff_cnt * i;
  307. // }
  308. //
  309. // }*/
  310. //
  311. // //3.2 统计增减点云的状态,区分点云增加,点云减小,点云没变化的部分
  312. // std::vector<int> hist_status_2d; //3种状态记录: -1取走,0没变化,1上苗
  313. // hist_status_2d.assign(m_hist_length, 0);
  314. // int add_cnt = 0;
  315. // int sub_cnt = 0;
  316. // for (int i = 0; i < m_hist_length; ++i) {
  317. // if (hist_diff.at(i) > th_hist) {
  318. // hist_status_2d.at(i) = -1;
  319. // sub_cnt += 1;
  320. // }
  321. // if (hist_diff.at(i) < -th_hist) {
  322. // hist_status_2d.at(i) = 1;
  323. // add_cnt += 1;
  324. // }
  325. // }
  326. //
  327. // //3.3 判断苗的整体情况
  328. // double seedling_distance = m_center_x.at(1) - m_center_x.at(0); //株间距离
  329. // double grid_one_seedling = seedling_distance / m_bin_step; //每穴位占histogram的桶数
  330. // //3.3.1进一排苗
  331. // if (add_cnt > grid_one_seedling*3.0) {
  332. // xstatus.assign(m_center_x.size(), true);
  333. // //update m_history_status
  334. // if (m_record_cursor == m_global_cursor) {
  335. // if (m_record_cursor < m_max_size) {
  336. // for (int i = 0; i < m_history_status.cols; ++i) {
  337. // m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
  338. // }
  339. // }
  340. // else {
  341. //
  342. // }
  343. // }
  344. // else {
  345. // //数据上移一行,数据放在最后一行
  346. // for (int row = 0; row < m_history_status.rows - 1; ++row) {
  347. // for (int col = 0; col < m_history_status.cols; ++col) {
  348. // m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
  349. // }
  350. // }
  351. // /*memcpy_s(m_history_status.data,
  352. // m_history_status.step[0] * (m_max_size - 1),
  353. // m_history_status.data + m_history_status.step[0],
  354. // m_history_status.step[0] * (m_max_size - 1));
  355. // */
  356. // for (int i = 0; i < m_history_status.cols; ++i) {
  357. // m_history_status.at<unsigned char>(m_max_size-1, i) = xstatus.at(i);
  358. // }
  359. // }
  360. // return;
  361. // }
  362. //
  363. // std::vector<size_t>sorted_idx;
  364. // std::vector<float>sub_seedling_score; //移出植株得分,记录每个穴位上点云变化得分
  365. // //3.3.2 变化很小,说明没有改变(没能成功抓走)
  366. // if (add_cnt + sub_cnt < 0.5 * grid_one_seedling) {
  367. // goto no_change;
  368. // }
  369. // //3.3.3 否则的话,就是抓走过一个苗
  370. // //找到被取走的苗的中心,然后根据dtype确定有苗的位置
  371. // //找覆盖范围最大的区域
  372. // double sub_cent_indx = sum_dn / sum_n; //计算改变范围的中心,目前没用到
  373. // sub_seedling_score.assign(m_center_x.size(), 0.0);
  374. // for (int idx = 0; idx < hist_status_2d.size(); ++idx) {
  375. // if (hist_status_2d.at(idx) >= 0) {
  376. // //这个histogram上没有移出,不统计, hist_status_2d的值域:-1取走,0没变化,1上苗
  377. // continue;
  378. // }
  379. // for (int i = 0; i < m_center_x.size(); ++i) {
  380. // int idx_low = m_idx_low.at(i);
  381. // int idx_up = m_idx_up.at(i);
  382. // if (idx >= idx_low && idx < idx_up) {
  383. // sub_seedling_score.at(i) += 1.0;
  384. // }
  385. // }
  386. // }
  387. // int sub_pos = -1;
  388. // sorted_idx = sort_indexes_e(sub_seedling_score, false);
  389. // for (auto& idx : sorted_idx) {
  390. // if (sub_seedling_score.at(idx) < 0.25 * grid_one_seedling) {
  391. // //如果改变量,不到穴位范围的一半,不认为是移走的
  392. // continue;
  393. // }
  394. // if (m_history_status.at<unsigned char>(m_record_cursor - 1, idx) == 0) {
  395. // //如果这个位置上一帧就没有苗,那判别也是错误的
  396. // continue;
  397. // }
  398. // sub_pos = idx;
  399. // break;//找到得分最高,并且满足条件的位置,就是被抓走的位置,跳出
  400. // }
  401. // if (sub_pos >= 0) {
  402. // xstatus.assign(m_center_x.size(), false);
  403. // int cursor = m_record_cursor-1;
  404. // for (int i = 0; i < m_history_status.cols; ++i) {
  405. // if (m_history_status.at<unsigned char>(cursor, i) == 1) {
  406. // xstatus.at(i) = true;
  407. // }
  408. // }
  409. // xstatus.at(sub_pos) = false;
  410. //
  411. // //update m_history_status
  412. // if (m_record_cursor == m_global_cursor) {
  413. // for (int i = 0; i < m_history_status.cols; ++i) {
  414. // m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
  415. // }
  416. // }
  417. // else{
  418. // //数据上移一行,数据放在最后一行
  419. // for (int row = 0; row < m_history_status.rows - 1; ++row) {
  420. // for (int col = 0; col < m_history_status.cols; ++col) {
  421. // m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
  422. // }
  423. // }
  424. // /*memcpy_s(m_history_status.data,
  425. // m_history_status.step[0] * (m_max_size - 1),
  426. // m_history_status.data + m_history_status.step[0],
  427. // m_history_status.step[0] * (m_max_size - 1));*/
  428. // for (int i = 0; i < m_history_status.cols; ++i) {
  429. // m_history_status.at<unsigned char>(m_max_size - 1, i) = xstatus.at(i);
  430. // }
  431. // }
  432. // return;
  433. // }
  434. // else {
  435. // //如果没有找到有效位置,按没有变化处理
  436. // goto no_change;
  437. // }
  438. //
  439. //no_change:
  440. // //没有改变,用上一次的结果
  441. // xstatus.assign(m_center_x.size(), true);
  442. // //update m_history_status
  443. // if (m_record_cursor == m_global_cursor) {
  444. // for (int i = 0; i < m_history_status.cols; ++i) {
  445. // m_history_status.at<unsigned char>(m_record_cursor, i) =
  446. // m_history_status.at<unsigned char>(m_record_cursor - 1, i);
  447. // if (m_history_status.at<unsigned char>(m_record_cursor - 1, i) == 0) {
  448. // xstatus.at(i) = false;
  449. // }
  450. // }
  451. // }
  452. // else{
  453. // //数据上移一行,数据放在最后一行
  454. // for (int row = 0; row < m_history_status.rows - 1; ++row) {
  455. // for (int col = 0; col < m_history_status.cols; ++col) {
  456. // m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
  457. // }
  458. // }
  459. // /*memcpy_s(m_history_status.data,
  460. // m_history_status.step[0] * (m_max_size - 1),
  461. // m_history_status.data + m_history_status.step[0],
  462. // m_history_status.step[0] * (m_max_size - 1));*/
  463. // for (int i = 0; i < m_history_status.cols; ++i) {
  464. // m_history_status.at<unsigned char>(m_max_size - 1, i) =
  465. // m_history_status.at<unsigned char>(m_max_size - 2, i);
  466. // if (m_history_status.at<unsigned char>(m_max_size - 2, i) == 0) {
  467. // xstatus.at(i) = false;
  468. // }
  469. // }
  470. // }
  471. //}
  472. int CSeedlingStatus::get_status(int& max_idx, float&max_change)
  473. {
  474. //根据历史信息评估:
  475. // 1)评估是否新上苗
  476. // 2)判断被取走的那个苗
  477. //状态 1 ---此次为新上苗, 0 无显著变化, -1 上一次取苗成功
  478. int status = 1;
  479. //1 如果没有记录输入,返回没有苗
  480. if (m_record_cursor <= 0) {
  481. return status;
  482. }
  483. float change_threshold = 500.0;//点云变化,是否有苗新加或取走的阈值
  484. float change_count = m_history_point_size.at<float>(m_record_cursor, 0) - m_history_point_size.at<float>(m_record_cursor - 1, 0);
  485. if (change_count > 2.0 * change_threshold) {
  486. status = 1;
  487. }
  488. else {
  489. if (change_count < -change_threshold) {
  490. status = -1;
  491. }
  492. else {
  493. status = 0;
  494. }
  495. }
  496. max_change = 0;
  497. max_idx = 0;
  498. for (int i = 0; i < m_history_histogram.cols; ++i) {
  499. float d = m_history_histogram.at<float>(m_record_cursor, i) - m_history_histogram.at<float>(m_record_cursor - 1, i);
  500. if (fabs(d) > fabs(max_change)) {
  501. max_change = d;
  502. max_idx = i;
  503. }
  504. }
  505. if (max_change < -change_threshold) {
  506. status = -1;
  507. }
  508. return status;
  509. }
  510. void CSeedlingStatus::real_result_update(
  511. std::vector<pcl::PointXYZ>& root, //识别到茎的根坐标
  512. std::vector<int>& stem_status //识别到茎的状态,1--有茎, 2--叶子遮挡
  513. )
  514. {
  515. m_stem_status.clear();
  516. m_stem_status.assign(m_center_x.size(), 0);
  517. for (int i = 0; i < root.size(); ++i) {
  518. pcl::PointXYZ& p = root.at(i);
  519. int mini = -1;
  520. float mind = 1000.0;
  521. for (int i = 0; i < m_center_x.size();++i) {
  522. float d = fabs(m_center_x.at(i) - p.x);
  523. if (d < mind) {
  524. mind = d;
  525. mini = i;
  526. }
  527. }
  528. if (mini >= 0) {
  529. m_stem_status.at(mini) = stem_status.at(i);
  530. }
  531. }
  532. }
  533. void CSeedlingStatus::occlusion_result_update(
  534. std::vector<int>& leaf_occlusion
  535. )
  536. {
  537. assert(m_center_x.size() == leaf_occlusion.size());
  538. assert(m_center_x.size() == m_stem_status.size());
  539. for (int i = 0; i < m_center_x.size(); ++i) {
  540. if (m_stem_status.at(i)==0 && leaf_occlusion.at(i)>0) {
  541. m_stem_status.at(i) = 2;
  542. }
  543. }
  544. }
  545. //获取植株的状态,是否有苗
  546. // 在real_result_update()和occlusion_result_update()调用后
  547. // 调用此函数,获取茎的状态
  548. void CSeedlingStatus::get_stem_status(
  549. std::vector<int>&stem_status
  550. )
  551. {
  552. //状态 1 ---此次为新上苗, 0 无显著变化, -1 上一次取苗成功
  553. float max_change_points_count;
  554. int max_change_center_idx;
  555. int status = get_status(max_change_center_idx, max_change_points_count);
  556. if (status > 0) {
  557. m_center_grabed_record.clear();
  558. m_center_grabed_record.assign(m_center_x.size(), -1);
  559. }
  560. stem_status.clear();
  561. if (status >= 0) {
  562. //用当前识别的结果
  563. }
  564. else {
  565. m_center_grabed_record.at(max_change_center_idx) = 0;
  566. //如果max_change_center_idx位置的苗上一次有苗,本次为2,那么久将2改成1
  567. if (max_change_points_count < 0) {
  568. if (m_history_status.at<unsigned char>(m_record_cursor - 1, max_change_center_idx) != 0) {
  569. if (m_stem_status.at(max_change_center_idx) == 2) {
  570. m_stem_status.at(max_change_center_idx) = 0;
  571. }
  572. }
  573. }
  574. }
  575. //更新根据: m_center_grabed_record更新m_stem_status中的叶子遮挡
  576. for (int i = 0; i < m_stem_status.size(); ++i) {
  577. if (m_center_grabed_record.at(i) == 0 && m_stem_status.at(i) == 2) {
  578. m_stem_status.at(i) = 0;
  579. }
  580. }
  581. for (int i = 0; i < m_stem_status.size(); ++i) {
  582. stem_status.push_back(m_stem_status.at(i));
  583. }
  584. //更新m_history_status
  585. if (m_record_cursor == m_global_cursor) {
  586. for (int i = 0; i < m_history_status.cols; ++i) {
  587. m_history_status.at<unsigned char>(m_record_cursor, i) = m_stem_status.at(i);
  588. }
  589. }
  590. else{
  591. //数据上移一行,数据放在最后一行
  592. for (int row = 0; row < m_history_status.rows - 1; ++row) {
  593. for (int col = 0; col < m_history_status.cols; ++col) {
  594. m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
  595. }
  596. }
  597. for (int i = 0; i < m_history_status.cols; ++i) {
  598. m_history_status.at<unsigned char>(m_max_size - 1, i) = m_stem_status.at(i);
  599. }
  600. }
  601. }
  602. }