Bladeren bron

v0.8.13 优化茎粗检测功能,采用茎两侧边缘点构建直线,计算直线间距离,再用点云平均距离进行补偿

chenhongjiang 1 jaar geleden
bovenliggende
commit
4e16fabe88
4 gewijzigde bestanden met toevoegingen van 247 en 125 verwijderingen
  1. 116 115
      ReadMe.txt
  2. 113 8
      grab_point_rs.cpp
  3. 17 1
      grab_point_rs.h
  4. 1 1
      graft_cv_api.cpp

+ 116 - 115
ReadMe.txt

@@ -1,124 +1,125 @@
-v0.5.9.2 增加了图片保存,自动定期删除功能;增加了histogram生成时,增加权重。
-v0.5.9.3 压叶切割点识别结果,不能用于切割,将切割点改成分叉点间,靠近右侧三分之一位置
-v0.5.9.4 去掉切后重识别相关的代码;增加识别结果的图片;修改stem_x0,stem_x1的识别方法;分叉中点作为切割点;适用于不压叶的情况
-v0.5.9.5 砧木切割点识别中,有的叶子较大且下垂,识别中将叶子识别成茎,造成错误,修改茎识别方法get_stem_x_range()
-v0.5.9.6 1)修改旋转叶展识别方法,改用最大叶宽的图像分叉y值;
-         2)配置文件中
-		     增加
+v0.5.9.2 澧炲姞浜嗗浘鐗囦繚瀛橈紝鑷�姩瀹氭湡鍒犻櫎鍔熻兘锛涘�鍔犱簡histogram鐢熸垚鏃讹紝澧炲姞鏉冮噸銆�
+v0.5.9.3 鍘嬪彾鍒囧壊鐐硅瘑鍒�粨鏋滐紝涓嶈兘鐢ㄤ簬鍒囧壊锛屽皢鍒囧壊鐐规敼鎴愬垎鍙夌偣闂达紝闈犺繎鍙充晶涓夊垎涔嬩竴浣嶇疆
+v0.5.9.4 鍘绘帀鍒囧悗閲嶈瘑鍒�浉鍏崇殑浠g爜锛涘�鍔犺瘑鍒�粨鏋滅殑鍥剧墖;淇�敼stem_x0,stem_x1鐨勮瘑鍒�柟娉曪紱鍒嗗弶涓�偣浣滀负鍒囧壊鐐癸紱閫傜敤浜庝笉鍘嬪彾鐨勬儏鍐�
+v0.5.9.5 鐮ф湪鍒囧壊鐐硅瘑鍒�腑锛屾湁鐨勫彾瀛愯緝澶т笖涓嬪瀭锛岃瘑鍒�腑灏嗗彾瀛愯瘑鍒�垚鑼庯紝閫犳垚閿欒�锛屼慨鏀硅寧璇嗗埆鏂规硶get_stem_x_range锛堬級
+v0.5.9.6 1锛変慨鏀规棆杞�彾灞曡瘑鍒�柟娉曪紝鏀圭敤鏈€澶у彾瀹界殑鍥惧儚鍒嗗弶y鍊硷紱
+         2锛夐厤缃�枃浠朵腑
+		     澧炲姞
 			 rs_min_hist_value: 5
-		     修改
+		     淇�敼
 		     oa_min_hist_value: 5
 			 oa_stem_x_padding: 40
 
-		 3)大叶下垂识别茎位置,增加中心点定位,在中心点的优选,然后计算var选择var大的
-		 4)返回结果中增加 double rs_cut_lpoint_x;//砧木下切割点x位置,毫米
-	                       double rs_cut_lpoint_y;//砧木下切割点y位置,毫米
-						   double sc_cut_lpoint_x;//穗苗切割下点x位置,毫米
-	                       double sc_cut_lpoint_y;//穗苗切割下点y位置,毫米
-					去除曲线长度
-v0.5.9.7 修改保存图片的位置,翻转,填充后的图片保存   
+		 3锛夊ぇ鍙朵笅鍨傝瘑鍒�寧浣嶇疆锛屽�鍔犱腑蹇冪偣瀹氫綅锛屽湪涓�績鐐圭殑浼橀€夛紝鐒跺悗璁$畻var閫夋嫨var澶х殑
+		 4锛夎繑鍥炵粨鏋滀腑澧炲姞 double rs_cut_lpoint_x;//鐮ф湪涓嬪垏鍓茬偣x浣嶇疆锛屾�绫�
+	                       double rs_cut_lpoint_y;//鐮ф湪涓嬪垏鍓茬偣y浣嶇疆锛屾�绫�
+						   double sc_cut_lpoint_x;//绌楄嫍鍒囧壊涓嬬偣x浣嶇疆锛屾�绫�
+	                       double sc_cut_lpoint_y;//绌楄嫍鍒囧壊涓嬬偣y浣嶇疆锛屾�绫�
+					鍘婚櫎鏇茬嚎闀垮害
+v0.5.9.7 淇�敼淇濆瓨鍥剧墖鐨勪綅缃�紝缈昏浆锛屽~鍏呭悗鐨勫浘鐗囦繚瀛�   
 v0.5.9.8 
-        1)修改最优角度识别中单调情况的算法,采用最大点的角度(原来3点二次差值会出现较大误差)   
-		2)去掉最优角度识别,人工上料保证叶展方向,拍照一次识别分叉点y高度(目前代码没有改动)
-		3)最优角度识别infer函数增加输出日志:分叉点和根点y的像素值和毫米值
+        1锛変慨鏀规渶浼樿�搴﹁瘑鍒�腑鍗曡皟鎯呭喌鐨勭畻娉曪紝閲囩敤鏈€澶х偣鐨勮�搴︼紙鍘熸潵3鐐逛簩娆″樊鍊间細鍑虹幇杈冨ぇ璇�樊锛�   
+		2锛夊幓鎺夋渶浼樿�搴﹁瘑鍒�紝浜哄伐涓婃枡淇濊瘉鍙跺睍鏂瑰悜锛屾媿鐓т竴娆¤瘑鍒�垎鍙夌偣y楂樺害(鐩�墠浠g爜娌℃湁鏀瑰姩)
+		3锛夋渶浼樿�搴﹁瘑鍒玦nfer鍑芥暟澧炲姞杈撳嚭鏃ュ織锛氬垎鍙夌偣鍜屾牴鐐箉鐨勫儚绱犲€煎拰姣�背鍊�
 
-v0.5.9.9 最优角度识别,append方法,返回当时的分叉点y坐标,最低点y坐标
-         实现一次图像识别返回结果(适用于人工上料,不自动旋转的情况),调用流程不变,只是调用次数为1
-		 增加返回参数   double rs_oa_stem_y_fork;//茎分叉点y,毫米
-		            	double rs_oa_clamp_y_end;//茎可视下端y,毫米
-v0.5.9.10 增加砧木切割点间连线
-v0.5.9.11 增加接口调用进入、离开的日志信息; 改rs_stem_dia_mp: 9.6e-001
-v0.5.9.12 穗苗上切割点识别修改,改用中值法取茎粗,达到茎粗(或95百分位)位置为上切割点
-v0.5.9.13 1)穗苗切割点有识别不到的情况(因为苗倾斜角度过大),修改(扩大)识别范围
-          2)砧木分叉点检测方法(通过滑动平均),不稳定,可能出现不能检测到分叉点的情况
-		     砧木准确的上切割点识别方法
-v0.5.9.14 修改测试中穗苗切割点检测出现bug,vector越界问题
-          修改  sc_stem_ymax_padding: 200
-v0.5.9.15 针对砧木旋转工位分叉点识别,修改util.cpp中的get_stem_x_range()   
-          修改参数 rs_morph_radius: 2
+v0.5.9.9 鏈€浼樿�搴﹁瘑鍒�紝append鏂规硶锛岃繑鍥炲綋鏃剁殑鍒嗗弶鐐箉鍧愭爣锛屾渶浣庣偣y鍧愭爣
+         瀹炵幇涓€娆″浘鍍忚瘑鍒�繑鍥炵粨鏋滐紙閫傜敤浜庝汉宸ヤ笂鏂欙紝涓嶈嚜鍔ㄦ棆杞�殑鎯呭喌锛夛紝璋冪敤娴佺▼涓嶅彉锛屽彧鏄�皟鐢ㄦ�鏁颁负1
+		 澧炲姞杩斿洖鍙傛暟   double rs_oa_stem_y_fork;//鑼庡垎鍙夌偣y锛屾�绫�
+		            	double rs_oa_clamp_y_end;//鑼庡彲瑙嗕笅绔痽锛屾�绫�
+v0.5.9.10 澧炲姞鐮ф湪鍒囧壊鐐归棿杩炵嚎
+v0.5.9.11 澧炲姞鎺ュ彛璋冪敤杩涘叆銆佺�寮€鐨勬棩蹇椾俊鎭�; 鏀箁s_stem_dia_mp: 9.6e-001
+v0.5.9.12 绌楄嫍涓婂垏鍓茬偣璇嗗埆淇�敼锛屾敼鐢ㄤ腑鍊兼硶鍙栬寧绮楋紝杈惧埌鑼庣矖锛堟垨95鐧惧垎浣嶏級浣嶇疆涓轰笂鍒囧壊鐐�
+v0.5.9.13 1锛夌�鑻楀垏鍓茬偣鏈夎瘑鍒�笉鍒扮殑鎯呭喌锛堝洜涓鸿嫍鍊炬枩瑙掑害杩囧ぇ锛夛紝淇�敼锛堟墿澶э級璇嗗埆鑼冨洿
+          2锛夌牕鏈ㄥ垎鍙夌偣妫€娴嬫柟娉曪紙閫氳繃婊戝姩骞冲潎锛夛紝涓嶇ǔ瀹氾紝鍙�兘鍑虹幇涓嶈兘妫€娴嬪埌鍒嗗弶鐐圭殑鎯呭喌
+		     鐮ф湪鍑嗙‘鐨勪笂鍒囧壊鐐硅瘑鍒�柟娉�
+v0.5.9.14 淇�敼娴嬭瘯涓��鑻楀垏鍓茬偣妫€娴嬪嚭鐜癰ug锛寁ector瓒婄晫闂��
+          淇�敼  sc_stem_ymax_padding: 200
+v0.5.9.15 閽堝�鐮ф湪鏃嬭浆宸ヤ綅鍒嗗弶鐐硅瘑鍒�紝淇�敼util.cpp涓�殑get_stem_x_range()   
+          淇�敼鍙傛暟 rs_morph_radius: 2
                    rs_morph_iteration: 5    
-	      修改砧木图像分割方法为直接二值化,然后close方法,用上述新参数,实现去毛刺
-		  砧木col方向的histogram,通过中值滤波再次去毛刺
-		  砧木下切割点位置换算bug修改
-v0.5.9.16 砧木切割工位切割点检测分2步
-          0)砧木分叉点检测方法,旋转工位和切割工位函数分开
-          1)原来的方法检测分叉点y坐标get_stem_y_fork_rs(),通过直径变化系数和直径(已知直径)偏差系数确定分叉点,
-		     并限定在茎根部和茎最宽位置(通过x0和x1限定)找出最大指定的方法确定分叉y值
-		  2)在1)的基础上增加get_stem_y_fork_rs_update()函数,基于1)中的结果,
-		     实现茎中心线检测;
-		     带角度的x方向padding图像区域剪裁;
-			 找出外边缘,计算中心线到边缘的最小距离;
-			 找出中线上点最大距离的点作为分叉参考点
+	      淇�敼鐮ф湪鍥惧儚鍒嗗壊鏂规硶涓虹洿鎺ヤ簩鍊煎寲锛岀劧鍚巆lose鏂规硶锛岀敤涓婅堪鏂板弬鏁帮紝瀹炵幇鍘绘瘺鍒�
+		  鐮ф湪col鏂瑰悜鐨刪istogram锛岄€氳繃涓�€兼护娉㈠啀娆″幓姣涘埡
+		  鐮ф湪涓嬪垏鍓茬偣浣嶇疆鎹㈢畻bug淇�敼
+v0.5.9.16 鐮ф湪鍒囧壊宸ヤ綅鍒囧壊鐐规�娴嬪垎2姝�
+          0锛夌牕鏈ㄥ垎鍙夌偣妫€娴嬫柟娉曪紝鏃嬭浆宸ヤ綅鍜屽垏鍓插伐浣嶅嚱鏁板垎寮€
+          1锛夊師鏉ョ殑鏂规硶妫€娴嬪垎鍙夌偣y鍧愭爣get_stem_y_fork_rs锛堬級锛岄€氳繃鐩村緞鍙樺寲绯绘暟鍜岀洿寰勶紙宸茬煡鐩村緞锛夊亸宸�郴鏁扮‘瀹氬垎鍙夌偣锛�
+		     骞堕檺瀹氬湪鑼庢牴閮ㄥ拰鑼庢渶瀹戒綅缃�紙閫氳繃x0鍜寈1闄愬畾锛夋壘鍑烘渶澶ф寚瀹氱殑鏂规硶纭�畾鍒嗗弶y鍊�
+		  2锛夊湪1锛夌殑鍩虹�涓婂�鍔爂et_stem_y_fork_rs_update锛堬級鍑芥暟锛屽熀浜�1锛変腑鐨勭粨鏋滐紝
+		     瀹炵幇鑼庝腑蹇冪嚎妫€娴嬶紱
+		     甯﹁�搴︾殑x鏂瑰悜padding鍥惧儚鍖哄煙鍓��锛�
+			 鎵惧嚭澶栬竟缂橈紝璁$畻涓�績绾垮埌杈圭紭鐨勬渶灏忚窛绂伙紱
+			 鎵惧嚭涓�嚎涓婄偣鏈€澶ц窛绂荤殑鐐逛綔涓哄垎鍙夊弬鑰冪偣
           
-		  3)修改参数   rs_row_th_ratio: 1.1999999999999999e+000
-	      4) 用到flann,增加opencv_flann2410d.lib
-v0.5.9.17 增加砧木切割工位切割点偏移参数
+		  3锛変慨鏀瑰弬鏁�   rs_row_th_ratio: 1.1999999999999999e+000
+	      4) 鐢ㄥ埌flann锛屽�鍔爋pencv_flann2410d.lib
+v0.5.9.17 澧炲姞鐮ф湪鍒囧壊宸ヤ綅鍒囧壊鐐瑰亸绉诲弬鏁�
           rs_cut_point_offset_ratio: 5.0000000000000000e-001
-v0.5.9.18 怀疑内存泄露,检测优化
-          1)高速连续加载砧木图片测试出现中途退出,1秒内图片id重复造成存储异常退出
-		    修改图片id,增加序列值(00-99)
-		  2)imginfo2mat()中构建mat矩阵,自己申请的内存(new),指针赋值给mat对象,mat对象
-		    析构是不负责释放,造成内存泄露,已修改
-v0.5.9.19 增加配置参数写入日志功能:启动-初始化,或认为设置参数后将最新配置参数写入日志文件
-          增加版本号日志
-		  增加宽大真叶的情况的处理
-v0.5.9.20 增加砧木分叉点检测优化,增加fork_rs.h,cpp(还没有全面测试)
-          修改砧木roi最大点识别,将比例参数1.5调整至2.0(utils.cpp)
-		  修改砧木茎中心最大内接园半径的方法,不采用flann查找(出现误差较大),改用pointPolygonTest()
-		  去掉opencv_flann2410d.lib
-		  按测试,修改rs_cut_point_offset_ratio: 9.0000000000000000e-001
-		  修改穗苗识别方法(用于标定位置的夹子被遮挡)
-v0.6.0 修改旋转角度识别算法,采用顶部拍照,一次识别旋转角度
-v0.6.1 移植到vs2015平台(vc14),选用OpenCV v4.55
-v0.6.2 增加上苗点云识别夹取位置接口及功能
-v0.6.3 增加茄科切后识别接口及功能(同一个接口支持砧木和穗苗)
-v0.6.4 增加算法参数读取文件进行更新的接口
-v0.6.5 修改代码,得到最左侧一株
-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.11 增加茄科切后重识别异常退出判断
-v0.6.12 增加茄科抓取目标大小判断,太小的目标跳出;增加自动ply数据保存功能;茄科切后重识别图片保存功能
-v0.6.13 增加聚类结果中点数小于20的类别剔除功能;修改降采样后整个点云数量小于50退出(原来是200)
-v0.6.14 修改茎识别方法,通过2d高密度点找到茎的位置,然后提取株的最大空间内点云,用直线分割的方法得到茎的位置,避免识别位置错误
-v0.6.15 修改抓取点识别方法,通过比较直线点云和原始点云相同位置邻域内xz的范围,确定此点是否是无干扰点的茎
-v0.6.16 加强苗的识别,增加倾斜苗的检测,修改排序错乱问题
-v0.7.0 支持多线程调用业务接口
-v0.7.1 增加voxelsize参数;修改茎密度最大值的1/3为最小茎密度的下限(原来为1/2,有些小苗识别不出来)
-v0.7.2 增加结果图片输出功能;日志增加image_id信息
-v0.7.3 修改抓取位置,提供茎节分叉的位置(以前提供可抓取的位置,避开茎节的点)
-v0.7.4 增加叶片剔除功能(在boxcrop和降采样后实现,直接采用欧式距离聚类)
-v0.7.5 优化叶片剔除功能(欧式距离聚类没能分割叶片和茎造成误剔除,本次采用ror方法剔除叶片,但有些耗时)
-v0.7.6 优化叶片剔除功能,修改ror,nb_point的数量系数,通过配置文件sc_grab_ror_ratio参数传入
-v0.7.7 优化茎判别问题:上下2片叶子,利用有效高度剔除;偏离z中心剔除,采用历史z均值
-v0.7.8 修改接穗抓点靠上一点
-v0.7.9 修改接穗抓点靠上一点,增加了grab_offset,用来在找到茎节后的上下偏移得到抓取点,+值向上偏,-值向下偏
-v0.7.10 增加茎节点位置绘制输出;茎节判别仅按dx方向大小判断(dz误差较大)
-v0.7.11 增加棋盘格识别,用于标定辅助
-v0.7.12 增加茎节peakfind功能
-v0.7.13 修改sc_grab_offset不起作用的bug
-v0.7.14 增加指定抓取位置的功能,抓取位置在ymax向下指定距离为抓取位置
-v0.7.15 优化茎节位置识别
-v0.7.16 优化茎节位置识别,增加平均茎节高度约束,10mm范围
-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.22 优化茎节位置识别,废弃基于历史平均茎节高度的约束,人工指定范围(高度上限,下限),不在范围内时,按下限位置
-v0.7.23 识别接口返回图片,返回茎的弯曲度,当前苗的数量
-v0.8.0 叶子遮挡识别;去除原来图片识别的内容;修改配置参数仅保留3d相关参数
-v0.8.1 叶子遮挡识别优化:通过x截取范围和穴位个数直接确定茎根中心位置
-v0.8.2 叶子遮挡识别优化:用叶子点云数量判断是否有遮挡,加上识别的茎的位置,统计植株的个数
-v0.8.3 叶子遮挡识别优化:解决叶子遮挡不计数问题;修改点云密度计算方法
-v0.8.4 叶子遮挡识别优化:小叶遮挡,茎没有识别出来,植株误判问题
-v0.8.5 叶子遮挡识别优化:修改叶子遮挡识别位置偏离问题,增加历史抓取信息约束
-v0.8.6 抓取位置调整
-v0.8.7 抓取顺序调整:先抓取有明确茎的位置,然后再去抓取遮挡位置的
-v0.8.8 砧木固定抓取位置,输出茎节高度;
-v0.8.9 输出多个茎节高度(最多3个);穗苗抓取逻辑修改;
-v0.8.10 优化茎节识别,实现邻域对比过滤,最近距离过滤,增加xx_grab_fork_ratio控制茎节检出;增加扩展茎粗检测茎节功能
-v0.8.11 优化增加扩展茎粗检测茎节功能,减小ex范围从单侧1.5到1.05
-v0.8.12 优化茎粗检测功能,采用xy面投影茎粗统计结果
+v0.5.9.18 鎬€鐤戝唴瀛樻硠闇诧紝妫€娴嬩紭鍖�
+          1)楂橀€熻繛缁�姞杞界牕鏈ㄥ浘鐗囨祴璇曞嚭鐜颁腑閫旈€€鍑猴紝1绉掑唴鍥剧墖id閲嶅�閫犳垚瀛樺偍寮傚父閫€鍑�
+		    淇�敼鍥剧墖id锛屽�鍔犲簭鍒楀€硷紙00-99锛�
+		  2锛塱mginfo2mat()涓�瀯寤簃at鐭╅樀锛岃嚜宸辩敵璇风殑鍐呭瓨锛坣ew锛夛紝鎸囬拡璧嬪€肩粰mat瀵硅薄锛宮at瀵硅薄
+		    鏋愭瀯鏄�笉璐熻矗閲婃斁锛岄€犳垚鍐呭瓨娉勯湶锛屽凡淇�敼
+v0.5.9.19 澧炲姞閰嶇疆鍙傛暟鍐欏叆鏃ュ織鍔熻兘锛氬惎鍔�-鍒濆�鍖栵紝鎴栬�涓鸿�缃�弬鏁板悗灏嗘渶鏂伴厤缃�弬鏁板啓鍏ユ棩蹇楁枃浠�
+          澧炲姞鐗堟湰鍙锋棩蹇�
+		  澧炲姞瀹藉ぇ鐪熷彾鐨勬儏鍐电殑澶勭悊
+v0.5.9.20 澧炲姞鐮ф湪鍒嗗弶鐐规�娴嬩紭鍖栵紝澧炲姞fork_rs.h,cpp(杩樻病鏈夊叏闈㈡祴璇�)
+          淇�敼鐮ф湪roi鏈€澶х偣璇嗗埆锛屽皢姣斾緥鍙傛暟1.5璋冩暣鑷�2.0锛坲tils.cpp锛�
+		  淇�敼鐮ф湪鑼庝腑蹇冩渶澶у唴鎺ュ洯鍗婂緞鐨勬柟娉曪紝涓嶉噰鐢╢lann鏌ユ壘锛堝嚭鐜拌�宸�緝澶э級锛屾敼鐢╬ointPolygonTest()
+		  鍘绘帀opencv_flann2410d.lib
+		  鎸夋祴璇曪紝淇�敼rs_cut_point_offset_ratio: 9.0000000000000000e-001
+		  淇�敼绌楄嫍璇嗗埆鏂规硶锛堢敤浜庢爣瀹氫綅缃�殑澶瑰瓙琚�伄鎸★級
+v0.6.0 淇�敼鏃嬭浆瑙掑害璇嗗埆绠楁硶锛岄噰鐢ㄩ《閮ㄦ媿鐓э紝涓€娆¤瘑鍒�棆杞��搴�
+v0.6.1 绉绘�鍒皏s2015骞冲彴锛坴c14锛夛紝閫夌敤OpenCV v4.55
+v0.6.2 澧炲姞涓婅嫍鐐逛簯璇嗗埆澶瑰彇浣嶇疆鎺ュ彛鍙婂姛鑳�
+v0.6.3 澧炲姞鑼勭�鍒囧悗璇嗗埆鎺ュ彛鍙婂姛鑳斤紙鍚屼竴涓�帴鍙f敮鎸佺牕鏈ㄥ拰绌楄嫍锛�
+v0.6.4 澧炲姞绠楁硶鍙傛暟璇诲彇鏂囦欢杩涜�鏇存柊鐨勬帴鍙�
+v0.6.5 淇�敼浠g爜锛屽緱鍒版渶宸︿晶涓€鏍�
+v0.6.6 澧炲姞鍓��鍚庢病鏈夌偣鐨勫紓甯稿�鐞�
+v0.6.7 淇�敼鐐逛簯鏄剧ず浠g爜锛屾樉绀烘姄鍙栫偣xy鏂瑰悜锛屽強z骞抽潰涓婄殑xoy鍧愭爣绯�
+v0.6.8 澧炲姞绌楄嫍鐨刬nbox瀹氫箟锛屽�鍔犳渶浼樿寧楂樼殑瀹氫箟锛涗慨鏀箆ector闅忔満璇诲彇[]涓篴t鏂规硶锛涘�鍔犳帴鍙e弬鏁扮敤浜庡畾涔夋姄鍙栬嫍鏄�牕鏈ㄨ繕鏄��鑻楋紱淇�敼浜嗘帴鍙e嚱鏁板悕绉�
+v0.6.9 淇�敼鎶撳彇鐮ф湪銆佺�鑻楃殑瀹氫箟0--绌楄嫍锛�1--鐮ф湪锛涚�鑻楀拰鐮ф湪鎶撳彇椤哄簭鐩稿弽
+v0.6.10 閲嶅啓鐮ф湪銆佺�鑻楀垏鍚庨噸璇嗗埆绠楁硶锛岀幇鍦ㄧ敤鍒囧悗渚ч潰鍥撅紝杈撳嚭澶圭埅鍩洪潰y鍊笺€佸垏鍚�3鐐箉涓庡熀闈�鍊肩殑璺濈�
+v0.6.11 澧炲姞鑼勭�鍒囧悗閲嶈瘑鍒�紓甯搁€€鍑哄垽鏂�
+v0.6.12 澧炲姞鑼勭�鎶撳彇鐩�爣澶у皬鍒ゆ柇锛屽お灏忕殑鐩�爣璺冲嚭锛涘�鍔犺嚜鍔╬ly鏁版嵁淇濆瓨鍔熻兘锛涜寗绉戝垏鍚庨噸璇嗗埆鍥剧墖淇濆瓨鍔熻兘
+v0.6.13 澧炲姞鑱氱被缁撴灉涓�偣鏁板皬浜�20鐨勭被鍒�墧闄ゅ姛鑳斤紱淇�敼闄嶉噰鏍峰悗鏁翠釜鐐逛簯鏁伴噺灏忎簬50閫€鍑猴紙鍘熸潵鏄�200锛�
+v0.6.14 淇�敼鑼庤瘑鍒�柟娉曪紝閫氳繃2d楂樺瘑搴︾偣鎵惧埌鑼庣殑浣嶇疆锛岀劧鍚庢彁鍙栨牚鐨勬渶澶х┖闂村唴鐐逛簯锛岀敤鐩寸嚎鍒嗗壊鐨勬柟娉曞緱鍒拌寧鐨勪綅缃�紝閬垮厤璇嗗埆浣嶇疆閿欒�
+v0.6.15 淇�敼鎶撳彇鐐硅瘑鍒�柟娉曪紝閫氳繃姣旇緝鐩寸嚎鐐逛簯鍜屽師濮嬬偣浜戠浉鍚屼綅缃�偦鍩熷唴xz鐨勮寖鍥达紝纭�畾姝ょ偣鏄�惁鏄�棤骞叉壈鐐圭殑鑼�
+v0.6.16 鍔犲己鑻楃殑璇嗗埆锛屽�鍔犲€炬枩鑻楃殑妫€娴�,淇�敼鎺掑簭閿欎贡闂��
+v0.7.0 鏀�寔澶氱嚎绋嬭皟鐢ㄤ笟鍔℃帴鍙�
+v0.7.1 澧炲姞voxelsize鍙傛暟锛涗慨鏀硅寧瀵嗗害鏈€澶у€肩殑1/3涓烘渶灏忚寧瀵嗗害鐨勪笅闄愶紙鍘熸潵涓�1/2锛屾湁浜涘皬鑻楄瘑鍒�笉鍑烘潵锛�
+v0.7.2 澧炲姞缁撴灉鍥剧墖杈撳嚭鍔熻兘锛涙棩蹇楀�鍔爄mage_id淇℃伅
+v0.7.3 淇�敼鎶撳彇浣嶇疆锛屾彁渚涜寧鑺傚垎鍙夌殑浣嶇疆锛堜互鍓嶆彁渚涘彲鎶撳彇鐨勪綅缃�紝閬垮紑鑼庤妭鐨勭偣锛�
+v0.7.4 澧炲姞鍙剁墖鍓旈櫎鍔熻兘锛堝湪boxcrop鍜岄檷閲囨牱鍚庡疄鐜�,鐩存帴閲囩敤娆у紡璺濈�鑱氱被锛�
+v0.7.5 浼樺寲鍙剁墖鍓旈櫎鍔熻兘锛堟�寮忚窛绂昏仛绫绘病鑳藉垎鍓插彾鐗囧拰鑼庨€犳垚璇�墧闄わ紝鏈��閲囩敤ror鏂规硶鍓旈櫎鍙剁墖锛屼絾鏈変簺鑰楁椂锛�
+v0.7.6 浼樺寲鍙剁墖鍓旈櫎鍔熻兘,淇�敼ror,nb_point鐨勬暟閲忕郴鏁帮紝閫氳繃閰嶇疆鏂囦欢sc_grab_ror_ratio鍙傛暟浼犲叆
+v0.7.7 浼樺寲鑼庡垽鍒�棶棰橈細涓婁笅2鐗囧彾瀛愶紝鍒╃敤鏈夋晥楂樺害鍓旈櫎锛涘亸绂粃涓�績鍓旈櫎锛岄噰鐢ㄥ巻鍙瞶鍧囧€�
+v0.7.8 淇�敼鎺ョ�鎶撶偣闈犱笂涓€鐐�
+v0.7.9 淇�敼鎺ョ�鎶撶偣闈犱笂涓€鐐癸紝澧炲姞浜唃rab_offset锛岀敤鏉ュ湪鎵惧埌鑼庤妭鍚庣殑涓婁笅鍋忕Щ寰楀埌鎶撳彇鐐癸紝+鍊煎悜涓婂亸锛�-鍊煎悜涓嬪亸
+v0.7.10 澧炲姞鑼庤妭鐐逛綅缃�粯鍒惰緭鍑猴紱鑼庤妭鍒ゅ埆浠呮寜dx鏂瑰悜澶у皬鍒ゆ柇锛坉z璇�樊杈冨ぇ锛�
+v0.7.11 澧炲姞妫嬬洏鏍艰瘑鍒�紝鐢ㄤ簬鏍囧畾杈呭姪
+v0.7.12 澧炲姞鑼庤妭peakfind鍔熻兘
+v0.7.13 淇�敼sc_grab_offset涓嶈捣浣滅敤鐨刡ug
+v0.7.14 澧炲姞鎸囧畾鎶撳彇浣嶇疆鐨勫姛鑳斤紝鎶撳彇浣嶇疆鍦▂max鍚戜笅鎸囧畾璺濈�涓烘姄鍙栦綅缃�
+v0.7.15 浼樺寲鑼庤妭浣嶇疆璇嗗埆
+v0.7.16 浼樺寲鑼庤妭浣嶇疆璇嗗埆,澧炲姞骞冲潎鑼庤妭楂樺害绾︽潫锛�10mm鑼冨洿
+v0.7.17 浼樺寲鑼庤妭浣嶇疆璇嗗埆,涓嶅瓨鍦ㄦ樉钁楄寧鑺傜殑鐢ㄥ钩鍧囪寧鑺傞珮搴︽浛浠o紝鍚﹀垯鐢ㄨ瘑鍒�埌鐨勮寧鑺備綅缃�
+v0.7.18 浼樺寲鑼庤妭浣嶇疆璇嗗埆,璇勪及鏂规硶鏀逛负椤剁偣楂樺害鍜屼腑鍊奸珮搴﹀樊锛屽�鍔犻槇鍊兼帶鍒舵槸鍚︽湁鏁�
+v0.7.19 浼樺寲鑼庤妭浣嶇疆璇嗗埆,鎶曞奖鍒�2涓哄钩闈㈠�鎵惧垎鍙夌偣锛宺s_grab_fork_th鍜宻c_grab_fork_th涓嶅湪璧蜂綔鐢�紝鏀惧純鍘嗗彶鍧囧€间綅缃�
+v0.7.20 浼樺寲鑼庤妭浣嶇疆璇嗗埆,鍦╲0.7.19鍩虹�涓婂姞涓婂巻鍙插潎鍊间綅缃�害鏉燂紝rs_grab_fork_th鍜宻c_grab_fork_th鏄�寧鑺傜矖鍜岃寧绮楃殑姣斿€肩郴鏁�
+v0.7.21 浼樺寲鑼庤妭浣嶇疆璇嗗埆,澧炲姞鍋忕�骞冲潎鑼庤妭楂樺害鐨勮窛绂诲弬鏁皉s_grab_to_meanfork_max_dist鍜宻c_grab_to_meanfork_max_dist
+v0.7.22 浼樺寲鑼庤妭浣嶇疆璇嗗埆,搴熷純鍩轰簬鍘嗗彶骞冲潎鑼庤妭楂樺害鐨勭害鏉燂紝浜哄伐鎸囧畾鑼冨洿锛堥珮搴︿笂闄愶紝涓嬮檺锛夛紝涓嶅湪鑼冨洿鍐呮椂锛屾寜涓嬮檺浣嶇疆
+v0.7.23 璇嗗埆鎺ュ彛杩斿洖鍥剧墖锛岃繑鍥炶寧鐨勫集鏇插害锛屽綋鍓嶈嫍鐨勬暟閲�
+v0.8.0 鍙跺瓙閬�尅璇嗗埆锛涘幓闄ゅ師鏉ュ浘鐗囪瘑鍒�殑鍐呭�锛涗慨鏀归厤缃�弬鏁颁粎淇濈暀3d鐩稿叧鍙傛暟
+v0.8.1 鍙跺瓙閬�尅璇嗗埆浼樺寲锛氶€氳繃x鎴�彇鑼冨洿鍜岀┐浣嶄釜鏁扮洿鎺ョ‘瀹氳寧鏍逛腑蹇冧綅缃�
+v0.8.2 鍙跺瓙閬�尅璇嗗埆浼樺寲锛氱敤鍙跺瓙鐐逛簯鏁伴噺鍒ゆ柇鏄�惁鏈夐伄鎸★紝鍔犱笂璇嗗埆鐨勮寧鐨勪綅缃�紝缁熻�妞嶆牚鐨勪釜鏁�
+v0.8.3 鍙跺瓙閬�尅璇嗗埆浼樺寲锛氳В鍐冲彾瀛愰伄鎸′笉璁℃暟闂��;淇�敼鐐逛簯瀵嗗害璁$畻鏂规硶
+v0.8.4 鍙跺瓙閬�尅璇嗗埆浼樺寲锛氬皬鍙堕伄鎸★紝鑼庢病鏈夎瘑鍒�嚭鏉ワ紝妞嶆牚璇�垽闂��
+v0.8.5 鍙跺瓙閬�尅璇嗗埆浼樺寲锛氫慨鏀瑰彾瀛愰伄鎸¤瘑鍒�綅缃�亸绂婚棶棰橈紝澧炲姞鍘嗗彶鎶撳彇淇℃伅绾︽潫
+v0.8.6 鎶撳彇浣嶇疆璋冩暣
+v0.8.7 鎶撳彇椤哄簭璋冩暣锛氬厛鎶撳彇鏈夋槑纭�寧鐨勪綅缃�紝鐒跺悗鍐嶅幓鎶撳彇閬�尅浣嶇疆鐨�
+v0.8.8 鐮ф湪鍥哄畾鎶撳彇浣嶇疆锛岃緭鍑鸿寧鑺傞珮搴︼紱
+v0.8.9 杈撳嚭澶氫釜鑼庤妭楂樺害锛堟渶澶�3涓�級锛涚�鑻楁姄鍙栭€昏緫淇�敼锛�
+v0.8.10 浼樺寲鑼庤妭璇嗗埆锛屽疄鐜伴偦鍩熷�姣旇繃婊わ紝鏈€杩戣窛绂昏繃婊わ紝澧炲姞xx_grab_fork_ratio鎺у埗鑼庤妭妫€鍑�;澧炲姞鎵╁睍鑼庣矖妫€娴嬭寧鑺傚姛鑳�
+v0.8.11 浼樺寲澧炲姞鎵╁睍鑼庣矖妫€娴嬭寧鑺傚姛鑳斤紝鍑忓皬ex鑼冨洿浠庡崟渚�1.5鍒�1.05
+v0.8.12 浼樺寲鑼庣矖妫€娴嬪姛鑳斤紝閲囩敤xy闈㈡姇褰辫寧绮楃粺璁$粨鏋�
+v0.8.13 浼樺寲鑼庣矖妫€娴嬪姛鑳斤紝閲囩敤鑼庝袱渚ц竟缂樼偣鏋勫缓鐩寸嚎锛岃�绠楃洿绾块棿璺濈�锛屽啀鐢ㄧ偣浜戝钩鍧囪窛绂昏繘琛岃ˉ鍋�

+ 113 - 8
grab_point_rs.cpp

@@ -1556,7 +1556,31 @@ void CRootStockGrabPoint::line_filter(
 		}*/
 	}
 }
+	void CRootStockGrabPoint::get_edge_line(
+		pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud, 
+		std::vector<int>& edge_idx,
+		pcl::ModelCoefficients::Ptr coefficients) 
+	{
+		pcl::PointCloud<pcl::PointXYZ>::Ptr edges(new pcl::PointCloud<pcl::PointXYZ>);
 
+		pcl::copyPointCloud(*in_cloud, edge_idx, *edges);
+
+		//植株点云直线查找
+		//找到inbox点云中的直线
+		float stem_radius = m_cparam.rs_grab_stem_diameter / 2.0;
+		if (m_dtype == 0) {
+			stem_radius = m_cparam.sc_grab_stem_diameter / 2.0;
+		}
+		//pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
+		pcl::PointIndices::Ptr inliers(new pcl::PointIndices);
+		pcl::SACSegmentation<pcl::PointXYZ> seg;
+		seg.setOptimizeCoefficients(true);
+		seg.setModelType(pcl::SACMODEL_LINE);
+		seg.setDistanceThreshold(stem_radius);
+		seg.setInputCloud(edges);
+		seg.segment(*inliers, *coefficients);
+
+	}
 
 	bool CRootStockGrabPoint::find_seedling_position_key(		
 		pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
@@ -2546,7 +2570,7 @@ void CRootStockGrabPoint::line_filter(
 		
 		//找到茎节
 		std::vector<int> fork_positions;
-		find_fork(in_line_cloud, mu, stem_width, fork_positions, stem_width_mu);
+		find_fork(in_line_cloud, line_model, mu, stem_width, fork_positions, stem_width_mu);
 		for (auto&y : fork_positions) {
 			fork_ys.push_back(y + ymin);
 		}
@@ -2710,6 +2734,7 @@ void CRootStockGrabPoint::line_filter(
 
 	void  CRootStockGrabPoint::find_fork(
 		pcl::PointCloud<pcl::PointXYZ>::Ptr in_line_cloud,
+		pcl::ModelCoefficients::Ptr line_model, //输入
 		//float& max_dist,
 		//int& max_idx,
 		float stem_width_ex_mu,//输入, 通过外沿矩形得到的x方向茎粗均值
@@ -2749,14 +2774,35 @@ void CRootStockGrabPoint::line_filter(
 
 		pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_visual(new pcl::PointCloud<pcl::PointXYZRGB>);
 		cloud_visual->resize(cloud_line_2d->size());
+		float dx, xi,xi_hat, yi,t;
+		std::vector<int> left_edge_idx, right_edge_idx;
 		for (size_t i = 0; i < cloud_line_2d->size(); ++i) {
 			cloud_visual->points.at(i).x = cloud_line_2d->points.at(i).x;
 			cloud_visual->points.at(i).y = cloud_line_2d->points.at(i).y;
 			cloud_visual->points.at(i).z = cloud_line_2d->points.at(i).z;
 			if (boundaries->points.at(i).boundary_point != 0) {
+				xi = cloud_line_2d->points.at(i).x;
+				yi = cloud_line_2d->points.at(i).y;
+				t = (yi - line_model->values.at(1)) / line_model->values.at(4);
+				xi_hat = line_model->values.at(3) * t + line_model->values.at(0);
+				dx = xi - xi_hat;
+
 				cloud_visual->points.at(i).r = 255;
-				cloud_visual->points.at(i).g = 0;
 				cloud_visual->points.at(i).b = 0;
+				cloud_visual->points.at(i).g = 0;
+				if (dx > 0.5) {
+					cloud_visual->points.at(i).r = 0;
+					cloud_visual->points.at(i).b = 200;
+					right_edge_idx.push_back(i);
+				}
+				if (dx < -0.5) {
+					cloud_visual->points.at(i).r = 0;
+					cloud_visual->points.at(i).g = 200;
+					left_edge_idx.push_back(i);
+				}
+				
+				
+				
 				cloud_lines->points.push_back(cloud_line_2d->points.at(i));
 			}
 			else {
@@ -2765,12 +2811,19 @@ void CRootStockGrabPoint::line_filter(
 				cloud_visual->points.at(i).b = 255;
 			}
 		}
+		//计算茎左右边缘的直线
+		pcl::ModelCoefficients::Ptr edge_line_left(new pcl::ModelCoefficients);
+		pcl::ModelCoefficients::Ptr edge_line_right(new pcl::ModelCoefficients);
+		get_edge_line(cloud_line_2d, left_edge_idx, edge_line_left);
+		get_edge_line(cloud_line_2d, right_edge_idx, edge_line_right);
+		pcl::PointXYZ p_left_min, p_left_max, p_right_min, p_right_max;
+		stem_width_mu = get_stem_width(edge_line_left, edge_line_right, p_left_min, p_left_max, p_right_min, p_right_max);
 
 		/*if (m_cparam.image_show) {
 			viewer_cloud(cloud_visual, string("boundary"));
 			viewer_cloud(cloud_lines, string("cloud_lines"));
 		}
-*/
+		*/
 		//3 find points with max distance to boundaries point
 		pcl::search::KdTree<pcl::PointXYZ>::Ptr bound_kdtree_ptr(new pcl::search::KdTree<pcl::PointXYZ>);
 		bound_kdtree_ptr->setInputCloud(cloud_lines);
@@ -2816,11 +2869,9 @@ void CRootStockGrabPoint::line_filter(
 		}
 		if (cnt > 0.0) {
 			mean_r /= cnt;
-		}
-		std::vector<float> stem_diameters_cpy(stem_diameters);
-		std::sort(stem_diameters_cpy.begin(),stem_diameters_cpy.end());
-		int idx80 = int(0.8*stem_diameters_cpy.size());
-		stem_width_mu = 2.0 * stem_diameters_cpy.at(idx80);
+		}	
+
+		
 
 		int del_radius = 4;
 		int security_r = (int)(stemd / 2.0 + 0.5);//保护半径
@@ -2910,6 +2961,11 @@ void CRootStockGrabPoint::line_filter(
 				p1.z = cloud_line_2d->points.at(0).z;
 				viewer.addLine(p0, p1, 1.0, 0.0, 0.0, "fork_y_" + string(_itoa(h, buf, 10)));
 			}
+
+			
+
+			viewer.addLine(p_left_min, p_left_max, std::string("left"));
+			viewer.addLine(p_right_min, p_right_max, std::string("right"));
 			
 
 			while (!viewer.wasStopped()) {
@@ -2918,6 +2974,55 @@ void CRootStockGrabPoint::line_filter(
 			}
 		}
 	}
+
+	float CRootStockGrabPoint::get_stem_width(
+		pcl::ModelCoefficients::Ptr edge_line_left,
+		pcl::ModelCoefficients::Ptr edge_line_right,
+		pcl::PointXYZ& p_left_min,
+		pcl::PointXYZ& p_left_max,
+		pcl::PointXYZ& p_right_min,
+		pcl::PointXYZ& p_right_max
+		)
+	{
+		float stem_width = 0.0;
+
+		double ymin = m_cparam.rs_grab_ymin;
+		double ymax = m_cparam.rs_grab_ymax;		
+		if (m_dtype == 0) {
+			ymin = m_cparam.sc_grab_ymin;
+			ymax = m_cparam.sc_grab_ymax;			
+		}
+
+		float t_left = (ymin - edge_line_left->values.at(1)) / edge_line_left->values.at(4);
+		double xleft = edge_line_left->values.at(3) * t_left + edge_line_left->values.at(0);
+		p_left_min.x = xleft;
+		p_left_min.y = ymin;
+		p_left_min.z = 0.0;
+
+		t_left = (ymax - edge_line_left->values.at(1)) / edge_line_left->values.at(4);
+		xleft = edge_line_left->values.at(3) * t_left + edge_line_left->values.at(0);
+		p_left_max.x = xleft;
+		p_left_max.y = ymax;
+		p_left_max.z = 0.0;
+
+
+		float t_right = (ymin - edge_line_right->values.at(1)) / edge_line_right->values.at(4);
+		double xright = edge_line_right->values.at(3) * t_right + edge_line_right->values.at(0);
+		p_right_min.x = xright;
+		p_right_min.y = ymin;
+		p_right_min.z = 0.0;
+
+		t_right = (ymax - edge_line_right->values.at(1)) / edge_line_right->values.at(4);
+		xright = edge_line_right->values.at(3) * t_right + edge_line_right->values.at(0);
+		p_right_max.x = xright;
+		p_right_max.y = ymax;
+		p_right_max.z = 0.0;
+
+		stem_width = 0.5 * (fabs(p_left_max.x - p_right_max.x) +
+			fabs(p_left_min.x - p_right_min.x));
+		stem_width += 1.5*m_cloud_mean_dist;
+		return stem_width;
+	}
 	void CRootStockGrabPoint::calculate_noise(
 		std::vector<float>&diamters,	//input
 		int security_radius,			//input

+ 17 - 1
grab_point_rs.h

@@ -73,13 +73,29 @@ namespace graft_cv {
 		);
 		//////////////////////////////////////////////////////////////////////////////////////
 		void  CRootStockGrabPoint::find_fork(
-			pcl::PointCloud<pcl::PointXYZ>::Ptr in_line_cloud,	
+			pcl::PointCloud<pcl::PointXYZ>::Ptr in_line_cloud,
+			pcl::ModelCoefficients::Ptr line_model,
 			float stem_width_ex_mu,//输入,stem_width_ex中有效值的均值
 			const std::vector<float>& stem_width_ex,//输入, 通过外沿矩形得到的x方向茎粗
 			std::vector<int>&fork_pos, //输出, 多个fork位置
 			float& stem_width_mu //输出, xy投影上x方向的茎粗均值
 		);
 
+		void get_edge_line(
+			pcl::PointCloud<pcl::PointXYZ>::Ptr in_cloud,
+			std::vector<int>& inbox_idx,
+			pcl::ModelCoefficients::Ptr coefficients
+		);
+
+		float get_stem_width(
+			pcl::ModelCoefficients::Ptr left_edge_line,
+			pcl::ModelCoefficients::Ptr right_edge_line,
+			pcl::PointXYZ& left_min,
+			pcl::PointXYZ& left_max,
+			pcl::PointXYZ& right_min,
+			pcl::PointXYZ& right_max
+			);
+
 
 		void gen_all_seedling_positions(
 			pcl::PointXYZ&key_center,	//输入,已知的苗的坐标

+ 1 - 1
graft_cv_api.cpp

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