浏览代码

v0.7.22 优化茎节位置识别,废弃基于历史平均茎节高度的约束,人工指定范围(高度上限,下限),不在范围内时,按下限位置

chenhongjiang 1 年之前
父节点
当前提交
8cf118d4ff
共有 7 个文件被更改,包括 157 次插入161 次删除
  1. 2 1
      ReadMe.txt
  2. 19 18
      config.cpp
  3. 7 6
      data_def_api.h
  4. 9 10
      gcv_conf.yml
  5. 115 88
      grab_point_rs.cpp
  6. 4 37
      grab_point_rs.h
  7. 1 1
      graft_cv_api.cpp

+ 2 - 1
ReadMe.txt

@@ -106,4 +106,5 @@ v0.7.17 
 v0.7.18 优化茎节位置识别,评估方法改为顶点高度和中值高度差,增加阈值控制是否有效
 v0.7.19 优化茎节位置识别,投影到2为平面寻找分叉点,rs_grab_fork_th和sc_grab_fork_th不在起作用,放弃历史均值位置
 v0.7.20 优化茎节位置识别,在v0.7.19基础上加上历史均值位置约束,rs_grab_fork_th和sc_grab_fork_th是茎节粗和茎粗的比值系数
-v0.7.21 优化茎节位置识别,增加偏离平均茎节高度的距离参数rs_grab_to_meanfork_max_dist和sc_grab_to_meanfork_max_dist
+v0.7.21 优化茎节位置识别,增加偏离平均茎节高度的距离参数rs_grab_to_meanfork_max_dist和sc_grab_to_meanfork_max_dist
+v0.7.22 优化茎节位置识别,废弃基于历史平均茎节高度的约束,人工指定范围(高度上限,下限),不在范围内时,按下限位置

+ 19 - 18
config.cpp

@@ -86,14 +86,14 @@ namespace graft_cv{
 			<< "rs_grab_ymax" << m_cparam->rs_grab_ymax
 			<< "rs_grab_zmin" << m_cparam->rs_grab_zmin
 			<< "rs_grab_zmax" << m_cparam->rs_grab_zmax
-			<< "rs_grab_stem_diameter" << m_cparam->rs_grab_stem_diameter
-			<< "rs_grab_y_opt" << m_cparam->rs_grab_y_opt
+			<< "rs_grab_stem_diameter" << m_cparam->rs_grab_stem_diameter			
 			<< "rs_grab_seedling_dist" << m_cparam->rs_grab_seedling_dist
 			<< "rs_grab_stem_min_pts" << m_cparam->rs_grab_stem_min_pts
 			<< "rs_grab_ror_ratio" << m_cparam->rs_grab_ror_ratio
 			<< "rs_grab_offset" << m_cparam->rs_grab_offset
 			<< "rs_grab_fork_th" << m_cparam->rs_grab_fork_th
-			<< "rs_grab_to_meanfork_max_dist" << m_cparam->rs_grab_to_meanfork_max_dist
+			<< "rs_grab_fork_yup" << m_cparam->rs_grab_fork_yup
+			<< "rs_grab_fork_ybt" << m_cparam->rs_grab_fork_ybt
 
 			<< "sc_grab_xmin" << m_cparam->sc_grab_xmin
 			<< "sc_grab_xmax" << m_cparam->sc_grab_xmax
@@ -101,14 +101,14 @@ namespace graft_cv{
 			<< "sc_grab_ymax" << m_cparam->sc_grab_ymax
 			<< "sc_grab_zmin" << m_cparam->sc_grab_zmin
 			<< "sc_grab_zmax" << m_cparam->sc_grab_zmax
-			<< "sc_grab_stem_diameter" << m_cparam->sc_grab_stem_diameter
-			<< "sc_grab_y_opt" << m_cparam->sc_grab_y_opt
+			<< "sc_grab_stem_diameter" << m_cparam->sc_grab_stem_diameter			
 			<< "sc_grab_seedling_dist" << m_cparam->sc_grab_seedling_dist
 			<< "sc_grab_stem_min_pts" << m_cparam->sc_grab_stem_min_pts
 			<< "sc_grab_ror_ratio" << m_cparam->sc_grab_ror_ratio
 			<< "sc_grab_offset" << m_cparam->sc_grab_offset
 			<< "sc_grab_fork_th" << m_cparam->sc_grab_fork_th
-			<< "sc_grab_to_meanfork_max_dist" << m_cparam->sc_grab_to_meanfork_max_dist
+			<< "sc_grab_fork_yup" << m_cparam->sc_grab_fork_yup
+			<< "sc_grab_fork_ybt" << m_cparam->sc_grab_fork_ybt
 			<< "}"; 	
 	};
 	void CGCvConfig::read(const cv::FileNode& node){ //Read serialization for this class
@@ -180,14 +180,14 @@ namespace graft_cv{
 		m_cparam->rs_grab_ymax = (double)node["rs_grab_ymax"];
 		m_cparam->rs_grab_zmin = (double)node["rs_grab_zmin"];
 		m_cparam->rs_grab_zmax = (double)node["rs_grab_zmax"];
-		m_cparam->rs_grab_stem_diameter = (double)node["rs_grab_stem_diameter"];
-		m_cparam->rs_grab_y_opt = (double)node["rs_grab_y_opt"];
+		m_cparam->rs_grab_stem_diameter = (double)node["rs_grab_stem_diameter"];		
 		m_cparam->rs_grab_seedling_dist = (double)node["rs_grab_seedling_dist"];
 		m_cparam->rs_grab_stem_min_pts = (int)node["rs_grab_stem_min_pts"];
 		m_cparam->rs_grab_ror_ratio = (double)node["rs_grab_ror_ratio"];
 		m_cparam->rs_grab_offset = (double)node["rs_grab_offset"];
 		m_cparam->rs_grab_fork_th = (double)node["rs_grab_fork_th"];
-		m_cparam->rs_grab_to_meanfork_max_dist = (double)node["rs_grab_to_meanfork_max_dist"];
+		m_cparam->rs_grab_fork_yup = (double)node["rs_grab_fork_yup"];
+		m_cparam->rs_grab_fork_ybt = (double)node["rs_grab_fork_ybt"];
 
 		m_cparam->sc_grab_xmin = (double)node["sc_grab_xmin"];
 		m_cparam->sc_grab_xmax = (double)node["sc_grab_xmax"];
@@ -195,14 +195,15 @@ namespace graft_cv{
 		m_cparam->sc_grab_ymax = (double)node["sc_grab_ymax"];
 		m_cparam->sc_grab_zmin = (double)node["sc_grab_zmin"];
 		m_cparam->sc_grab_zmax = (double)node["sc_grab_zmax"];
-		m_cparam->sc_grab_stem_diameter = (double)node["sc_grab_stem_diameter"];
-		m_cparam->sc_grab_y_opt = (double)node["sc_grab_y_opt"];
+		m_cparam->sc_grab_stem_diameter = (double)node["sc_grab_stem_diameter"];		
 		m_cparam->sc_grab_seedling_dist = (double)node["sc_grab_seedling_dist"];
         m_cparam->sc_grab_stem_min_pts = (int)node["sc_grab_stem_min_pts"];
 		m_cparam->sc_grab_ror_ratio = (double)node["sc_grab_ror_ratio"];
 		m_cparam->sc_grab_offset = (double)node["sc_grab_offset"];
 		m_cparam->sc_grab_fork_th = (double)node["sc_grab_fork_th"];
-		m_cparam->sc_grab_to_meanfork_max_dist = (double)node["sc_grab_to_meanfork_max_dist"];
+		m_cparam->sc_grab_fork_yup = (double)node["sc_grab_fork_yup"];
+		m_cparam->sc_grab_fork_ybt = (double)node["sc_grab_fork_ybt"];
+
   }
 	string get_cparam_info(ConfigParam*m_cparam)
 	{
@@ -278,14 +279,14 @@ namespace graft_cv{
 			<< "rs_grab_ymax:\t" << m_cparam->rs_grab_ymax << endl
 			<< "rs_grab_zmin:\t" << m_cparam->rs_grab_zmin << endl
 			<< "rs_grab_zmax:\t" << m_cparam->rs_grab_zmax << endl
-			<< "rs_grab_stem_diameter:\t" << m_cparam->rs_grab_stem_diameter << endl
-			<< "rs_grab_y_opt:\t" << m_cparam->rs_grab_y_opt << endl
+			<< "rs_grab_stem_diameter:\t" << m_cparam->rs_grab_stem_diameter << endl			
             << "rs_grab_seedling_dist:\t" << m_cparam->rs_grab_seedling_dist << endl
 			<< "rs_grab_stem_min_pts:\t" << m_cparam->rs_grab_stem_min_pts << endl
 			<< "rs_grab_ror_ratio:\t" << m_cparam->rs_grab_ror_ratio << endl
 			<< "rs_grab_offset:\t" << m_cparam->rs_grab_offset << endl
 			<< "rs_grab_fork_th:\t" << m_cparam->rs_grab_fork_th << endl
-			<< "rs_grab_to_meanfork_max_dist:\t" << m_cparam->rs_grab_to_meanfork_max_dist << endl
+			<< "rs_grab_fork_yup:\t" << m_cparam->rs_grab_fork_yup << endl
+			<< "rs_grab_fork_ybt:\t" << m_cparam->rs_grab_fork_ybt << endl
 
 			<< "sc_grab_xmin:\t" << m_cparam->sc_grab_xmin << endl
 			<< "sc_grab_xmax:\t" << m_cparam->sc_grab_xmax << endl
@@ -293,14 +294,14 @@ namespace graft_cv{
 			<< "sc_grab_ymax:\t" << m_cparam->sc_grab_ymax << endl
 			<< "sc_grab_zmin:\t" << m_cparam->sc_grab_zmin << endl
 			<< "sc_grab_zmax:\t" << m_cparam->sc_grab_zmax << endl
-			<< "sc_grab_stem_diameter:\t" << m_cparam->sc_grab_stem_diameter << endl
-			<< "sc_grab_y_opt:\t" << m_cparam->sc_grab_y_opt << endl
+			<< "sc_grab_stem_diameter:\t" << m_cparam->sc_grab_stem_diameter << endl			
 			<< "sc_grab_seedling_dist:\t" << m_cparam->sc_grab_seedling_dist << endl
 			<< "sc_grab_stem_min_pts:\t" << m_cparam->sc_grab_stem_min_pts << endl
 			<< "sc_grab_ror_ratio:\t" << m_cparam->sc_grab_ror_ratio << endl
 			<< "sc_grab_offset:\t" << m_cparam->sc_grab_offset << endl
 			<< "sc_grab_fork_th:\t" << m_cparam->sc_grab_fork_th << endl
-			<< "sc_grab_to_meanfork_max_dist:\t" << m_cparam->sc_grab_to_meanfork_max_dist << endl
+			<< "sc_grab_fork_yup:\t" << m_cparam->sc_grab_fork_yup << endl
+			<< "sc_grab_fork_ybt:\t" << m_cparam->sc_grab_fork_ybt << endl
 			<< "}" << endl; 	
 		return buff.str();
 	}

+ 7 - 6
data_def_api.h

@@ -112,13 +112,13 @@ typedef struct{
 	double rs_grab_zmax;
 
 	double rs_grab_stem_diameter;	
-	double rs_grab_y_opt;
 	double rs_grab_seedling_dist;
 	int rs_grab_stem_min_pts;
 	double rs_grab_ror_ratio;
 	double rs_grab_offset;
-	double rs_grab_fork_th;
-	double rs_grab_to_meanfork_max_dist;
+	double rs_grab_fork_th;	
+	double rs_grab_fork_yup; //茎节高度上限
+	double rs_grab_fork_ybt; //茎节高度下限, 不在范围内,按下限
 
 	// scion grab based points cloud
 	double sc_grab_xmin;
@@ -128,14 +128,15 @@ typedef struct{
 	double sc_grab_zmin;
 	double sc_grab_zmax;
 
-	double sc_grab_stem_diameter;
-	double sc_grab_y_opt;
+	double sc_grab_stem_diameter;	
 	double sc_grab_seedling_dist;
 	int sc_grab_stem_min_pts;
 	double sc_grab_ror_ratio;
 	double sc_grab_offset;
 	double sc_grab_fork_th;
-	double sc_grab_to_meanfork_max_dist;
+	double sc_grab_fork_yup; //茎节高度上限
+	double sc_grab_fork_ybt; //茎节高度下限, 不在范围内,按下限
+	
 
 
 } ConfigParam;

+ 9 - 10
gcv_conf.yml

@@ -80,17 +80,19 @@ conf_parameters:
 
    rs_grab_xmin: -200
    rs_grab_xmax: 250
-   rs_grab_ymin: -50
+   rs_grab_ymin: -30
    rs_grab_ymax: 10
    rs_grab_zmin: 300
-   rs_grab_zmax: 440
+   rs_grab_zmax: 380
    rs_grab_stem_diameter: 5.0
-   rs_grab_y_opt: 30
+   # rs_grab_y_opt: 30
    rs_grab_seedling_dist: 40.0
    rs_grab_stem_min_pts: 50
    rs_grab_ror_ratio: 0.85
    rs_grab_offset: 0
    rs_grab_fork_th: 1.5
+   rs_grab_fork_yup: 10
+   rs_grab_fork_ybt: -10
 
 
    sc_grab_xmin: -200
@@ -99,18 +101,15 @@ conf_parameters:
    sc_grab_ymax: 10
    sc_grab_zmin: 300
    sc_grab_zmax: 400
-   #sc_grab_xmin: -30 
-   #sc_grab_xmax: 170
-   #sc_grab_ymin: -10
-   #sc_grab_ymax: 100
-   #sc_grab_zmin: 420
-   #sc_grab_zmax: 550   
+   
    sc_grab_stem_diameter: 5.0
-   sc_grab_y_opt: 30
+   # sc_grab_y_opt: 30
    sc_grab_seedling_dist: 40.0
    sc_grab_stem_min_pts: 45
    sc_grab_ror_ratio: 0.85
    sc_grab_offset: 0
    sc_grab_fork_th: 1.5
+   sc_grab_fork_yup: 10
+   sc_grab_fork_ybt: 0
    
 

+ 115 - 88
grab_point_rs.cpp

@@ -40,9 +40,7 @@ namespace graft_cv {
 		m_ppImgSaver(0),
 		m_1st_row_zmean_rs(-1.0),
 		m_1st_row_zmean_sc(-1.0),
-		m_cloud_mean_dist(0.0),
-		m_stem_fork_ys_size(20),
-		m_stem_fork_pos_mu(0)
+		m_cloud_mean_dist(0.0)		
 	{
 	}
 
@@ -2170,63 +2168,63 @@ void CRootStockGrabPoint::line_filter(
 	//	pt.z = in_cloud->points.at(nearest_idx).z;
 	//	pt_idx = nearest_idx;
 	//}
-	void CRootStockGrabPoint::get_optimal_seed(
-		pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
-		pcl::PointXYZ&pt,
-		int &pt_idx)
-	{
-		/*double d1 = m_cparam.rs_grab_stem_diameter;
-		double d2 = m_cparam.rs_grab_stem_diameter * 4.0;
-		if (m_dtype != 0) {
-			d1 = m_cparam.sc_grab_stem_diameter;
-			d2 = m_cparam.sc_grab_stem_diameter * 4.0;
-		}
-		std::vector<pcl::PointXYZ>cluster_center;
-		std::vector<std::vector<int>> cluster_member;
-		euclidean_clustering_ttsas(in_cloud, d1, d2, cluster_center, cluster_member);*/
+	//void CRootStockGrabPoint::get_optimal_seed(
+	//	pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
+	//	pcl::PointXYZ&pt,
+	//	int &pt_idx)
+	//{
+	//	/*double d1 = m_cparam.rs_grab_stem_diameter;
+	//	double d2 = m_cparam.rs_grab_stem_diameter * 4.0;
+	//	if (m_dtype != 0) {
+	//		d1 = m_cparam.sc_grab_stem_diameter;
+	//		d2 = m_cparam.sc_grab_stem_diameter * 4.0;
+	//	}
+	//	std::vector<pcl::PointXYZ>cluster_center;
+	//	std::vector<std::vector<int>> cluster_member;
+	//	euclidean_clustering_ttsas(in_cloud, d1, d2, cluster_center, cluster_member);*/
 
-		float min_y_dist = 1.0e6;
-		int opt_idx = -1;
-		int member_size = 5;
-		float y_opt = m_cparam.rs_grab_y_opt;
-		if (m_dtype == 0) {
-			y_opt = m_cparam.sc_grab_y_opt;
-		}
-		for (int i = 0; i < in_cloud->points.size(); ++i) {
-			/*if (cluster_member.at(i).size() < member_size) {
-				continue;
-			}*/
-			if (fabs(in_cloud->points.at(i).y - y_opt) < min_y_dist) {
-				min_y_dist = fabs(in_cloud->points.at(i).y - y_opt);
-				opt_idx = i;
-			}
-		}
-		if (opt_idx < 0) {
-			if (m_pLogger) {
-				stringstream buff;
-				buff << m_pcdId <<": get_optimal_seed failed, get invalid optimal cluster id";
-				m_pLogger->ERRORINFO(buff.str());
-			}
-			return;
-		}
-		//find nearest pt
-		/*float nearest_dist = 1.0e6;
-		int nearest_idx = -1;
-		for (int i = 0; i < cluster_member.at(opt_idx).size(); ++i) {
-			int idx = cluster_member.at(opt_idx).at(i);
-			float dist = fabs(in_cloud->points.at(idx).x - cluster_center.at(opt_idx).x) +
-				fabs(in_cloud->points.at(idx).y - cluster_center.at(opt_idx).y) +
-				fabs(in_cloud->points.at(idx).z - cluster_center.at(opt_idx).z);
-			if (dist < nearest_dist) {
-				nearest_dist = dist;
-				nearest_idx = idx;
-			}
-		}*/
-		pt.x = in_cloud->points.at(opt_idx).x;
-		pt.y = in_cloud->points.at(opt_idx).y;
-		pt.z = in_cloud->points.at(opt_idx).z;
-		pt_idx = opt_idx;
-	}
+	//	float min_y_dist = 1.0e6;
+	//	int opt_idx = -1;
+	//	int member_size = 5;
+	//	float y_opt = m_cparam.rs_grab_y_opt;
+	//	if (m_dtype == 0) {
+	//		y_opt = m_cparam.sc_grab_y_opt;
+	//	}
+	//	for (int i = 0; i < in_cloud->points.size(); ++i) {
+	//		/*if (cluster_member.at(i).size() < member_size) {
+	//			continue;
+	//		}*/
+	//		if (fabs(in_cloud->points.at(i).y - y_opt) < min_y_dist) {
+	//			min_y_dist = fabs(in_cloud->points.at(i).y - y_opt);
+	//			opt_idx = i;
+	//		}
+	//	}
+	//	if (opt_idx < 0) {
+	//		if (m_pLogger) {
+	//			stringstream buff;
+	//			buff << m_pcdId <<": get_optimal_seed failed, get invalid optimal cluster id";
+	//			m_pLogger->ERRORINFO(buff.str());
+	//		}
+	//		return;
+	//	}
+	//	//find nearest pt
+	//	/*float nearest_dist = 1.0e6;
+	//	int nearest_idx = -1;
+	//	for (int i = 0; i < cluster_member.at(opt_idx).size(); ++i) {
+	//		int idx = cluster_member.at(opt_idx).at(i);
+	//		float dist = fabs(in_cloud->points.at(idx).x - cluster_center.at(opt_idx).x) +
+	//			fabs(in_cloud->points.at(idx).y - cluster_center.at(opt_idx).y) +
+	//			fabs(in_cloud->points.at(idx).z - cluster_center.at(opt_idx).z);
+	//		if (dist < nearest_dist) {
+	//			nearest_dist = dist;
+	//			nearest_idx = idx;
+	//		}
+	//	}*/
+	//	pt.x = in_cloud->points.at(opt_idx).x;
+	//	pt.y = in_cloud->points.at(opt_idx).y;
+	//	pt.z = in_cloud->points.at(opt_idx).z;
+	//	pt_idx = opt_idx;
+	//}
 	//通过比较直线点云和原始点云相同位置邻域内xz的范围,确定此点是否是无干扰点的茎
 	//void CRootStockGrabPoint::get_optimal_seed_compare(
 	//	pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,		//	全部有效点云
@@ -2310,7 +2308,7 @@ void CRootStockGrabPoint::line_filter(
 		pcl::PointCloud<pcl::PointXYZ>::Ptr in_line_cloud,	//input	茎上直线点云
 		pcl::ModelCoefficients::Ptr line_model,				//input
 		pcl::PointXYZ&pt,									//  返回抓取的点坐标,基于pt_ref的偏移点
-		pcl::PointXYZ &pt_ref,										//	返回点茎节的参考点
+		pcl::PointXYZ &pt_ref,								//	返回点茎节的参考点
 		std::vector<int>& valid_line_index					//  返回有效直线点index
 	)
 	{
@@ -2343,7 +2341,7 @@ void CRootStockGrabPoint::line_filter(
 		box_filter_line.setInputCloud(in_line_cloud);
 
 		float radius = m_cparam.rs_grab_stem_diameter;
-		float opt_y = m_cparam.rs_grab_y_opt;
+		/*float opt_y = m_cparam.rs_grab_y_opt;
 		bool opt_y_valid = false;
 		if (opt_y >= m_cparam.rs_grab_ymin && opt_y <= m_cparam.rs_grab_ymax) {
 			opt_y_valid = true;
@@ -2354,7 +2352,7 @@ void CRootStockGrabPoint::line_filter(
 			if (opt_y >= m_cparam.sc_grab_ymin && opt_y <= m_cparam.sc_grab_ymax) {
 				opt_y_valid = true;
 			}
-		}
+		}*/
 
 		float cx, cy, cz, t;
 		float rx = 1.5;
@@ -2362,7 +2360,7 @@ void CRootStockGrabPoint::line_filter(
 		float rz = 1.5;
 		float dz, dx;
 		//用户指定抓取的y高度,按抓取高度找到对应的点, pt_ref参考位置为上顶点,pt为抓取点
-		if (opt_y_valid) {
+		/*if (opt_y_valid) {
 			cy = opt_y;
 			t = (cy - line_model->values.at(1)) / line_model->values.at(4);
 			cx = line_model->values.at(3) * t + line_model->values.at(0);
@@ -2390,7 +2388,7 @@ void CRootStockGrabPoint::line_filter(
 			pt_ref.y = cy;
 			pt_ref.z = z_mu;			
 			return;
-		}
+		}*/
 
 		// 如果opt_y_valid==false,就是用户没有指定抓取的y高度	
 		float max_dist_to_boundary = 0.0;
@@ -2469,17 +2467,17 @@ void CRootStockGrabPoint::line_filter(
 
 		//3 如果fork方法得到位置信息,进行更新,并记录历史
 		float max_power_th = m_cparam.rs_grab_fork_th;
-		float max_dist_to_mean_fork = m_cparam.rs_grab_to_meanfork_max_dist;
+		//float max_dist_to_mean_fork = m_cparam.rs_grab_to_meanfork_max_dist;
 		if (m_dtype == 0) { 
 			max_power_th = m_cparam.sc_grab_fork_th; 
-			max_dist_to_mean_fork = m_cparam.sc_grab_to_meanfork_max_dist;
+			//max_dist_to_mean_fork = m_cparam.sc_grab_to_meanfork_max_dist;
 		}
 
 		if (max_idx_to_boundary >= 0) {
 			max_pos = int(in_line_cloud->points.at(max_idx_to_boundary).y + 0.5 - ymin);
 			max_pos_ref = max_pos;
 			//记录历史信息
-			if (2.0*max_dist_to_boundary > max_power_th * mu) {
+			/*if (2.0*max_dist_to_boundary > max_power_th * mu) {
 				m_stem_fork_ys.insert(m_stem_fork_ys.begin(), max_pos);
 				if (m_stem_fork_ys.size() > m_stem_fork_ys_size) { m_stem_fork_ys.pop_back(); }
 				m_stem_fork_pos_mu = int(get_hist_mean<int>(m_stem_fork_ys) + 0.5);
@@ -2494,34 +2492,63 @@ void CRootStockGrabPoint::line_filter(
 						", ratio is = "<< ratio;
 					m_pLogger->INFO(buff.str());
 				}
-			}			
+			}		*/	
 		}
 		
 
-		//4 用历史均值进行约束,如果偏差大于max_dist_to_mean_fork mm,采用历史均值
+		//4 用茎节上下限高度值进行约束,如果超限,用最低限高度作为茎节高度
+		double grab_fork_yup = m_cparam.rs_grab_fork_yup;
+		double grab_fork_ybt = m_cparam.rs_grab_fork_ybt;
+		if (m_dtype == 0) {
+			grab_fork_yup = m_cparam.sc_grab_fork_yup;
+			grab_fork_ybt = m_cparam.sc_grab_fork_ybt;
+		}
 		bool out_of_range = false;
-		if (m_stem_fork_pos_mu > 0) {
-			if (fabs(max_pos - (float)m_stem_fork_pos_mu) > max_dist_to_mean_fork) {
-				out_of_range = true;
-				int original_max_pos = max_pos;
-				max_pos = m_stem_fork_pos_mu;
-				max_pos_ref = max_pos;
-				if (m_pLogger) {
-					stringstream buff;
-					buff << m_pcdId << ": warning,self fork postiont = " << original_max_pos <<
-						", USE mean fork postiont " << m_stem_fork_pos_mu;
-					m_pLogger->INFO(buff.str());
-				}
+		if ((max_pos + ymin) > grab_fork_yup || (max_pos + ymin) < grab_fork_ybt) {
+			out_of_range = true;
+			int original_max_pos = max_pos;
+			max_pos = int(grab_fork_ybt - ymin + 0.5);
+			max_pos_ref = max_pos;
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_pcdId << ": warning,self fork postiont = " << original_max_pos <<
+					", USE bottom limit fork postiont " << max_pos <<
+					", valid fork postiont range:[" << int(grab_fork_ybt - ymin + 0.5) <<
+					", " << int(grab_fork_yup - ymin + 0.5) << "]";
+				m_pLogger->INFO(buff.str());
 			}
-			else {
-				if (m_pLogger) {
-					stringstream buff;
-					buff << m_pcdId << ": self fork postiont = "<< max_pos<<
-						", reference mean fork postiont = " << m_stem_fork_pos_mu;
-					m_pLogger->INFO(buff.str());
-				}
+		}
+		else {
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_pcdId << ": self fork postiont = " << max_pos <<
+					", valid fork postiont range:[" << int(grab_fork_ybt - ymin + 0.5)<<
+					", "<< int(grab_fork_yup - ymin + 0.5) << "]";
+				m_pLogger->INFO(buff.str());
 			}
 		}
+		
+		/*if (fabs(max_pos - (float)m_stem_fork_pos_mu) > max_dist_to_mean_fork) {
+			out_of_range = true;
+			int original_max_pos = max_pos;
+			max_pos = m_stem_fork_pos_mu;
+			max_pos_ref = max_pos;
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_pcdId << ": warning,self fork postiont = " << original_max_pos <<
+					", USE mean fork postiont " << m_stem_fork_pos_mu;
+				m_pLogger->INFO(buff.str());
+			}
+		}
+		else {
+			if (m_pLogger) {
+				stringstream buff;
+				buff << m_pcdId << ": self fork postiont = "<< max_pos<<
+					", reference mean fork postiont = " << m_stem_fork_pos_mu;
+				m_pLogger->INFO(buff.str());
+			}
+		}*/
+		
 
 		//5 按指定量偏移
 		if(m_dtype == 0){

+ 4 - 37
grab_point_rs.h

@@ -31,33 +31,11 @@ namespace graft_cv {
 		CImStoreManager** m_ppImgSaver;
 
 		pcl::PointCloud<pcl::PointXYZ>::Ptr m_raw_cloud;
-		double m_cloud_mean_dist;
-
-		//历史茎节位置,用于计算平均茎节位置
-		std::vector<int>m_stem_fork_ys;
-		int m_stem_fork_ys_size;
-		int m_stem_fork_pos_mu;
-
+		double m_cloud_mean_dist;	
 
 
 		int read_ply_file(const char* fn);
-		double compute_nearest_neighbor_distance(pcl::PointCloud<pcl::PointXYZ>::Ptr);
-
-		////////////////////////////////////////////////
-		//---> 2023-8-8优化,seedling order识别错误问题
-		/*void CRootStockGrabPoint::find_tray_top_edge(
-			pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
-			float & tray_top_edge_y
-		);
-		void CRootStockGrabPoint::find_seedling_position_line_based(
-			pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
-			std::vector<int> &first_seedling_cloud_idx,
-			pcl::PointXYZ&xz_center
-		);
-		void segement_line(
-			pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud
-		);*/
-		//<---------
+		double compute_nearest_neighbor_distance(pcl::PointCloud<pcl::PointXYZ>::Ptr);		
 
 		/////////////////////////////////////////////////////////////////////////////////////
 		//叶子剔除,通过欧式距离聚类,然后判断每一个类别是否是叶子
@@ -177,24 +155,13 @@ namespace graft_cv {
 			double &dy_obb,
 			double &angle_obb);
 
-		void get_optimal_seed(
-			pcl::PointCloud<pcl::PointXYZ>::Ptr,
-			pcl::PointXYZ&pt,
-			int &pt_idx);
+		
         //已知检测出苗的位置,找出有可能有苗的位置
 		void tilted_seedling_discover(
 			std::vector<pcl::PointXYZ>&cluster_center,	//输入,已知的苗的坐标
 			std::vector<pcl::PointXYZ>&tilted_center	//输出,有倾斜苗的坐标
 		);
-
-		//通过比较直线点云和原始点云相同位置邻域内xz的范围,确定此点是否是无干扰点的茎
-		/*void get_optimal_seed_compare(
-			pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
-			pcl::PointCloud<pcl::PointXYZ>::Ptr in_line_cloud,
-			pcl::PointXYZ&pt,
-			int &pt_idx,
-			std::vector<int>& valid_line_index
-		);*/
+		
 		//通过比较直线点云和原始点云相同位置邻域内xz的范围,确定此点是否是无干扰点的茎
 		void get_optimal_seed_compare(
 			pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,		//input

+ 1 - 1
graft_cv_api.cpp

@@ -20,7 +20,7 @@ extern CRITICAL_SECTION g_cs;
 namespace graft_cv
 {
 
-	char *g_version_str = "0.7.21";
+	char *g_version_str = "0.7.22";
 
 	//configure
 	string g_conf_file = "./gcv_conf.yml";