在这里插入图片描述

核心实现思路

  1. 滑动窗口策略:在图像上滑动固定大小的窗口,对每个窗口进行分类
  2. 多维特征提取:结合统计特征、纹理特征、边缘特征、形状特征等
  3. 随机森林分类:训练二分类器判断窗口是否包含目标
  4. 后处理优化:使用非极大值抑制减少重复检测

特征工程的重要性

  • LBP纹理特征:捕捉局部纹理模式
  • 灰度共生矩阵:描述纹理的统计特性
  • 边缘密度:反映目标边界信息
  • 形状描述符:圆形度、面积比等几何特征

实际应用建议

  1. 数据收集:收集大量正负样本进行训练
  2. 特征优化:根据具体目标调整特征提取策略
  3. 参数调优:调整窗口大小、步长、置信度阈值等
  4. 多尺度检测:使用不同尺寸的窗口检测不同大小的目标

适用场景

  • 计算资源受限的嵌入式设备
  • 目标具有明显纹理或形状特征的场景
  • 需要快速部署和调试的原型系统
  • 传统图像处理流程的补充

import cv2
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from skimage.feature import local_binary_pattern, graycomatrix, graycoprops
from skimage.measure import regionprops
import os
from typing import List, Tuple
import matplotlib.pyplot as pltclass RandomForestObjectDetector:"""基于随机森林的目标检测器"""def __init__(self, window_size=(64, 64), step_size=16, n_estimators=100):"""初始化检测器Args:window_size: 滑动窗口大小step_size: 滑动步长n_estimators: 随机森林中树的数量"""self.window_size = window_sizeself.step_size = step_sizeself.rf_classifier = RandomForestClassifier(n_estimators=n_estimators,random_state=42,max_depth=10,min_samples_split=5)self.is_trained = Falsedef extract_features(self, image_patch: np.ndarray) -> np.ndarray:"""从图像块中提取特征Args:image_patch: 输入图像块Returns:特征向量"""features = []# 确保图像是灰度图if len(image_patch.shape) == 3:gray = cv2.cvtColor(image_patch, cv2.COLOR_BGR2GRAY)else:gray = image_patch.copy()# 1. 基础统计特征features.extend([np.mean(gray),           # 均值np.std(gray),            # 标准差np.median(gray),         # 中位数np.min(gray),            # 最小值np.max(gray),            # 最大值np.var(gray)             # 方差])# 2. 纹理特征 - LBP (局部二值模式)radius = 3n_points = 8 * radiuslbp = local_binary_pattern(gray, n_points, radius, method='uniform')lbp_hist, _ = np.histogram(lbp.ravel(), bins=n_points + 2, range=(0, n_points + 2), density=True)features.extend(lbp_hist)# 3. 灰度共生矩阵特征try:# 计算灰度共生矩阵glcm = graycomatrix(gray, distances=[1], angles=[0, 45, 90, 135], levels=256, symmetric=True, normed=True)# 提取纹理属性contrast = graycoprops(glcm, 'contrast').mean()dissimilarity = graycoprops(glcm, 'dissimilarity').mean()homogeneity = graycoprops(glcm, 'homogeneity').mean()energy = graycoprops(glcm, 'energy').mean()correlation = graycoprops(glcm, 'correlation').mean()features.extend([contrast, dissimilarity, homogeneity, energy, correlation])except:# 如果GLCM计算失败,添加默认值features.extend([0, 0, 0, 0, 0])# 4. 边缘特征edges = cv2.Canny(gray, 50, 150)edge_density = np.sum(edges > 0) / edges.sizefeatures.append(edge_density)# 5. 梯度特征grad_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)grad_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)grad_magnitude = np.sqrt(grad_x**2 + grad_y**2)features.extend([np.mean(grad_magnitude),np.std(grad_magnitude)])# 6. 形状特征 (通过二值化后的连通区域)_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)if contours:# 找最大轮廓largest_contour = max(contours, key=cv2.contourArea)area = cv2.contourArea(largest_contour)perimeter = cv2.arcLength(largest_contour, True)# 形状描述符if perimeter > 0:circularity = 4 * np.pi * area / (perimeter ** 2)else:circularity = 0features.extend([area / (gray.shape[0] * gray.shape[1]), circularity])else:features.extend([0, 0])return np.array(features)def sliding_window(self, image: np.ndarray) -> List[Tuple]:"""在图像上应用滑动窗口Args:image: 输入图像Returns:窗口位置和图像块的列表"""windows = []h, w = image.shape[:2]for y in range(0, h - self.window_size[1] + 1, self.step_size):for x in range(0, w - self.window_size[0] + 1, self.step_size):window = image[y:y + self.window_size[1], x:x + self.window_size[0]]if window.shape[:2] == self.window_size:windows.append(((x, y), window))return windowsdef prepare_training_data(self, positive_samples: List[np.ndarray], negative_samples: List[np.ndarray]) -> Tuple[np.ndarray, np.ndarray]:"""准备训练数据Args:positive_samples: 正样本图像块列表negative_samples: 负样本图像块列表Returns:特征矩阵和标签向量"""features = []labels = []print("提取正样本特征...")for sample in positive_samples:feature = self.extract_features(sample)features.append(feature)labels.append(1)  # 正样本标签print("提取负样本特征...")for sample in negative_samples:feature = self.extract_features(sample)features.append(feature)labels.append(0)  # 负样本标签return np.array(features), np.array(labels)def train(self, positive_samples: List[np.ndarray], negative_samples: List[np.ndarray]):"""训练随机森林分类器Args:positive_samples: 正样本图像块列表negative_samples: 负样本图像块列表"""print("准备训练数据...")X, y = self.prepare_training_data(positive_samples, negative_samples)print(f"训练数据形状: {X.shape}, 标签分布: {np.bincount(y)}")# 分割训练和验证集X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)print("训练随机森林分类器...")self.rf_classifier.fit(X_train, y_train)# 验证性能val_pred = self.rf_classifier.predict(X_val)print("\n验证集性能:")print(classification_report(y_val, val_pred))self.is_trained = Trueprint("训练完成!")def detect(self, image: np.ndarray, confidence_threshold: float = 0.7) -> List[Tuple]:"""在图像中检测目标Args:image: 输入图像confidence_threshold: 置信度阈值Returns:检测结果列表 [(x, y, w, h, confidence), ...]"""if not self.is_trained:raise ValueError("模型尚未训练,请先调用train()方法")detections = []windows = self.sliding_window(image)print(f"处理 {len(windows)} 个窗口...")for (x, y), window in windows:# 提取特征features = self.extract_features(window).reshape(1, -1)# 预测prediction = self.rf_classifier.predict(features)[0]confidence = self.rf_classifier.predict_proba(features)[0][1]  # 正类概率if prediction == 1 and confidence >= confidence_threshold:detections.append((x, y, self.window_size[0], self.window_size[1], confidence))return detectionsdef non_max_suppression(self, detections: List[Tuple], overlap_threshold: float = 0.3) -> List[Tuple]:"""非极大值抑制Args:detections: 检测结果列表overlap_threshold: 重叠阈值Returns:过滤后的检测结果"""if not detections:return []# 按置信度排序detections = sorted(detections, key=lambda x: x[4], reverse=True)keep = []while detections:# 保留置信度最高的检测current = detections.pop(0)keep.append(current)# 计算与其他检测的重叠remaining = []for detection in detections:iou = self.calculate_iou(current, detection)if iou < overlap_threshold:remaining.append(detection)detections = remainingreturn keep@staticmethoddef calculate_iou(box1: Tuple, box2: Tuple) -> float:"""计算两个边界框的IoU"""x1, y1, w1, h1, _ = box1x2, y2, w2, h2, _ = box2# 计算交集xi1 = max(x1, x2)yi1 = max(y1, y2)xi2 = min(x1 + w1, x2 + w2)yi2 = min(y1 + h1, y2 + h2)if xi2 <= xi1 or yi2 <= yi1:return 0.0intersection = (xi2 - xi1) * (yi2 - yi1)union = w1 * h1 + w2 * h2 - intersectionreturn intersection / union if union > 0 else 0.0def visualize_detections(self, image: np.ndarray, detections: List[Tuple], title: str = "检测结果"):"""可视化检测结果Args:image: 原始图像detections: 检测结果列表title: 图像标题"""img_vis = image.copy()for x, y, w, h, confidence in detections:# 绘制边界框cv2.rectangle(img_vis, (x, y), (x + w, y + h), (0, 255, 0), 2)# 添加置信度标签label = f"{confidence:.2f}"cv2.putText(img_vis, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)plt.figure(figsize=(12, 8))plt.imshow(cv2.cvtColor(img_vis, cv2.COLOR_BGR2RGB))plt.title(f"{title} - 检测到 {len(detections)} 个目标")plt.axis('off')plt.show()# 使用示例
def create_sample_data():"""创建示例训练数据"""# 创建模拟的正样本 (包含目标的图像块)positive_samples = []for _ in range(100):# 模拟水坝结构 - 矩形形状with一些纹理sample = np.random.randint(50, 100, (64, 64), dtype=np.uint8)# 添加矩形结构cv2.rectangle(sample, (10, 20), (50, 40), 150, -1)# 添加噪声noise = np.random.normal(0, 10, sample.shape)sample = np.clip(sample + noise, 0, 255).astype(np.uint8)positive_samples.append(sample)# 创建模拟的负样本 (背景图像块)negative_samples = []for _ in range(200):# 随机背景纹理sample = np.random.randint(0, 50, (64, 64), dtype=np.uint8)# 添加随机纹理noise = np.random.normal(0, 15, sample.shape)sample = np.clip(sample + noise, 0, 255).astype(np.uint8)negative_samples.append(sample)return positive_samples, negative_samples# 完整使用示例
if __name__ == "__main__":# 1. 创建检测器detector = RandomForestObjectDetector(window_size=(64, 64), step_size=32)# 2. 准备训练数据print("创建示例数据...")positive_samples, negative_samples = create_sample_data()# 3. 训练模型detector.train(positive_samples, negative_samples)# 4. 创建测试图像test_image = np.random.randint(0, 50, (300, 400), dtype=np.uint8)# 在测试图像中放置几个目标cv2.rectangle(test_image, (50, 50), (114, 114), 150, -1)cv2.rectangle(test_image, (200, 150), (264, 214), 150, -1)# 5. 进行检测print("进行目标检测...")detections = detector.detect(test_image, confidence_threshold=0.6)# 6. 应用非极大值抑制filtered_detections = detector.non_max_suppression(detections, overlap_threshold=0.3)print(f"原始检测数量: {len(detections)}")print(f"NMS后检测数量: {len(filtered_detections)}")# 7. 可视化结果if len(filtered_detections) > 0:detector.visualize_detections(cv2.cvtColor(test_image, cv2.COLOR_GRAY2BGR), filtered_detections)else:print("未检测到目标")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84360.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84360.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84360.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.6 move_base导航初体验

1.环境搭建 在工作空间src下git wpr_simulation&#xff0c;安装install_for_noetic.sh&#xff0c;然后再回退工作空间进行编译 下载参数文件 git clone https://github.com/6-robot/wpb_home.git下载需要魔法&#xff0c;在这里可以使用手机热点进行平替 进入脚本文件夹 …

Mysql高级——MVCC(多版本并发控制)

MySQL MVCC&#xff08;多版本并发控制&#xff09;详解 MVCC&#xff08;Multi-Version Concurrency Control&#xff09;是 MySQL InnoDB 存储引擎实现的一种并发控制机制&#xff0c;用于在保证事务隔离性的同时&#xff0c;提高数据库的并发性能。下面从原理、实现、事务隔…

Oracle union连接的怎么排序

在Oracle数据库中&#xff0c;使用UNION或UNION ALL操作符来合并两个或多个查询结果时&#xff0c;如果想对这些合并后的结果进行排序&#xff0c;通常有两种方法可以实现&#xff1a; 方法1&#xff1a;在最后的查询结果上使用ORDER BY 你可以在所有使用UNION或UNION ALL合并…

uni-app总结2-所需知识储备和学习途径

使用uni-app进行跨平台开发&#xff0c;开发者不用去掌握各个平台的开发语言&#xff0c;只需一套代码即可完成多端的产品输出。那么使用uni-app需要掌握什么呢&#xff0c;这里给大家分享一下。 Vue.js uni-app里是通过Vue来开发的&#xff0c;所以首先肯定是要掌握Vue语言。…

如何高效实现公司文件管理

要实现公司文件管理的高效&#xff0c;企业应聚焦统一文件规范、部署文档管理系统、强化权限控制、推动协同编辑、实施定期清理、推进文化建设、引入可视化分析。其中&#xff0c;统一文件规范是文件高效管理的基础。若缺乏清晰的命名规则与分类体系&#xff0c;即便配备了先进…

多模态大语言模型arxiv论文略读(124)

MediConfusion: Can you trust your AI radiologist? Probing the reliability of multimodal medical foundation models ➡️ 论文标题&#xff1a;MediConfusion: Can you trust your AI radiologist? Probing the reliability of multimodal medical foundation models …

nacos的总结

服务发现与健康监测&#xff1a;Nacos 支持多种服务注册方式&#xff0c;包括 API、SDK 和 Annotation 等&#xff0c;服务消费者可以通过 DNS 或 RPC 方式方便地发现服务。其健康检查机制通过主动和被动的方式实时监测服务实例的健康状态&#xff0c;确保流量不会被发送到不健…

低轨导航 | 低轨卫星导航PNT模型,原理,公式,matlab代码

一、PNT模型原理 低轨卫星PNT(定位、导航、授时)模型利用低轨星座的快速几何构型变化和强信号特性,通过三类核心观测值实现增强定位: 几何增强原理 低轨卫星速度7km/s(比GNSS快8-10倍)5分钟内观测几何变化相当于地面站24小时变化量加速模糊度收敛和误差分离信号增强原理…

基于python的查询工具,查询手机号的卡号归属地

本文介绍了一个利用Python进行电话号码归属地查询的代码示例。代码使用requests库发送HTTP请求&#xff0c;伪装浏览器UA头&#xff0c;通过lxml库解析网页数据&#xff0c;并运用XPath提取号码归属地信息。程序构建了查询URL&#xff0c;发送GET请求后解析返回的HTML内容&…

AI面试系统选型HR应考虑哪些问题?

北森人才管理研究院发布的《2025 企业校园招聘 AI 应用实用指南》数据显示&#xff1a;全球 44% 的企业已在招聘环节部署AI技术&#xff0c;72% 的 HR 每周至少使用一次 AI 工具&#xff0c;87% 的 HR 认为 AI 能显著提升招聘效率。 来源于《北森2025 企业校园招聘 AI 应用实用…

Redis02

redis的持久化机制 1.redis为什么需要持久化 redis本身运行时数据保存在内存中&#xff0c;那么在关闭redis的进程或者关闭计算机后数据肯定被会操作系统从内存中清掉。 redis持久化方式有两种: RDB AOF redis默认采用了一种持久化方式&#xff0c;即RDB &#xff08;Redi…

Gartner发布网络安全组织设计指南:设计网络安全组织的五项原则和六种主要安全组织类型

安全和风险管理领导者经常寻求一种通用的模型来组织其职能&#xff0c;这可能导致效率低下和需求得不到满足。然而&#xff0c;目前并没有一个标准的组织模型。这项研究可以帮助他们根据企业实际情况&#xff0c;设计出最合适的网络安全组织。 主要发现 许多安全和风险管理 (SR…

简述redis的单线程模式

在redis版本6之前&#xff0c;网络IO和键值对读写都是由一个线程来完成的。而redis的其他功能&#xff0c;比如持久化、异步删除、集群数据同步等&#xff0c;是由其他线程完成的。 为什么采用单线程 多线程有助于提升吞吐率&#xff08;系统同时处理的请求数&#xff09;&am…

WebSocket深度指南:从零基础到生产级应用

📚目录 1. WebSocket基础概念深度解析 2. WebSocket协议技术详解 3. WebSocket生命周期与状态管理 4. Spring Boot WebSocket完整实现 5. 完整聊天室项目实战 6. 高级功能与扩展应用 1. WebSocket基础概念深度解析 1.1 什么是WebSocket?深度理解 WebSocket是HTML5开…

复现 apache HTTPD 换行解析漏洞(CVE-2017-15715)

一、漏洞环境 docker环境 http://192.168.99.124:8082二、漏洞原理 Apache HTTPD是一款HTTP服务器&#xff0c;它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞&#xff0c;在解析PHP时&#xff0c;1.php\x0A将被按照PHP后缀进行解析&#xff0c;导致…

创始人 IP 起盘方法论:从 0 到 1 的系统化破局路径

在流量逻辑不断更新的当下&#xff0c;创始人 IP 如何构建可持续的商业闭环&#xff1f;结合行业头部案例的实战经验&#xff0c;可梳理出一套兼顾落地性与前瞻性的起盘策略&#xff0c;帮助 IP 在波动的市场中建立稳定的变现能力。 一、定位&#xff1a;在动态中验证方向 某…

数据结构 6(算法)

一、算法 1、概念 问题的求解方法 2、算法的特性和设计要求 算法的特性&#xff1a; 确定性 有穷性 输入输出 可行性 设计要求&#xff1a; 正确性 高效性 低存储 健壮性 可读性 3、时间复杂度O(n) 用于评估程序执行…

Android 开发问题:android.content.res.Resources$NotFoundException: Resource ID

android.content.res.Resources$NotFoundException: Resource ID #0xff412804问题原因 该异常表示 Android 系统尝试通过资源 ID 查找资源&#xff0c;例如&#xff0c;颜色、图片等&#xff0c;但未查找到对应资源 其中&#xff0c;0xff412804 是一个硬编码的整型颜色值&…

03.自动特征提取(深度学习)核心逻辑:通过多层非线性变换,让模型自动学习从原始数据到高层特征的映射。为什么多层非线性变换可以达到这样的效果?

在深度学习中,多层非线性变换能够实现自动特征提取的核心原因在于其对数据表征的分层学习能力和非线性映射的表达优势。以下从理论基础、数学机制、实际效果三个层面展开解析: 一、非线性变换的本质:突破线性模型的表达局限 线性模型的局限性 线性变换(如矩阵乘法)只能学…

42-Oracle 23 ai 安全新特性(Audit统一审计)

小伙伴们业务和安全运维中需要数据库审计都是由哪些模块来实现的&#xff0c;专门的第三方产品吗&#xff1f;在医疗领域防统方等业务场景和数据库的审计集合很是紧密。 在Oracle逐个版本的演进中&#xff0c;Oracle 23ai 的审计特性在安全领域的重大革新&#xff0c;延续传统…