基于视觉与图像的植物信息采集与处理技术解析【附代码】
✨ 长期致力于机器视觉、图像处理、Android系统、叶片面积、茎节识别、冠层投影面积与体积研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
✅如需沟通交流,点击《获取方式》
(1)多视角三维叶片建模与曲面面积计算方法:
提出一种基于多视角图像序列的叶片三维重建及曲面面积测量方案,命名为MVLeaf3D。采用一台固定焦距的工业相机(1280x1024分辨率)绕叶片每间隔15度拍摄一幅图像,共采集24幅,同时拍摄同一平面内的棋盘格校准板用于相机标定。通过张正友标定法获取相机内参(焦距fx=1250,fy=1252,主点cx=640,cy=512)和畸变系数(k1=-0.32,k2=0.15)。利用PhotoModeler软件基于运动恢复结构生成叶片的三维点云,点云密度达到每平方厘米200个点。然后采用泊松表面重建生成三角网格,再通过MATLAB自编的曲面积分算法计算网格表面积:对每个三角形,计算两个边向量的叉积模长的一半并累加。选取50片不同形状的植物叶片(包含卵圆形、披针形和心形),将该方法结果与叶片扫描仪+Photoshop平面测量结果对比,MVLeaf3D的平均相对误差为0.9%,最大误差2.1%,精度达到99%以上。对于自然生长状态下有卷曲的叶片,测量重复性标准差为0.03平方厘米。该方法还输出叶片的平均曲率和高斯曲率分布图,可用于叶片形态分类。
(2)基于连续投影算法和高光谱成像的甘蔗茎节识别系统:
开发一套高光谱成像装置(波长400-1000nm,光谱分辨率5nm)采集甘蔗茎节区域的图像立方体。每个甘蔗样本采集128个波段,采用连续投影算法SPA提取对茎节判别最敏感的特征波段,最终选出5个波段:498nm、562nm、617nm、739nm和885nm。在这5个波段上,构建一个偏最小二乘判别模型SPA-PLS-DA,模型校正集包含120个茎节样本和120个非茎节样本,校正集识别率达到99.44%,预测集(60+60样本)识别率为98.31%。为了实现在线定位,将5个特征波段的图像进行波段融合,采用自适应阈值分割(Otsu法)提取茎节候选区域,再通过形态学闭运算(圆形结构元素半径3像素)连接断裂区域。通过计算候选区域的质心坐标作为茎节位置,并用白色标记线在原图上显示。对另外20个甘蔗样本进行验证,茎节定位的平均像素误差为3.2像素,对应实际距离1.2mm。将该模型部署到基于Raspberry Pi的嵌入式系统上,单次茎节检测耗时约0.3秒,可为自动化种植机械提供实时导航输入。
(3)机载LiDAR树木冠层投影面积与体积提取及Android柑橘测量系统:
针对城区树木冠层参数快速获取需求,设计一种基于机载LiDAR点云的冠层投影面积和体积提取算法。首先对原始点云进行滤波分类,采用渐进加密三角网滤波分离地面点和建筑物点,剩余点云作为树木点。对树木点云进行连通域标记,设置欧氏距离阈值0.5m,识别出每棵独立树木。冠层投影面积采用角度法搜索边界:以树木点云质心为极点,按方位角排序点云边界点,再用任意多边形面积公式计算。冠层体积则将树木点云垂直分层(每0.2m一层),每层点云投影到水平面,采用Alpha Shapes算法提取轮廓并计算该层截面面积,然后按层高积分求和。选取10个样地(每样地100x100m)进行验证,LiDAR测量冠层投影面积与人工测量(皮尺测冠幅椭圆)的相关系数R=0.96,体积测量与多旋翼无人机照片三维重建结果的偏差在12%以内。在Android端开发柑橘信息测量App,基于OpenCV4Android,调用平板后置摄像头(1300万像素)采集柑橘在不同角度的5-15幅图像。实现步骤:图像灰度化、高斯滤波(5x5核)、Canny边缘检测(阈值50-150)、提取轮廓,再通过立体视觉匹配得到关键点三维坐标。对6个不同距离(100-350mm)的标准圆球测量,体积准确率98.5%以上。测量10组不规则柑橘,与排水法对比,平均准确率98.2%,计算时间小于5秒。
import cv2 import numpy as np from scipy.spatial import Delaunay def leaf_surface_area_from_mesh(vertices, triangles): # 三维网格曲面面积计算 area = 0.0 for tri in triangles: v0, v1, v2 = vertices[tri[0]], vertices[tri[1]], vertices[tri[2]] # 两边向量叉积的模的一半 cross = np.cross(v1 - v0, v2 - v0) area += 0.5 * np.linalg.norm(cross) return area def spa_feature_selection(X, y, n_features=5): # 连续投影算法选择特征波段 m, p = X.shape selected = [] remaining = list(range(p)) # 第一步选择与y相关性最大的波段 corrs = [abs(np.corrcoef(X[:,i], y)[0,1]) for i in remaining] selected.append(remaining[np.argmax(corrs)]) remaining.remove(selected[-1]) for _ in range(n_features-1): projections = [] for r in remaining: proj = X[:,r] - np.dot(X[:,selected[-1]], X[:,r]) / np.dot(X[:,selected[-1]], X[:,selected[-1]]) * X[:,selected[-1]] projections.append(np.linalg.norm(proj)) idx = remaining[np.argmax(projections)] selected.append(idx) remaining.remove(idx) return selected def lidar_canopy_area(points, z_thresh=2.0): # 冠层投影面积计算(多边形面积) canopy = points[points[:,2] > z_thresh] # 高于2m的作为冠层 if len(canopy) < 3: return 0.0 # 角度法搜索边界点 center = np.mean(canopy[:,:2], axis=0) angles = np.arctan2(canopy[:,1]-center[1], canopy[:,0]-center[0]) sorted_idx = np.argsort(angles) boundary = canopy[sorted_idx, :2] # 多边形面积(鞋带公式) x = boundary[:,0]; y = boundary[:,1] return 0.5 * np.abs(np.dot(x, np.roll(y,1)) - np.dot(y, np.roll(x,1))) def android_citrus_volume(images, calib_file): # 简化的柑橘体积测量(多视图立体) # 假设images是多角度拍摄的图像列表 orb = cv2.ORB_create() bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) points_3d = [] for i in range(len(images)-1): kp1, des1 = orb.detectAndCompute(images[i], None) kp2, des2 = orb.detectAndCompute(images[i+1], None) matches = bf.match(des1, des2) matches = sorted(matches, key=lambda x: x.distance)[:50] # 简化的三角测量(实际需要相机位姿) for m in matches: pt1 = np.array(kp1[m.queryIdx].pt) pt2 = np.array(kp2[m.trainIdx].pt) # 假设基线已知,用平均深度近似 depth = 150.0 # mm points_3d.append([pt1[0], pt1[1], depth]) points_3d = np.array(points_3d) if len(points_3d) < 4: return 0 # 用凸包体积近似 hull = Delaunay(points_3d[:,:2]) # 简化:用椭圆拟合长轴短轴计算体积 radii = np.std(points_3d, axis=0)[:2] return (4/3)*np.pi*radii[0]*radii[1]*np.mean(points_3d[:,2])