|
@@ -282,14 +282,7 @@ namespace graft_cv {
|
|
|
m_pLogger->INFO(buff.str());
|
|
|
}
|
|
|
}
|
|
|
- //判断m_root_centers位置上是否有苗
|
|
|
- //
|
|
|
- int first_row_seedling_number = 0;
|
|
|
- seedling_detect_by_point_cloud();
|
|
|
- for (auto&has_seedling : m_root_center_with_seedling) {
|
|
|
- if (has_seedling) { first_row_seedling_number += 1; }
|
|
|
- }
|
|
|
-
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
//3 原来的降采样没有意义,改成统计平均距离
|
|
|
m_cloud_mean_dist = 0.0;
|
|
@@ -303,8 +296,9 @@ namespace graft_cv {
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
// 4 对截取的点云进行ror滤除大面积联通区域,剔除叶片
|
|
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_dowm_sampled(new pcl::PointCloud<pcl::PointXYZ>);
|
|
|
- std::vector<int> non_leaf_indices;
|
|
|
- leaf_filter_ror(cloud_ror, non_leaf_indices);
|
|
|
+ std::vector<int> non_leaf_indices;
|
|
|
+ std::vector<int> leaf_indices;
|
|
|
+ leaf_filter_ror(cloud_ror, non_leaf_indices, leaf_indices);
|
|
|
pcl::copyPointCloud(*cloud_ror, non_leaf_indices, *cloud_dowm_sampled);
|
|
|
if (m_pLogger) {
|
|
|
stringstream buff;
|
|
@@ -316,6 +310,11 @@ namespace graft_cv {
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
+ //判断m_root_centers位置上是否有叶片遮挡
|
|
|
+ occluded_seedling_detect_by_leaf(cloud_ror, leaf_indices);
|
|
|
+
|
|
|
+
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
//5 seedling position,找到第一个位置上的植株
|
|
|
std::vector<int> first_seedling_cloud_idx; //存储找到的第一个位置上植株茎上直线点的index
|
|
@@ -324,8 +323,9 @@ namespace graft_cv {
|
|
|
if (m_pLogger) {
|
|
|
m_pLogger->INFO(m_pcdId + ": begin find seedling position");
|
|
|
}
|
|
|
- int first_row_seedling_number_with_stem = 0;
|
|
|
- bool fund_seedling = find_seedling_position_key(cloud_dowm_sampled, first_seedling_cloud_idx, xz_center, line_model, first_row_seedling_number_with_stem);
|
|
|
+
|
|
|
+ int first_row_seedling_number = 0;
|
|
|
+ bool fund_seedling = find_seedling_position_key(cloud_dowm_sampled, first_seedling_cloud_idx, xz_center, line_model, first_row_seedling_number);
|
|
|
if (!fund_seedling && first_row_seedling_number == 0) {
|
|
|
if (m_pLogger) {
|
|
|
stringstream buff;
|
|
@@ -655,25 +655,37 @@ obstructed:
|
|
|
|
|
|
}
|
|
|
//根据历史根的位置,计算对应位置点云数量,进而判断此位置是否有苗
|
|
|
- void CRootStockGrabPoint::seedling_detect_by_point_cloud()
|
|
|
+ void CRootStockGrabPoint::occluded_seedling_detect_by_leaf(
|
|
|
+ pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud, //input 输入点云数据
|
|
|
+ std::vector<int>& leaf_idx
|
|
|
+ )
|
|
|
{
|
|
|
m_root_center_with_seedling.clear();
|
|
|
+ m_root_center_with_seedling.assign(m_root_centers.size(), false);
|
|
|
std::vector<int> pcd_cnt;
|
|
|
- int th_pcd_size = m_cparam.rs_grab_seedling_min_pts;
|
|
|
+ //int th_pcd_size = m_cparam.rs_grab_seedling_min_pts;
|
|
|
+ double stem_diameter = m_cparam.rs_grab_stem_diameter;
|
|
|
+ double y_min = m_cparam.rs_grab_ymin;
|
|
|
+ double y_max = m_cparam.rs_grab_ymax;
|
|
|
+
|
|
|
if (m_dtype == 0) {
|
|
|
- th_pcd_size = m_cparam.sc_grab_seedling_min_pts;
|
|
|
+ //th_pcd_size = m_cparam.sc_grab_seedling_min_pts;
|
|
|
+ stem_diameter = m_cparam.sc_grab_stem_diameter;
|
|
|
+ y_min = m_cparam.sc_grab_ymin;
|
|
|
+ y_max = m_cparam.sc_grab_ymax;
|
|
|
}
|
|
|
+ int th_pcd_size = stem_diameter * (y_max - y_min) * m_cloud_mean_dist;
|
|
|
std::vector<pcl::PointXYZ> aabb_mins_maxs;
|
|
|
- for (auto&rc : m_root_centers) {
|
|
|
+ for (int i = 0; i < m_root_centers.size(); ++i) {
|
|
|
+ CStemResult& rc = m_root_centers.at(i);
|
|
|
pcl::PointXYZ aabb_min;
|
|
|
pcl::PointXYZ aabb_max;
|
|
|
- int cnt = get_point_count_inbox(rc, aabb_min, aabb_max);
|
|
|
+ int cnt = get_point_count_inbox(rc, aabb_min, aabb_max, in_cloud, leaf_idx);
|
|
|
pcd_cnt.push_back(cnt);
|
|
|
bool has_seedling = cnt > th_pcd_size;
|
|
|
- m_root_center_with_seedling.push_back(has_seedling);
|
|
|
+ m_root_center_with_seedling.at(i) = has_seedling;
|
|
|
aabb_mins_maxs.push_back(aabb_min);
|
|
|
- aabb_mins_maxs.push_back(aabb_max);
|
|
|
-
|
|
|
+ aabb_mins_maxs.push_back(aabb_max);
|
|
|
}
|
|
|
|
|
|
if (m_pLogger) {
|
|
@@ -704,28 +716,68 @@ obstructed:
|
|
|
}
|
|
|
|
|
|
}
|
|
|
- int CRootStockGrabPoint::get_point_count_inbox(const CStemResult& sr,
|
|
|
+ //int CRootStockGrabPoint::get_point_count_inbox(const CStemResult& sr,
|
|
|
+ // pcl::PointXYZ& aabb_min,
|
|
|
+ // pcl::PointXYZ& aabb_max)
|
|
|
+ //{
|
|
|
+ // double seedling_distance = m_cparam.rs_grab_seedling_dist;
|
|
|
+ // double min_y = m_cparam.rs_grab_ymin;
|
|
|
+ // if (m_dtype == 0) {
|
|
|
+ // seedling_distance = m_cparam.sc_grab_seedling_dist;
|
|
|
+ // min_y = m_cparam.sc_grab_ymin;
|
|
|
+ // }
|
|
|
+ // double min_x = sr.root_x - 0.5 * seedling_distance;
|
|
|
+ // double max_x = sr.root_x + 0.5 * seedling_distance;
|
|
|
+ // double min_z = sr.root_z - 0.75 * seedling_distance;
|
|
|
+ // double max_z = sr.root_z + 0.25 * seedling_distance;
|
|
|
+ // double max_y = min_y + 150.0; //假定苗高150mm
|
|
|
+
|
|
|
+ // int count = 0;
|
|
|
+ // for (auto&pt : m_raw_cloud->points) {
|
|
|
+ // if(pt.y >= min_y && pt.y <= max_y &&
|
|
|
+ // pt.x >=min_x && pt.x<=max_x &&
|
|
|
+ // pt.z >= min_z && pt.z <= max_z)
|
|
|
+ // {
|
|
|
+ // count++;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // aabb_min.x = min_x;
|
|
|
+ // aabb_min.y = min_y;
|
|
|
+ // aabb_min.z = min_z;
|
|
|
+ // aabb_max.x = max_x;
|
|
|
+ // aabb_max.y = max_y;
|
|
|
+ // aabb_max.z = max_z;
|
|
|
+
|
|
|
+ // return count;
|
|
|
+ //}
|
|
|
+
|
|
|
+ int CRootStockGrabPoint::get_point_count_inbox(const CStemResult& sr,
|
|
|
pcl::PointXYZ& aabb_min,
|
|
|
- pcl::PointXYZ& aabb_max)
|
|
|
+ pcl::PointXYZ& aabb_max,
|
|
|
+ pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud, //input 输入点云数据
|
|
|
+ std::vector<int>& leaf_idx)
|
|
|
{
|
|
|
double seedling_distance = m_cparam.rs_grab_seedling_dist;
|
|
|
double min_y = m_cparam.rs_grab_ymin;
|
|
|
+ double max_y = m_cparam.rs_grab_ymax;
|
|
|
if (m_dtype == 0) {
|
|
|
seedling_distance = m_cparam.sc_grab_seedling_dist;
|
|
|
min_y = m_cparam.sc_grab_ymin;
|
|
|
+ max_y = m_cparam.sc_grab_ymax;
|
|
|
}
|
|
|
double min_x = sr.root_x - 0.5 * seedling_distance;
|
|
|
double max_x = sr.root_x + 0.5 * seedling_distance;
|
|
|
double min_z = sr.root_z - 0.75 * seedling_distance;
|
|
|
- double max_z = sr.root_z + 0.25 * seedling_distance;
|
|
|
- double max_y = min_y + 150.0; //假定苗高150mm
|
|
|
+ double max_z = sr.root_z + 0.25 * seedling_distance;
|
|
|
|
|
|
int count = 0;
|
|
|
- for (auto&pt : m_raw_cloud->points) {
|
|
|
- if(pt.y >= min_y && pt.y <= max_y &&
|
|
|
- pt.x >=min_x && pt.x<=max_x &&
|
|
|
+ //for (auto&pt : m_raw_cloud->points) {
|
|
|
+ for (auto&i : leaf_idx) {
|
|
|
+ pcl::PointXYZ& pt = in_cloud->points.at(i);
|
|
|
+ if (pt.y >= min_y && pt.y <= max_y &&
|
|
|
+ pt.x >= min_x && pt.x <= max_x &&
|
|
|
pt.z >= min_z && pt.z <= max_z)
|
|
|
- {
|
|
|
+ {
|
|
|
count++;
|
|
|
}
|
|
|
}
|
|
@@ -932,7 +984,8 @@ void CRootStockGrabPoint::leaf_filter(
|
|
|
// 基于孤立点滤除的方法检测叶子区域
|
|
|
void CRootStockGrabPoint::leaf_filter_ror(
|
|
|
pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud, //input 输入点云数据
|
|
|
- std::vector<int> &stem_cloud_idx //output, 过滤后的点云序号
|
|
|
+ std::vector<int> &stem_cloud_idx, //output, 过滤后的点云序号
|
|
|
+ std::vector<int>& leaf_idx //output, 叶子的点云序号
|
|
|
)
|
|
|
{
|
|
|
//计算点云平均间距
|
|
@@ -976,7 +1029,7 @@ void CRootStockGrabPoint::leaf_filter_ror(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- std::vector<int> leaf_idx;
|
|
|
+ leaf_idx.clear();
|
|
|
leaf_idx.assign(leaf_idx_set.begin(), leaf_idx_set.end());
|
|
|
|
|
|
//in_img是经过开运算的图像,其中像素位置的点云为叶子区域
|
|
@@ -1603,7 +1656,27 @@ void CRootStockGrabPoint::line_filter(
|
|
|
int raw_idx = first_row_index.at(i);
|
|
|
pcl::PointXYZ&pt = target_filtered_root.at(raw_idx);
|
|
|
cluster_index.push_back(pt.x);
|
|
|
+ //update m_root_center_with_seedling
|
|
|
+ double min_dist = hole_step;
|
|
|
+ int min_i = -1;
|
|
|
+ for (int rc_i = 0; rc_i < m_root_centers.size(); ++rc_i)
|
|
|
+ {
|
|
|
+ double dist = fabs(pt.x - m_root_centers.at(rc_i).root_x);
|
|
|
+ if (dist < min_dist) {
|
|
|
+ min_dist = dist;
|
|
|
+ min_i = rc_i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (min_i >= 0) {
|
|
|
+ m_root_center_with_seedling.at(min_i) = true;
|
|
|
+ }
|
|
|
}
|
|
|
+ //统计苗数量
|
|
|
+ first_row_size = 0;
|
|
|
+ for (auto&has_seedling : m_root_center_with_seedling) {
|
|
|
+ if (has_seedling) { first_row_size += 1; }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
int first_idx = std::min_element(cluster_index.begin(), cluster_index.end()) - cluster_index.begin();
|
|
|
if (m_dtype == 0) {
|
|
@@ -1618,8 +1691,7 @@ void CRootStockGrabPoint::line_filter(
|
|
|
xz_center.x = target_filtered_root.at(first_idx).x;
|
|
|
xz_center.y = target_filtered_root.at(first_idx).y;
|
|
|
xz_center.z = target_filtered_root.at(first_idx).z;
|
|
|
- line_model = target_filtered_models.at(first_idx);
|
|
|
- first_row_size = first_row_index.size();
|
|
|
+ line_model = target_filtered_models.at(first_idx);
|
|
|
|
|
|
if (m_pLogger) {
|
|
|
stringstream buff;
|
|
@@ -2689,18 +2761,18 @@ void CRootStockGrabPoint::line_filter(
|
|
|
for (size_t i = 0; i < cluster_center.size();++i) {
|
|
|
pcl::PointXYZ &p = cluster_center.at(i);
|
|
|
pcl::PointXYZ px0, px1, py1, py0;
|
|
|
- px0.x = p.x - 5.0;
|
|
|
+ px0.x = p.x;
|
|
|
px0.y = p.y;
|
|
|
px0.z = p.z;
|
|
|
- px1.x = p.x + 5.0;
|
|
|
+ px1.x = p.x + 10.0;
|
|
|
px1.y = p.y;
|
|
|
px1.z = p.z;
|
|
|
|
|
|
py0.x = p.x;
|
|
|
- py0.y = p.y - 5.0;
|
|
|
+ py0.y = p.y;
|
|
|
py0.z = p.z;
|
|
|
py1.x = p.x;
|
|
|
- py1.y = p.y + 5.0;
|
|
|
+ py1.y = p.y + 10.0;
|
|
|
py1.z = p.z;
|
|
|
|
|
|
viewer.addLine(px0, px1, 255, 0, 0, "x" + string(_itoa(cnt, buf, 10)));
|