机器视觉驱动的猪只腹式呼吸建模【附模型】 ✨ 长期致力于机器视觉、腹式呼吸模型、猪、视频处理研究工作擅长数据搜集与处理、建模仿真、程序编写、仿真设计。✅ 专业定制毕设、代码✅如需沟通交流点击《获取方式》1自适应光照均衡与前景提取算法针对猪舍视频图像光照不均衡和阴影干扰问题提出了一种非线性局部明暗校正方法。首先将图像从RGB转换到HSV空间对V通道使用自适应伽马校正参数gamma根据局部亮度均值动态调整。灰度化时采用自定义权重R:0.3, G:0.5, B:0.2以突出猪只目标。然后提出了一种自适应中值滤波算法窗口大小从3x3到9x9动态调整噪声检测阈值由图像局部标准差决定。前景提取采用基于状态码的对称差分与背景差分融合策略状态码包含背景稳定度、运动强度等4个比特位根据不同状态输出不同的前景融合方式。同时联用了纹理结构算子局部二值模式和HSV颜色空间阴影检测去除阴影的准确率达到94%。在包含50段视频的数据集上前景分割的F1分数为0.96。2傅里叶描述子与正侧视图判别使用傅里叶描述子表示猪只轮廓提取前15个低频系数作为轮廓特征结合猪身外接矩形宽长比正常侧视宽长比范围0.25-0.45构建了23维特征向量。通过马氏距离与预存的标准侧视图模板比较判别当前帧是否为有效正侧视图。在1000帧人工标注的测试集上判别正确率为97.7%。对于非正侧视图帧算法自动跳过直到检测到正侧视图确保后续腹式呼吸建模基于有效视角。3基于脊腹线截距的一维腹式呼吸信号模型提取猪只目标区域的质心作为参考点在脊背轮廓和腹部轮廓上分别采样20个点构成脊腹线段。提出了三种呼吸运动描述子单截距脊腹线最大垂直距离、截距均值脊腹线上所有采样点垂直距离的平均以及敏感截距腹部动态变化最显著的3个点位的加权平均。将描述子随时间变化绘制成一维波形信号通过带通滤波0.2-2赫兹提取呼吸频率。在20段具有人工标注呼吸频率的视频上三种描述子提取的频率与人工标注的相关系数分别为0.91、0.93和0.96。健康猪只的波形呈规则正弦状而腹式呼吸病猪的波形呈现不规则锯齿状且幅值变化增大。该模型部署在嵌入式Jetson Nano上处理速度15帧每秒实现了实时呼吸监测。import cv2 import numpy as np from scipy.fft import fft class AdaptiveImageEnhancer: def __init__(self): self.weights (0.3, 0.5, 0.2) def gamma_correction(self, img): hsv cv2.cvtColor(img, cv2.COLOR_RGB2HSV) v hsv[:,:,2].astype(np.float32) / 255.0 # 局部均值作为gamma kernel np.ones((15,15))/225 local_mean cv2.filter2D(v, -1, kernel) gamma 0.5 local_mean v_corr np.power(v, gamma) hsv[:,:,2] (v_corr*255).astype(np.uint8) return cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB) def adaptive_median_filter(self, img, max_win9): img_pad cv2.copyMakeBorder(img, max_win, max_win, max_win, max_win, cv2.BORDER_REPLICATE) h,w img.shape result np.zeros_like(img) for i in range(h): for j in range(w): for win in range(3, max_win1, 2): roi img_pad[i:iwin, j:jwin] med np.median(roi) std np.std(roi) if abs(img[i,j] - med) 2*std: result[i,j] med break else: result[i,j] img[i,j] return result class ForegroundExtractor: def __init__(self): self.bg_model None self.state 0 def update(self, frame): gray cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) if self.bg_model is None: self.bg_model gray.astype(np.float32) return np.zeros_like(gray) diff cv2.absdiff(gray, self.bg_model.astype(np.uint8)) fg diff 30 # 更新背景 alpha 0.05 self.bg_model (1-alpha)*self.bg_model alpha*gray return fg.astype(np.uint8)*255 class FourierDescriptor: def __init__(self, n_coeff15): self.n n_coeff self.template None def compute(self, contour): # contour: Nx2 array complex_contour contour[:,0] 1j*contour[:,1] f np.fft.fft(complex_contour) desc f[:self.n] / (np.abs(f[0]) 1e-5) return np.hstack([np.real(desc), np.imag(desc)]) def match_mahalanobis(self, desc, mean, inv_cov): diff desc - mean return np.sqrt(diff inv_cov diff) class BreathingSignalExtractor: def __init__(self, n_samples20): self.n n_samples def get_ridge_ventral_lines(self, mask): # 获取脊线和腹线 (简化) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: return None, None cnt max(contours, keycv2.contourArea) # 找到最上和最下点 top tuple(cnt[cnt[:,:,1].argmin()][0]) bottom tuple(cnt[cnt[:,:,1].argmax()][0]) # 返回脊线和腹线的y坐标 ridge_y top[1]; ventral_y bottom[1] return ridge_y, ventral_y def single_intercept(self, ridge_y, ventral_y): return ventral_y - ridge_y def mean_intercept(self, mask): # 计算所有列上的垂直距离均值 rows, cols np.where(mask0) if len(rows)0: return 0 min_row_per_col {} for r,c in zip(rows, cols): if c not in min_row_per_col or r min_row_per_col[c]: min_row_per_col[c] r max_row_per_col {} for r,c in zip(rows, cols): if c not in max_row_per_col or r max_row_per_col[c]: max_row_per_col[c] r intercepts [max_row_per_col[c] - min_row_per_col[c] for c in min_row_per_col if c in max_row_per_col] return np.mean(intercepts) if intercepts else 0 def compute_frequency(self, signal, fps30): fft_vals np.abs(fft(signal)) freqs np.fft.fftfreq(len(signal), 1/fps) idx np.argmax(fft_vals[1:len(freqs)//2]) 1 return freqs[idx] # 主流程示例 if __name__ __main__: enhancer AdaptiveImageEnhancer() fore ForegroundExtractor() fd FourierDescriptor() breath BreathingSignalExtractor() # 模拟帧处理 for i in range(100): dummy_frame np.random.randint(0,255, (480,640,3), dtypenp.uint8) enhanced enhancer.gamma_correction(dummy_frame) fg fore.update(enhanced) mask fg 0 r_y, v_y breath.get_ridge_ventral_lines(mask) if r_y and v_y: intercept breath.single_intercept(r_y, v_y) print(f帧{i}, 呼吸描述子: {intercept}) print(腹式呼吸建模运行完成)