Kaynağa Gözat

Merge branch 'v0.7.0' of chenhongjiang/graft_cv into dev

chenhongjiang 1 yıl önce
ebeveyn
işleme
acb61afad8
10 değiştirilmiş dosya ile 134 ekleme ve 41 silme
  1. 3 1
      ReadMe.txt
  2. 8 2
      config.cpp
  3. 6 0
      data_def_api.h
  4. 10 8
      gcv_conf.yml
  5. 16 6
      grab_point_rs.cpp
  6. 77 20
      graft_cv_api.cpp
  7. 4 3
      graft_cv_api.h
  8. 3 1
      imstorage_manager.cpp
  9. 4 0
      logger.cpp
  10. 3 0
      logger.h

+ 3 - 1
ReadMe.txt

@@ -84,4 +84,6 @@ v0.6.12 
 v0.6.13 增加聚类结果中点数小于20的类别剔除功能;修改降采样后整个点云数量小于50退出(原来是200)
 v0.6.14 修改茎识别方法,通过2d高密度点找到茎的位置,然后提取株的最大空间内点云,用直线分割的方法得到茎的位置,避免识别位置错误
 v0.6.15 修改抓取点识别方法,通过比较直线点云和原始点云相同位置邻域内xz的范围,确定此点是否是无干扰点的茎
-v0.6.16 加强苗的识别,增加倾斜苗的检测,修改排序错乱问题
+v0.6.16 加强苗的识别,增加倾斜苗的检测,修改排序错乱问题
+v0.7.0 支持多线程调用业务接口
+v0.7.1 增加voxelsize参数;修改茎密度最大值的1/3为最小茎密度的下限(原来为1/2,有些小苗识别不出来)

+ 8 - 2
config.cpp

@@ -105,6 +105,7 @@ namespace graft_cv{
 			<< "rs_grab_y_opt" << m_cparam->rs_grab_y_opt
 			<< "rs_grab_seedling_dist" << m_cparam->rs_grab_seedling_dist
 			<< "rs_grab_stem_min_pts" << m_cparam->rs_grab_stem_min_pts
+			<< "rs_grab_voxel_size" << m_cparam->rs_grab_voxel_size
 
 			<< "sc_grab_xmin" << m_cparam->sc_grab_xmin
 			<< "sc_grab_xmax" << m_cparam->sc_grab_xmax
@@ -116,6 +117,7 @@ namespace graft_cv{
 			<< "sc_grab_y_opt" << m_cparam->sc_grab_y_opt
 			<< "sc_grab_seedling_dist" << m_cparam->sc_grab_seedling_dist
 			<< "sc_grab_stem_min_pts" << m_cparam->sc_grab_stem_min_pts
+			<< "sc_grab_voxel_size" << m_cparam->sc_grab_voxel_size
 			<< "}"; 	
 	};
 	void CGCvConfig::read(const cv::FileNode& node){ //Read serialization for this class
@@ -203,7 +205,8 @@ namespace graft_cv{
 		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_seedling_dist = (double)node["rs_grab_seedling_dist"];
-		m_cparam->rs_grab_stem_min_pts = (double)node["rs_grab_stem_min_pts"];
+		m_cparam->rs_grab_stem_min_pts = (int)node["rs_grab_stem_min_pts"];
+		m_cparam->rs_grab_voxel_size = (double)node["rs_grab_voxel_size"];
 
 		m_cparam->sc_grab_xmin = (double)node["sc_grab_xmin"];
 		m_cparam->sc_grab_xmax = (double)node["sc_grab_xmax"];
@@ -214,7 +217,8 @@ namespace graft_cv{
 		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_seedling_dist = (double)node["sc_grab_seedling_dist"];
-        m_cparam->sc_grab_stem_min_pts = (double)node["sc_grab_stem_min_pts"];
+        m_cparam->sc_grab_stem_min_pts = (int)node["sc_grab_stem_min_pts"];
+		m_cparam->sc_grab_voxel_size = (double)node["sc_grab_voxel_size"];
   }
 	string get_cparam_info(ConfigParam*m_cparam)
 	{
@@ -308,6 +312,7 @@ namespace graft_cv{
 			<< "rs_grab_y_opt:\t" << m_cparam->rs_grab_y_opt << 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_voxel_size:\t" << m_cparam->rs_grab_voxel_size << endl
 
 
 			<< "sc_grab_xmin:\t" << m_cparam->sc_grab_xmin << endl
@@ -320,6 +325,7 @@ namespace graft_cv{
 			<< "sc_grab_y_opt:\t" << m_cparam->sc_grab_y_opt << 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_voxel_size:\t" << m_cparam->sc_grab_voxel_size << endl
 			<< "}" << endl; 	
 		return buff.str();
 	}

+ 6 - 0
data_def_api.h

@@ -115,6 +115,7 @@ typedef struct{
 	double rs_grab_y_opt;
 	double rs_grab_seedling_dist;
 	int rs_grab_stem_min_pts;
+	double rs_grab_voxel_size;
 
 	// scion grab based points cloud
 	double sc_grab_xmin;
@@ -128,6 +129,7 @@ typedef struct{
 	double sc_grab_y_opt;
 	double sc_grab_seedling_dist;
 	int sc_grab_stem_min_pts;
+	double sc_grab_voxel_size;
 
 
 
@@ -140,6 +142,10 @@ typedef struct
 	double rs_grab_y;//砧木上苗抓取位置y,毫米
 	double rs_grab_z;//砧木上苗抓取位置z,毫米
 
+	double sc_grab_x;//穗苗上苗抓取位置x,毫米
+	double sc_grab_y;//穗苗上苗抓取位置y,毫米
+	double sc_grab_z;//穗苗上苗抓取位置z,毫米
+
 	double rs_oa;//砧木最优角度
 	//double rs_oa_base;//砧木基质最优角度
 	//double rs_oa_stem_y_fork;//茎分叉点y,毫米

+ 10 - 8
gcv_conf.yml

@@ -68,22 +68,24 @@ conf_parameters:
    rs_grab_xmin: -200
    rs_grab_xmax: 200
    rs_grab_ymin: -45
-   rs_grab_ymax: 30
+   rs_grab_ymax: 0
    rs_grab_zmin: 300
-   rs_grab_zmax: 450
+   rs_grab_zmax: 400
    rs_grab_stem_diameter: 5.0
    rs_grab_y_opt: -30
    rs_grab_seedling_dist: 40.0
-   rs_grab_stem_min_pts: 40
+   rs_grab_stem_min_pts: 50
+   rs_grab_voxel_size: 0.02
    sc_grab_xmin: -200
    sc_grab_xmax: 200
-   sc_grab_ymin: -50
-   sc_grab_ymax: 30
+   sc_grab_ymin: -45
+   sc_grab_ymax: -15
    sc_grab_zmin: 300
-   sc_grab_zmax: 500
+   sc_grab_zmax: 400
    sc_grab_stem_diameter: 5.0
-   sc_grab_y_opt: -10
+   sc_grab_y_opt: -20
    sc_grab_seedling_dist: 40.0
-   sc_grab_stem_min_pts: 35
+   sc_grab_stem_min_pts: 30
+   sc_grab_voxel_size: 0.02
    
 

+ 16 - 6
grab_point_rs.cpp

@@ -196,7 +196,10 @@ namespace graft_cv {
 		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_dowm_sampled(new pcl::PointCloud<pcl::PointXYZ>);
 		pcl::VoxelGrid<pcl::PointXYZ> outrem;
 		outrem.setInputCloud(cloud_ror);
-		outrem.setLeafSize(stem_radius, stem_radius, stem_radius);
+		//outrem.setLeafSize(stem_radius, stem_radius, stem_radius);
+		double voxel_size = m_cparam.rs_grab_voxel_size;
+		if (m_dtype == 0) { voxel_size = m_cparam.sc_grab_voxel_size; }
+		outrem.setLeafSize(voxel_size, voxel_size, voxel_size);
 		outrem.filter(*cloud_dowm_sampled);
 
 		if (m_pLogger) {
@@ -254,9 +257,16 @@ namespace graft_cv {
 		if (m_pLogger) {
 			m_pLogger->INFO("end get_optimal_seed");
 		}
-		posinfo.rs_grab_x = selected_pt.x;
-		posinfo.rs_grab_y = selected_pt.y;
-		posinfo.rs_grab_z = selected_pt.z;
+		if (m_dtype == 0) {
+			posinfo.sc_grab_x = selected_pt.x;
+			posinfo.sc_grab_y = selected_pt.y;
+			posinfo.sc_grab_z = selected_pt.z;
+		}
+		else {
+			posinfo.rs_grab_x = selected_pt.x;
+			posinfo.rs_grab_y = selected_pt.y;
+			posinfo.rs_grab_z = selected_pt.z;
+		}
 
 		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 		//6 debug 显示结果
@@ -731,13 +741,13 @@ void CRootStockGrabPoint::line_filter(
 			box_filter.filter(inbox_idx);
 			pcl::copyPointCloud(*in_cloud, inbox_idx, *seedling_inbox);
 			//点数过滤
-			if (inbox_idx.size() < int(max_density/2)) { continue; }
+			if (inbox_idx.size() < int(max_density/3)) { continue; }
 			//y方向分布范围滤波
 			pcl::PointXYZ min_v;
 			pcl::PointXYZ max_v;
 			pcl::getMinMax3D(*seedling_inbox, min_v, max_v);
 			float dy = max_v.y - min_v.y;
-			if (dy / (ymax - ymin) < 0.5) { continue; }
+			if (dy / (ymax - ymin) < 0.35) { continue; }
 			//y方向分布中心滤波
 			float dy_c = 0.5*(max_v.y + min_v.y);
 			if ((dy_c-ymin) / (ymax - ymin) > 0.75) { continue; }

+ 77 - 20
graft_cv_api.cpp

@@ -19,7 +19,7 @@ extern CRITICAL_SECTION g_cs;
 namespace graft_cv
 {
 
-	char *g_version_str = "0.6.16";
+	char *g_version_str = "0.7.1";
 
 	//configure
 	string g_conf_file = "./gcv_conf.yml";	
@@ -44,12 +44,13 @@ namespace graft_cv
 	CRootStockCutPointReid g_rs_cp_reid = CRootStockCutPointReid(g_cp,&g_logger);
 	CScionCutPoint g_sc_cp = CScionCutPoint(g_cp,&g_logger);
 
-	CRootStockGrabPoint g_rs_gp(g_cp, &g_logger);
+	CRootStockGrabPoint g_sola_grab_rs(g_cp, &g_logger);
+	CRootStockGrabPoint g_sola_grab_sc(g_cp, &g_logger);
 
-	CSolaCutPointReid g_sola_rs = CSolaCutPointReid(g_cp, 1, &g_logger);
-	CSolaCutPointReid g_sola_sc = CSolaCutPointReid(g_cp, 0, &g_logger);
+	CSolaCutPointReid g_sola_reid_rs = CSolaCutPointReid(g_cp, 1, &g_logger);
+	CSolaCutPointReid g_sola_reid_sc = CSolaCutPointReid(g_cp, 0, &g_logger);
 
-	//
+	//??¶àÏß³ÌÓÐÎÊÌâ
 	map<string, cv::Mat> g_img_cache;
 	
 
@@ -140,9 +141,10 @@ namespace graft_cv
 		g_oa.set_image_saver(&g_pImStore);
 		g_rs_cp.set_image_saver(&g_pImStore);
 		g_sc_cp.set_image_saver(&g_pImStore);
-		g_rs_gp.set_image_saver(&g_pImStore);
-		g_sola_rs.set_image_saver(&g_pImStore);
-		g_sola_rs.set_image_saver(&g_pImStore);		
+		g_sola_grab_rs.set_image_saver(&g_pImStore);
+		g_sola_grab_sc.set_image_saver(&g_pImStore);
+		g_sola_reid_rs.set_image_saver(&g_pImStore);
+		g_sola_reid_sc.set_image_saver(&g_pImStore);		
 		return 0;
 	}
 
@@ -296,23 +298,23 @@ namespace graft_cv
 		return 0;
 	};*/
 	//
-	int sola_grab_point(
+	int sola_grab_point_rs(
 		float* points,
 		int pixel_size,
-		int pt_size, 
-		int dtype,
+		int pt_size, 		
 		PositionInfo& posinfo,
 		const char* fn/*=0*/
 	)
 	{
 		memset(&posinfo, 0, sizeof(PositionInfo));
+		int dtype = 1;
 		try {
-			int rst = g_rs_gp.load_data(points, pixel_size, pt_size, fn);
+			int rst = g_sola_grab_rs.load_data(points, pixel_size, pt_size, fn);
 			if (rst <= 0) {
 				g_logger.ERRORINFO("invalid points");
 				return 1;
 			}
-			int oa = g_rs_gp.grab_point_detect(dtype, posinfo);
+			int oa = g_sola_grab_rs.grab_point_detect(dtype, posinfo);
 			if (oa != 0) {
 				g_logger.ERRORINFO("no points");
 				return 1;
@@ -334,6 +336,43 @@ namespace graft_cv
 
 	}
 
+	int sola_grab_point_sc(
+		float* points,
+		int pixel_size,
+		int pt_size,		
+		PositionInfo& posinfo,
+		const char* fn/*=0*/
+	)
+	{
+		memset(&posinfo, 0, sizeof(PositionInfo));
+		int dtype = 0;
+		try {
+			int rst = g_sola_grab_sc.load_data(points, pixel_size, pt_size, fn);
+			if (rst <= 0) {
+				g_logger.ERRORINFO("invalid points");
+				return 1;
+			}
+			int oa = g_sola_grab_sc.grab_point_detect(dtype, posinfo);
+			if (oa != 0) {
+				g_logger.ERRORINFO("no points");
+				return 1;
+			}
+		}
+		catch (std::exception &err) {
+			g_logger.ERRORINFO(err.what());
+			return 1;
+		}
+		catch (string& msg) {
+			g_logger.ERRORINFO(msg);
+			return 1;
+		}
+		catch (...) {
+			g_logger.ERRORINFO("unknown error");
+			return 1;
+		}
+		return 0;
+
+	}
 
 	//9
 	int rs_oa_get_result(
@@ -422,16 +461,34 @@ namespace graft_cv
 	}
 
 	// 
-	int sola_cut_point_reid(ImgInfo*imginfo, int sola_type, PositionInfo& posinfo)
+	int sola_cut_point_reid_rs(ImgInfo*imginfo, PositionInfo& posinfo)
 	{
 		memset(&posinfo, 0, sizeof(PositionInfo));
+		int sola_type = 1;
 		try {
-			if (sola_type == 0) {
-				g_sola_sc.cut_point_reid(imginfo, cv::Mat(), posinfo);
-			}
-			else {
-				g_sola_rs.cut_point_reid(imginfo, cv::Mat(), posinfo);
-			}			
+			g_sola_reid_rs.cut_point_reid(imginfo, cv::Mat(), posinfo);
+		}
+		catch (std::exception &err) {
+			g_logger.ERRORINFO(err.what());
+			return 1;
+		}
+		catch (string& msg) {
+			g_logger.ERRORINFO(msg);
+			return 1;
+		}
+		catch (...) {
+			g_logger.ERRORINFO("unknown error");
+			return 1;
+		}
+		return 0;
+	}
+
+	int sola_cut_point_reid_sc(ImgInfo*imginfo, PositionInfo& posinfo)
+	{
+		memset(&posinfo, 0, sizeof(PositionInfo));
+		int sola_type = 0;
+		try {
+			g_sola_reid_sc.cut_point_reid(imginfo, cv::Mat(), posinfo);
 		}
 		catch (std::exception &err) {
 			g_logger.ERRORINFO(err.what());

+ 4 - 3
graft_cv_api.h

@@ -77,8 +77,8 @@ GCV_API void get_version(char* buf);
 //				posinfo.rs_pre_z;
 //				其余数据为0
 //  返回: 0- 正常; 其他- 失败
-GCV_API int sola_grab_point(float* points, int pixel_size, int pt_size, int dtype, PositionInfo& posinfo, const char* fn=0);
-
+GCV_API int sola_grab_point_rs(float* points, int pixel_size, int pt_size, PositionInfo& posinfo, const char* fn=0);
+GCV_API int sola_grab_point_sc(float* points, int pixel_size, int pt_size, PositionInfo& posinfo, const char* fn = 0);
 
 
 //12  砧木最优角度识别,追加图像,要求图像的角度按顺序,第一帧图像角度为0,最后一帧图像角度为180
@@ -152,7 +152,8 @@ GCV_API int rs_cut_point_reid(ImgInfo*, const char* pre_img_id, PositionInfo& po
 //                           图1: 灰度图像,拟合椭圆
 //                            
 //   返回: 0- 正常; 1- 失败
-GCV_API int sola_cut_point_reid(ImgInfo*, int sola_type, PositionInfo& posinfo);
+GCV_API int sola_cut_point_reid_rs(ImgInfo*, PositionInfo& posinfo);
+GCV_API int sola_cut_point_reid_sc(ImgInfo*, PositionInfo& posinfo);
 
 
 

+ 3 - 1
imstorage_manager.cpp

@@ -249,11 +249,13 @@ int CImStoreManager::saveBinPly(
 {
 	if (!is_valid_folder()) { return 1; }
 	if (pcd->points.size()==0) { return 1; }
+	
+	EnterCriticalSection(&g_cs_pcd);
 	string tar_file = m_storeDir + "/" + name_id + ".ply";		
 	PcdParam pcdp;
 	pcdp.pcd_name = tar_file;
 	pcl::copyPointCloud(*pcd, pcdp.pcd);	
-	EnterCriticalSection(&g_cs_pcd);
+	
 	m_pcds.push(pcdp);
 	//cout<<"=========="<<pcdp.pcd_name<<endl;
 	LeaveCriticalSection(&g_cs_pcd);

+ 4 - 0
logger.cpp

@@ -7,6 +7,7 @@ namespace graft_cv{
 		:m_target(terminal)
 		,m_level(debug)
 		,m_outfile(ofs)
+		,m_pMtx(new std::mutex())
 	{
 		cout<<currTime()<<" [WELCOME] ===========start logger==========="<<endl;
 	}
@@ -15,6 +16,7 @@ namespace graft_cv{
 		,m_level(level)
 		,m_path(path)
 		,m_outfile(ofs)
+		, m_pMtx(new std::mutex())
 	{
 		string tmp = currTime() +" [WELCOME] ===========start logger===========\n";
 		if(m_target !=terminal){
@@ -40,6 +42,7 @@ namespace graft_cv{
 	}
 	void CGcvLogger::output(string text, log_level act_level)
 	{
+		m_pMtx->lock();
 		string prefix;
 		if(act_level == debug){
 			prefix = " [DEBUG] ";
@@ -65,6 +68,7 @@ namespace graft_cv{
 			m_outfile<< output_content;
 			m_outfile.flush();
 		}
+		m_pMtx->unlock();
 	}
 
 	void CGcvLogger::DEBUG(string text)

+ 3 - 0
logger.h

@@ -4,6 +4,7 @@
 #include <string>
 
 #include <fstream>
+#include <mutex>
 
 using namespace std;
 
@@ -18,6 +19,8 @@ namespace graft_cv{
 		log_target m_target;
 		string m_path;
 		log_level m_level;
+		std::shared_ptr<std::mutex> m_pMtx;
+
 		void output(string text, log_level act_level);
 	public:
 		CGcvLogger(ofstream&);