Преглед на файлове

v0.6.12 增加茄科抓取目标大小判断,太小的目标跳出;增加自动ply数据保存功能;茄科切后重识别图片保存功能

chenhongjiang преди 1 година
родител
ревизия
aff9b53f98
променени са 10 файла, в които са добавени 135 реда и са изтрити 13 реда
  1. 3 1
      ReadMe.txt
  2. 15 1
      cut_point_rs_reid.cpp
  3. 1 0
      cut_point_rs_reid.h
  4. 1 1
      data_def.h
  5. 2 2
      gcv_conf.yml
  6. 16 4
      grab_point_rs.cpp
  7. 5 0
      grab_point_rs.h
  8. 4 1
      graft_cv_api.cpp
  9. 68 3
      imstorage_manager.cpp
  10. 20 0
      imstorage_manager.h

+ 3 - 1
ReadMe.txt

@@ -78,4 +78,6 @@ v0.6.6 
 v0.6.7 修改点云显示代码,显示抓取点xy方向,及z平面上的xoy坐标系
 v0.6.8 增加穗苗的inbox定义,增加最优茎高的定义;修改vector随机读取[]为at方法;增加接口参数用于定义抓取苗是砧木还是穗苗;修改了接口函数名称
 v0.6.9 修改抓取砧木、穗苗的定义0--穗苗,1--砧木;穗苗和砧木抓取顺序相反
-v0.6.10 重写砧木、穗苗切后重识别算法,现在用切后侧面图,输出夹爪基面y值、切后3点y与基面y值的距离
+v0.6.10 重写砧木、穗苗切后重识别算法,现在用切后侧面图,输出夹爪基面y值、切后3点y与基面y值的距离
+v0.6.11 增加茄科切后重识别异常退出判断
+v0.6.12 增加茄科抓取目标大小判断,太小的目标跳出;增加自动ply数据保存功能;茄科切后重识别图片保存功能

+ 15 - 1
cut_point_rs_reid.cpp

@@ -421,6 +421,20 @@ int CSolaCutPointReid::cut_point_reid(
 	find_cut_ys(contours[max_idx],
 			minx,  maxx, miny, maxy,
 			cut_miny, cut_midy, cut_maxy);
+	int box_width, box_height;
+	box_width = abs(maxx - minx);
+	box_height = abs(maxy - miny);
+	if (box_width < 5) {
+		throw_msg(m_imgId + " no valid object");
+	}
+	float hw_ratio = (float)(box_height) / (float)(box_width);
+	if (hw_ratio < 1.0) {
+		throw_msg(m_imgId + " no valid object");
+	}
+	float area_th = (float)(m_grayImg.rows*m_grayImg.cols) / 5.0;
+	if (max_area > area_th) {
+		throw_msg(m_imgId + " no valid object");
+	}
 
     // 夹爪基面的y
 	int base_y = maxy;	//	砧木情况
@@ -541,7 +555,7 @@ void CSolaCutPointReid::find_cut_ys(
     //计算茎的直径
 	std::vector<int> hist_width_copy(hist_width);
 	sort(hist_width_copy.begin(), hist_width_copy.end());
-	int pert_idx = int(0.98*hist_width_copy.size());
+	int pert_idx = int(0.95*hist_width_copy.size());
 	int stem_width = hist_width_copy.at(pert_idx);
 
 	int max_idx = max_element(hist.begin(), hist.end()) - hist.begin();

+ 1 - 0
cut_point_rs_reid.h

@@ -56,6 +56,7 @@ public:
 		cv::Mat&,					//切后图片,测试用		
 		PositionInfo& posinfo
 	);
+	void set_image_saver(CImStoreManager** ppis) { m_ppImgSaver = ppis; }
 private:
 	int m_stem_type; //植株类别:0--穗苗;1--砧木
 					 //global configure parameters

+ 1 - 1
data_def.h

@@ -3,7 +3,7 @@
 namespace graft_cv{
 	extern char *g_version_str;
 	//enum camera {rs_clamp_rad, rs_clamp_tan, rs_cut_rad, rs_cut_tan, sc_clamp_rad, sc_clamp_tan, sc_cut_rad, sc_cut_tan};
-	enum img_type {oa,rs,rs_reid,sc,sola_rs_reid, sola_sc_reid };
+	enum img_type {oa,rs,rs_reid,sc,sola_rs_reid, sola_sc_reid, sola_rs_pcd, sola_sc_pcd};
 	template<class T>
 	class roi_box{
 	public:

+ 2 - 2
gcv_conf.yml

@@ -67,8 +67,8 @@ conf_parameters:
    sc_cut_pixel_ratio: 8.7499999999999994e-002
    rs_grab_xmin: -200
    rs_grab_xmax: 200
-   rs_grab_ymin: -150
-   rs_grab_ymax: 150
+   rs_grab_ymin: 0
+   rs_grab_ymax: 50
    rs_grab_zmin: 200
    rs_grab_zmax: 320
    rs_grab_stem_diameter: 5.0

+ 16 - 4
grab_point_rs.cpp

@@ -28,7 +28,9 @@ namespace graft_cv {
 	CRootStockGrabPoint::CRootStockGrabPoint(ConfigParam&cp, CGcvLogger*pLog/*=0*/)
 		:m_cparam(cp),
 		m_pLogger(pLog),
-		m_dtype(0)
+		m_dtype(0),
+		m_pcdId(""),
+		m_ppImgSaver(0)
 	{
 	}
 
@@ -79,8 +81,18 @@ namespace graft_cv {
 			}
 		}	
 
+		if (m_dtype == 0) {
+			m_pcdId = getImgId(img_type::sola_sc_pcd);
+		}
+		else {
+			m_pcdId = getImgId(img_type::sola_rs_pcd);
+		}
+
+		if (m_ppImgSaver && *m_ppImgSaver) {
+			(*m_ppImgSaver)->saveBinPly(m_raw_cloud, m_pcdId);
+		}
 		if (m_cparam.image_show) {
-			viewer_cloud(m_raw_cloud, std::string("raw point cloud"));
+			viewer_cloud(m_raw_cloud, std::string("raw point cloud"));			
 		}
 		return rst;
 	}
@@ -181,10 +193,10 @@ namespace graft_cv {
 
 		if (m_pLogger) {
 			stringstream buff;
-			buff << "VoxelGrid dowm_sampled point cloud " << cloud_dowm_sampled->width * cloud_dowm_sampled->height << " data points";
+			buff << "VoxelGrid dowm_sampled point cloud " << cloud_dowm_sampled->width * cloud_dowm_sampled->height << " data points (if < 200, return)";
 			m_pLogger->INFO(buff.str());
 		}
-		if (cloud_dowm_sampled->width * cloud_dowm_sampled->height < 1) {
+		if (cloud_dowm_sampled->width * cloud_dowm_sampled->height < 200) {
 			return 1;
 		}
 

+ 5 - 0
grab_point_rs.h

@@ -5,6 +5,7 @@
 #include "data_def_api.h"
 #include "data_def.h"
 #include "logger.h"
+#include "imstorage_manager.h"
 
 namespace graft_cv {
 	class CRootStockGrabPoint {
@@ -14,11 +15,15 @@ namespace graft_cv {
 		int grab_point_detect( int dtype, PositionInfo& posinfo);
 		float* get_raw_point_cloud(int &data_size);
 		int load_data(float*pPoint, int pixel_size, int pt_size, const char* fn = 0);
+		void set_image_saver(CImStoreManager** ppis) { m_ppImgSaver = ppis; }
 	private:
 		//global configure parameters
 		ConfigParam& m_cparam;
 		CGcvLogger * m_pLogger;
 		int m_dtype;
+		string m_pcdId;
+
+		CImStoreManager** m_ppImgSaver;
 
 		pcl::PointCloud<pcl::PointXYZ>::Ptr m_raw_cloud;
 

+ 4 - 1
graft_cv_api.cpp

@@ -19,7 +19,7 @@ extern CRITICAL_SECTION g_cs;
 namespace graft_cv
 {
 
-	char *g_version_str = "0.6.10";
+	char *g_version_str = "0.6.12";
 
 	//configure
 	string g_conf_file = "./gcv_conf.yml";	
@@ -140,6 +140,9 @@ 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);		
 		return 0;
 	}
 

+ 68 - 3
imstorage_manager.cpp

@@ -2,6 +2,8 @@
 #include <io.h>
 #include <time.h>
 #include <stdio.h>
+#include <pcl\io\ply_io.h>
+#include <pcl\point_types.h>
 #include "imstorage_manager.h"
 
 //namespace graft_gcv
@@ -9,6 +11,7 @@
 
 
 CRITICAL_SECTION g_cs;
+CRITICAL_SECTION g_cs_pcd;
 
 void getFiles( string path, vector<string>& files, time_t clean_time )
 {
@@ -40,6 +43,7 @@ void getFiles( string path, vector<string>& files, time_t clean_time )
 }
 bool g_thread_run=false;
 bool g_thread_run_saver=true;
+bool g_thread_run_saver_pcd = true;
 int WINAPI TheadFuncClearn(LPVOID lpParam)
 {
     ThreadParamClean*  threadParam = (ThreadParamClean *) lpParam;    
@@ -95,12 +99,39 @@ int WINAPI TheadFuncSave(LPVOID lpParam)
     }
     return 0;
 }
+int WINAPI TheadFuncSavePcd(LPVOID lpParam)
+{
+	ThreadParamSavePcd*  threadParam = (ThreadParamSavePcd *)lpParam;
+	int nIndex = threadParam->nIndex;
+	queue<PcdParam>* pcdQ = threadParam->pcdQ;
+	while (true)
+	{
+		if (!g_thread_run_saver_pcd) { break; }
+		if (pcdQ->size() == 0) {
+			Sleep(50);
+			continue;
+		}
+		try {
+			EnterCriticalSection(&g_cs_pcd);
+			PcdParam& pcd_info = pcdQ->front();
+			pcl::io::savePLYFile(pcd_info.pcd_name, pcd_info.pcd, true);			
+			//cout<<im_info.img_name<<"\t"<<imgQ->size()<<endl;
+			pcdQ->pop();
+		}
+		catch (...) {
+			//int tes = 0;
+		}
+		LeaveCriticalSection(&g_cs_pcd);
+	}
+	return 0;
+}
 	
 CImStoreManager::CImStoreManager()
 	:m_storeDays(7)
 	,m_storeDir(""),
 	m_workHandle(0),
-	m_workHandleSave(0)
+	m_workHandleSave(0),
+	m_workHandleSavePcd(0)
 {	
 	InitializeCriticalSection(&g_cs);
 	ThreadParamSave paramSave;
@@ -114,16 +145,32 @@ CImStoreManager::CImStoreManager()
 		(LPVOID)&paramSave, 
 		NULL, 
 		NULL);
+
+	InitializeCriticalSection(&g_cs_pcd);
+	ThreadParamSavePcd paramSavePcd;
+	paramSavePcd.nIndex = 0;
+	//paramSave.state = &g_thread_run;
+	paramSavePcd.pcdQ = &m_pcds;
+	m_workHandleSavePcd = CreateThread(
+		NULL,
+		0,
+		(LPTHREAD_START_ROUTINE)TheadFuncSavePcd,
+		(LPVOID)&paramSavePcd,
+		NULL,
+		NULL);
 	Sleep(500);
 }
 CImStoreManager::~CImStoreManager(){
 	g_thread_run=false;
 	g_thread_run_saver=false;
-	HANDLE handles[2];
+	g_thread_run_saver_pcd = false;
+	HANDLE handles[3];
 	handles[0]=m_workHandle;
 	handles[1]=m_workHandleSave;
-	WaitForMultipleObjects(2,handles,TRUE,500);
+	handles[2] = m_workHandleSavePcd;
+	WaitForMultipleObjects(3,handles,TRUE,500);
 	DeleteCriticalSection(&g_cs);
+	DeleteCriticalSection(&g_cs_pcd);
 
 }
 
@@ -195,4 +242,22 @@ int CImStoreManager::saveImage(cv::Mat&img,string name_id)
 	
 	return 0;
 }
+
+int CImStoreManager::saveBinPly(
+	pcl::PointCloud<pcl::PointXYZ>::Ptr pcd, 
+	string name_id)
+{
+	if (!is_valid_folder()) { return 1; }
+	if (pcd->points.size()==0) { return 1; }
+	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);
+
+	return 0;
+}
 //};

+ 20 - 0
imstorage_manager.h

@@ -4,6 +4,8 @@
 #include <opencv2\opencv.hpp>
 #include <windows.h>
 #include <queue> 
+#include <pcl\point_types.h>
+#include <pcl\point_cloud.h>
 
 //using namespace cv;
 using namespace std;
@@ -16,6 +18,13 @@ typedef struct
 	cv::Mat image;
 } ImgParam;
 
+typedef struct
+{
+	string pcd_name;
+	pcl::PointCloud<pcl::PointXYZ> pcd;
+} PcdParam;
+
+
 typedef struct 
 {	
     int nIndex;
@@ -23,6 +32,13 @@ typedef struct
         
 } ThreadParamSave;
 
+typedef struct
+{
+	int nIndex;
+	queue<PcdParam>* pcdQ;
+
+} ThreadParamSavePcd;
+
 typedef struct 
 {	
     string folder;
@@ -33,6 +49,7 @@ typedef struct
 
 int WINAPI TheadFuncClearn(LPVOID lpParam);
 int WINAPI TheadFuncSave(LPVOID lpParam);
+int WINAPI TheadFuncSavePcd(LPVOID lpParam);
 void getFiles( string path, vector<string>& files, time_t clean_time);
 
 class CImStoreManager{
@@ -48,6 +65,7 @@ public:
 	//saveImage() return 0--ok, 1 -- invalid image or folder
 	int saveImage(cv::Mat&img,string name_id);
 	void restart_start_worker();
+	int saveBinPly(pcl::PointCloud<pcl::PointXYZ>::Ptr pcd, string name_id);
 
 
 protected:
@@ -56,7 +74,9 @@ protected:
 	bool is_valid_folder();
 	HANDLE m_workHandle;
 	HANDLE m_workHandleSave;
+	HANDLE m_workHandleSavePcd;
 	queue<ImgParam> m_images;
+	queue<PcdParam> m_pcds;
 };
 
 //};