Переглянути джерело

v0.8.17 修改内存报错的bug

chenhongjiang 1 рік тому
батько
коміт
583837af88
7 змінених файлів з 107 додано та 384 видалено
  1. 2 1
      ReadMe.txt
  2. 65 363
      grab_occlusion.cpp
  3. 1 0
      grab_occlusion.h
  4. 14 10
      grab_point_rs.cpp
  5. 1 1
      graft_cv_api.cpp
  6. 23 8
      utils.cpp
  7. 1 1
      utils.h

+ 2 - 1
ReadMe.txt

@@ -125,4 +125,5 @@ v0.8.12 优化茎粗检测功能,采用xy面投影茎粗统计结果
 v0.8.13 优化茎粗检测功能,采用茎两侧边缘点构建直线,计算直线间距离,再用点云平均距离进行补偿
 v0.8.14 优化茎粗检测功能,增加xx_grab_offset_cut, 在ybt、yup中间点进行偏移,在这个位置计算茎粗;茎edge直线拟合,剔除茎节的影响
 v0.8.15 优化茎节检测功能,增加xx_grab_fork_height,控制识别较长的茎节
-v0.8.16 修改茎节检测中while循环死循环的bug
+v0.8.16 修改茎节检测中while循环死循环的bug
+v0.8.17 修改内存报错的bug

+ 65 - 363
grab_occlusion.cpp

@@ -98,173 +98,6 @@ namespace graft_cv {
 		}
 	}
 
-	//void CStemResultInfos::_update_root_centers() {
-	//	//依据m_infos中的数据,苗间距m_seedling_dist,聚类生成茎的平均位置,茎的点云平均数量
-	//	//更新m_root_centers
-
-	//	//以root_center为基础进行聚类,如果root_center是空的,因当前数据进行聚类
-	//	std::vector<CStemResult> root_centers;
-	//	double d1 = m_seedling_dist / 2.0;
-	//	double d2 = d1*1.75;
-	//	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2d_pos(new pcl::PointCloud < pcl::PointXYZ>);
-	//	for (auto&sr : m_infos) {
-	//		cloud2d_pos->points.push_back(pcl::PointXYZ((float)sr.root_x, 0.0, (float)sr.root_z));
-	//	}
-	//	cloud2d_pos->width = cloud2d_pos->points.size();
-	//	std::vector<pcl::PointXYZ>cluster_center;
-	//	std::vector<std::vector<int>> cluster_member;
-	//	euclidean_clustering_ttsas(cloud2d_pos, d1, d2, cluster_center, cluster_member);
-
-	//	for (size_t i = 0; i < cluster_center.size(); ++i) {
-	//		double x = (double)cluster_center.at(i).x;
-	//		double y = (double)cluster_center.at(i).y;
-	//		double z = (double)cluster_center.at(i).z;
-	//		int count = (int)cluster_member.at(i).size();
-	//		int pc_size = 0.0;
-	//		for (auto& idx : cluster_member.at(i)) {
-	//			pc_size += m_infos.at(idx).stem_size;
-	//		}
-	//		pc_size = (int)(pc_size / (float)count);
-
-	//		CStemResult sr = CStemResult(x, y, z, pc_size, std::string(""), count);
-	//		root_centers.push_back(sr);
-	//	}
-
-	//	if (m_root_centers.size() == 0) {
-	//		//如果没有历史数据,直接赋值
-	//		m_root_centers = root_centers;
-	//	}
-	//	else {
-	//		if (m_infos.size() > 50) {
-	//			//如果当前数据量较大,用当前的结果
-	//			m_root_centers = root_centers;
-	//		}
-	//		else {
-	//			//否则将当前结果合并到m_root_centers
-	//			//m_root_centers
-	//			for (auto& cent : root_centers) {					
-	//				double dist_min = d2;
-	//				int min_root_idx = 0;
-
-	//				for (int j = 0; j < m_root_centers.size();++j) {
-	//					CStemResult& root = m_root_centers.at(j);
-	//					double dist = root.calcluate_distance(cent);
-	//					if (dist < dist_min) {
-	//						dist_min = dist;
-	//						min_root_idx = j;
-	//					}
-	//				}
-	//				if (dist_min < d1) {
-	//					//merge
-	//					double mu_x, mu_y,mu_z;
-	//					CStemResult& min_root = m_root_centers.at(min_root_idx);
-	//					mu_x = (min_root.root_x * min_root.root_count +
-	//						cent.root_x * cent.root_count) / (double)(min_root.root_count + cent.root_count);
-
-	//					mu_y = (min_root.root_y * min_root.root_count +
-	//						cent.root_y * cent.root_count) / (double)(min_root.root_count + cent.root_count);
-
-	//					mu_z = (min_root.root_z * min_root.root_count +
-	//						cent.root_z * cent.root_count) / (double)(min_root.root_count + cent.root_count);
-
-	//					min_root.root_x = mu_x;
-	//					min_root.root_y = mu_y;
-	//					min_root.root_z = mu_z;
-	//					min_root.root_count += cent.root_count;
-	//				}
-	//				else {
-	//					//add root
-	//					m_root_centers.push_back(cent);
-	//				}
-	//			}
-	//		}
-	//	}
-	//	//m_root_centers 排序、剔除
-	//	std::sort(m_root_centers.begin(), m_root_centers.end(),
-	//		[](const CStemResult& sr1, const CStemResult& sr2) {return sr1.root_x < sr2.root_x; });
-	//	//nms		
-	//	_filter_root_centers(d1, d2);
-	//}
-	//void CStemResultInfos::_filter_root_centers(double d1, double d2)
-	//{
-	//	//对生成的根中心m_root_centers进行过滤,剔除异常
-	//	//1 z值,通过中值,距离中值远的剔除
-
-	//	if (m_root_centers.size() > 3) {
-	//		std::vector<double>root_z;
-	//		for (auto&rc : m_root_centers) {
-	//			root_z.push_back(rc.root_z);
-	//		}
-	//		std::sort(root_z.begin(), root_z.end());
-	//		double mid_z = 0.0;
-	//		if (root_z.size() % 2 == 1) {
-	//			int idx = (m_root_centers.size() - 1) / 2;
-	//			mid_z = root_z.at(idx);
-	//		}
-	//		else {
-	//			int idx = root_z.size() / 2;
-	//			mid_z = 0.5 * (root_z.at(idx) + root_z.at(idx - 1));
-	//		}
-	//		std::vector<CStemResult> valid_root_centers;
-	//		for (auto&rc : m_root_centers) {
-	//			if (fabs(rc.root_z - mid_z) < d2) {
-	//				valid_root_centers.push_back(rc);
-	//			}
-	//		}
-	//		m_root_centers = valid_root_centers;
-	//	}
-
-	//	//2 按x做分组,排除权重小的
-	//	if (m_root_centers.size() > 3) {
-	//		std::vector<double> center_dist;
-	//		for (int i = 0; i < m_root_centers.size(); ++i) {
-	//			double x = m_root_centers.at(i).root_x;
-	//			double mod_sum = 0.0;
-	//			for (int j = 0; j < m_root_centers.size(); ++j) {
-	//				double dist = fabs(m_root_centers.at(j).root_x - x);
-	//				double mod = fmod(dist, m_seedling_dist);
-	//				double mod_inv = m_seedling_dist - mod;
-	//				mod = min(mod, mod_inv);
-	//				mod_sum += mod;
-	//			}
-	//			mod_sum /= (m_root_centers.size() - 1);
-	//			center_dist.push_back(mod_sum);
-	//		}
-
-	//		std::vector<CStemResult> valid_root_centers;
-	//		for (int i = 0; i < center_dist.size(); ++i) {
-	//			double dist = center_dist.at(i);
-	//			if (dist < d1) {
-	//				valid_root_centers.push_back(m_root_centers.at(i));
-	//			}
-	//		}
-	//		m_root_centers = valid_root_centers;
-	//	}
-	//	//3 数量少的剔除
-	//	int total_count = 0;
-	//	for (auto&rc : m_root_centers) {
-	//		total_count += rc.root_count;
-	//	}
-	//	if (total_count > 50) {
-	//		bool need_del = false;
-	//		for (auto& rc : m_root_centers) {
-	//			if (rc.root_count <= 2) {
-	//				need_del = true;
-	//				break;
-	//			}
-	//		}
-	//		if (need_del) {
-	//			std::vector<CStemResult> valid_root_centers;
-	//			for (int i = 0; i < m_root_centers.size(); ++i) {					
-	//				if (m_root_centers.at(i).root_count > 2) {
-	//					valid_root_centers.push_back(m_root_centers.at(i));
-	//				}
-	//			}
-	//			m_root_centers = valid_root_centers;
-	//		}
-	//		
-	//	}
-	//}
 	void CStemResultInfos::gen_root_centers()
 	{
 		//根据 m_seedling_dist, m_holes_number, m_xmin, m_xmax生成初始的穴位中心
@@ -285,172 +118,7 @@ namespace graft_cv {
 			m_root_centers.push_back(sr);
 		}
 	}
-
-	//void CStemResultInfos::set_json_filename(std::string& filename) {
-	//	m_json_filename = std::string(filename);
-	//}
-	//void CStemResultInfos::read_root_centers(
-	//	std::string& filename
-	//) 
-	//{
-	//	//读取历史数据,每次启动时,去取
-	//	m_json_filename = std::string(filename);
-	//	//1 文件是否存在
-	//	ifstream f(filename.c_str());
-	//	if (!f.good()) {
-	//		//文件不存在
-	//		if (m_pLogger) {
-	//			stringstream buff;
-	//			buff << m_pcdId << ": json file not exists:" << filename;
-	//			m_pLogger->INFO(buff.str());
-	//		}
-	//		return;
-	//	}	
-
-	//	cv::FileStorage fs(filename, cv::FileStorage::READ);
-	//	cv::FileNode root_centers = fs["root_centers"];
-	//	cv::FileNodeIterator it = root_centers.begin(), it_end = root_centers.end();
-	//	m_root_centers.clear();
-	//	for (; it != it_end; ++it) {
-	//		double x = (double)(*it)["x"];
-	//		double y = (double)(*it)["y"];
-	//		double z = (double)(*it)["z"];
-	//		int size = (int)(*it)["size"];
-	//		std::string bid = (std::string)(*it)["batch_id"];
-	//		int count = (int)(*it)["count"];
-	//		CStemResult sr = CStemResult(x,y,z,size, bid, count);
-	//		m_root_centers.push_back(sr);
-	//	}
-	//	fs.release();
-
-	//}
-	//void CStemResultInfos::write_root_centers(
-	//	std::string& filename
-	//)
-	//{
-	//	cv::FileStorage fs(filename, cv::FileStorage::WRITE);
-	//	fs << "root_centers" << "[";
-	//	for (auto& sr : m_root_centers) {		
-	//		fs << "{" << "x" << sr.root_x
-	//			<< "y" << sr.root_y
-	//			<< "z" << sr.root_z
-	//			<< "size" << sr.stem_size
-	//			<< "batch_id" << sr.batch_id	
-	//			<< "count" << sr.root_count
-	//			<< "}";
-	//	}
-	//	fs << "]";
-	//	fs.release();
-
-	//}
-
-	//void CStemResultInfos::euclidean_clustering_ttsas(
-	//	pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
-	//	double d1, double d2,
-	//	std::vector<pcl::PointXYZ>&cluster_center,
-	//	std::vector<std::vector<int>> &clustr_member
-	//)
-	//{
-	//	if (m_pLogger) {
-	//		stringstream buff;
-	//		buff << m_pcdId << ": root center estimate: euclidean_clustering_ttsas() begin...";
-	//		m_pLogger->INFO(buff.str());
-	//	}
-	//	std::vector<int> cluster_weight;
-	//	std::vector<int> data_stat;
-
-	//	std::vector<pcl::PointXYZ>cluster_center_raw;
-	//	std::vector<std::vector<int>> clustr_member_raw;
-
-	//	for (size_t i = 0; i < in_cloud->points.size(); ++i) { data_stat.push_back(0); }
-	//	size_t data_len = in_cloud->points.size();
-	//	int exists_change = 0;
-	//	int prev_change = 0;
-	//	int cur_change = 0;
-	//	int m = 0;
-	//	while (std::find(data_stat.begin(), data_stat.end(), 0) != data_stat.end()) {
-	//		bool new_while_first = true;
-	//		for (size_t i = 0; i < data_len; ++i) {
-	//			if (data_stat.at(i) == 0 && new_while_first && exists_change == 0) {
-	//				new_while_first = false;
-	//				std::vector<int> idx;
-	//				idx.push_back(i);
-	//				clustr_member_raw.push_back(idx);
-	//				pcl::PointXYZ center;
-	//				center.x = in_cloud->points.at(i).x;
-	//				center.y = in_cloud->points.at(i).y;
-	//				center.z = in_cloud->points.at(i).z;
-
-	//				cluster_center_raw.push_back(center);
-	//				data_stat.at(i) = 1;
-	//				cur_change += 1;
-	//				cluster_weight.push_back(1);
-	//				m += 1;
-	//			}
-	//			else if (data_stat[i] == 0) {
-	//				std::vector<float> distances;
-	//				for (size_t j = 0; j < clustr_member_raw.size(); ++j) {
-	//					std::vector<float> distances_sub;
-	//					for (size_t jj = 0; jj < clustr_member_raw.at(j).size(); ++jj) {
-	//						size_t ele_idx = clustr_member_raw.at(j).at(jj);
-	//						double d = sqrt(
-	//							(in_cloud->points.at(i).x - in_cloud->points.at(ele_idx).x) * (in_cloud->points.at(i).x - in_cloud->points.at(ele_idx).x) +
-	//							(in_cloud->points.at(i).y - in_cloud->points.at(ele_idx).y) * (in_cloud->points.at(i).y - in_cloud->points.at(ele_idx).y) +
-	//							(in_cloud->points.at(i).z - in_cloud->points.at(ele_idx).z) * (in_cloud->points.at(i).z - in_cloud->points.at(ele_idx).z));
-	//						distances_sub.push_back(d);
-	//					}
-	//					double min_dist = *std::min_element(distances_sub.begin(), distances_sub.end());
-	//					distances.push_back(min_dist);
-	//				}
-	//				int min_idx = std::min_element(distances.begin(), distances.end()) - distances.begin();
-	//				if (distances.at(min_idx) < d1) {
-	//					data_stat.at(i) = 1;
-	//					double w = cluster_weight.at(min_idx);
-	//					cluster_weight.at(min_idx) += 1;
-	//					clustr_member_raw.at(min_idx).push_back(i);
-	//					cluster_center_raw.at(min_idx).x = (cluster_center_raw.at(min_idx).x * w + in_cloud->points.at(i).x) / (w + 1);
-	//					cluster_center_raw.at(min_idx).y = (cluster_center_raw.at(min_idx).y * w + in_cloud->points.at(i).y) / (w + 1);
-	//					cluster_center_raw.at(min_idx).z = (cluster_center_raw.at(min_idx).z * w + in_cloud->points.at(i).z) / (w + 1);
-	//					cur_change += 1;
-	//				}
-	//				else if (distances.at(min_idx) > d2) {
-	//					std::vector<int> idx;
-	//					idx.push_back(i);
-	//					clustr_member_raw.push_back(idx);
-	//					pcl::PointXYZ center;
-	//					center.x = in_cloud->points.at(i).x;
-	//					center.y = in_cloud->points.at(i).y;
-	//					center.z = in_cloud->points.at(i).z;
-
-	//					cluster_center_raw.push_back(center);
-	//					data_stat.at(i) = 1;
-	//					cur_change += 1;
-	//					cluster_weight.push_back(1);
-	//					m += 1;
-	//				}
-
-	//			}
-	//			else if (data_stat.at(i) == 1) {
-	//				cur_change += 1;
-	//			}
-	//		}
-	//		exists_change = fabs(cur_change - prev_change);
-	//		prev_change = cur_change;
-	//		cur_change = 0;
-	//	}
-
-	//	// copy result
-	//	for (size_t i = 0; i < clustr_member_raw.size(); ++i) {
-	//		//if (clustr_member_raw.at(i).size() < 20) { continue; }
-	//		cluster_center.push_back(cluster_center_raw.at(i));
-	//		clustr_member.push_back(clustr_member_raw.at(i));
-	//	}
-	//	if (m_pLogger) {
-	//		stringstream buff;
-	//		buff << m_pcdId << ":  root center estimate: euclidean_clustering_ttsas() end";
-	//		m_pLogger->INFO(buff.str());
-	//	}
-	//}
+	
 
 CSeedlingStatus::CSeedlingStatus(
 	int dtype,
@@ -465,6 +133,7 @@ CSeedlingStatus::CSeedlingStatus(
 	, m_xmin(x_min)
 	, m_xmax(x_max)
 	, m_record_cursor(-1)
+	, m_global_cursor(-1)
 	, m_max_size(50)
 	, m_pc_mean_dist(pc_mean_dist)
 {
@@ -504,11 +173,12 @@ void CSeedlingStatus::append_hist(
 )
 {
 	assert(xhist.size() == m_hist_length);
-	
-	if (m_record_cursor < m_max_size) {
+	m_global_cursor++;
+	if (m_record_cursor < m_max_size-1) {
 		m_record_cursor++;
 		float pc_size = 0.0;
 		for (int i = 0; i < xhist.size(); ++i) {
+			if (i >= m_hist_length) { continue; }
 			m_history_histogram.at<float>(m_record_cursor,i) = xhist.at(i);
 			pc_size += xhist.at(i);
 		}
@@ -517,22 +187,30 @@ void CSeedlingStatus::append_hist(
 	}
 	else {
 		//数据上移一行,数据放在最后一行
-		memcpy_s(m_history_histogram.data,
+		for (int row = 0; row < m_history_histogram.rows - 1; ++row) {
+			for (int col = 0; col < m_history_histogram.cols; ++col) {
+				m_history_histogram.at<float>(row, col) = m_history_histogram.at<float>(row + 1, col);
+			}
+		}
+		for (int row = 0; row < m_history_point_size.rows - 1; ++row) {
+			m_history_point_size.at<float>(row, 0) = m_history_point_size.at<float>(row+1, 0);
+		}
+		/*memcpy_s(m_history_histogram.data,
 			m_history_histogram.step[0] * (m_max_size - 1),
 			m_history_histogram.data + m_history_histogram.step[0], 
-			m_history_histogram.step[0] * (m_max_size - 1));
+			m_history_histogram.step[0] * (m_max_size - 1));*/
 
-		memcpy_s(m_history_point_size.data,
+		/*memcpy_s(m_history_point_size.data,
 			m_history_point_size.step[0] * (m_max_size - 1),
 			m_history_point_size.data + m_history_point_size.step[0],
-			m_history_point_size.step[0] * (m_max_size - 1));
+			m_history_point_size.step[0] * (m_max_size - 1));*/
 
 		float pc_size = 0.0;
 		for (int i = 0; i < xhist.size(); ++i) {
-			m_history_histogram.at<float>(m_max_size - 1, i) = float(xhist.at(i));
+			m_history_histogram.at<float>(m_history_histogram.rows - 1, i) = float(xhist.at(i));
 			pc_size += xhist.at(i);
 		}
-		m_history_point_size.at<float>(m_max_size - 1, 0) = pc_size;
+		m_history_point_size.at<float>(m_history_point_size.rows - 1, 0) = pc_size;
 		get_status(xstatus);
 	}
 	
@@ -541,8 +219,8 @@ void CSeedlingStatus::append_hist(
 void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
 {
 	xstatus.clear();
-	xstatus.assign(m_center_x.size(), false);
-
+	xstatus.assign(m_center_x.size(), false);		
+	
 	//1 如果没有记录输入,返回没有苗
 	if (m_record_cursor < 0) { return; }
 
@@ -582,7 +260,14 @@ void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
 	float sum_dn = 0.0;
 	float sum_n = 0.0;
 	float diff_cnt = 0.0;
-	if (m_record_cursor < m_max_size) {
+	for (int i = 0; i < m_hist_length; ++i) {
+		diff_cnt = m_history_histogram.at<float>(m_record_cursor - 1, i) -
+			m_history_histogram.at<float>(m_record_cursor, i);
+		hist_diff.at(i) = diff_cnt;
+		sum_n += diff_cnt;
+		sum_dn += diff_cnt * i;
+	}
+	/*if (m_record_cursor < m_max_size) {
 		for (int i = 0; i < m_hist_length; ++i) {
 			diff_cnt = m_history_histogram.at<float>(m_record_cursor - 1, i) - 
 				m_history_histogram.at<float>(m_record_cursor, i);
@@ -600,7 +285,7 @@ void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
 			sum_dn += diff_cnt * i;
 		}
 
-	}
+	}*/
 	
 	//3.2 统计增减点云的状态,区分点云增加,点云减小,点云没变化的部分
 	std::vector<int> hist_status_2d;	//3种状态记录: -1取走,0没变化,1上苗
@@ -625,17 +310,28 @@ void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
 	if (add_cnt > grid_one_seedling*3.0) {		
 		xstatus.assign(m_center_x.size(), true);
 		//update m_history_status
-		if (m_record_cursor < m_max_size) {
-			for (int i = 0; i < m_history_status.cols; ++i) {
-				m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
+		if (m_record_cursor == m_global_cursor) {
+			if (m_record_cursor < m_max_size) {
+				for (int i = 0; i < m_history_status.cols; ++i) {
+					m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
+				}
+			}
+			else {
+				
 			}
 		}
 		else {
-			memcpy_s(m_history_status.data,
+			//数据上移一行,数据放在最后一行
+			for (int row = 0; row < m_history_status.rows - 1; ++row) {
+				for (int col = 0; col < m_history_status.cols; ++col) {
+					m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
+				}
+			}
+			/*memcpy_s(m_history_status.data,
 				m_history_status.step[0] * (m_max_size - 1),
 				m_history_status.data + m_history_status.step[0],
 				m_history_status.step[0] * (m_max_size - 1));
-			
+			*/
 			for (int i = 0; i < m_history_status.cols; ++i) {
 				m_history_status.at<unsigned char>(m_max_size-1, i) = xstatus.at(i);
 			}
@@ -683,13 +379,7 @@ void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
 	}
 	if (sub_pos >= 0) {
 		xstatus.assign(m_center_x.size(), false);
-		int cursor = m_record_cursor - 1;
-		if (m_record_cursor < m_max_size) {
-			cursor = m_record_cursor - 1;		
-		}
-		else {
-			cursor = m_max_size - 1;			
-		}
+		int cursor = m_record_cursor-1;		
 		for (int i = 0; i < m_history_status.cols; ++i) {
 			if (m_history_status.at<unsigned char>(cursor, i) == 1) {
 				xstatus.at(i) = true;					
@@ -698,16 +388,22 @@ void CSeedlingStatus::get_status(std::vector<bool>&xstatus)
 		xstatus.at(sub_pos) = false;
 		
 		//update m_history_status
-		if (m_record_cursor < m_max_size) {
+		if (m_record_cursor == m_global_cursor) {
 			for (int i = 0; i < m_history_status.cols; ++i) {
 				m_history_status.at<unsigned char>(m_record_cursor, i) = xstatus.at(i);
 			}
 		}
 		else{
-			memcpy_s(m_history_status.data,
+			//数据上移一行,数据放在最后一行
+			for (int row = 0; row < m_history_status.rows - 1; ++row) {
+				for (int col = 0; col < m_history_status.cols; ++col) {
+					m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
+				}
+			}
+			/*memcpy_s(m_history_status.data,
 				m_history_status.step[0] * (m_max_size - 1),
 				m_history_status.data + m_history_status.step[0],
-				m_history_status.step[0] * (m_max_size - 1));
+				m_history_status.step[0] * (m_max_size - 1));*/
 			for (int i = 0; i < m_history_status.cols; ++i) {
 				m_history_status.at<unsigned char>(m_max_size - 1, i) = xstatus.at(i);
 			}
@@ -723,7 +419,7 @@ no_change:
 	//没有改变,用上一次的结果
 	xstatus.assign(m_center_x.size(), true);
 	//update m_history_status
-	if (m_record_cursor < m_max_size) {
+	if (m_record_cursor == m_global_cursor) {
 		for (int i = 0; i < m_history_status.cols; ++i) {
 			m_history_status.at<unsigned char>(m_record_cursor, i) = 
 				m_history_status.at<unsigned char>(m_record_cursor - 1, i);
@@ -733,10 +429,16 @@ no_change:
 		}
 	}
 	else{
-		memcpy_s(m_history_status.data,
+		//数据上移一行,数据放在最后一行
+		for (int row = 0; row < m_history_status.rows - 1; ++row) {
+			for (int col = 0; col < m_history_status.cols; ++col) {
+				m_history_status.at<float>(row, col) = m_history_status.at<float>(row + 1, col);
+			}
+		}
+		/*memcpy_s(m_history_status.data,
 			m_history_status.step[0] * (m_max_size - 1),
 			m_history_status.data + m_history_status.step[0],
-			m_history_status.step[0] * (m_max_size - 1));
+			m_history_status.step[0] * (m_max_size - 1));*/
 		for (int i = 0; i < m_history_status.cols; ++i) {
 			m_history_status.at<unsigned char>(m_max_size - 1, i) = 
 				m_history_status.at<unsigned char>(m_max_size - 2, i);

+ 1 - 0
grab_occlusion.h

@@ -111,6 +111,7 @@ namespace graft_cv {
 		CGcvLogger * m_pLogger;
 		int m_max_size;	//最大记录长度
 		int m_record_cursor;
+		int m_global_cursor;
 		cv::Mat m_history_histogram;	//历史点云x方向分布直方图
 		cv::Mat m_history_point_size;	//历史点云框内数量
 		cv::Mat m_history_status;		//历史穴位是有苗状态

+ 14 - 10
grab_point_rs.cpp

@@ -210,7 +210,7 @@ namespace graft_cv {
 		// 抓取位置识别入口函数,实现整个抓取位置识别功能,返回抓取位置信息
 		// dtype == 0, scion
 		// dtype != 0, rootstock
-		// 输入,穗苗--0, 砧木--1
+		// 输入,穗苗--0, 砧木--1		
 
 		if (m_raw_cloud->width * m_raw_cloud->height < 1) {
 			if (m_pLogger) {
@@ -290,7 +290,7 @@ namespace graft_cv {
 		if (m_pLogger) {
 			m_pLogger->INFO(m_pcdId + ": end ror");
 		}
-
+		
 		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 		//?? 用截取到的点云,初步找到植株的位置中心
 		m_root_centers.clear();
@@ -335,11 +335,10 @@ namespace graft_cv {
 			}
 			m_pSeedlingStatus->set_x_centers(root_cxs);
 		}
-
-		std::vector<int>xhist_inbox;		
-		get_point_x_hist(xhist_inbox);
-		m_pSeedlingStatus->append_hist(xhist_inbox, m_root_center_with_seedling_history);
 		
+		std::vector<int>xhist_inbox;		
+		get_point_x_hist(xhist_inbox);			
+		m_pSeedlingStatus->append_hist(xhist_inbox, m_root_center_with_seedling_history);		
 		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 		// 4 对截取的点云进行ror滤除大面积联通区域,剔除叶片
 		pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_dowm_sampled(new pcl::PointCloud<pcl::PointXYZ>);
@@ -502,9 +501,8 @@ namespace graft_cv {
 			(*m_ppImgSaver)->saveImage(rst_img, m_pcdId + "_rst_0");
 		}
 		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-		//8 页面显示结果
-		this->clear_imginfo();
-		m_pImginfoResult = mat2imginfo(rst_img);
+		//8 页面显示结果		
+		m_pImginfoResult = mat2imginfo(rst_img, &m_pImginfoResult);
 		posinfo.pp_images[0] = m_pImginfoResult;
 
 		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -850,6 +848,9 @@ namespace graft_cv {
 		int x0 = int(x_min);
 		int x1 = int(x_max);
 		int h_size = int((x1 - x0)/binw);
+		if (h_size <= 0) {
+			h_size = 1;
+		}
 		int idx = 0;
 		x_hist.assign(h_size, 0);
 
@@ -859,7 +860,10 @@ namespace graft_cv {
 				pt.z >= z_min && pt.z < z_max)
 			{ 
 				idx = int((pt.x - x0) / binw);
-				x_hist.at(idx)++;
+				if (idx >= 0 && idx < h_size) {
+					x_hist.at(idx)++;
+				}
+				
 			}
 		}
 

+ 1 - 1
graft_cv_api.cpp

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

+ 23 - 8
utils.cpp

@@ -29,20 +29,35 @@ namespace graft_cv{
 		return m;
 	};
 
-	ImgInfo* mat2imginfo(const cv::Mat&img){
+	ImgInfo* mat2imginfo(const cv::Mat&img, ImgInfo** ppimginfo){
 		assert(img.channels() == 1 || img.channels() == 3);
-		ImgInfo* imginfo = new ImgInfo();
-		imginfo->channel = img.channels();
-		imginfo->height = img.rows;
-		imginfo->width = img.cols;
-		imginfo->data = 0;
-		imginfo->data = new byte[imginfo->height * imginfo->width * imginfo->channel];
+		bool is_usable = false;
+		ImgInfo* imginfo = 0;
+		if (ppimginfo != 0 && isvalid(*ppimginfo) && (*ppimginfo)->channel == img.channels() &&
+			(*ppimginfo)->height == img.rows && (*ppimginfo)->width == img.cols) {
+			is_usable = true;
+		}
+		else {
+			if (ppimginfo != 0 && isvalid(*ppimginfo)) {
+				imginfo_release(ppimginfo);
+			}
+		}
+		if (is_usable) {
+			imginfo = *ppimginfo;
+		}
+		else {
+			imginfo = new ImgInfo();
+			imginfo->channel = img.channels();
+			imginfo->height = img.rows;
+			imginfo->width = img.cols;
+			imginfo->data = 0;
+			imginfo->data = new byte[imginfo->height * imginfo->width * imginfo->channel];
+		}		
 		memset(imginfo->data, 0, imginfo->height * imginfo->width * imginfo->channel);
 		//IplImage ipl_img = cvIplImage(img);
 		for (int i = 0; i<imginfo->height; ++i) {
 			memcpy(imginfo->data + i*imginfo->width * imginfo->channel, img.ptr(i), imginfo->width * imginfo->channel);
 		}
-
 		return imginfo;
 	};
 	void imginfo_release(ImgInfo**ppImgInfo){

+ 1 - 1
utils.h

@@ -17,7 +17,7 @@ namespace graft_cv{
 
 	// convert ImgInfo to cv mat 
 	cv::Mat imginfo2mat(ImgInfo*);
-	ImgInfo* mat2imginfo(const cv::Mat&);
+	ImgInfo* mat2imginfo(const cv::Mat&, ImgInfo** imginfo);
 	void imginfo_release(ImgInfo**);
 	bool isvalid(const ImgInfo*);
 	string currTime();